I want to pass result of the getconf PAGESIZE command output as preprocessor define to my program in form of -DPAGESIZE=`getconf PAGESIZE` for [[gnu::assume_aligned(PAGESIZE)]] in custom allocator declaration.
I tried the following:
add_definitions(-DPAGESIZE=`getconf PAGESIZE`)
But it expanded exactly as -DPAGESIZE="\`getconf" ... PAGESIZE`, where ... is contents of other CMAKE_CXX_FLAGS*. I.e. there is an issue with escaping of backticks in CMakeLists.txt files.
How to properly pass such an arguments to compiler/linker in CMakeLists.txt files? Maybe is there another way to achieve desired?
Also I tried add_definitions(-DPAGESIZE="$$(getconf PAGESIZE)") ($$ expanded as $ by cmake), but -DPAGESIZE and the rest part are splitted by cmake. add_definitions("-DPAGESIZE=$$(getconf PAGESIZE)") makes cmake to escape every dollar sign though.
According to documentation for add_definitions command, preprocessor definitions, passed to this command, are appended to COMPILE_DEFINITIONS property:
Flags beginning in -D or /D that look like preprocessor definitions are automatically added to the COMPILE_DEFINITIONS directory property for the current directory.
And content of COMPILE_DEFINITIONS property, according to its documentation is always escaped by CMake, so you cannot preserve special meaning of backticks in the build command:
CMake will automatically escape the value correctly for the native build system
Your may modify CMAKE_CXX_FLAGS manually, as you show in your comment.
The better way is to use execute_process command for run needed command at configuration stage, and use its output for add_definitions command. (Or use this output for create additional header file with configure_file).
Related
Is there a way to pass C_INCLUDE_DIRS and LD_LIBRARY_PATH from cmake command line or is there a way to set env so that CMAKE can find and use them?
It is not fully clear what you intend to do with these variables. Here are some possibilities:
Inside a CMake script you can read environment variables using the syntax $ENV{<VARIABLE_NAME>}. So in your CMakeLists.txt you can have something like
message( "Found environment variable LD_LIBRARY_PATH=$ENV{LD_LIBRARY_PATH}" )
If you want to add the location contained in this variable to be available to your CMake target executables and libraries then you can use the link_directories() command as
link_directories( $ENV{LD_LIBRARY_PATH} )
Or if you have someone else's project and you want to instruct CMake to look for libraries in some additional directories you can use CMAKE_PREFIX_PATH or CMAKE_LIBRARY_PATH. For example to pass these variables in a command line you could do
cmake -D CMAKE_PREFIX_PATH=/path/to/custom/location
One should care when use an environment variable which denotes path and want the project to work on Windows. The problem is with a path separator: CMake uses forward slash, /, but Windows uses backslash, \.
For convert a path from the native (OS-specific) to the CMake, one may use file(TO_CMAKE_PATH) command flow:
# Save environment variable into the CMake but with the proper path separator
file(TO_CMAKE_PATH "$ENV{SOME_PATH_VAR}" SOME_PATH_VAR_CMAKE)
# Following commands could use the created CMake variable
include_directories(${SOME_PATH_VAR_CMAKE})
Also, find_* commands (e.g. find_path) have PATH and HINTS options, which can transform paths from environment variables automatically, using ENV <VAR> syntax:
find_path(MYLIB_INCLUDE_DIRECTORY # Result variable
mylib.h # File to search for
HINTS ENV SOME_PATH_VAR # Take a hint from the environment variable
)
If you want to do the (seems to me anyway) obvious thing with them, which is to get find_library and find_path to find things located therein, I finally figured out that you should use the INCLUDE and LIB. This is mentioned in the docs for find_library but it's not obvious that those are environment variables. So, e.g.:
export LIB=$LIB;$LD_LIBRARY_PATH
export INCLUDE=$INCLUDE;$C_INCLUDE_PATH;$CPLUS_INCLUDE_PATH
Would maybe get you where you want to be.
How can you add binary stripping to CMake for gcc and clang as a post-processing step but only in release builds? MSVC strips by default so it does not have to be handled.
One of the problems is that clang does not have a -s compilation flag but gcc does so doing it this way does not work.
Another idea is to use the strip command. The -s switch again exists on Linux but not on XCode (this is Apple's development toolchain).
So the final choice is to use the strip command without any arguments besides the binary itself which appears to be a decent generic solution. How can this be used in CMake?
In CMake add_custom_command can execute post build commands such as strip. The PROJECT_NAME variable is defined as your target binary e.g.
# Set the project name
set(PROJECT_NAME "MyProject")
project(${PROJECT_NAME})
Place the following code after add_executable of your CMakeLists.txt:
# Strip binary for release builds
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD
COMMAND $<$<CONFIG:release>:${CMAKE_STRIP} ${PROJECT_NAME}>)
CMAKE_STRIP is the file path to the platform's strip utility (e.g. /usr/bin/strip on Linux). The $<$<CONFIG:cfg>:str> generator expression will expand to str when building the configuration cfg, and to an empty string otherwise. In this scenario, this directly means "call strip when building in Release, and do nothing otherwise". Note that the CONFIG generator is case insensitive on your build type, and will work when using multi-config generators.
While using add_custom_command, I was having issues with the COMMAND generator expression containing spaces. The ARGS option can be used while still toggling the inclusion of the custom command through a generator expression for the COMMAND option:
add_custom_command(
TARGET "${TARGET}" POST_BUILD
DEPENDS "${TARGET}"
COMMAND $<$<CONFIG:release>:${CMAKE_STRIP}>
ARGS --strip-all $<TARGET_FILE:${TARGET}>
)
This results in strip --strip-all myapp being called when config is release, but no command being called when it's not, despite the args being specified in a separate option.
Is there a way to pass C_INCLUDE_DIRS and LD_LIBRARY_PATH from cmake command line or is there a way to set env so that CMAKE can find and use them?
It is not fully clear what you intend to do with these variables. Here are some possibilities:
Inside a CMake script you can read environment variables using the syntax $ENV{<VARIABLE_NAME>}. So in your CMakeLists.txt you can have something like
message( "Found environment variable LD_LIBRARY_PATH=$ENV{LD_LIBRARY_PATH}" )
If you want to add the location contained in this variable to be available to your CMake target executables and libraries then you can use the link_directories() command as
link_directories( $ENV{LD_LIBRARY_PATH} )
Or if you have someone else's project and you want to instruct CMake to look for libraries in some additional directories you can use CMAKE_PREFIX_PATH or CMAKE_LIBRARY_PATH. For example to pass these variables in a command line you could do
cmake -D CMAKE_PREFIX_PATH=/path/to/custom/location
One should care when use an environment variable which denotes path and want the project to work on Windows. The problem is with a path separator: CMake uses forward slash, /, but Windows uses backslash, \.
For convert a path from the native (OS-specific) to the CMake, one may use file(TO_CMAKE_PATH) command flow:
# Save environment variable into the CMake but with the proper path separator
file(TO_CMAKE_PATH "$ENV{SOME_PATH_VAR}" SOME_PATH_VAR_CMAKE)
# Following commands could use the created CMake variable
include_directories(${SOME_PATH_VAR_CMAKE})
Also, find_* commands (e.g. find_path) have PATH and HINTS options, which can transform paths from environment variables automatically, using ENV <VAR> syntax:
find_path(MYLIB_INCLUDE_DIRECTORY # Result variable
mylib.h # File to search for
HINTS ENV SOME_PATH_VAR # Take a hint from the environment variable
)
If you want to do the (seems to me anyway) obvious thing with them, which is to get find_library and find_path to find things located therein, I finally figured out that you should use the INCLUDE and LIB. This is mentioned in the docs for find_library but it's not obvious that those are environment variables. So, e.g.:
export LIB=$LIB;$LD_LIBRARY_PATH
export INCLUDE=$INCLUDE;$C_INCLUDE_PATH;$CPLUS_INCLUDE_PATH
Would maybe get you where you want to be.
I try to set a preprocessor macro in the command line of CMake. I've tried:
set generator="Visual Studio 8 2005"
set params=-D MY_MACRO=1
cmake.exe -G %generator% %params% ..\some_project
but it's neither defined when I compile nor can I find the name MY_MACRO in the files generated by CMake at all, except for CMakeCache.txt where it's present in the form:
MY_MACRO:UNINITIALIZED=1
How can I do it?
A good alternative would be to define a cmake option:
OPTION(DEFINE_MACRO "Option description" ON) # Enabled by default
Followed by a condition:
IF(DEFINE_MACRO)
ADD_DEFINITIONS(-DMACRO)
ENDIF(DEFINE_MACRO)
Then you can turn that option ON/OFF via command line with cmake using the -D flag. Example:
cmake -DDEFINE_MACRO=OFF ..
To make sure the compiler is receiving the definition right, you can call make in verbose mode and check for the macro being defined or not:
make VERBOSE=1
This is a good solution also because make will recompile your code when any of cmake options changes.
Try this: -D CMAKE_CXX_FLAGS=/DMY_MACRO=1
The motivation behind the question was to batch build 3rd party libraries, which is why I wanted to avoid modifying CMakeLists. So years later, even though I don't need that anymore, I figured out that it's easily achievable by means external to CMake:
Invoke CMake as usual, no special flags.
Then:
With MSVC: The compiler reads the CL environment variable to get extra command line arguments. So
set CL=/DMY_MACRO=1 %CL%
then invoke MSBuild to do its job.
With Makefiles: The generated makefiles use the CFLAGS and CXX_FLAGS variables as makefiles are expected to do. So the build can be started by
make CXX_FLAGS=-DMY_MACRO=1
or by setting the corresponding environment variables.
Unless you have a good reason not to, you should use ADD_DEFINITIONS(<name>=<value>[, ...]).
Just add the following line to your CMakeLists.txt:
ADD_DEFINITIONS("MY_MACRO=1")
CMake will take care of the syntax of the switches (be it -D<name>=<value>, or /D<name>=<value>).
Does exist a variable which contains the compiler flags used in some call to CMake's ADD_LIBRARY function, for example the ones used when we add a module:
ADD_LIBRARY(mylib MODULE mysrc.cpp)
Or, is there a way of getting such flags?
Turning my comments into an answer
There is not a single CMake variable to get the all compiler flags. The problem is that the CMake generator will finally put together the compiler flags (from various CMake variables and properties incl. from depending targets). So you don't have all the flags during configuration step.
I see the following possible problem/solution pairs:
CMake is a cross-platform wrapper around your compiler (that's actually what the C stands for), so no need to extract the compiler flags into an external script
If you just want to add sort of a filter to what is called by CMake you can user set "launcher" variables/properties accordingly e.g. CMAKE_CXX_COMPILER_LAUNCHER or RULE_LAUNCH_LINK
If you want the compiler calls in a machine readable JSON format you could export those by setting CMAKE_EXPORT_COMPILE_COMMANDS
If you just want to see the compiler calls incl. all the flags you could set CMAKE_VERBOSE_MAKEFILE
If you really just need the compiler flags on the output and you don't want CMake to actually compile anything, you could - at least for CMake's Makefile generators - modify CMAKE_CXX_COMPILE_OBJECT and CMAKE_CXX_CREATE_SHARED_MODULE like this:
set(CMAKE_DEPFILE_FLAGS_CXX "")
set(
CMAKE_CXX_COMPILE_OBJECT
"<CMAKE_COMMAND> -E echo <FLAGS>"
)
set(
CMAKE_CXX_CREATE_SHARED_MODULE
"<CMAKE_COMMAND> -E echo <CMAKE_SHARED_MODULE_CXX_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_MODULE_CREATE_CXX_FLAGS>"
)
file(WRITE mysrc.cpp "")
add_library(mylib MODULE mysrc.cpp)
References
Is Cmake set variable recursive?
What does the "c" in cmake stand for?
How to use CMAKE_EXPORT_COMPILE_COMMANDS?
Using CMake with GNU Make: How can I see the exact commands?
Retrieve all link flags in CMake