<div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><br><br><div class="gmail_quote"><div dir="ltr">Le mar. 27 nov. 2018 à 11:28, Rolf Eike Beer <<a href="mailto:eike@sf-mail.de">eike@sf-mail.de</a>> a écrit :<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Am 2018-11-09 10:04, schrieb Torsten Robitzki:<br>
> Hi,<br>
> I hope this question was not asked before. I work in the embedded<br>
> field and there it is usually to have at least two different build<br>
> platforms. The Host platform, where unit tests are build (and where<br>
> CMake is running) and an embedded Target platform, where targets are<br>
> build with a cross compiler. Sometimes such a system comes with<br>
> self-written tools that are build and run on the Host platform to<br>
> build a target for the embedded Target platform (adding meta data to a<br>
> binary to be used by a bootloader for example).<br>
> <br>
> Usually I have two different build folders, one for the Host platform<br>
> and one for the Target platform, using different calls to cmake to<br>
> choose from a set of tools and targets. But when using this approach,<br>
> it is necessary that the Host platform build ran before the Target<br>
> platform build, so that tools that are required for the Target<br>
> platform are build during the Host target build.<br>
> <br>
> One solution I’ve came up with, is to build the required tools during<br>
> the Target platform build, using an add_custom_target() to invoke the<br>
> Target compiler directly. This works fine, as long as the tools are<br>
> basically build just out of a couple of files.<br>
> <br>
> What would be the „CMake-Way“ to add the tools (that have to be build<br>
> on the Target platform) as dependency to targets that have to be build<br>
> for the Target (cross compile) platform?<br>
<br>
TL;DR: there is not "good" way yet. But there should be one.<br>
<br></blockquote><div><br></div><div>I do agree with that quote I was quite surprised (a long time ago) that CMake did not support cross-compiling.</div><div>Back then I was using recursive hand-written makefiles for cross-compiling. When I wanted to build</div><div>the whole thing I only had to hit "make" and wait.</div><div><br></div><div>Moreover I think CMake cross-compiling support was biased by the fact CMake wasn't designed for that initially.</div><div>Please don't take my remark as bare criticism I am using CMake for a long time now, I do like CMake very much</div><div>and I was pleased to see the cross-compiling support coming.</div><div><br></div><div>However from my point of view and my cross-compiling experience when you cross-compile you have:</div><div><br></div><div>1) the host compiler which is used to compile "host tools" </div><div>2) the target compiler (may be several of them) to "cross-compile" </div><div><br></div><div>My assumption are:</div><div> a) when you cross-compile your build is a "whole" and you shouldn't have to setup some superbuild</div><div>   structure for building host tools ht_exe and another for target1 tool t1t_exe and another one for target2 tool t2t_exe.</div><div> </div><div> b) what you want is to build:</div><div>     ht_exe for the host</div><div>     possibly use ht_exe during the build to generate some [source] file</div><div>     t1t_exe for the [cross]target1</div><div>     t2t_exe for the [cross]target2</div><div><br></div><div> c)  you seldomly compile the same source for the host AND the target, but it may happen.</div><div>  </div><div><div>And you want to build all that stuff with a single configure+build command AND take advantage</div><div>of fast and efficient parallel build for the **whole build**. I don't want to </div><div><br></div><div>cd /build/for/host</div><div>ninja</div><div>cd /build/for/target1</div><div>ninja</div><div>etc...</div><div><br></div></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"> Helpful would be a special <br>
variable for CMAKE_INSTALL_PREFIX as this needs a bit of attention (and <br>
a non-sysroot thing prefix in the toolchain file). Confused? Granted, <br>
here is an example:<br>
<br>
if (CMAKE_CROSSCOMPILING)<br>
     set(HOST_INSTALL_DIR "/some/where")<br>
     add_host_build(. host HOST_INSTALL_DIR)<br>
endif ()<br>
add_executable(magic magic.cpp)<br>
install(TARGETS magic DESTINATION bin) # installs both the host and the <br>
target tool!<br>
add_custom_command(OUTPUT ${CMAKE_CURRENT_BUILD_DIR}/foo.cpp COMMAND <br>
magic) # will call the host build<br>
if (NOT CMAKE_HOST_BUILD)<br>
     add_executable(foo ${CMAKE_CURRENT_BUILD_DIR}/foo.cpp)<br>
     install(TARGETS foo DESTINATION bin)<br>
