[CMake] [HOWTO] Easily Cross-Compile CMake (with xstatic)

Rolf Eike Beer eike at sf-mail.de
Fri Oct 26 15:48:21 EDT 2018


Zach van Rijn wrote:
> On Fri, 2018-10-26 at 11:09 +0200, Rolf Eike Beer wrote:
> > ...
> 
> Hi Eike,
> 
> Thank you for writing. I agree that my approach is a bit brutish
> and aim to revise/reduce it to a minimum example. My goal was to
> describe a process that is uniform between compilers, easily
> automated, and less likely to break between CMake releases.
> 
> > So, the 2 things that I do not understand why you need them at
> > all:
> > 
> > -why do the bootstrap thing and move compilers? Just build a
> > recent CMake with your host toolchain, package that, and drop
> > it into the build container. The need for the host compiler
> > should be gone at this point
> 
> While it would make sense to build a complete (sufficiently-
> recent) CMake that performs the final build, I have not had
> consistent success (using the same exact compilers and systems)
> in doing so. For example, even specifying all of the settings as
> in your 'toolchain.cmake' file (below in this email), omitting
> the 'CMAKE_SYSTEM_NAME=Linux' part:
> 
> ...
> cmake-3.12.3/Utilities/cmcurl/lib/strerror.c:32:6: error: #error
> "strerror_r MUST be either POSIX, glibc or vxworks-style"
> ...

That's exactly what I meant with:

> > Well, it did not, but that was just because the embedded curl tries to do
> > some try_run() things that do not work. Since I already have a cross-curl
> > library at hand I decided to just use that, and things worked.

> and the build fatally aborts. If we add this back,
> 
> ...
> CMake Error: TRY_RUN() invoked in cross-compiling mode, please
> set the following cache variables appropriately:
> ...

You can instead just pass the expected codes, you just have to pass them as 
cache variables using "-C cache_file".

> # In an empty 'build/' directory in the root of CMake source:
> 
> $ cmake ..                                                     \
>     -DCMAKE_SYSTEM_NAME=Linux                                  \
>     -DCMAKE_C_COMPILER=/bin/gcc                      `# cross` \
>     -DCMAKE_C_FLAGS="-static --static -g0 -s -Os"              \
>     -DCMAKE_CXX_COMPILER=/bin/g++                    `# cross` \
>     -DCMAKE_CXX_FLAGS="-static --static -g0 -s -Os"            \
>     -DCMAKE_FIND_ROOT_PATH=/armv7l-linux-musleabihf  `# cross` \
>     -DCMAKE_SYSROOT=/armv7l-linux-musleabihf         `# cross` \
>     -DCMAKE_FIND_ROOT_PATH_MODE_PROGRAM=NEVER                  \
>     -DCMAKE_FIND_ROOT_PATH_MODE_LIBRARY=ONLY                   \
>     -DCMAKE_FIND_ROOT_PATH_MODE_INCLUDE=ONLY                   \
>     -DCMAKE_FIND_ROOT_PATH_MODE_PACKAGE=ONLY                   \
>     -DKWSYS_LFS_WORKS=ON                                       \
>     -DKWSYS_LFS_WORKS__TRYRUN_OUTPUT=""                        \
>     -DHAVE_FSETXATTR_5=ON                                      \
>     -DHAVE_FSETXATTR_5__TRYRUN_OUTPUT=""                       \
>     -DHAVE_GLIBC_STRERROR_R=OFF               `# because musl` \
>     -DHAVE_GLIBC_STRERROR_R__TRYRUN_OUTPUT=""                  \
>     -DHAVE_POSIX_STRERROR_R=ON                `# because musl` \
>     -DHAVE_POSIX_STRERROR_R__TRYRUN_OUTPUT=""                  \
>     -DHAVE_POLL_FINE_EXITCODE=ON                               \
>     -DHAVE_POLL_FINE_EXITCODE__TRYRUN_OUTPUT=""
> 
> ...
> CMake Warning:
>   Manually-specified variables were not used by the project:
> 
>     KWSYS_LFS_WORKS__TRYRUN_OUTPUT

You need to pass things like CMAKE_SYSTEM_NAME in the toolchain file in order 
to get the cross-build mode properly initialized, passing them on the 
commandline is not enough.

> Specifically because it would either require defining all of the
> above variables, including toolchain path(s), or running some
> sort of script or command like 'sed' to attempt to replace all
> hard-coded occurrences of the original toolchain. You can see
> that there are many:

No, you start in a clean build directory and pass the initial CMake invocation 
the toolchain file with -D CMAKE_TOOLCHAIN_FILE=toolchain-arm.cmake. CMake 
will then know only this compiler, and will find the other programs using the 
same triplet. Have one build dir per target, and one toolchain file per 
target. Maybe it's only one toolchain file that you need, when they differ 
only in the target triplet, which can then be placed e.g. in an environment 
variable before the first build.

> In summary, while I agree my original method could be
> simplified, I propose it for the following reasons:
> 
> (1) Avoid building two full CMake binaries (one for build system
>     and one for target host system)

You do, bootstrapping builds a CMake binary. Not a full-featured one, but 
still. And you can reuse them for every target.

> (2) Avoid breakage between CMake versions, if new tests are
>     are added, as script automation would become difficult

These should not differ between patch releases, and the differences between 
minor versions should also be pretty minimal.

> (3) As an alternative to the "standard" approach which you
>     mention, as some users may have difficulty in determining
>     exactly how to populate these variables.

"-C"

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/attachments/20181026/c8deb058/attachment.sig>


More information about the CMake mailing list