what is the difference between compiling with cmake .. -DVAR="something" and cmake .. but using add_compile_definitions(VAR="something") in CMakeLists.txt? How to achieve the same behavior as in command line argument but using CMakeLists.txt?
what is the difference between compiling with cmake .. -DVAR="something" and cmake .. but using add_compile_definitions(VAR="something") in CMakeLists.txt?
The cmake command line -D option does: "Create or update a CMake CACHE entry". The -DVAR=something set's cmake variable VAR to something.
add_compile_definitions does: "Add preprocessor definitions to the compilation of source files". In this case it adds a macro VAR to be set to "something" (I think including the quotes).
They do different things.
Prefer target_compile_definitions instead of add_compile_definitions.
How to achieve the same behavior as in command line argument but using CMakeLists.txt?
If you want to set the cmake variable VAR to something do:
// in CMakeLists.txt
set(VAR something)
But this will not set the variable in cmake cache. The same behavior would be rather something along:
set(VAR something CACHE STRING "" FORCE)
Related
I have a CMakeLists.txt with the following in it, that I can not modify:
set(BUILD_SHARED_LIBS ON)
I want to override this variable use the commandline. I tried this:
cmake -UBUILD_SHARED_LIBS -DBUILD_SHARED_LIBS=OFF ..
but it has no effect. Is there any way to tell cmake to use a value from the commandline instead of this value?
Note: I am aware that using the cache like shown below would solve the problem, but as I cannot edit the file, that sadly is not an option:
set(BUILD_SHARED_LIBS ON CACHE BOOL "library build mode")
Using command line you cannot override setting of the normal (non-cached) variable.
If you pass a variable via command line, then it is always a cache variable. At the time when normal flavor of the variable is set in the CMakeLists.txt, both flavors exist. But when a variable is dereferenced, CMake prefers normal flavor to the cached one. See more in the variables' documentation.
I can use cmake like this:
cmake -DPYTHON_EXECUTABLE=~/build/python ..
How could I write this in my CMakeLists.txt so that I could simply run this:
cmake ..
Include
set(PYTHON_EXECUTABLE $ENV{HOME}/build/python CACHE FILEPATH "")
in your CMakeLists.txt. For more information about the set command see the online documentation or run cmake --help set.
EDIT: The CACHE FILEPATH "" part here is mandatory, as pointed out below.
I am running a CMake (3.4.3) like this as explained in the CMake FAQ's:
export CC="cc_args.py $PWD/../bin/gcc"
export CXX="cc_args.py $PWD/../bin/g++"
cmake -DCMAKE_BUILD_TYPE=Debug ..
However when I print CMAKE_CXX_COMPILER and CMAKE_C_COMPILER it still points to the system's default compilers in /usr/bin. It only works when I explicitly read-in the environment variables like this:
IF (NOT $ENV{CC} STREQUAL "")
SET(CMAKE_C_COMPILER $ENV{CC})
ENDIF ()
IF (NOT $ENV{CXX} STREQUAL "")
SET(CMAKE_CXX_COMPILER $ENV{CXX})
ENDIF ()
But even then the building fails with this message:
/bin/sh: 1: /home/peterg/bin/cc_args.py /home/peterg/Code/build/../bin/g++: not found
However I am certain that all paths are correct since executing just the path between the two colons outputs this as expected:
g++: fatal error: no input files
compilation terminated.
Update:
It seems the compiling process does not like spaces in the compiler paths. I've now created two scripts (one for GCC and one for CC) which wrap the commands and propagate the arguments and that seems to work. But it still seems I am doing something fundamentally wrong because CMake would also not accept the exported CC=proxy_script_cc.sh and GCC=proxy_script_gcc.sh variables without spaces by itself.
Turning my comment into an answer
Problem
I've given you code a try and could reproduce your problem
CMake Error at [...]/cmake-3.5/Modules/CMakeDetermineCXXCompiler.cmake:56 (message):
Could not find compiler set in environment variable CXX:
cc_args.py [... PWD ...]/../bin/g++.
If I look at CMakeDetermineCXXCompiler.cmake code and at get_filename_component() documentation, it just means that it didn't find cc_args.py in "the system search path" or relative to your binary output directory.
Solution
So it does work when you give a full path or a relative path to your binary output dir with something like
export CC="../cc_args.py ../bin/gcc"
export CXX="../cc_args.py ../bin/g++"
Alternative
CMake does allow to define "launcher scripts" e.g. with CMAKE_<LANG>_COMPILER_LAUNCHER
$ cmake -DCMAKE_BUILD_TYPE=Debug
-DCMAKE_C_COMPILER_LAUNCHER=../cc_args.py
-DCMAKE_CXX_COMPILER_LAUNCHER=../cc_args.py
..
References
How to Use CCache with CMake?
Save and reprint warnings for successfully-compiled files on subsequent builds?
Pass -DCMAKE_CXX_COMPILER=<path/to/compiler> to your CMake call. That's less error prone compared to fiddling with shell variables.
Suppose I have a package called Foo. If I run CMake on a CMakeLists.txt file that contains find_package(Foo), then I can print out the values of variables such as ${Foo_LIBRARIES} and ${Foo_INCLUDES}.
Is there an easy way to display these variables without having to run CMake on a CMakeLists.txt file, and without having to manually inspect the config.cmake file?
You asked: (1) Is there an easy way to display these variables without having to run cmake on a CMakeLists.txt file, and (2) without having to manually inspect the config.cmake file?
I can give you a yes answer to (2) but it does require that you (re)run cmake. But since you can re-run your cmake configure step by simply executing cmake . in the build directory, re-running cmake should not keep you from trying this approach. My answer is given in this SO answer and uses the get_cmake_property command. Here is that code encapsulated into a cmake macro, print_all_variables, so I can use it when debugging my cmake scripts.
macro(print_all_variables)
message(STATUS "print_all_variables------------------------------------------{")
get_cmake_property(_variableNames VARIABLES)
foreach (_variableName ${_variableNames})
message(STATUS "${_variableName}=${${_variableName}}")
endforeach()
message(STATUS "print_all_variables------------------------------------------}")
endmacro()
The macros are invoked with same syntax as cmake functions:
print_all_variables()
To simply print a value, you could do something like this:
message(STATUS "foo include dir: ${foo_INCLUDE}")
where ${foo_INCLUDE} is the value you desire to print.
Note: I'm using cmake > 3.14
Run CMake and have a look at the cache with the ccmake GUI tool. Then you'll get all the variables.
Or run CMake with -LH then you will get all variables printed after configuration.
So I think it is not possible to get the variables without running CMake.
Run cmake in find-package mode. Example to display a package`s include directories:
cmake -DNAME=ZLIB -DCOMPILER_ID=GNU -DLANGUAGE=C -DMODE=COMPILE --find-package
Example to display the libraries:
cmake -DNAME=ZLIB -DCOMPILER_ID=GNU -DLANGUAGE=C -DMODE=LINK --find-package
The NAME must be set to the package name. You can obtain your COMPILER_ID on this page. LANGUAGE can be C, CXX or Fortran.
I am always suspicious of variables changing values throughout a script somewhere so I like to see the value of a variable at a particular point in the running script. Combining the ideas from both Phil and Aaron B. this is what I'm using:
function(PRINT_VAR VARNAME)
message(STATUS "${VARNAME}: ${${VARNAME}}")
endfunction()
PRINT_VAR("CMAKE_CXX_COMPILER")
Then I can just litter PRINT_VAR statements around like I'm debugging code back in 1980
These variables are generally hardcoded into FindFoo.cmake so that it is not possible to extract them without running the function first. Note that sometimes the value of Foo_LIBRARIES depends on the system configuration, which is unknown until find_package(Foo) is run.
I want write cmake ... -variable=value.
I want use this variable in code.
example:
cmake CMakeLists.txt -TEST_MESSAGE=Hello
and
cmake_minimum_required (VERSION 2.6)
set (PROJECT hello_world)
project (${PROJECT})
message (${TEST_MESSAGE})
How to?
A) Create a wrapper (batch, bash script, Python script or whatever) called "cmake" to parse arguments and inside the wrapper call
cmake ... -Dvariable=value
B) Or get source of CMAKE, modify parsing of command line arguments code, recompile it yourself and use.
But I would strongly suggest to just use -D option as everyone else