# Building Compile-time Tools When Cross-compiling

**URL:** https://discourse.cmake.org/t/building-compile-time-tools-when-cross-compiling/601
**Category:** Usage
**Created:** [February 7, 2020, 6:28pm UTC](https://discourse.cmake.org/t/building-compile-time-tools-when-cross-compiling/601 "2020-02-07T18:28:49Z")
**Posts on this page:** 11
**Page:** 1

<div class="post-metadata">

### Author: ![marco1475](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/m/c89c15/32.png) [@marco1475](https://discourse.cmake.org/u/marco1475)
#### Post date: [February 7, 2020, 6:28pm UTC](https://discourse.cmake.org/t/building-compile-time-tools-when-cross-compiling/601/1 "2020-02-07T18:28:49Z")

</div>

Hi,

As part of my compilation process I need to run a custom _build tool_ that parses XML files and generates a C++ header and source file, which are in turn included and compiled by the main executable. My _build tool_ is an executable target within my CMake setup that the main executable references via `add_custom_command()`.

This works great not only because my _build tool_ gets automatically built and executed at the right time (i.e. before the generated source files are needed by the main executable’s build process), making iteration a breeze, but also because both my _build tool_ and the main executable share the same libraries, which avoids building them twice.

**Is this setup incompatible with cross-compilation?**

Let’s say I am on a Windows host machine and want to cross-compile the main executable for Linux. My _build tool_ needs to be built for Windows, as it will be executed on the host machine during the compilation process. But my main executable is being built for Linux, so it pulls in Linux-specific libraries (e.g. a system IO abstraction library that is used by both executables).

Now the sharing of libraries between the executables is problematic, as I would want to pull in different versions of each library (i.e. `SystemIO_Windows` for my build tool and `SystemIO_Linux` for the main executable; see “Library Setup” below).

I am aware of `CMAKE_HOST_SYSTEM_NAME` vs. `CMAKE_SYSTEM_NAME`, CMake toolchains, etc., but as far as I can tell neither addresses the issue of needing to **pull in the same target multiple times with different build settings**.

Is my only option removing my _build tool_ from the build process and using it as a pre-built executable?

Thanks!

> **Library Setup**
>
> The “System” library’s `CMakeLists.txt` includes different files depending on which platform is being targeted, i.e. on Windows “System” would add only the `Windows_IO.cpp` file and on Linux the `Linux_IO.cpp` file. I cannot have both files added at the same time because when I am not cross-compiling, `Linux_IO.cpp` would fail to compile on Windows.

---

<div class="post-metadata">

### Author: ![craig.scott](https://discourse.cmake.org/user_avatar/discourse.cmake.org/craig.scott/32/20_2.png) [@craig.scott](https://discourse.cmake.org/u/craig.scott)
#### Post date: [February 8, 2020, 5:28am UTC](https://discourse.cmake.org/t/building-compile-time-tools-when-cross-compiling/601/2 "2020-02-08T05:28:42Z")

</div>

The technique discussed in the following is one way of handling this:

> <https://stackoverflow.com/questions/36084785/building-a-tool-immediately-so-it-can-be-used-later-in-same-cmake-run>

---

<div class="post-metadata">

### Author: ![ClausKlein](https://discourse.cmake.org/user_avatar/discourse.cmake.org/clausklein/32/352_2.png) [@ClausKlein](https://discourse.cmake.org/u/ClausKlein)
#### Post date: [February 9, 2020, 9:37am UTC](https://discourse.cmake.org/t/building-compile-time-tools-when-cross-compiling/601/3 "2020-02-09T09:37:40Z")

</div>

Why do you not use _add\_custom\_command_() and an preinstalled host tool like an **idl** compiler, or **xslt** transformator, …?

You may find an usage example here [https://github.com/apriorit/FindIDL/blob/master/cmake/FindIDL.cmake](https://github.com/apriorit/FindIDL/blob/master/cmake/FindIDL.cmake)

---

<div class="post-metadata">

### Author: ![marco1475](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/m/c89c15/32.png) [@marco1475](https://discourse.cmake.org/u/marco1475)
#### Post date: [February 10, 2020, 3:28am UTC](https://discourse.cmake.org/t/building-compile-time-tools-when-cross-compiling/601/4 "2020-02-10T03:28:02Z")

</div>

I have simplified what the tool does since it’s not important to the problem at hand. Unfortunately, it has to be a custom tool.

I really enjoy the effortless iteration that including it as a dependent target in the larger CMakeLists.txt provides, but maybe that is not achievable when cross-compiling. Craig Scott’s solution, while inventive, might be too involved to implement. Especially when compared with simply pointing the custom command to a pre-built binary of the tool when cross-compiling.

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)
#### Post date: [February 16, 2020, 12:55am UTC](https://discourse.cmake.org/t/building-compile-time-tools-when-cross-compiling/601/5 "2020-02-16T00:55:51Z")

</div>

VTK handles it this way:

- Create an option which makes just the tools used on the host during a build ([https://gitlab.kitware.com/vtk/vtk/blob/a5f938b2fdfefa522439065e040cb42f65d88444/CMakeLists.txt#L231](https://gitlab.kitware.com/vtk/vtk/blob/a5f938b2fdfefa522439065e040cb42f65d88444/CMakeLists.txt#L231)) and install a package with a different namespace than normal builds
- If cross compiling without an emulator, require that host tools package ([https://gitlab.kitware.com/vtk/vtk/blob/master/CMake/vtkCrossCompiling.cmake](https://gitlab.kitware.com/vtk/vtk/blob/master/CMake/vtkCrossCompiling.cmake))
- If the host tools are found, use them in the `add_custom_command` call ([https://gitlab.kitware.com/vtk/vtk/blob/a5f938b2fdfefa522439065e040cb42f65d88444/CMake/vtkModule.cmake#L3047](https://gitlab.kitware.com/vtk/vtk/blob/a5f938b2fdfefa522439065e040cb42f65d88444/CMake/vtkModule.cmake#L3047)), using `CMAKE_CROSSCOMPILING_EMULATOR` if available

---

<div class="post-metadata">

### Author: ![alex](https://discourse.cmake.org/user_avatar/discourse.cmake.org/alex/32/125_2.png) [@alex](https://discourse.cmake.org/u/alex)
#### Post date: [June 16, 2020, 9:31pm UTC](https://discourse.cmake.org/t/building-compile-time-tools-when-cross-compiling/601/6 "2020-06-16T21:31:22Z")

</div>

Could [ExternalProject](https://cmake.org/cmake/help/latest/module/ExternalProject.html) be used instead in a super-build configuration, or not?

---

<div class="post-metadata">

### Author: ![craig.scott](https://discourse.cmake.org/user_avatar/discourse.cmake.org/craig.scott/32/20_2.png) [@craig.scott](https://discourse.cmake.org/u/craig.scott)
#### Post date: [June 16, 2020, 9:41pm UTC](https://discourse.cmake.org/t/building-compile-time-tools-when-cross-compiling/601/7 "2020-06-16T21:41:41Z")

</div>

Yes, I’ve used ExternalProject to mix different compilers in the one project (firmware for an embedded device that gets included in a software package for the host platform). The stackoverflow Q&A I linked to mentions this is possible in its question, but was explicitly out of scope for that particular situation. For the question posted here, it could probably be made to work, but you may have a bit of fiddling to do in order to have your main build know where the build tool’s executable will be. Once you put something out into an ExternalProject, you become responsible for telling your main build where all its build artefacts are. In a true super build, you can usually do that by installing to a staging area and telling later ExternalProjects to look there in `find_package()`, etc. calls using `CMAKE_PREFIX_PATH`. Not sure this fits the use case here though.

---

<div class="post-metadata">

### Author: ![marco1475](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/m/c89c15/32.png) [@marco1475](https://discourse.cmake.org/u/marco1475)
#### Post date: [June 23, 2020, 9:36pm UTC](https://discourse.cmake.org/t/building-compile-time-tools-when-cross-compiling/601/8 "2020-06-23T21:36:12Z")

</div>

Hm, ExternalProject is an interesting approach. Unfortunately, the project I work on is philosophically not quite ready for a super build.

Thanks for the ideas everyone!

---

<div class="post-metadata">

### Author: ![cerna](https://discourse.cmake.org/user_avatar/discourse.cmake.org/cerna/32/1299_2.png) [@cerna](https://discourse.cmake.org/u/cerna)
#### Post date: [June 5, 2021, 11:14am UTC](https://discourse.cmake.org/t/building-compile-time-tools-when-cross-compiling/601/9 "2021-06-05T11:14:12Z")

</div>

Thinking about using the ExternalProject functionality for the exact same purpose (compile a compiler with HOST compiler 😉 when everything else is compiled with TARGET compiler specified in Toolchain file) - this seems to work and produces the right ELF files.

However, when the external project has a source in the same repository as the main project, how do I specify the dependency and checking for out-of-date state? (After build, when changing the code of an external project and running just `make` or `ninja` will not recompile the external project and everything using it to compile.)

And also, can I somehow change the compiler before specifying new `project()` win multi-project build? (Project branches added with `add_subdirectory()`.) I would like to set the compiler compiled as `ExternalProject`.

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)
#### Post date: [June 5, 2021, 11:20am UTC](https://discourse.cmake.org/t/building-compile-time-tools-when-cross-compiling/601/10 "2021-06-05T11:20:56Z")

</div>

> [@cerna](#):
>
> I would like to set the compiler compiled as `ExternalProject`.

The results of `ExternalProject` are not available in the configure step project where its `ExternalProject_add` exists. CMake requires the compiler be available when it configures, so this would need to be a separate `ExteralProject_add` call in order to consume the host toolchain.

---

<div class="post-metadata">

### Author: ![cerna](https://discourse.cmake.org/user_avatar/discourse.cmake.org/cerna/32/1299_2.png) [@cerna](https://discourse.cmake.org/u/cerna)
#### Post date: [June 5, 2021, 11:27am UTC](https://discourse.cmake.org/t/building-compile-time-tools-when-cross-compiling/601/11 "2021-06-05T11:27:37Z")

</div>

You are right, I forgot that CMake is testing the compiler during configure.

I guess in that case the Craig Scotts’s solution is applying to this scenario too.
