Escaping quotes for COMPILE_DEFINITIONS - visual-studio-2010

Currently I'm working on a cmake script to compile generated C code. I'm trying to generate a Visual Studio 10 project. The code contains several #include statements which have to be preprocessed before compilition:
#indude INC_FILE
Before starting with CMake the code was compiled with a manually maintained Visual Studio project. I added a preprocessor definition to replace INC_FILE with the final include header:
INC_FILE="foo.h"
For my new CMak script I tried to add this statement to the COMPILE_DEFINITION variable:
set_property(TARGET ${TARGET_NAME} APPEND_STRING PROPERTY COMPILE_DEFINITION "INC_FILE="foo.h"")
Sadly this doesn't work because the quotes are removed. In the generated visual studio project I found the in the project file:
INC_FILE=foo.h
I tried to escape the quotes:
"INC_FILE=\"foo.h\""
INC_FILE=\"foo.h\"
"INC_FILE=\\"foo.h\\"
"INC_FILE="foo.h"
All the above mentions possibilites didn't work. Are there any other tricks in cmake to get a correct quotes escaping for my preprocessor definition?

Tested with cmake 2.8.12.1:
add_executable(foo foo.cpp)
target_compile_definitions(foo PUBLIC FOO_INCL="foo.hpp")
Note 1
You can use include option instead of file's name macro:
#if defined(FOO_INCLUDE_SOME_FILE)
# include "some_file.hpp"
#elif defined(FOO_INCLUDE_OTHER_FILE)
# include "other_file.hpp"
#endif
IMHO it looks much cleaner.
Note 2
If you have a bad time with special characters use configure_file command:
> cat some_file.hpp.in
#include "#FOO_INCLUDE_FILE#"
> cat CMakeLists.txt
set(FOO_INCLUDE_FILE "other_file.hpp")
configure_file(some_file.hpp.in ${foo_BINARY_DIR}/include/some_file.hpp #ONLY)

Related

CMake: how to embed build configuration (Debug, Release, MinSizeRel,...) into binary?

I'm using Cmake's configure_file() function to generate a header that I include into my project.
This way, I can for example store into the resulting binary the git commit hash of the code beeing compiled.
Now I'm trying to make my program aware of the compilation configuration which has been used: Debug, Release, MinSizeRel or RelWithDebInfo.
The toolchain used is VisualStudio, therefore all configurations are generated by CMake at the same time. So for example, CMAKE_BUILD_TYPE is alays set to Release.
What is the common way to make the program built aware of the the build mode used ?
You may create a file, containing build type-specific values, using file(GENERATE) command. This command expands generator expressions.
For example, the call
file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/build_$<CONFIG>
CONTENT "Build type: $<CONFIG>")
at the end of configuration will create build_Debug file with content Build type: Debug, build_Release file with content Build type: Release and so on.
Resulted files could be used in custom commands:
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/some_file_$<CONFIG>
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/build_$<CONFIG>
COMMAND do-something-with build_$<CONFIG>
)
Note, that file(GENERATE) doesn't expand variables. So if you want to combine in the resulted file both variables values and generator expressions, then you need to "pipe" configure_file with file(GENERATE).
my_file.in:
var: #MY_VAR#
build type: $<CONFIG>
CMakeLists.txt:
# Creates intermediate file with expanded variables.
configure_file(my_file.in my_file_intermediate #ONLY)
# Expands generator expressions in the intermediate file and creates "final" files
file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/my_file_$<CONFIG>
INPUT ${CMAKE_CURRENT_BINARY_DIR}/my_file_intermediate)
You can use CMake generator expressions with the add_compile_definitions command (or any other command which accepts generator expressions).
Like this: add_compile_definitions(CONFIG_TYPE="$<CONFIG>"). Then use the CONFIG_TYPE macro in your C++ code.

define gets ignored by target_compile_definitions