endif ()<br></blockquote><div><br></div><div>I get your point but I think we may try a more declarative way.</div><div><br></div><div><div>add_executable(magic magic.cpp)</div><div>install(TARGETS magic DESTINATION bin)</div></div><div><div>add_custom_command(OUTPUT ${CMAKE_CURRENT_BUILD_DIR}/foo.cpp COMMAND magic)</div></div><div><div>add_executable(foo ${CMAKE_CURRENT_BUILD_DIR}/foo.cpp)</div><div>install(TARGETS foo DESTINATION bin)</div></div><div><br></div><div>set_target_properties(magic PROPERTIES BUILD_TARGET "host;cross_target1")</div><div>set_target_properties(foo PROPERTIES BUILD_TARGET "cross_target1")</div><div><br></div><div>after that we know that `magic` is to be built both for "host" and "cross_target1" whereas</div><div>`foo` is only for "cross_target1". </div><div><br></div><div>before that we may have to "declaratively" define what is cross_target1 (and may be cross_target2) with something like:</div><div><br></div><div>enable_cross_target(NAME cross_target1 TOOLCHAIN ${CMAKE_CURRENT_SOURCE _DIR}/cmake/target1-toolchain.cmake)</div><div>enable_cross_target(NAME cross_target2 TOOLCHAIN ${CMAKE_CURRENT_SOURCE _DIR}/cmake/target2-toolchain.cmake)<br></div><div>and assume "host" builtin target is the one coming from the command line.<br></div><div><br></div><div>each define_cross_target(..) will create a separate subdir in the build tree (much like CMAKE_CFG_INTDIR is working for multi-config generators)</div><div>may something like ${CMAKE_CURRENT_BINARY_DIR}/${CROSS_TARGET_NAME} if we assume cross target name are unique.</div><div><br></div><div>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</div><div>and/or cross target2 etc...</div><div><br></div><div>add_custom_command COMMAND argument refering to a built target </div><div>always refer to "host target" because there is usually no need (or mean) to execute cross target during the build anyway.</div><div><br></div><div>in the end you will have a project which specify all the target (exe, lib, custom) the usual declarative "modern CMake" way</div><div>and you won't have your CMakeLists.txt filled with </div><div><br></div><div>IF(CMAKE_CROSSCOMPILING) </div><div><br></div><div>IF(NOT CMAKE_HOST_BUILD)</div><div><br></div><div>controls.</div><div><br></div><div>if you need cross_target specific CMAKE_XXXX variables, they should either go in the target toolchain file </div><div>or should be put in with </div><div>cross_target_set(cross_target1 VARIABLE CMAKE_INSTALL_PREFIX "/opt/target1")<br></div><div><br></div><div>You may even decide that if a "build target" is not enabled because you have something like:</div><div><br></div><div>if (CROSS_BUILD_TARGET1)</div><div><div>   enable_cross_target(NAME cross_target1 TOOLCHAIN ${CMAKE_CURRENT_SOURCE _DIR}/cmake/target1-toolchain.cmake)</div><div>endif()</div><div><br></div><div>if (CROSS_BUILD_TARGET2)</div><div>   enable_cross_target(NAME cross_target2 TOOLCHAIN ${CMAKE_CURRENT_SOURCE _DIR}/cmake/target2-toolchain.cmake)</div></div><div>endif()</div><div><br></div><div>The build could succeed and emit some warning telling that some "cross target" were not built.</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
This should end up in a layout like this:<br>
<br>
/tmp/install/prefix/tools/bin/magic.exe # Windows host<br>
/tmp/install/prefix/sysroot/usr/bin/magic # Unix guest<br>
/tmp/install/prefix/sysroot/usr/bin/foo<br>
<br>
The toolchain file would look somehow like this:<br>
<br>
set(CMAKE_HOST_PREFIX prefix<br>
set(CMAKE_SYSROOT ${CMAKE_HOST_PREFIX}/sysroot)<br>
<br>
and the CMake command would look like this:<br>
<br>
cmake -D CMAKE_TOOLCHAIN_FILE=tc.cmake -D CMAKE_INSTALL_PREFIX=/usr -D <br>
CMAKE_HOST_INSTALL_PREFIX=tools ...<br></blockquote><div><br></div><div>I think that most of the time specifying the toolchain on the command line drives you to some superbuild structure.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
The wish-season is coming up, so that's sort of what I would like to <br>
have. Now it's your turn. No bikeshedding please, only deliveries ;)<br></blockquote><div><br></div><div>I wish an integrated multi-target cross building support in CMake with little or no flow-control scripting command in the CMakeLists.txt. </div><div><br></div></div>-- <br><div dir="ltr" class="gmail_signature"><div dir="ltr"><div><div dir="ltr"><div>Eric<br></div></div></div></div></div></div></div></div></div></div></div></div></div></div>