Get list arguments/flag cmake - cmake

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

Related

How to make a project written with Tcl in CMake?

I am using cmake version 3.14.0-rc3 to make my codes. When I target any code written in C or C++ in my CMakelist.txt as follows, it works pretty and makes the executable file.
cmake_minimum_required(VERSION 3.3)
PROJECT (HELLO)
ADD_EXECUTABLE(hello hello_world.cpp)
but while I am trying to make this code with Tcl scripts, it fails and I receive the following fatal error:
Fatal error while making a tcl script with cmake
Can anyone help me to overcome this issue? It seems that cmake is not normally able to compile Tcl scripts.
Thank in advance for your kind replies and helps.
Bests,
Daryon
You have to watch out for a different path, e.g., running custom commands or adding custom targets to your CMake project. You seem to confuse the nature of libraries, executables, and external commands in the context of CMake, I am afraid.
I think there should be a way to execute Tcl scripts with CMake as
well.
You might want to attempt the following: In CMakeLists.txt, you define a custom target MyTarget that calls out to a TCLSH executable, if available:
CMAKE_MINIMUM_REQUIRED(VERSION 3.3)
PROJECT (HELLO)
find_program (TCLSH tclsh)
if (TCLSH)
add_custom_target(
MyTarget ALL
COMMAND TCLSH myScript.tcl
)
endif (TCLSH)
(1) find_program and if/endif will make the custom target only available under the condition that an executable called tclsh was found.
(2) myScript.tcl is a Tcl script in your project directory.
(3) Running cmake . && make will call out to effectively to: tclsh myScript.tcl, producing:
$cmake . && make
-- Configuring done
-- Generating done
-- Build files have been written to: /tmp/hello
This is a message written by Tcl scripts
Built target MyTarget
This is just to get you started, you will have to read more about adding commands, targets, or executing sub-processes from within CMake.

CMake call add_subdirectory within custom command

I'm working with a code generator that produces C++ and a CMakeLists.txt file, unfortunately I cannot use this in my main CMakeLists.txt file for testing purposes.
For example you have the following CMakeLists.txt file:
project(SomeProject CXX C)
add_custom_command(OUTPUT ${SRCS}
COMMAND ${CODEGEN_CLI_PATH} -i "${INPUT}" -o "${OUT}"
COMMENT "Generating sources"
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
VERBATIM
)
add_custom_target(CODEGEN
DEPENDS
${SRCS}
)
# Needs to be executed after the custom command
add_subdirectory(${GENERATED_CMAKE_LISTS_LOCATION})
Is it possible to use functions such as add_subdirectory only after you execute custom commands for a particular target, such as CODEGEN?
I've already tried to execute it by adding an extra line to the existing custom command:
COMMAND ${CMAKE_COMMAND} -D DIR=${GENERATED_CMAKE_LISTS_LOCATION} -P add_subdirectories.cmake
Unfortuantly this doesn't work because it isn't allowed to execute functions like add_subdirectory in script mode.
Neither I can manage to call custom made functions (that are executing add_subdirectory) from add_custom_command that are located in the same file.
Nope, it is not possible. The add_subdirectory command is run during configuration step, while CODEGEN is a target that runs during build.
You seem to be doing something wrong, so the only advice I can give you is to use execute_process command to run commands you need. The execute_process command is executed during configuration stage, so it will be able to generate files you need before add_subdirectory.
But again, please describe your problem, why do you want CMake to do that.
I have a huge fixed unsigned char array that I compiled into a static library. The way I work around it is by:
if(NOT EXISTS ${PATH_TO_FOLDER}/smeagol.a)
add_subdirectory(smeagol)
endif()
I'm still looking for a nicer kung-fu way to do it using cmake. I feel that its out there, and I will update this answer once i find it.

How to include a cmake Makefile after a target has been executed?

