pkgsrc-Users archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Cross-buliding rust


on and off, "because it's there", I've been working on getting rust
running on NetBSD/macppc.

The normal route to build rust is to start from a "bootstrap kit"
which is a binary (possibly an earlier version) of rust, as larger
parts of the compiler is written in rust.

However, to build rust for a "new" OS/arch combination (such as any of
the NetBSD powerpc ports) requires doing a cross-build.  Internally
rust has a copy of llvm embedded, and llvm is already able to generate
powerpc code.  Additionally, the NetBSD/powerpc support was already
added to rust, I beleive primarily via this pull request:

So, after quite a few trial and error attempts (more about the
failures I hit and how they were worked around below), these are the
steps to repeat the cross-build:

1) You need a full build of tools and user-land for the target
   platform.  This is most easily produced by our script,
   building a full release.  The setup I used assumes that you'll keep
   the tools/ and dest/ directories under a common root.

   Uncomment these parts of lang/rust/Makefile and modify to suit
   where this common root is:

   #CROSS_ROOT=            /u/macppc
   #MAKE_ENV+=             CROSS_ROOT=${CROSS_ROOT}

2) Tell the wrapper script used to run the cross-compiler which GNU
   target it's supposed to build for.  This is part of the "tools"
   binary names:

   #GNU_CROSS_TARGET=      powerpc--netbsd

3) You need to tell rust the "triplet" for your target, and to use a
   wrapper script to run the cross-compiler.  You need to instruct
   rust to build a compiler to be run on the target ("host") as well
   as include code generation for the intended run-time target
   ("target").  Uncomment:

   #TARGET=                powerpc-unknown-netbsd
   #CONFIGURE_ARGS+=       --host=${TARGET}
   #CONFIGURE_ARGS+=       --target=${TARGET}
   #CONFIGURE_ARGS+=       --set=target.${TARGET}.cc=${.CURDIR}/files/gcc-wrap
   #CONFIGURE_ARGS+=       --set=target.${TARGET}.cxx=${.CURDIR}/files/c++-wrap
   #CONFIGURE_ARGS+=       --set=target.${TARGET}.linker=${.CURDIR}/files/gcc-wrap
   #CONFIGURE_ARGS+=       --set=target.${TARGET}.ar=${CROSS_ROOT}/tools/bin/${GNU_CROSS_TARGET}-ar

4) You need to instruct rust where openssl can be found, uncomment:

   #MAKE_ENV+=             OPENSSL_DIR=/usr

5) The rust build wants to use the target binaries from the
   http-parser package.  You need to ensure that package's contents
   (for the target) is installed in ${CROSS_ROOT}/usr/pkg.

6) The rust build wants to use libssh2.  Not only that, but it
   actually wants to use a bug-fixed non-formally-released version of
   libssh2.  It has a copy of the source embedded within itself, and
   it builds it, but there is an undiagnosed error in the build
   causing libssh2.a to be built but not found during the subsequent
   use of it, as it's not installed in the internal directory where it
   is apparently supposed to be found during linking.

   I beleive I've only seen this when building natively on
   NetBSD/macppc so you may not need to consder this when
   cross-building.  My native build machine has a copy of libssh2.a
   sitting in its /usr/lib (from the rust build, not from the

7) If you have llvm installed already, perhaps an earlier version
   (e.g. llvm 5.*) you need to deinstall it, otherwise the wrong
   include files will be used.

With that you should be set to cross-build a rust bootstrap by simply
doing "make" in the lang/rust package.  The result will be found in
${WRKSRC}/build/dist/, the files needed are (in my case)


Below follows a summary of the various build errors I experienced and
which gave riste to the various points above:

A) "dead lock detected".  This is an error message from our ld.elf_so
and which might occur if you run the cross build on a multiprocessor,
as the rust compiler will by default try to use all you cores (i.e.
runs threaded) and apparently *sometimes* does an operation our run-
time linker disapproves of.  The root cause has yet to be diagnosed.

Workaround: restart the build.

B) If you have an earlier llvm package (for the moment e.g. 5.0.0)
installed, you might hit

cargo:warning=../rustllvm/PassWrapper.cpp: In function 'void LLVMRustPrintTargetCPUs(LLVMTargetMachineRef)':
cargo:warning=../rustllvm/PassWrapper.cpp:314:57: error: 'const class llvm::MCSubtargetInfo' has no member named 'getCPUTable'
cargo:warning=   const ArrayRef<SubtargetFeatureKV> CPUTable = MCInfo->getCPUTable();
cargo:warning=                                                         ^
cargo:warning=../rustllvm/PassWrapper.cpp: In function 'void LLVMRustPrintTargetFeatures(LLVMTargetMachineRef)':
cargo:warning=../rustllvm/PassWrapper.cpp:331:58: error: 'const class llvm::MCSubtargetInfo' has no member named 'getFeatureTable'
cargo:warning=   const ArrayRef<SubtargetFeatureKV> FeatTable = MCInfo->getFeatureTable();
cargo:warning=                                                          ^
exit code: 1

Fix: deinstall the llvm package, restart the build.

C) If you didn't point OPENSSL_DIR correctly, you might hit

   Compiling openssl-sys v0.9.28
error: failed to run custom build command for `openssl-sys v0.9.28`
process didn't exit successfully: `/usr/pkgsrc/lang/rust/work/rustc-1.28.0-src/build/x86_64-unknown-netbsd/stage2-tools/release/build/openssl-sys-720f6e16fbe661b9/build-script-build` (exit code: 101)
--- stdout
run pkg_config fail: "Cross compilation detected. Use PKG_CONFIG_ALLOW_CROSS=1 to override"