I am looking to build a library and I need to pass two defines to that build, but cmake's target_compile_definitions() scrambles them in a manner that renders them unusable.
The two defines are:
-D'_LIB_EXCEPTION_ABI=__attribute__((visibility("default")))'
-D'_LIB_FALLTHROUGH()=((void)0)'
Unfortunately, the first one gets translated to (in the command build line):
-D'_LIB_EXCEPTION_ABI="\__attribute__((visibility(\"default\")))'"
While the second one is missing altogether from the command line.
CMake has known limitations on what compile definitions could be.
Among these limitations are function-style definitions (_LIB_FALLTHROUGH()) and ones containing double quotes (").
Instead of attempting to overcome these limitations, it is recommended to create a separate header file with these compile definitions:
#define _LIB_EXCEPTION_ABI __attribute__((visibility("default")))
#define _LIB_FALLTHROUGH() ((void)0)
This header file could be included with -include compiler option (gcc) or /FI option (Visual Studio).

Undefinition of MSVC definition _MBCS and definition of _UNICODE not possible calling cmake from command line [duplicate]

This question already has answers here:
How to define a C++ preprocessor macro through the command line with CMake?
(4 answers)
Closed 3 years ago.
I want to generate a visual studio project 2010 with cmake from a CMakeLists.txt. Basically this works fine. However, one detail lead to my following observation:
The default character set for the generated visual studio project is 'Multibyte Character'. I want to change it to Unicode. As far as I found out, I need to define either _UNICODE or UNICODE, but I also need to undefine _MBCS. This works out, if I put it in the CMakeLists.txt, but I can't get it working, if I want to set these definitions by command line:
CMakeList.txt, works fine:
add_definitions ( -D_UNICODE )
remove_definitions ( -D_MBCS )
Command line, definitions are ignored by cmake, if I do it like this:
cmake -D_UNICODE="" -U_MBCS=""
Command line, definitions are ignored by cmake, if I do it like this:
cmake -DCMAKE_CXX_FLAGS_INIT="-D_UNICODE -U_MBCS"
I assumed that both ways are the same, but obviously the handling of the definitions from command line is different. I am doing something wrong or is it only possible by using add_definitions / remove_definitions ?
By the way, I'm using cmake 3.10.
The -D flags passed to cmake are completely unrelated to the -D flags passed to the compiler. See cmake(1). In short, cmake -DVARIABLE=VALUE ... is roughly equivalent to using set(VARIABLE VALUE CACHE STRING "") inside your CMakeLists.txt.
If you cannot use add_definitions or target_compile_definitions, you can still pass flags to the compiler by setting CMAKE_CXX_FLAGS_INIT the first time you invoke cmake or by changing CMAKE_CXX_FLAGS on later invocations of cmake:
cmake -DCMAKE_CXX_FLAGS_INIT="-D_UNICODE -U_MBCS" ...

Get rid of CMake Rules folder

Is there a way to get rid of the CMake Rules folders in targets in Visual Studio?
In this case the game target uses cotire for precompiled header support and the omg target has a custom command that parses the .mix file and outputs the ..._gen.h file.
Also would it be possible to remove the CMakeLists.txt file from there too? I know it's there for convenience but in my workflow it isn't that useful.
EDIT: Started a second bounty because I really need this - these "CMake Rules" folders are bloating my solution explorer because I have 100+ projects which all have them!
I would accept anything - a CMake way, a VS way (some "solution explorer view" or macro or whatever)...
EDIT 2:
here is sort-of the cmake for the omg target:
add_library(omg SHARED D:/omg.cpp D:/omg.mix)
add_custom_command(OUTPUT D:/omg_gen.h MAIN_DEPENDENCY D:/omg.mix COMMAND python D:/mixify.py D:/omg.mix D:/omg_gen.h)
add_custom_target(${target}_gen_${mix_name_only} DEPENDS ${gen_header})
add_dependencies(omg omg_gen)
target_sources(omg PUBLIC D:/omg_gen.h)
so omg_gen.h is generated from omg.mix and then included in omg.cpp
The .rule files are needed by CMake to attach the custom commands to some "dummy" self-generated file, if there are no input files given. You can see this when you look at the .rule file properties of your Visual Studio project in question (see Custom Build Tool/General/Command Line).
If you're not changing the CMake script code containing those target, you can't get rid of them.
You can only move them into the project's root source folder or any other folder you specify.
I've successfully tested the following example:
cmake_minimum_required(VERSION 2.8)
project(NoRulesSourceGroup NONE)
# Overwrite the rule for "CMake Rules" with do-not-match-anything (-> root)
source_group("CMake Rules" REGULAR_EXPRESSION "^$")
# Move ".rule" files somewhere else
source_group("Some Other Source Group" REGULAR_EXPRESSION "\\.rule$")
add_custom_target(
${PROJECT_NAME}
COMMAND ${CMAKE_COMMAND} -E echo "Hello World"
)
Edit: You could also combine the above regular expression with a match for CMakeLists.txt:
source_group("Some Other Source Group" REGULAR_EXPRESSION "CMakeLists\\.txt|\\.rule$")
Edit: If you can modify your CMake script code, you should add to your add_custom_command() call:
MAIN_DEPENDENCY
Specify the primary input source file to the command. This is treated just like any value given to the DEPENDS option but also suggests to Visual Studio generators where to hang the custom command. At most one custom command may specify a given source file as its main dependency.
In your case you won't even need the additional custom target since you have a dependency through the header file. I've successfully tested the following derived from your question's example:
file(WRITE omg.cpp "")
file(WRITE omg.mix "")
add_library(omg SHARED omg.cpp omg.mix)
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/omg_gen.h
MAIN_DEPENDENCY omg.mix
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/omg.mix ${CMAKE_CURRENT_BINARY_DIR}/omg_gen.h
)
target_sources(omg PUBLIC ${CMAKE_CURRENT_BINARY_DIR}/omg_gen.h)
References
source_group()
Source/cmMakefile.cxx

Concatenation problems with debug print macro under gcc

To completely disable a debug output in c-source,
I usually define the following SIMPLE macro #1
#define dprintf(args)
To enable a debug output, I define macro #2 alternatively
#define dprintf(args) printk##args
The usage in source looks like:
dprintf(("Irqs:%lu\n",irqs));
A preprocessor should create following line if I use macro #2
printk("Irqs:%lu\n",irqs);
Under Windows Visual c++, there is no problem.
Using gcc version 4.4.1 (Ubuntu 4.4.1-4ubuntu9) under NETBEANS IDE 6.8,
I got the following error message:
"printk" and "(" does not give a valid preprocessing token
I tried the following under Linux
#define dprintk(args...) printk(args)
This works only with
dprintf("Irqs:%lu\n",irqs);
Visual C++ however does not know args...
I have to compile source code on windows
and Linux(386) platform alternatively.
Does anyone have an idea ?
Why not #define dprintf(args) print args ?
The double parenthesis could have been added to replace the variadic macro in visual C++ : the preprocessor will handle macro invocation as if there was only one parameter.
The token pasting operator ## can only be used to concatenate tokens, as its name implies. Some compilers, e.g. newer versions of gcc, enforce this more rigidly than others, as you have now discovered. As philippe says, though, you don't actually need ## in this particular example.

Resources