Different compilers/toolchains for different targets

I have been using CMake as a build system generator to cross compile for ARM Cortex M microcontrollers for a while now, and to great success (well, honestly it was only successful after I bought @craig.scott 's book).

Now I may have run into an issue with the extensibility of the cross-compilation support.

I’d like to be able to build unit tests for my project using CppUTest/CppUMock along side the app as a separate build target. The tests would just test the business logic portions of my application on my host machine, with hardware components mocked out, meaning I’d want it to compile and run the tests on my HOST system.

I use the cortex M version of GCC (arm-none-eabi-gcc) as a compiler for the microcontroller app. But the code that will be under test has been verified to be hardware agnostic and compile under both arm-none-eabi-gcc and standard x86_64 GCC. So I know the app code under test would support this

What I can’t figure out how to create a target that uses a different compiler from the other targets though… Is this possible?

I’d like to build my app target (and associated library targets) using arm-none-eabi-gcc but build my tests with the host system compiler.

Seems simple, but I can’t figure it out?

Any and all help appreciated!

CMake can only build for one target platform in a single build. If you want to build for a different platform, you need to do that as a separate build. I can suggest a couple of options (more like variations of the same option):

OPTION 1: Add test cases that build a sub-build for the host architecture rather than the one being targeted by the main build.

For this, I’d suggest exploring the ctest --build-and-test mode. You may want to avoid having many small tests and instead have a few tests that combine things if you go down this path. Main reason is that on some platforms, doing the compiler checks for a build can be expensive (many seconds).

OPTION 2: Design your project so that it automatically adapts to whether it is building for the ARM platform or the host platform. If the latter, mock out the necessary bits and otherwise build as normal. Then you would just need to have two builds - one for ARM, one for the host. If you wanted to, you could potentially combine this with OPTION 1 and make it a test case that invokes ctest --build-and-test for the host build, but it may be more complicated than you need.

2 Likes

Hi Craig,

Thanks for the response. I do have a lot of small test cases so that probably negates option 1.

Regarding option 2, could you please elaborate a little more about what you mean when you say

Design your project so that it automatically adapts to whether it is building for the ARM platform or the host platform.

When you say “two builds” do you mean create two “build types” similar to Debug and Release? I didn’t think those could use different toolchain files?

I mean two completely separate build directories. Same source tree, but different builds. The project source would only add the tests if building for the host architecture, as well as only building the platform-independent parts of the rest of the project. You can switch behavior based on CMAKE_SYSTEM_NAME. Easiest is probably to just compare whether it is the same as CMAKE_HOST_SYSTEM_NAME or not.

1 Like