[cmake-developers] [CMake] dependencies of cross compiliations

Rolf Eike Beer eike at sf-mail.de
Wed Nov 28 15:02:52 EST 2018


Am Dienstag, 27. November 2018, 19:55:56 CET schrieb Eric Noulard:
> Le mar. 27 nov. 2018 à 11:28, Rolf Eike Beer <eike at sf-mail.de> a écrit :
> > Am 2018-11-09 10:04, schrieb Torsten Robitzki:
> > > Hi,
> > > I hope this question was not asked before. I work in the embedded
> > > field and there it is usually to have at least two different build
> > > platforms. The Host platform, where unit tests are build (and where
> > > CMake is running) and an embedded Target platform, where targets are
> > > build with a cross compiler. Sometimes such a system comes with
> > > self-written tools that are build and run on the Host platform to
> > > build a target for the embedded Target platform (adding meta data to a
> > > binary to be used by a bootloader for example).
> > > 
> > > Usually I have two different build folders, one for the Host platform
> > > and one for the Target platform, using different calls to cmake to
> > > choose from a set of tools and targets. But when using this approach,
> > > it is necessary that the Host platform build ran before the Target
> > > platform build, so that tools that are required for the Target
> > > platform are build during the Host target build.
> > > 
> > > One solution I’ve came up with, is to build the required tools during
> > > the Target platform build, using an add_custom_target() to invoke the
> > > Target compiler directly. This works fine, as long as the tools are
> > > basically build just out of a couple of files.
> > > 
> > > What would be the „CMake-Way“ to add the tools (that have to be build
> > > on the Target platform) as dependency to targets that have to be build
> > > for the Target (cross compile) platform?
> > 
> > TL;DR: there is not "good" way yet. But there should be one.
> 
> I do agree with that quote I was quite surprised (a long time ago) that
> CMake did not support cross-compiling.
> Back then I was using recursive hand-written makefiles for cross-compiling.
> When I wanted to build
> the whole thing I only had to hit "make" and wait.
> 
> Moreover I think CMake cross-compiling support was biased by the fact CMake
> wasn't designed for that initially.
> Please don't take my remark as bare criticism I am using CMake for a long
> time now, I do like CMake very much
> and I was pleased to see the cross-compiling support coming.
> 
> However from my point of view and my cross-compiling experience when you
> cross-compile you have:
> 
> 1) the host compiler which is used to compile "host tools"
> 2) the target compiler (may be several of them) to "cross-compile"
> 
> My assumption are:
>  a) when you cross-compile your build is a "whole" and you shouldn't have
> to setup some superbuild
>    structure for building host tools ht_exe and another for target1 tool
> t1t_exe and another one for target2 tool t2t_exe.
> 
>  b) what you want is to build:
>      ht_exe for the host
>      possibly use ht_exe during the build to generate some [source] file
>      t1t_exe for the [cross]target1
>      t2t_exe for the [cross]target2
> 
>  c)  you seldomly compile the same source for the host AND the target, but
> it may happen.
> 
> And you want to build all that stuff with a single configure+build command
> AND take advantage
> of fast and efficient parallel build for the **whole build**. I don't want
> to
> 
> cd /build/for/host
> ninja
> cd /build/for/target1
> ninja
> etc...
> 
> >  Helpful would be a special
> > 
> > variable for CMAKE_INSTALL_PREFIX as this needs a bit of attention (and
> > a non-sysroot thing prefix in the toolchain file). Confused? Granted,
> > here is an example:
> > 
> > if (CMAKE_CROSSCOMPILING)
> > 
> >      set(HOST_INSTALL_DIR "/some/where")
> >      add_host_build(. host HOST_INSTALL_DIR)
> > 
> > endif ()
> > add_executable(magic magic.cpp)
> > install(TARGETS magic DESTINATION bin) # installs both the host and the
> > target tool!
> > add_custom_command(OUTPUT ${CMAKE_CURRENT_BUILD_DIR}/foo.cpp COMMAND
> > magic) # will call the host build
> > if (NOT CMAKE_HOST_BUILD)
> > 
> >      add_executable(foo ${CMAKE_CURRENT_BUILD_DIR}/foo.cpp)
> >      install(TARGETS foo DESTINATION bin)
> > 
> > endif ()
> 
> I get your point but I think we may try a more declarative way.
> 
> add_executable(magic magic.cpp)
> install(TARGETS magic DESTINATION bin)
> add_custom_command(OUTPUT ${CMAKE_CURRENT_BUILD_DIR}/foo.cpp COMMAND magic)
> add_executable(foo ${CMAKE_CURRENT_BUILD_DIR}/foo.cpp)
> install(TARGETS foo DESTINATION bin)
> 
> set_target_properties(magic PROPERTIES BUILD_TARGET "host;cross_target1")
> set_target_properties(foo PROPERTIES BUILD_TARGET "cross_target1")

