Cmake Cortex-M multitarget build

Hi

Im trying to achieve a cmake build environment where i can build multiple targets (binaries) at once.

cmake and make/ninja actually run successfully, but the generated ELF’s somehow do not run at all. When i run them with a segger debug session, they seem not to be able to map gdb addresses to source files.

what i also notice is that targetA and B are identical in size, even if they do not execute the same in the main program.

i found a lot of good inputs on github for cmake, both for either A.) cortex-M or B.) multiple-target builds, but never combined. i assume i have some configuration error.

Could someone help me out? If needed, i can also provide the entire project as a zip.

thank you!

== the main project (CMAKELISTS) =====================
set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_SYSTEM_PROCESSOR arm)
set(CMAKE_ASM_COMPILER arm-none-eabi-gcc)
set(CMAKE_C_COMPILER arm-none-eabi-gcc)
set(CMAKE_CXX_COMPILER arm-none-eabi-g++)
set(CMAKE_EXE_LINKER_FLAGS “-specs=nano.specs -Wl,–gc-sections” CACHE INTERNAL “”)
set(CMAKE_ASM_COMPILER_ID GNU)
set(CMAKE_C_COMPILER_ID GNU)
set(CMAKE_CXX_COMPILER_ID GNU)
set(CMAKE_ASM_COMPILER_FORCED TRUE)
set(CMAKE_C_COMPILER_FORCED TRUE)
set(CMAKE_CXX_COMPILER_FORCED TRUE)

enable_language (ASM)
set (CMAKE_ASM_FLAGS “${CFLAGS} -x assembler-with-cpp”)
set (CPU_OPTIONS -mthumb -mcpu=cortex-m3)

cmake_minimum_required (VERSION 3.17.3)

project (main-project)

set (CMAKE_ASM_FLAGS_DEBUG “-g”)
set (CMAKE_C_FLAGS_DEBUG “-Og -g -UNDEBUG -DDEBUG”)
set (CMAKE_CXX_FLAGS_DEBUG “-Og -g -UNDEBUG -DDEBUG”)
set (CMAKE_ASM_FLAGS_RELEASE “-g”)
set (CMAKE_C_FLAGS_RELEASE “-Og -g -UNDEBUG -DDEBUG”)
set (CMAKE_CXX_FLAGS_RELEASE “-Og -g -UNDEBUG -DDEBUG”)

add_definitions( -DEFM32GG380F1024 )
add_definitions( -DDEBUG_EFM )

add_subdirectory (libraries/math_lib_1)
add_subdirectory (libraries/math_lib_2)
add_subdirectory (libraries/efm32)
add_subdirectory (libraries/dummy_interface)

add_subdirectory (targetA)
add_subdirectory (targetB)
add_subdirectory (targetZ)

== TARGET A ========================================

identical to B and Z just different main program

project (targetA)

include_directories( ${PROJECT_NAME}
${CMAKE_SOURCE_DIR}
${CMAKE_SOURCE_DIR}/targetA
)

link_directories( ${PROJECT_NAME}
${CMAKE_SOURCE_DIR}
)

add_executable ( ${PROJECT_NAME}
main
dummy
targetA_interface
)

set ( LINKER_SCRIPT “libraries/linker/targetA_linker.ld” )

target_link_libraries ( ${PROJECT_NAME}
PRIVATE
${CPU_OPTIONS}
-T${LINKER_SCRIPT}
-Wl,–gc-sections
-nostartfiles
-Xlinker
-Map=${PROJECT_NAME}.map
m
gcc
math_lib_1
math_lib_2
efm32
dummy_interface
)
set_target_properties( ${PROJECT_NAME}
PROPERTIES
SUFFIX “.elf”
)
=== LIB =======================================

add_library ( efm32
startup_efm32gg
system_efm32gg)
target_include_directories ( efm32
PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})

First off, I would not suggest setting CMAKE_<lang>_COMPILER, or in fact anything above your enable_language(), inside your project file. Those should instead be set via a CMake toolchain file.

Second, you can get rid of the enable_language() call and change project(main-project) to project(main-project ASM). This will also skip enabling C and C++ (assuming they’re not needed of course.)

Third, your linker options:

${CPU_OPTIONS}
-T${LINKER_SCRIPT}
-Wl,–gc-sections
-nostartfiles
-Xlinker
-Map=${PROJECT_NAME}.map

should be in a target_link_options() call instead.

Fourth, what’s going on here?

add_executable ( ${PROJECT_NAME}
main
dummy
targetA_interface
)

These look like target names rather than source files, which makes me think they should be linked with target_link_libraries() instead. Does your program have any source files, or is it simply combining libraries?

And finally, I would use objdump -s and objdump -S on your output to see if any code is getting compiled in at all.

A.)
target_link_options then it wont link anylonger at all, ninja stops execution at some point

B.)

add_executable ( ${PROJECT_NAME}
main
dummy
targetA_interface
)

those are 3 target specific source files (*.cpp)

I would like to share my project with you, but the website does not allow newbie-users to attach data. can i somehow else publish my project?

How about starting a small repository on GitHub? You can of course strip out any proprietary data you don’t want to share.

Ok ill do the github repository later, good idea. but for now i dont have an account, so ill share it with wetransfer
(offline)

Thanks. I just took a look at your project.

I would suggest making the .cpp extension in add_executable() (and add_library()) explicit for the sake of readability.

When I said to use target_link_options(), I didn’t mean to move everything into target_link_options(), just things that are not libraries. So it would look something like:

target_link_options ( ${PROJECT_NAME}
PRIVATE
${CPU_OPTIONS}
-T${LINKER_SCRIPT}
-Wl,–gc-sections
-nostartfiles
-Xlinker
-Map=${PROJECT_NAME}.map
)
target_link_libraries(${PROJECT_NAME}
m
gcc
math_lib_1
math_lib_2
efm32
dummy_interface
)

ok thanks. i applied your suggestions. its still building suggessfully, but the final binary is the same.

the objdump seems to have all functions available, so i assume everything is linked into the binary correctly (hard assumption though!)

One more thing… did you run CMake with -DCMAKE_BUILD_TYPE=Debug?

The issue is it hardfaults directly after the Reset_Handler().
I dont see whats going bad here at the moment.