CMake: detect "--config Release" in if condition - cmake

I want to build a target only in release mode, so i need a 'if(RELEASE)' or something.
I found
if (CMAKE_BUILD_TYPE EQUAL "RELEASE")
but it doesnt work, because i build with the following command
cmake --build . --config Release
which apparently doesnt set CMAKE_BUILD_TYPE.
What's the correct way to detect Release vs Debug build with modern cmake?
(I cant use generator expressions because i need an actual if() )

Related

How do I use CMake with debugging information?

At the moment I'm compiling via
cmake --build . --config RelWithDebInfo
I'm not sure if this makes sense but it works. I would like to use the debugging of CMake which, afaik, can be set via DCMAKE_BUILD_TYPE=Debug. When I try to use this the compiling itself works:
cmake -DCMAKE_BUILD_TYPE=Debug .
but here I don't get an .exe file somewhere. I guess I miss the --build or --config option from before but how do I properly add them?
edit: Thanks to vre's input I'm coming along better. However, this is the output now:
C:\geant4\sim> cmake -DCMAKE_BUILD_TYPE=Debug .
-- Selecting Windows SDK version 10.0.22000.0 to target Windows 10.0.19042.
-- Configuring done
-- Generating done
CMake Warning:
Manually-specified variables were not used by the project:
CMAKE_BUILD_TYPE
-- Build files have been written to: C:/geant4/sim
why is the build type not used?

How can I make colcon work with a plain preset-based CMake project with multiple presets in parallel?

Prologue
I have a preset-based plain CMake project so that I can build and test it with cmake --preset $PRESET && cmake --build --preset $PRESET && ctest --preset $PRESET. Note that it nicely interacts with Microsoft's CMake Tools extension for Visual Studio Code, be it for building, testing, debugging and Intellisense.
Since I want to handle multiple presets in parallel, I set CMakePresets.json's binaryDir property to ${sourceDir}/build/${presetName}/.
Issue
I want to also build this plain CMake project with colcon. colcon build --cmake-args "--preset $PRESET" doesn't work, though, as it produces
WARNING:colcon.colcon_cmake.task.cmake.build:Could not build CMake package 'root_project_name' because the CMake cache has no 'CMAKE_PROJECT_NAME' variable
root_project_name being the argument to CMake's project() command in the top CMakeLists.txt.
How can I resolve this warning and the subsequent build failure?
Straightforward solution
Not setting CMakePresets.json's binaryDir property at all works fine with colcon, but doesn't allow for multiple preset builds in parallel.
Solution with multiple preset builds in parallel
The reason for this behavior is colcon-core's build verb's passing the build base directory (default: build) suffixed by the found package's name (here: root_project_name) to the colcon-cmake extension here.
The solution is to pass the correct build base to colcon (i.e. colcon build --build-base ./build/$PRESET/ --cmake-args "--preset $PRESET") and to adapt your CMakePresets.json's binaryDir property to ${sourceDir}/build/${presetName}/root_project_name/.
Note that this then works with colcon test as well, i.e. colcon test --build-base ./build/$PRESET/ --ctest-args "--preset $PRESET".

How to write CMakeLists.txt with NOT using 'MSBuild.exe' on windows? [duplicate]