Fix: Point OPENSSL_DIR=/usr and use the sysroot of your target, as is
done by the gcc-wrap script.

D) If you don't use the gcc-wrap script, and don't redirect the
includes to use the target's include files, you might hit:

/var/tmp//cctsAmmO.s: Assembler messages:
/var/tmp//cctsAmmO.s:123: Error: unrecognized opcode: `rorw'
/var/tmp//cctsAmmO.s:1511: Error: unrecognized opcode: `rorw'
/var/tmp//cctsAmmO.s:1561: Error: unrecognized opcode: `rorw'
/var/tmp//cctsAmmO.s:1705: Error: unrecognized opcode: `rorw'
/var/tmp//cctsAmmO.s:1767: Error: unrecognized opcode: `rorw'

This is caused by the compiler picking up native include files with
inline assembly of the build host.  Not what you want.

Fix: use the gcc-wrap script, pointing includes into your target's

E) Failure to install the http-parser package in the target destdir
might lead to this build failure:

CMakeFiles/Makefile2:87: recipe for target 'src/CMakeFiles/git2internal.dir/all' failed
Makefile:129: recipe for target 'all' failed

--- stderr
fatal: not a git repository (or any of the parent directories): .git
CMake Warning:
  Manually-specified variables were not used by the project:


/usr/pkgsrc/lang/rust/work/rustc-1.28.0-src/src/vendor/libgit2-sys/libgit2/src/netops.c:15:25: fatal error: http_parser.h: No such file or directory
compilation terminated.

Fix: install the http-parser package (binary for the target, of
course) in the target's destdir's usr/pkg/.

F) Failure to point library searching into the target's destdir might
result in attempts at linking the build host's libraries into the
target binaries, which won't work, obviously:

  = note: /u/macppc/tools/lib/gcc/powerpc--netbsd/5.5.0/../../../../powerpc--netbsd/bin/ld: cannot find -lhttp_parser
          /u/macppc/tools/lib/gcc/powerpc--netbsd/5.5.0/../../../../powerpc--netbsd/bin/ld: skipping incompatible /usr/lib/ when searching for -lssl
          /u/macppc/tools/lib/gcc/powerpc--netbsd/5.5.0/../../../../powerpc--netbsd/bin/ld: skipping incompatible /usr/lib/libssl.a when searching for -lssl
          /u/macppc/tools/lib/gcc/powerpc--netbsd/5.5.0/../../../../powerpc--netbsd/bin/ld: skipping incompatible /usr/lib/ when searching for -lcrypto


Fix: Use the gcc-wrap script also for linking; it will instruct the
linker to search the target's destdir for libraries.

G) Failure to find the http_parser library:

  = note: /u/macppc/tools/lib/gcc/powerpc--netbsd/5.5.0/../../../../powerpc--netbsd/bin/ld: cannot find -lhttp_parser
          collect2: error: ld returned 1 exit status

Fix: as above for E), install the http-parser package for the target
in in the target destdir's usr/pkg/.

The above are all errors experienced while cross building, I also hit
a few snags using the initial bootstrap kit on the target:

H) Initially, had an undefined symbol

error: couldn't load codegen backend "/usr/pkgsrc/lang/rust/work/rust-bootstrap/lib/rustlib/powerpc-unknown-netbsd/codegen-backends/": "/usr/pkgsrc/lang/rust/work/rust-bootstrap/lib/rustlib/powerpc-unknown-netbsd/codegen-backends/ Undefined PLT symbol \"backtrace\" (symnum = 23441)"

Fix: now causes -lexecinfo to be included
when linking rust -- thanks to Ryo for the patch.  (I've not figured
out why this wasn't a problem for NetBSD/amd64.)

I) The build didn't know what "macppc" was:

unknown cpu type: macppc

Fix: now has code to use `uname -p`
on NetBSD, since `uname -p` is reasonably reliable on NetBSD, at least
in comparison to others...

J) You might get a build error compiling the furst rust file, similar
to this:

   Compiling serde v1.0.70
Expected no forward declarations!
!537 = <temporary!> !{}
scope points into the type hierarchy
!538 = !DILocation(line: 1394, scope: !534)
LLVM ERROR: Broken function found, compilation aborted!
error: Could not compile `serde`.

I got a hint on rustc's IRC channel that this might be related the
generation of debug information.

Fix: This is the various --disable-debug* options which will be
supplied on NetBSD/powerpc and also resulted in the -Cdebuginfo=0
setting of RUSTFLAGS in  Admittedly
the latter could perhaps be made conditional on NetBSD/powerpc, but
isn't at the moment.

K) You might experience error related to the build of libssh2-sys:

error: could not find native static library `ssh2`, perhaps an -L flag is missing?

error: aborting due to previous error

error: Could not compile `libssh2-sys`.

This is the same error as mentioned above in 6).

Fix: I did (somewhat cheesily, I have yet to find a proper fix):

find work/rustc* -name libssh2.a
cp <where-it-was-found> /usr/lib

L) The build of XZ Utils 5.2.3 might fail with

checking for ld used by /usr/pkgsrc/lang/rust/files/gcc-wrap... no

Fix: If, for diagnostic purposes, you need to echo the compiler
invocation command, echo it to stderr, not stdout, so that "gcc-wrap
-print-prog-name=ld" can work as intended and not include spurious
output.  (The gcc-wrap has this info in a comment prior to the
commented-out correct echo command.)

M) You may hit the error from B) also when running on the target.

Fix: deinstall the llvm package.

Best regards,

- Håvard

Home | Main Index | Thread Index | Old Index