CMake for multiple targets - cmake

[enter image description here][1]Could You please help me writing my CMakeLists.txt file for embedded system (ARM MCU) using Eclipse IDE? I have two targets (executables): test.elf, test_boot.elf.
project(test C ASM)
add_executable(${PROJECT_NAME}.elf
${DRIVERS_DIR}/hal_clkctr.c
${DRIVERS_DIR}/hal_ioctr.c
source/startup_ELIOT01.s
source/system_ELIOT01.c
source/main.c
${SYSTEM_DIR}/can.c
${SYSTEM_DIR}/gpio.c
${SYSTEM_DIR}/i2c.c
${SYSTEM_DIR}/mutex.c
${SYSTEM_DIR}/onewire.c
${SYSTEM_DIR}/sdcard.c
${SYSTEM_DIR}/spi.c
${SYSTEM_DIR}/sysclk.c
${SYSTEM_DIR}/systick.c
${SYSTEM_DIR}/uart.c
${MODULES_DIR}/adc.c
${MODULES_DIR}/dac.c
${MODULES_DIR}/ds18b20.c
${MODULES_DIR}/ioexpander.c
${MODULES_DIR}/powermonitor.c
${MODULES_DIR}/rtc.c
${TESTS_DIR}/memtest.c
${TESTS_DIR}/testcmd.c
${TESTS_DIR}/tests.c
${APPLICATION_DIR}/print.c
${APPLICATION_DIR}/utils_syscalls.c
)
add_executable(${PROJECT_NAME}_boot.elf
${DRIVERS_DIR}/hal_clkctr.c
${DRIVERS_DIR}/hal_ioctr.c
source/startup_ELIOT01.s
source/system_ELIOT01.c
source/main_boot.c
${SYSTEM_DIR}/sysclk.c
${SYSTEM_DIR}/uart.c
${APPLICATION_DIR}/print.c
)
I also have two linker files (test.ld and boot.ld). And i wonder how is it possible to set different linkers for my executables? Because set_target_property results in errors like "Undefined reference to..." in startup file. But i'm sure that startup is fine because i've built the project with one test.elf executable many times. Below is the second part of my CMakeLists.txt. As you can see, CMake creates boot.elf linking test.ld but not boot.ld file. The same thing happens with .map file.
SET(CMAKE_EXE_LINKER_FLAGS "-T${CMAKE_CURRENT_LIST_DIR}/${DEVICE_DIR}/test.ld -D__USE_CMSIS")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0 -g3 -Wl,-Map=${PROJECT_NAME}.map")
add_custom_command(
TARGET ${PROJECT_NAME}.elf POST_BUILD
COMMAND ${CMAKE_OBJDUMP} -D ${PROJECT_NAME}.elf > ${PROJECT_NAME}.dis
COMMENT "[post] Create disassemble file ${PROJECT_NAME}.dis"
)
add_custom_command(
TARGET ${PROJECT_NAME}_boot.elf POST_BUILD
COMMAND ${CMAKE_OBJDUMP} -D ${PROJECT_NAME}_boot.elf > ${PROJECT_NAME}_boot.dis
COMMENT "[post] Create disassemble file ${PROJECT_NAME}_boot.dis"
)
P.S. By the way, add_custom_command works fine for both targets...
Dear Armandas, here it is..
Code written by Your advice:
target_link_options(${PROJECT_NAME}.elf
PRIVATE
-T${CMAKE_CURRENT_LIST_DIR}/${DEVICE_DIR}/test.ld -D__USE_CMSIS
)
target_link_options(${PROJECT_NAME}_boot.elf
PRIVATE
-T${CMAKE_CURRENT_LIST_DIR}/${DEVICE_DIR}/boot.ld -D__USE_CMSIS
)
#SET(CMAKE_EXE_LINKER_FLAGS "-T${CMAKE_CURRENT_LIST_DIR}/${DEVICE_DIR}/boot.ld -D__USE_CMSIS")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0 -g3 -Wl,-Map=${PROJECT_NAME}_boot.map")
add_custom_command(
TARGET ${PROJECT_NAME}.elf POST_BUILD
COMMAND ${CMAKE_OBJDUMP} -D ${PROJECT_NAME}.elf > ${PROJECT_NAME}.dis
COMMENT "[post] Create disassemble file ${PROJECT_NAME}.dis"
)
add_custom_command(
TARGET ${PROJECT_NAME}_boot.elf POST_BUILD
COMMAND ${CMAKE_OBJDUMP} -D ${PROJECT_NAME}_boot.elf > ${PROJECT_NAME}_boot.dis
COMMENT "[post] Create disassemble file ${PROJECT_NAME}_boot.dis"
)
It has following errors:
d:/eliot01-sdk/toolchain/bin/../lib/gcc/arm-none-eabi/7.2.1/../../../../arm-none-eabi/bin/ld.exe: address 0x33a0 of test_boot.elf section `.text' is not within region 'FLASH'
d:/eliot01-sdk/toolchain/bin/../lib/gcc/arm-none-eabi/7.2.1/../../../../arm-none-eabi/bin/ld.exe: test_boot.elf section '.ARM.extab' will not fit in region 'FLASH'
d:/eliot01-sdk/toolchain/bin/../lib/gcc/arm-none-eabi/7.2.1/../../../../arm-none-eabi/bin/ld.exe: address 0x33a0 of test_boot.elf section '.text' is not within region 'FLASH'
d:/eliot01-sdk/toolchain/bin/../lib/gcc/arm-none-eabi/7.2.1/../../../../arm-none-eabi/bin/ld.exe: region 'FLASH' overflowed by 4024415372 bytes
make[2]: *** [CMakeFiles\test_boot.elf.dir\build.make:207: test_boot.elf] Error 1
make[1]: *** [CMakeFiles\Makefile2:110: CMakeFiles/test_boot.elf.dir/all] Error 2
make[1]: *** Waiting for unfinished jobs....
And the same errors for test.elf executable

Use target_link_options:
target_link_options(${project_name}.elf
PRIVATE
-T${CMAKE_CURRENT_LIST_DIR}/${DEVICE_DIR}/test.ld
)
target_link_options(${project_name}_boot.elf
PRIVATE
-T${CMAKE_CURRENT_LIST_DIR}/${DEVICE_DIR}/boot.ld
)

Thanks everyone! I've found solution here: Pass CMAKE_CXX_FLAGS to target_compile_options

Related

CMake: require building of files in addition to building targets

In this simple CMakefile, the first script list.sh outputs a list of 2 generated files file1.proto;file2.proto, instructing CMake that they can be built from source source.xml (using the second script gen.sh).
cmake_minimum_required(VERSION 3.13)
set(source "source.xml")
execute_process(
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/list.sh ${source}
OUTPUT_VARIABLE protos
)
message("${protos}: ${source}")
add_custom_command(
OUTPUT ${protos}
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/gen.sh ${source}
DEPENDS ${source}
)
add_custom_target(my_target DEPENDS ${protos})
Everything works well if I run:
$ cmake ..
file1.proto;file2.proto: source.xml
-- Configuring done
-- Generating done
-- Build files have been written to: /build
$ make my_target
[100%] Generating file1.proto, file2.proto
[100%] Built target my_target
What should I add to be able to also run the code generation with:
$ make file1.proto
[EDIT] autocomplete suggests only the following for command make:
$ make (TAB TAB)
all cmake_force edit_cache/ preinstall
clean default_target help preinstall/
clean/ depend my_target rebuild_cache
cmake_check_build_system edit_cache my_target/ rebuild_cache/
Solution from #KamilCuk :
Adding the following makes it possible to build each proto file individually
(it works, but then cmake complains about circular dependencies!)
foreach(p ${protos})
add_custom_target(${p} DEPENDS {CMAKE_CURRENT_BINARY_DIR}/${p})
endforeach()

Random executable output with CMake

Can I have a random name for the executable file of each build?
Or, in another words, a different name for the executable of each build action?
I wonder if a random-variable could be inserted into the build-tool-chain.
The reason of such a name is that my company's virus-checking is quite slow -- it took a long long time checking each executable, even longer then the build.
I'm using CLion 2016.2 on Win7, tool-chain is MinGW_w64_5.0, bundled CMake 3.5.2
You could always define POST_BUILD steps that call another CMake script. The only downside in the following approach would be that you can't - since it's random - reuse the executable's output name in CMake itself:
CMakeLists.txt
cmake_minimum_required(VERSION 3.5)
project(RandomExeName)
file(WRITE main.cpp "int main() { return 0; }")
add_executable(${PROJECT_NAME} main.cpp)
add_custom_command(
TARGET ${PROJECT_NAME}
POST_BUILD
COMMAND ${CMAKE_COMMAND} -D _file:PATH="$<TARGET_FILE:${PROJECT_NAME}>"
-P ${CMAKE_SOURCE_DIR}/CopyToRandom.cmake
)
set_property(TARGET ${PROJECT_NAME} PROPERTY SUFFIX ".temp")
CopyToRandom.cmake
string(RANDOM _random)
file(GLOB _old_files RELATIVE "${CMAKE_BINARY_DIR}" "*.exe")
execute_process(
COMMAND "${CMAKE_COMMAND}" -E remove ${_old_files}
COMMAND "${CMAKE_COMMAND}" -E copy "${_file}" "${_random}.exe"
)
# generate shortcut
get_filename_component(_name "${_file}" NAME_WE)
file(
WRITE "${_name}.sh"
"#!/bin/bash\n"
"${_random}.exe"
)
No you can't. Or you have to reconfigure for every build.
Regarding your actual problem: Advice the virus checker to exclude your build directories.

Error with variables when invoking CMake from CMake

I need to invoke cmake from within cmake so that I can have binaries built before project files are generated. I have the following CmakeLists.txt:
cmake_minimum_required(VERSION 3.2)
project(StarEngine)
set(CMAKE_CXX_FLAGS "-std=c++11")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
find_package(OpenGL REQUIRED)
include_directories(${OPENGL_INCLUDE_DIR})
#copy the other cmake file into where we'd like to invoke cmake
configure_file(deps-CMakeLists.txt deps/CMakeLists.txt)
execute_process(COMMAND ${CMAKE_COMMAND} . WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/deps)
#eventually binaries will be built, for now this doesn't accomplish anything
execute_process(COMMAND ${CMAKE_COMMAND} --build . WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/deps)
And its friend, deps-CmakeLists.txt, a test script:
set(GENERATED_DIR "test")
MESSAGE( STATUS ${GENERATED_DIR} )
In the following file structure:
Project
build
Code
CmakeLists.txt
deps-CmakeLists.txt
No matter what I put in for the variable value, it is blank when displayed in MESSAGE. I imagine this is weird behavior resulting from invoking cmake from cmake. I had a bunch of other strange errors to, but I suspect if I can figure out this one that will help crack them all.
Thanks to #Florian, the problem was with variable replacement and I needed to add the COPYONLY option to configure_file

How to instruct CMake to use the build architecture compiler

When using CMake for cross compiling, one generally specifies a toolchain file via the CMAKE_TOOLCHAIN_FILE option. In GNU terminology, one can specify the host architecture toolset using this file. However, one can generally not expect to be able to execute anything built with this toolchain. So often enough, some build tools need to be compiled for the build architecture.
Consider the following setup. I have two source files genfoo.c and bar.c. During build, genfoo.c needs to be compiled and run. Its output needs to be written to foo.h. Then I can compile bar.c, which #include "foo.h". Since CMake defaults to using the host architecture toolchain, the instructions for bar.c are easy. But how do I tell it to use the build architecture toolchain for compiling genfoo.c? Simply saying add_executable(genfoo genfoo.c) will result in using the wrong compiler.
CMake can only handle one compiler at a time. So - if you don't go the long way to set up the other compiler as a new language - you will end up with two configuration cycles.
I see the following approaches to automate this process:
Taking the example "CMake Cross Compiling - Using executables in the build created during the build?" from the CMake pages as a starting point I'll get:
CMakeLists.txt
cmake_minimum_required(VERSION 3.0)
project(FooBarTest)
# When crosscompiling import the executable targets
if (CMAKE_CROSSCOMPILING)
set(IMPORT_PATH "IMPORTFILE-NOTFOUND" CACHE FILEPATH "Point it to the export file path from a native build")
file(TO_CMAKE_PATH "${IMPORT_PATH}" IMPORT_PATH_CMAKE)
include(${IMPORT_PATH_CMAKE}/genfooTargets.cmake)
# Then use the target name as COMMAND, CMake >= 2.6 knows how to handle this
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/foo.h
COMMAND genfoo
)
add_executable(bar bar.cpp ${CMAKE_CURRENT_BINARY_DIR}/foo.h)
target_include_directories(bar PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
endif()
# Only build the generator if not crosscompiling
if (NOT CMAKE_CROSSCOMPILING)
add_executable(genfoo genfoo.cpp)
export(TARGETS genfoo FILE "${CMAKE_CURRENT_BINARY_DIR}/genfooTargets.cmake")
endif()
Then using a script like:
build.sh
#!/bin/bash
if [ ! -d hostBuild ]; then
cmake -E make_directory hostBuild
cmake -E chdir hostBuild cmake ..
fi
cmake --build hostBuild
if [ ! -d crossBuild ]; then
cmake -E make_directory crossBuild
cmake -E chdir crossBuild cmake .. -DIMPORT_PATH=${PWD}/hostBuild -DCMAKE_TOOLCHAIN_FILE=toolchain.cmake
fi
cmake --build crossBuild
I'll get the desired results by calling ./build.sh.
Splitting the CMakeLists.txt and maybe even replace the export()/include() with something where I know the output path of my build tools e.g. by using CMAKE_RUNTIME_OUTPUT_DIRECTORY would simplify things:
CMakeLists.txt
cmake_minimum_required(VERSION 3.0)
project(FooBarTest)
# Then use the target name as COMMAND. CMake >= 2.6 knows how to handle this
add_custom_command(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/foo.h
COMMAND genfoo
)
add_executable(bar bar.cpp ${CMAKE_CURRENT_BINARY_DIR}/foo.h)
target_include_directories(bar PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
buildTools/CMakeLists.txt
cmake_minimum_required(VERSION 3.0)
project(BuildTools)
add_executable(genfoo genfoo.cpp)
build.sh
#!/bin/bash
if [ ! -d crossBuild ]; then
cmake -E make_directory crossBuild
cmake -E chdir crossBuild cmake .. -DCMAKE_TOOLCHAIN_FILE=toolchain.cmake
fi
if [ ! -d hostBuild ]; then
cmake -E make_directory hostBuild
cmake -E chdir hostBuild cmake ../buildTools -DCMAKE_RUNTIME_OUTPUT_DIRECTORY:PATH=${PWD}/crossBuild
fi
cmake --build hostBuild
cmake --build crossBuild
References
Making a CMake library accessible by other CMake packages automatically
CMake build multiple targets in different build directories
How do I make CMake output into a 'bin' dir?
It is possible to do that completely within CMake.
The trick is to run a separate CMake configuring stage within its own space, silently dismissing every crosscompiling setting and using the host's default toolchain, then import the generated outputs into it's parent, crosscompiling build.
First part:
set(host_tools_list wxrc generate_foo)
if(CMAKE_CROSSCOMPILING)
# Pawn off the creation of the host utilities into its own dedicated space
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/host_tools)
file(TO_NATIVE_PATH ${CMAKE_COMMAND} native_cmake_command)
file(TO_NATIVE_PATH ${CMAKE_CURRENT_SOURCE_DIR} native_cmake_current_source_dir)
execute_process(
COMMAND "${native_cmake_command}" "-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}" "${native_cmake_current_source_dir}"
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/host_tools
)
add_custom_target(host_tools
COMMAND ${CMAKE_COMMAND} --build . --target host_tools --config $<CONFIG>
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/host_tools
)
include(${CMAKE_CURRENT_BINARY_DIR}/host_tools/host_tools.cmake)
foreach(tgt IN ITEMS ${host_tools_list})
add_dependencies(host${tgt} host_tools)
endforeach()
else()
# Add an empty target, host tools are built inplace
add_custom_target(host_tools
DEPENDS ${host_tools_list}
)
endif()
... then you add the usual add_executable and whatever ...
At the end:
if(NOT CMAKE_CROSSCOMPILING)
foreach(tgt IN ITEMS ${host_tools_list})
add_executable(host${tgt} ALIAS ${tgt})
endforeach()
export(TARGETS ${host_tools_list} NAMESPACE host FILE host_tools.cmake)
endif()
When it crosscompiles, it pawns off the creation of the host-run tools into its own dedicated space, and imports the targets as "hostwxrc" and "hostgenerate_foo", with a dependency on generating the host_tools themselves .
When it doesn't crosscompile, it builds wxrc and generate_foo as-is, and aliases them to hostwxrc and hostgenerate_foo.
After this, when you use $<TARGET_FILE:wxrc>, you refer to the wxrc built for the target platform, and $<TARGET_FILE:hostwxrc> refers to the wxrc built for the host platform, regardless whether they are the same or not.

CMake: How to add dependency on linker script for executable

I have a CMake script where the final executable is linked with my own linker script:
cmake_minimum_required(VERSION 3.1)
project(test_app)
set(LINKER_SCRIPT "linker.ld")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -T ${LINKER_SCRIPT}")
add_executable(${PROJECT_NAME}.elf
main.cpp
startup.cpp
)
How do I make an executable dependent also on the linker script file (trigger linking if linker.ld was changed)?
You can add a LINK_DEPENDS property to your executable target, using set_target_properties. Add the following line after your add_executable command:
set_target_properties(${TARGET_NAME} PROPERTIES LINK_DEPENDS ${LINKER_SCRIPT})
The first argument to set_target_properties is the target name, i.e. the first argument you passed to add_executable.
I found this mail which described three possible ways for forcing an executable to be dependent on a linker script. Its author prefers this way:
CMakeLists.txt:
CMAKE_MINIMUM_REQUIRED(VERSION 2.8 FATAL_ERROR)
PROJECT(LINKERSCRIPT C)
FILE(WRITE main.c "void main(){}")
# dummy.c must exist:
ADD_EXECUTABLE(EXE main.c dummy.c)
# linkerscript must exist:
SET_SOURCE_FILES_PROPERTIES(
dummy.c PROPERTIES OBJECT_DEPENDS ${CMAKE_SOURCE_DIR}/linkerscript
)
Here dummy.c is an empty file, which is listed for the add_executable() command only for make resulted executable dependent on the linker script via the OBJECT_DEPENDS property.