[mbed-os 6.15.1] get rid of (a lot of!) unnecessary modules

I know that this topic has been discussed already several times and I found some discussions around this, and often it says that is was a known waekness of mbed build tools to include more than necessary. I read a lot of different discussions on the net dating back in 2020 and 2021, where I found that the new cmake based CLI V2 of mbed-tools should solve this “issue”.

Now I tried latest mbedOS 6.15.1 with mbed-tools 7.53.0. with the bare-metal-blinky example. because this should really be one of the smallest “test cases” one can run.
It runs fine out of the box but when I compare the solution to a bilnky done “by.-hand” using HAL drivers only, it seems that A LOT of completely unrelated modules /dependencies are compiled and linked by mbed-os.
I know there is the serial module included and a minimum printf, which I can understand.
But looking at the map file (which has ~60k lines) there is also code e.g. for CAN which for sure has nothing to do with the dependencies of the blinky.

The mbed_app.json definitely uses the line “requires”: [“bare-metal”], so that should be the way to go as far as I understand. What am I missing? Which setting /configuration do I have to use to get all the unrelated stuff out of the project? (the point is not only memory footprint but also for the sake of clarity and “compactness” of the project).

Thanks a lot!

Hello Franz,

This link might help you to get started. It works with CLI1. The last version is available at the end of the thread. If you’ll find more unrelated stuff you can enhance (fine tune) it.

Hi Zoltan!
Thanks for the quick reply. Just that I understand correctly: is “.mbedignore” still the preferred way with CLI V2 or is is related to CLI V1 only. I somewhere (cannot find the link again) read that - as of release of the new build tools baed on cmake - .mbedignore should only be considered as a workaround since it has some major drawbacks such as manually fiddling the files when folders change and error prone since done by hand compared to a build system?

As I side-Note: I do not really care about compilation times, since they are fast enough on my machine. It is more the thing that even simple project get “clunky” and tons of files/drivers are copied into the build directory that are unrelated to the application. Maybe this is just something I have to deal with - just wanted to know about where the real “problem” resides that those modules are identified as “related dependencies” when they really are not… =)

From what I understand of the CLI V2 system, a bare metal build should be pretty good about only including only the base Mbed platform, the manufacturer HAL, and low level driver code. I’m curious, what symbols are you seeing that shouldn’t be there in the final output? Also what target is this, and what mbed CMake targets are you linking to your application?

Hi Jamie!
I did not change anything, it is the bare metal blinky example :wink: I do not manually link anything else. Target is the L432KC_Nucleo.

Am not in front of the PC right now but as I said above, it links some CAN driver, low power Timer, Serial Module (although that might be on purpose?)
Would it help if I upload the .map file here?

BTW: I tested the addition of a .mbedignore file, seems that this one is ignored also (not respected), but maybe this is some work in progress on CLi V2, will test with CLi V1 tomorrow.

Could someone import and build the blinkt example on cli v2 so I can compare?

OK, I think I understand the source of some of the confusion here. Basically, Mbed relies pretty heavily on a linker feature known as “gc-sections”. What this does is, after linking is performed, it removes any symbols from the final image which are not referenced from anywhere else. Thanks to this, Mbed can compile all the core source files always in the standard build process without worrying about what the user actually uses – the linker will clean up all the unused functions.

However, it looks like the map file gets generated before this process happens, so it will show a lot of HAL and Mbed code that isn’t used and isn’t included in the final code image. I think that’s why you’re seeing things that clearly shouldn’t be there.

Instead of looking at the map file, I tend to use these two commands to analyze the symbols in an image:
For functions:

arm-none-eabi-nm -SC --size-sort YOUR_PROGRAM.elf | grep ' [TtWw] '

For data:

arm-none-eabi-nm -SC --size-sort YOUR_PROGRAM.elf | grep ' [BbDdCc] '

These will print all function symbols / data symbols that actually got included in the final image. If I run these on a hello world program built for your target, I just see things like serial port stuff, timer stuff, mbed core functions, and C library functions – no CAN stuff.

Hope that clears things up!


Good explanation by Jamie, just wanted to summarize that if you see something in the map file, it doesn’t mean that it is included in the final binary.

You are right though that the Mbed build system is not optimized and messy, however at least the Cmake based CLI 2 is a huge improvement on the old tools.

1 Like

Thanks a lot to Jamie and Bora for the detailed explanation, especially for the nm command. This shades some light into the insides of the binary. If I look at the output of the command for functions, I still see symbols like

134226784 00000016 T CAN1_TX_IRQHandler
134226800 00000016 T CAN1_SCE_IRQHandler
134226768 00000016 T CAN1_RX0_IRQHandler

… but since I output the size in decimal, the 16 bytes for the CAN1 handlers are not really a topic regarding size although still interesting that those symbols are there…

//EDIT: just tried mbed CLI V1 as a comparsion and found out 2 things.
1.) without an .mbedignore file CLI V1 indeed compilation of the blinky takes A LOT longer than on V2 so I guess this is the huge improvement of the build system used in CLI V2
2.) when using an .mbedignore where many things are excluded, the build takes a similar time as on V2, which at least shows that the CLI V1 respects the ignore file.

It seems that CLI V2 dies not care about the .mbedingore file , altough I am not sure yet =)

Those are the exception (interrupt) handlers, which are always included in the interrupt vector table, no matter if you use them or not.

CLI2 does not care about .mbedignore since it uses CMake to manage the dependencies.