How to assign cmake variables in the CMakeLists.txt - cmake

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.

Related

Cmake command line arguments vs add_compile_definitions

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)

Cmake - how include paths with only read access? [duplicate]

Is it possible to specify an include directory when running cmake. For example
cmake . -INCLUDE=/foo/bar
The header files are in a separate directory from the sources that I would like to compile, and I would like to remedy this without tinkering with the Makefile generated by cmake.
Update
The project does have a CMakeLists.txt. Excerpt:
INCLUDE_DIRECTORIES(${EO_SOURCE_DIR}/src)
INCLUDE_DIRECTORIES(${EO_SOURCE_DIR}/src/ga)
INCLUDE_DIRECTORIES(${EO_SOURCE_DIR}/src/utils)
Can ${EO_SOURCE_DIR} be set from the command line?
If the path to your headers is fixed in relation to your sources, then you should be able to avoid having to pass this info via the command line.
Say your project's directory structure is:
/CMakeLists.txt
/my_sources/main.cpp
/my_sources/foo.cpp
/my_includes/foo.hpp
and in your CMakeLists.txt, you currently have something like:
add_executable(MyExe my_sources/main.cpp my_sources/foo.cpp)
then to add the /my_includes folder to the the list of include search paths, you only need to add the following:
include_directories(my_includes)
For further info about include_directories, run
cmake --help-command include_directories
Answer to update in question:
Yes, using the -D command line option just do
cmake . -DEO_SOURCE_DIR:PATH=<Path to required dir>
The variable ${EO_SOURCE_DIR} gets cached as a result of this, so you only need this -D argument once (unless the required path changes or you delete your CMakeCache file, etc.)
Proper way to do this is to define a variable in CMakeLists.txt and ask user to set it:
set(YOURLIB_INCLUDE_DIR "" CACHE FILEPATH "Path to yourlib includes")
if(NOT EXISTS ${YOURLIB_INCLUDE_DIR}/header.h)
message(SEND_ERROR "Can't find header.h in ${YOURLIB_INCLUDE_DIR})
endif()
include_directories(${YOURLIB_INCLUDE_DIR})
Now you can set it from the command line: cmake -D YOURLIB_INCLUDE_DIR=/path/to/yourlib/include .

using variable in cmake as define

I have problem of a defined string
If I have in sources code
static const QStringList g_arrGenersControllerCommonLibDefinitions(QString(U_LIBS).split(";"));
How can I specify in cmake that he writes to a variable
like this
add_definitions(-DU_LIBS="${U_LIBS}")
How can I specify in cmake
The problem not in CMake only but also in gcc. When you pass definition through CMake it arrives to gcc without escaping. You can try make VERBOSE=1 to see it.
Here is a solution:
cmake_minimum_required (VERSION 2.8)
project (CMPD)
find_package (Qt5Core REQUIRED)
set (U_LIBS)
set (U_LIBS "${U_LIBS}/usr/lib/libu.so")
set (U_LIBS "${U_LIBS}\\\;/usr/lib/libu.so.0")
set (U_LIBS "${U_LIBS}\\\;/usr/lib/libu.so.0.0")
set (U_LIBS "${U_LIBS}\\\;/usr/lib/libu.so.0.0.0")
add_definitions(-DU_LIBS="${U_LIBS}")
add_executable (cmpd ${PROJECT_SOURCE_DIR}/main.cpp)
target_link_libraries (cmpd Qt5::Core)
Output:
("/usr/lib/libu.so", "/usr/lib/libu.so.0", "/usr/lib/libu.so.0.0", "/usr/lib/libu.so.0.0.0")
The sources are available here.

Display CMake variables without running CMake on a CMakeLists.txt file or manually inspecting config.cmake?

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.

cmake - get the used commandline flags "-D"

i recently switched a few projects from autotools to cmake.
one common thing i liked on autotools is that - if i go into the src build directory. there is config.log/config.status - where at the top the ./configure --params command is listed - so it is easy to rerun the former used commandline flags.
(like after compiling some stuff - i want to add a another --enable-this - so copy & paste from config.log/status - and rerun the ./configure --old-params --enable-this)
in cmake - i have a bunch of -D flags - how can i find the used commandline like in config.log/status - with a cmake project?
i know there is the CMakeCache... - but its hard to extract the used flags
edit:
i came up with the following solution:
#save commandline to rebuild this :)
set(USED_CMD_LINE "cmake ")
set(MY_CMAKE_FLAGS CMAKE_BUILD_TYPE CMAKE_INSTALL_PREFIX ENABLE_SSL ENABLE_LUA ENABLE_SSH ENABLE_SNMP MYSQL_USER MYSQL_PASS MYSQL_HOST MYSQL_DB FULL_FEATURES USE_COVERAGE)
FOREACH(cmd_line_loop IN ITEMS ${MY_CMAKE_FLAGS})
if(${cmd_line_loop})
STRING(CONCAT USED_CMD_LINE ${USED_CMD_LINE} "-D" ${cmd_line_loop} "=" ${${cmd_line_loop}} " ")
endif()
ENDFOREACH(cmd_line_loop)
STRING(CONCAT USED_CMD_LINE ${USED_CMD_LINE} " .. ")
#store to a file aka "config.status"
FILE(WRITE ${CMAKE_CURRENT_BINARY_DIR}/config.status ${USED_CMD_LINE} )
creates a file config.status in the build folder - containing all set cmake params.
pro:
seems to solve my problem
seems to work on subsequent cmake calls
con:
unable to set chmod on FILE(write ? the variable
MY_CMAKE_FLAGScontains the known flags - needs to be manually
updated if a new flag is added
regards
Cmake does not give you easy way to list all used -D flags (defines). However, for correctly written CMakeLists, it is not needed to know the full command line with all -D flags to change one particular define/option.
Consider this snipplet:
SET(my_var_1 TRUE CACHE BOOL "my var 1")
SET(my_var_2 TRUE CACHE BOOL "my var 2")
message(STATUS "my_var_1 ${my_var_1}")
message(STATUS "my_var_2 ${my_var_2}")
First cmake invocation:
>cmake .. -Dmy_var_1=FALSE
-- my_var_1 FALSE
-- my_var_2 TRUE
-- Configuring done
-- Generating done
-- Build files have been written to: out
Second cmake invocation:
>cmake .. -Dmy_var_2=FALSE
-- my_var_1 FALSE
-- my_var_2 FALSE
-- Configuring done
-- Generating done
-- Build files have been written to: out
Note that my_var_1=FALSE even it is not explicitely stated (taken from cache)
One feature that may be helpful is turning on the flag CMAKE_EXPORT_COMPILE_COMMANDS in the project's CMake cache. During build, this will make CMake generate a JSON file compile_commands.json in the binary directory that contains the exact compiler calls for all translation units.
You may want to take a look at what is done in the bootstrap script in CMake's source code:
# Write our default settings to Bootstrap${_cmk}/InitialCacheFlags.cmake.
echo '
# Generated by '"${cmake_source_dir}"'/bootstrap
# Default cmake settings. These may be overridden any settings below.
set (CMAKE_INSTALL_PREFIX "'"${cmake_prefix_dir}"'" CACHE PATH "Install path prefix, prepended onto install directories." FORCE)
set (CMAKE_DOC_DIR "'"${cmake_doc_dir}"'" CACHE PATH "Install location for documentation (relative to prefix)." FORCE)
set (CMAKE_MAN_DIR "'"${cmake_man_dir}"'" CACHE PATH "Install location for man pages (relative to prefix)." FORCE)
set (CMAKE_DATA_DIR "'"${cmake_data_dir}"'" CACHE PATH "Install location for data (relative to prefix)." FORCE)
' > "${cmake_bootstrap_dir}/InitialCacheFlags.cmake"
[...]
"${cmake_bootstrap_dir}/cmake" "${cmake_source_dir}" "-C${cmake_bootstrap_dir}/InitialCacheFlags.cmake" "-G${cmake_bootstrap_generator}" ${cmake_options} ${cmake_bootstrap_system_libs} "$#"
The boostrap script is generating a InitialCacheFlags.cmake file and is then preloading it with the cmake -C option.
And - if you additionally want to output the values to stdout - this initial-cache CMake script also accepts message() commands besides the set(... CACHE) commands.
See also How to store CMake build settings