I can specify multiple CMake targets in one build. For example:
cmake --build ./build/ --target t1 t2 t3
However, setting those targets in the "Build target:" field in the Teamcity Build Step configuration produces this command line:
cmake --build ./build/ --target 't1 t2 t3'
This causes build to fail.
Is there a way to specify multiple targets in one step? Or the philosophy is to have one target per step?
Teamcity version 2022.04.4 (build 108763)
I guess you're using TeamCity CMake plugin. I'm afraid in that case you can't alter plugin behaviour unless you're willing to patch plugin (https://github.com/JetBrains/CMake-runner-plugin). Consider switching to command line runner and manually generate cmake cmd
Related
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".
Is there a way to configure CMake such that a single make command will launch both host and target builds? I have a project that is meant to be run on a target platform but requires some generated data from a generator that needs to run on the host platform (PC). From CMake's documentation and looking around, I need a 2 pass build - first host to create the generator then the target crosscompiling build. My question is specifically how to launch the 2-pass build with a single make command through CMake configurations (not using an external bash or python script).
Things I know
CMake doesn't allow changing toolchain within a single build
Almost solutions like: How to instruct CMake to use the build architecture compiler? Which is fine except I need to skip the 2nd step of using an external script
How to separate what's run during crosscompiling or not cmake - compile natively and crosscompile the same code
It is supposedly possible to launch multiple CMake builds using CMake How to make CMake targeting multiple plattforms in a single build
Turning my comment into an answer
Let's say you have an buildTool sub-directory for the host build tools:
buildTools\CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
project(BuildTools)
add_executable(genfoo genfoo.cpp)
Then you could have a main:
CMakeLists.txt
if (CMAKE_CROSSCOMPILING)
set(_genfoo "bin/genfoo${CMAKE_EXECUTABLE_SUFFIX}")
add_custom_command(
OUTPUT ${_genfoo}
COMMAND ${CMAKE_COMMAND}
-DCMAKE_BUILD_TYPE:STRING="Release"
-DCMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE:PATH="${CMAKE_BINARY_DIR}/bin"
-B"bin"
-H"${CMAKE_SOURCE_DIR}/buildTools"
COMMAND ${CMAKE_COMMAND} --build bin --config Release
)
else()
set(_genfoo genfoo)
add_subdirectory(buildTools)
endif()
add_custom_command(
OUTPUT foo.h
COMMAND ${_genfoo}
DEPENDS ${_genfoo}
)
add_executable(bar bar.cpp foo.h)
target_include_directories(bar PRIVATE ${CMAKE_BINARY_DIR})
References
How to instruct CMake to use the build architecture compiler?
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")
Using CMake, I have a series of executables that are built, then added as tests, like this:
set(TestID 1)
add_executable (Test${TestID} Test${TestID}.cpp)
# Create test
configure_file(${TestID}.endf ${TestID}.endf COPYONLY)
add_test( NAME ${TestID} COMMAND Test${TestID} )
This works fineāthe executables are created and the tests are correctly added. However, I don't want the test executables to be added to the all target.
Instead of having my tests built along with everything else, I would like them built right before the execution of the tests; maybe as part of make test or as part of ctest.
How can I do this?
Set the EXCLUDE_FROM_ALL flag upon creating the test executable target to exclude the target from the all target:
add_executable (Test${TestID} EXCLUDE_FROM_ALL Test${TestID}.cpp)
Making sure that the test targets are built before the execution of the tests is more tricky. You cannot add a dependency to the built-in test target with add_dependencies, because the test target belongs to a group of reserved targets (like all, clean and a few others) that only exist in the created build system.
As a work-around you can use the TEST_INCLUDE_FILES directory property to trigger the build of the required test executables before the tests are run. Create a file BuildTestTargets.cmake.in in the source directory with the following contents:
execute_process(COMMAND "#CMAKE_COMMAND#" --build . --target Test1)
execute_process(COMMAND "#CMAKE_COMMAND#" --build . --target Test2)
Then add the following code to your CMakeLists.txt:
configure_file("BuildTestTargets.cmake.in" "BuildTestTargets.cmake")
set_directory_properties(PROPERTIES TEST_INCLUDE_FILES
"${CMAKE_CURRENT_BINARY_DIR}/BuildTestTargets.cmake")
CTest will then include and run the file BuildTestTargets.cmake as a first step before the tests are run.
I'm trying to build a project in a cross-platform manner.
I'm using CMake to generate project files on the fly, but it's not clear how to then compile those project files in a cross-platform way. I found try_compile but it's not clear whether this will do what I want. Any ideas?
For example, say I am using Visual Studio 2010 against project foo. I am expecting CMake to generate foo.sln, and then build it (generate the binaries). I know how to automate the first part, but how do I automate the second?
From the CMake docs:
"CMake is a cross-platform build system generator."
So in other words, once CMake has generated the project files, it's work is really done.
You can invoke the native build tool via CMake using the --build flag, e.g.
cmake --build . --config Release --target install -- /M:4
See here for further info.