Given the following minimal example.
cmake_minimum_required(VERSION 2.8)
project(include_test)
add_custom_command(OUTPUT OtherCMakeLists.txt
COMMAND "${CMAKE_CURRENT_BINARY_DIR}/create_other_cmakelists")
add_custom_target(do_something DEPENDS OtherCMakeLists.txt)
What do_something should do here is first create OtherCMakeLists.txt. Now, let's assume that do_something has to do something else afterwards, e.g. compiling some code. I'd like that when the targets from something else are executed, the CMakeLists.txt will behave as if OtherCMakeLists.txt was included with include.
Is this possible?
As an example why this could be useful: OtherCMakeLists.txt might add some compiler flags that have influence on further compiling.
To my knowledge, it is not possible to generate CMakeLists.txt file with a custom target/command and use include CMake command with generated CMakeLists.txt
The problem is that the include command is called at so-called "Configuration time" (when cmake executable tries to parse all CMakeLists.txt), but the generation of file (CMakeLists.txt) is performed at "Build time" (when make command is invoked on generated build system)
add_custom_command has 2 different signatures:
add_custom_command(OUTPUT ...) will be executed at build time, too late to apply rules from a generated CMakeLists.txt generated.
add_custom_command(TARGET ...) to attach a specific command to a target. This command can be run on PRE_BUILD, PRE_LINK or POST_BUILD. Probably not what you want to achieve...
If you are trying to add some dynamic to your compile process, adding custom commands or target may not be your best option.
You should try to read doc for some other CMake commands that can be helpful in your case:
configure_file() that can process a file (OtherCMakeLists.txt.in) into another file (OtherCMakeLists.txt) replacing variables by their values. This is achieved at configuration time
execute_process() to run a command a configuration time (thx to #ComicSansMS)
set_target_properties() to set some compiler or link flags to a specific target depending on some conditions
The list of properties you can set on targets

CMake: execute a macro/function as the command of add_custom_command

I'm using an external library which provides a CMake function for automatic code generation, to be used in my CMakeLists. The problem is that whenever I modify a CMakeLists then the function is run again, triggering the recompilation of the newly generated but unchanged sources. I'd need something like add_custom_command with the possibility to specify the CMake function as COMMAND instead of an executable, so that the function is run only if the automatically generated files are not already present.
Is this feasible? If not, does it exist another way to obtain the same result?
Thanks.
Take a look to this SO post.
You can call your function in a separate CMake script, call this script with add_custom_target and cmake -P then add a dependency to your binary :
add_custom_target(run_script COMMAND ${CMAKE_COMMAND} -P separate_script.cmake)
add_executable(your_binary ...)
# or add_library(your_binary ...)
add_dependencies(your_binary run_script)
Is there a way to pass a parameter to the separate_script.cmake?
You can use the cmake variables to pass values when you call the script e.g.
"COMMAND ${CMAKE_COMMAND} -DPARAM=value -P separate_script.cmake"
To prevent that function to run, just wrap it into if:
if(NOT EXISTS ${CMAKE_BINARY_DIR}/blah-blah/generated.cpp)
run_your_provided_command(BLAH_BLAH)
endif()
Easy!
Update: To run it when config file has changed just use little more complicated condition:
if(
NOT EXISTS ${CMAKE_BINARY_DIR}/blah-blah/generated.cpp OR
${CMAKE_SOURCE_DIR}/blah-blah.config IS_NEWER_THAN ${CMAKE_BINARY_DIR}/blah-blah/generated.cpp
)
...
and use add_dependencies command to make sure your binary will be rebuild in case of config file modifications:
add_executable(
YourBinary
...
${CMAKE_BINARY_DIR}/blah-blah/generated.cpp
)
add_dependencies(YourBinary ${CMAKE_SOURCE_DIR}/blah-blah.config)

How to configure external cmake libraries?

What I wanted to do is call
add_subdirectory(ext/oglplus)
and be done with it. Unfortunately it is not that simple. There is a huge buildscript which detects various opengl settings. So I tried the following
ExternalProject_Add(liboglplus
SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/ext/oglplus
CONFIGURE_COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/ext/oglplus/configure.py --use-glew
BUILD_COMMAND ${MAKE})
The problem that I have is don't really want to build it like that. It also doesn't build correctly because for some reason it wants to install the library and because there is no install target it will abort the compilation.
But the build script is calling cmake under the hood.
So what I want to do is to tell cmake to use "cofigure.py" instead of "cmake .." and then use it like any other cmake library.
Is this possible?
I used to call Linux Kernel KBuild from CMake using
ADD_CUSTOM_COMMAND() and ADD_CUSTOM_TARGET()
This way you can run arbitrary commands (like your config.py) and use the output.
First setup the command with all command-line options as CMake-variables, in tou case this would be calling the config.py script ${CMAKE_CURRENT_SOURCE_DIR}/ext/oglplus/.
Instead of encoding the Path to your script in the command (adding ext/oglplus) I think it may be better adding WORKING_DIRECTORY to the custom command:
add_custom_command
SET(KBUILD_CMD ${CMAKE_MAKE_PROGRAM}
-C ${KERNEL_BUILD_DIR}
CROSS_COMPILE=${CROSS_COMPILE} ARCH=${ARCH}
EXTRA_CFLAGS=${KBUILD_EXTRA_CFLAGS}
INSTALL_MOD_PATH=${INSTALL_MOD_PATH}
M=${CMAKE_CURRENT_SOURCE_DIR}
KBUILD_EXTRA_SYMBOLS=${depends_module_ksyms}
)
Add a custom command that calls your build-script and creates a file in the CMAKE_CURRENT_BINARY_DIRECTORY (note the second COMMAND to touch a file)
ADD_CUSTOM_COMMAND(
OUTPUT ${module_name}.built
COMMAND ${KBUILD_CMD} modules
COMMAND cmake -E touch ${module_name}.built
COMMENT "Kernel make modules ${module_name}"
VERBATIM
)
Add a custom target, its always out of date, but if you want it to be called automatically add ALL otherwise you have to explicityly call make module_build, I guess this is what you want.
ADD_CUSTOM_TARGET("${module_name}_build" ALL
DEPENDS ${depends_module_ksyms}
${CMAKE_CURRENT_BINARY_DIR}/${module_name}.built
COMMENT "Building Kernel Module ${module_name}"
)