That makes sense in general. We would need generator expressions for those to 
be able to e.g. selectively include sources into one or the other build.

> after that we know that `magic` is to be built both for "host" and
> "cross_target1" whereas
> `foo` is only for "cross_target1".
> 
> before that we may have to "declaratively" define what is cross_target1
> (and may be cross_target2) with something like:
> 
> enable_cross_target(NAME cross_target1 TOOLCHAIN ${CMAKE_CURRENT_SOURCE
> _DIR}/cmake/target1-toolchain.cmake)
> enable_cross_target(NAME cross_target2 TOOLCHAIN ${CMAKE_CURRENT_SOURCE
> _DIR}/cmake/target2-toolchain.cmake)
> and assume "host" builtin target is the one coming from the command line.
> 
> each define_cross_target(..) will create a separate subdir in the build
> tree (much like CMAKE_CFG_INTDIR is working for multi-config generators)
> may something like ${CMAKE_CURRENT_BINARY_DIR}/${CROSS_TARGET_NAME} if we
> assume cross target name are unique.

That would mean we would need something like "-D 
CMAKE_TOOLCHAIN_FILES=foo.cmake,bar.cmake" to pass multiple of them. In 
general you invert what I have said, having the host directory on the outside. 
That makes sense if you have multiple cross-targets in the same build tree.

But: I'm not sure I'm into this. It may make sense for some projects, but less 
for others, e.g. if the generators are target-specific. How do I tell CMake 
that this is not possible? I would go for the simple way and say: host tools 
are build with the target tools. If you have multiple targets, then you have 
multiple build dirs, the host tools are build multiple times.

> all cmake command (install, add_executable, add_library, etc...) shall know
> that a target is to be build for the host and/or cross target1
> and/or cross target2 etc...
> 
> add_custom_command COMMAND argument refering to a built target
> always refer to "host target" because there is usually no need (or mean) to
> execute cross target during the build anyway.

Yes.

> in the end you will have a project which specify all the target (exe, lib,
> custom) the usual declarative "modern CMake" way
> and you won't have your CMakeLists.txt filled with
> 
> IF(CMAKE_CROSSCOMPILING)
> 
> IF(NOT CMAKE_HOST_BUILD)
> 
> controls.

We will need some of those at the end anyway. Let's stay with Qt: they need a 
host libpng to build some whatever helpers for QtWebEngine, as well as a 
target one. Both of course need to be kept separated, and one may acually 
decide to search for host dependencies with less flags, other versions or 
whatever.

> if you need cross_target specific CMAKE_XXXX variables, they should either
> go in the target toolchain file
> or should be put in with
> cross_target_set(cross_target1 VARIABLE CMAKE_INSTALL_PREFIX "/opt/target1")
> 
> You may even decide that if a "build target" is not enabled because you
> have something like:

And here things are getting messy. If we stick with one-target-per-builddir as 
we already do for say 32 and 64 bit now the code will get cleaner.

> I think that most of the time specifying the toolchain on the command line
> drives you to some superbuild structure.

Which is not bad by itself, but I would like to see that CMake can provide 
things that avoid people reinventing the boilerplate code, and probably 
getting them wrong at least 80% of the time. Like they would do with 
dependencies and other things if they would write their Makefiles by hand 
instead of using CMake, just one level higher.

> > The wish-season is coming up, so that's sort of what I would like to
> > have. Now it's your turn. No bikeshedding please, only deliveries ;)
> 
> I wish an integrated multi-target cross building support in CMake with
> little or no flow-control scripting command in the CMakeLists.txt.

That would mean introducing HOST and TARGET flags to every find_* call, I'm 
not sure if that is cleaner than explicit if()'s. But I'm not fundamentally 
opposed to it, I'm just not sure it's worth the effort.

Eike
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 195 bytes
Desc: This is a digitally signed message part.
URL: <https://cmake.org/pipermail/cmake-developers/attachments/20181128/85e67612/attachment.sig>


More information about the cmake-developers mailing list