This question already has answers here:
cmake: Selecting a generator within CMakeLists.txt
(5 answers)
Closed 3 years ago.
I'm trying to write the CMakeLists.txt for building a custom targets only project.
That is, it's not for the usual C/C++ project; all build recipes are provided using ADD_CUSTOM_COMMAND() and ADD_CUSTOM_TARGET(). The reason why I'm using CMake is to manage dependencies between build target stuffs and utilize the advantages of incremental build.
The problem is, when I execute cmake CMakeLists.txt on Windows cmd.exe, it tries to find Windows SDK or MSBuild.exe -- which are never needed for building targets in the project.
cmd.exe> cmake CMakeLists.txt
-- Selecting Windows SDK version 10.0.18362.0 to target Windows 10.0.17134.
CMake Error at CMakeLists.txt:6 (PROJECT):
Failed to run MSBuild Command:
MSBuild.exe
to get the value of VCTargetsPath:
Cannot find file
-- Configuring incomplete, errors occurred!
See also "CMakeFiles/CMakeOutput.log"
The header of the CMakeLists.txt is:
cmake_minimum_required ( VERSION 3.0 )
set ( CMAKE_GENERATOR "Unix Makefile" )
set ( CMAKE_VERBOSE_MAKEFILE true )
# Project name
project ( "awesome-project" NONE ) # <language>=NONE for skipping compiler check
...
As I mentioned above, all recipes of the build targets are provided in the CMakeLists.txt; neither Windows SDK nor Visual Studio is required.
I think there is some CMake directives for skipping the invocation of MSBuild, but I could not find it. How can I write the CMakeLists.txt in this case?
As the answer here suggests, setting the CMAKE_GENERATOR variable in the CMake file has no effect when running CMake for the first time. CMake will use the default generator on the first attempt, if no generator is provided via the command line or via environment variable. So try adding the command line option -G to specify the generator like this:
cmake -G "Unix Makefiles" .
Then, on subsequent CMake runs, the generator setting will be cached and you no longer need to provide the -G generator option.
As a side note, you can simply provide the path to your top-level CMakeLists.txt file. So if it's in the current directory, you can just use . for the path.
The documentation is pretty explicit The value of this variable should never be modified by project code. A generator may be selected via the cmake(1) -G option, interactively in cmake-gui(1), or via the CMAKE_GENERATOR environment variable.
You can always make a CMake script that runs CMake with the proper options to create the project.
You may want to keep watch on CMAKE_VERBOSE_MAKEFILE because This variable is a cache entry initialized (to FALSE) by the project() command. I wouldn't be surprised if it doesn't work as shown in your script. Instead You'd probably have to add a -D option on the command line to set it. https://bytefreaks.net/programming-2/make-building-with-cmake-verbose

How to do Parallel CMake ExternalProject Builds

When building a CMake project (e.g. on Windows), I can perform a parallel build by executing the following command:
cmake --build . -- /m
The /m switch is passed to msbuild and I get parallelized builds. However, if I have some external project in my CMakeLists, that switch is not passed through to its build command.
What's the best way to ensure my ExternalProject is built in parallel? I don't want to hardcode a BUILD_COMMAND if I can avoid it.
In CMake 3.12, support was added to kick off parallel jobs from within cmake.
The previous versions only supported this via passthrough arguments after the --, which understandably wouldn't pass through to external builds. Though, I'm not sure if the new support works for ExternalProject, it'd be great to try and report back if it works!
I had the same problem with make based external_projects. I ended up with the solution to pass the -j8 flag via a cmake cached variable.
set(EXTERNAL_BUILD_ARGS "/m" CACHE STRING "flags for external project builds")

Is there a workaround that I can use so that I can test the build type when using CMake in combination with Visual Studio and multiple configurations?

I would like to work with 'Debug', 'Release', 'Debug_Unicode' and 'Release_Unicode'
I have been able to use the DEBUG_CONFIGURATIONS variable so that the 'Debug Unicode' configuration correctly gets used as debug
This is what I tried to do in the CmakeLists.txt file:
target_link_libraries(tests
optimized ${CMAKE_BINARY_DIR}/src/${CMAKE_BUILD_TYPE}/foo.lib
debug ${CMAKE_BINARY_DIR}/src/${CMAKE_BUILD_TYPE}/foo.lib
)
Clearly CMake is able to make a choice between debug and release at this point, as it has to choose the 'optimized' or 'debug' library.
However, CMAKE_BUILD_TYPE is an empty string.
The best that I have been able to come up with is to work with a separate solution file for each of the configurations,
passing in CMAKE_BUILD_TYPE myself:
cmake -G Visual Studio 11 2012 Win64 -DCMAKE_BUILD_TYPE=Debug_Unicode C:\foo
As Antonio was mentioning
target_link_libraries(tests foo)
or just
add_dependencies(tests foo)
would be sufficient to link the correct library from the same configuration.
If you want to do more advanced stuff, take a look at the generator expressions. They are configuration sensitive incl. in Visual Studio's multi-configuration environment and they would work also for the target_link_libraries() command.
So your example would look like:
target_link_libraries(tests ${CMAKE_BINARY_DIR}/src/$<CONFIG>/foo.lib)
I have used generator expression e.g. in custom commands that need to be aware of the output path of my DLL (if foo would be generating an MSTest DLL):
add_test(
NAME RunFooTest
WORKING_DIRECTORY $<TARGET_FILE_DIR:foo>
COMMAND vstest.console.exe /InIsolation /Platform:x86 $<TARGET_FILE:$foo>
)
And - just because you mentioned different solutions - you can use CMake to build a certain configuration from the command line. This would in your case look like e.g.
cmake --build C:\foo --target ALL_BUILD --config Debug_Unicode