4

We're writing an application for an embedded ARM/Linux device. Development is performed on a Windows PC, using a crosscompiler, Eclipse and Ninja. CMake currently can create the build scripts that work well for the intended purpose.

We have unit tests that run on the embedded device attached to the net, once the project is pushed (over Git) to the server.

We're trying to implement unit tests, that would run on the PC, before we try them on the device. That means building natively, using MinGW GCC - of course we can't launch the ARM Linux executables on the PC.

Even if we switch the toolchain, launching CMake to rebuild the ruleset for Ninja, or create two build directories, one for PC, one for ARM, the problem remains that CMake will try to run a test executable, and later during build, unit tests will be attempted on the ARM build.

How can we configure the builds (through CMake) to create both - and not attempt to run the crosscompiled ones on the PC?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
SF.
  • 13,549
  • 14
  • 71
  • 107
  • You could check for [`CMAKE_CROSSCOMPILING`](https://cmake.org/cmake/help/latest/variable/CMAKE_CROSSCOMPILING.html). See e.g. [How to instruct CMake to use the build architecture compiler?](http://stackoverflow.com/questions/36173840/how-to-instruct-cmake-to-use-the-build-architecture-compiler). – Florian May 24 '16 at 11:27
  • Could you please add a CMake code example of how you are doing the "run a test executable"? Did you add it as `add_custom_command(TARGET ... POST_BUILD ...)` and/or with `add_test()`? I think in both case just putting a `if (NOT CMAKE_CROSSCOMPILING)`|`endif()` around this particular command should do the trick. – Florian May 25 '16 at 07:53
  • @Florian: In the top-level CMakeLists.txt there's just `ADD_SUBDIRECTORY(UnitTests)`. Then in the directory there's `ExternalProject_Add(GMockDownload GIT_REPOSITORY "https://github.com/google/googletest.git" ...` which does the rest of the work. Yes, `if (NOT CMAKE_CROSSCOMPILING)` helps here. It seems two separate build dirs and launching cmake twice is the way. Not optimal, because I'm getting two Eclipse projects instead of merely two Build Configurations. – SF. May 25 '16 at 08:05

1 Answers1

3

I have a similar setup in my projects (building from the same sources a simulator, unit tests, and the target binary), and you can check for CMAKE_CROSSCOMPILING to differentiate your two use cases. Just putting

if (NOT CMAKE_CROSSCOMPILING)
    ....
endif()

around the particular commands should do the trick.

And you need to have two binary output directories. CMake does not allow to mix toolchains in one directory.

But you don't need to have two IDE projects. In my projects:

  • I've added all sources - incl. the "cross-compile only" files - into the library/executable targets
    • I'm marking them as "excluded from build" for the PC only variants
    • So all sources will show-up in one IDE project (e.g. for searching through the code)
  • I've added the cross-compiling call as a custom target
    • I've removed it from the default build, but you can explicitly start it from your IDE
    • In my case it's an external script, but you can also pass the necessary calls directly in COMMAND parameters
    • You could even use another ExternalProject_Add() to include your own project for cross-compiling

Here are some code snippets for this kind of approach:

if (NOT CMAKE_CROSSCOMPILING)
    set(PC "ON" CACHE INTERNAL "hw-platform PC")
    unset(MCU CACHE)
else()
    set(MCU "ON" CACHE INTERNAL "hw-platform MCU")
    unset(PC CACHE)
endif()

...

if (PC)
    # Exclude files that only compile/work on MCU
    set_source_files_properties(... PROPERTIES HEADER_FILE_ONLY 1)
endif()

...

if (PC)
    add_test(...)
endif()

...

if (PC AND EXISTS "${CMAKE_SOURCE_DIR}/buildMcu.cmd")
    add_custom_target(
        BUILD_MCU
        COMMAND buildMcu.cmd
        WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
    )
    set_target_properties(BUILD_MCU PROPERTIES EXCLUDE_FROM_DEFAULT_BUILD 1)
endif()

References

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Florian
  • 39,996
  • 9
  • 133
  • 149