I’m using ninja multi configuration to configure my project and building both debug and release versions of the embedded software
When using Cpack to package both configurations, I end up with only one set of binaries, as during packaging one overwrites the other (as it seems)
Commands:
cmake -B build -G "Ninja Multi-Config"
cmake --build build --config Release
cmake --build build --config Debug
cd build
cpack -C "Debug;Release"
I have the cmake variable CMAKE_RUNTIME_OUTPUT_DIRECTORY
set to bin
so both build directories (Release and Debug) are under build/bin
Here is the packaging part of my top level CMakeLists.txt
include(GNUInstallDirs)
install(TARGETS ${PROJECT_NAME})
set(CPACK_PACKAGE_INSTALL_DIRECTORY ${CPACK_PACKAGE_NAME})
set(CPACK_VERBATIM_VARIABLES YES)
set(CPACK_PACKAGE_FILE_NAME "${PROJECT_NAME}-${PROJECT_VERSION}-TriCore")
set(CPACK_OUTPUT_FILE_PREFIX "${CMAKE_BINARY_DIR}/package")
set(CPACK_INCLUDE_TOPLEVEL_DIRECTORY OFF)
set(CPACK_SYSTEM_NAME "tricore")
set(CPACK_GENERATOR "TGZ")
include(CPack)
I end up with tar.gz which contains only one bin directory under which only on .elf file for the target I’m installing.
my expectation was to have a .tar.gz file with the following structure
– bin/Debug/app.elf
– bin/Release/app.elf
What am I missing here? Shouldn’t the cpack -C "Debug;Release"
package both and avoids overwriting content on top of each other by separating directories?
@craig.scott I’m following the chapter 28.3.2 from the 14th edition of your book!
CMake is doing what you are telling it to do. The installed directory structure is independent of the directory structure used in the build directory. In your case, you have let install(TARGETS)
use the default install destinations, which is appropriate when only installing a single configuration. However, as you’ve discovered, if you install multiple configurations, the last one will overwrite the earlier installed configuration’s binaries.
You need decide whether you want to install binaries to the same directory but with different file names, or with the same file names but installed to different directories. Either way, you will need to specify additional details compared to what you have now. Of the two strategies, personally I’d probably go with same directory, different file names. There is precedent for that with libraries, with debug libraries often having a d
or _debug
suffix on the library’s base name. On linux, this would give you files like libblah.a
for Release and libblahd.a
or libblah_debug.a
for Debug. You would set these most easily with the OUTPUT_NAME
or OUTPUT_NAME_<CONFIG>
target properties. This approach also has the advantage that it doesn’t change the relative paths to things, so embedded RPATH details will be much easier to specify.
Thanks Craig, very insightful as usual.
For my use case, this is a bare-metal embedded software project, the package will be delivered to production plants as well as development team, so not to confuse production (they need to use release), I went with specifying the different install directories solution.
install(
TARGETS ${PROJECT_NAME}
CONFIGURATIONS Debug Release RelWithDebInfo MinSizeRel
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}/$<LOWER_CASE:$<CONFIG>>
PERMISSIONS OWNER_READ GROUP_READ WORLD_READ)
However, I’m thinking another better solution for the bare-metal embedded SW case is to take the .elf file from the debug build (since it’s what’s really useful) and the hex file (used in production) from the release build, it should work smoothly using RUNTIME DESTINATION
couples with OUTPUT_NAME_<CONFIG>