Skip to content

CMake: From USCRPL/mbed-cmake to Mbed OS first-party CMake #13981

Closed
@ladislas

Description

@ladislas

Description of defect

Intro

As mentioned in #13974, I'm in the process of moving our current project from USCRPL/mbed-cmake to mbed os first-party CMake.

I thought it might be interesting for others to share our progress, our questions, feedback and issues we might be facing. I think that github is better than the forum for this as it is easier to share code, other repos and reference issues and PR

Our project is quite complex, with a main src directory containing our product firmware (main program). We have different drivers and libraries that are being used by the firmware.

We also have a lot of spikes: standalone projects (with their own main.cpp) to test components, features, libs, technical solutions, etc.

The following repository is a simpler example of our big project, and I'll use it to test all the features.

https://github.com/ladislas/mbed-cmake-template

How it works now

USCRPL/mbed-cmake allows us to have the spikes and the main program live in the same repository and compile together without any issues. We then use openocd to flash the .bin we want to use in our product.

USCRPL/mbed-cmake first creates a mbed-os-static STATIC library (https://github.com/USCRPL/mbed-cmake/blob/c0b0f7d4080bba179b9390e877eb0c1e7467f6d0/cmake/MbedOS-GCCArm.cmake#L35-L37) which is then wrapped into an mbed-os INTERFACE that defined the linker script and link options (https://github.com/USCRPL/mbed-cmake/blob/c0b0f7d4080bba179b9390e877eb0c1e7467f6d0/cmake/MbedOS-GCCArm.cmake#L50-L58). It's this mbed-os INTERFACE that our main program, spikes drivers and libs link with.

From a user perspective, mbed-os-static is compiled once for the main program and for all the spikes, drivers and libs. Adding a new spike with just a main.cpp file, will only increment the whole compilation steps number by one.

First try with Mbed OS first-party CMake

On the other hand, mbed os first-party cmake "recompiles" all the needed sources for each target depending on it. Adding a new spike linking with mbed-os will throw in the compilation a few hundred more "steps". Looking at the output, one can clearly see that mbed os or target files are compiled multiple times for the libs, the spikes and the main program.

Issues

And then it stops as the way it handles the linker script is not made for multiple add_executable targets.

Another issue was that adding another executable and calling mbed_set_mbed_target_linker_script resulted in the following error about .compile_time_defs.txt:

CMake Error: Files to be generated by multiple different commands: "/Users/ladislas/dev/ladislas/mbed-cmake-template/build/compile_time_defs.txt"

The issue comes from here:

file(GENERATE OUTPUT "${CMAKE_BINARY_DIR}/compile_time_defs.txt" CONTENT "${_compile_definitions}\n")
set(${definitions_file} @${CMAKE_BINARY_DIR}/compile_time_defs.txt PARENT_SCOPE)
and is easily fixed by using:

-    file(GENERATE OUTPUT "${CMAKE_BINARY_DIR}/compile_time_defs.txt" CONTENT "${_compile_definitions}\n")
-    set(${definitions_file} @${CMAKE_BINARY_DIR}/compile_time_defs.txt PARENT_SCOPE)
+    file(GENERATE OUTPUT "${CMAKE_BINARY_DIR}/${target}.compile_time_defs.txt" CONTENT "${_compile_definitions}\n")
+    set(${definitions_file} @${CMAKE_BINARY_DIR}/${target}.compile_time_defs.txt PARENT_SCOPE)

Note that the two files generated are identical. If they can never be different, it would be better to juste generate one and use it for all executable.

Questions

Please note I'm neither a CMake expert nor a .ld expert.

From my understanding: for the same mbed target (DISCO_F769NI in our case), the linker script is always the same. If we change target, we must change the linker script. In real life projects this happens seldom as your board/target is usually the same for a long period of time. But even if we need to change it, a new run of mbed-tools configure will provide everything needed.

Currently mbed-os, mbed-core, mbed-rtos are defined as INTERFACE libraries, meaning they are not compiled on their own (as static or object libraries would be), but become part of the target (other library or executable) that links with it.

So calling mbed_set_mbed_target_linker_script for each executable will also call mbed_set_toolchain_options multiple times.

My first question is:

What is the reason for using INTERFACE for the whole mbed-os? Why not use a static library wrapped in an interface?

And secondly:

Is supporting a project structure such as mine with multiple executable targets on the roadmap?

I'd be happy to help in this case.

Thanks for reading till here and also thanks for bringing CMake to mbed-os! :)

(cc @0xc0170 @hugueskamba @rajkan01 @multiplemonomials @ProExpertProg)

Target(s) affected by this defect ?

DISCO_F769NI

Toolchain(s) (name and version) displaying this defect ?

arm-none-eabi-gcc --version
arm-none-eabi-gcc (GNU Arm Embedded Toolchain 9-2020-q2-update) 9.3.1 20200408 (release)

What version of Mbed-os are you using (tag or sha) ?

33a7e66

What version(s) of tools are you using. List all that apply (E.g. mbed-cli)

mbed --version
1.10.4

mbed-tools --version
3.5.1.dev36

How is this defect reproduced ?

to do

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions