cross: add crossdirect package (!222)
A set of wrapper executables that launch native cross compilers inside foreign chroots. Speeds up cross compilation a lot, compared to the distcc-sshd method.
This commit is contained in:
parent
0d966c7a6f
commit
68c1d5d2bd
2 changed files with 137 additions and 0 deletions
60
cross/crossdirect/APKBUILD
Normal file
60
cross/crossdirect/APKBUILD
Normal file
|
@ -0,0 +1,60 @@
|
|||
# Wrapper for the "crossdirect" compilation method.
|
||||
# pmbootstrap mounts the native chroot in the foreign arch (e.g. armhf) chroot
|
||||
# as /native. This package gets installed into the native chroot, and creates
|
||||
# wrappers like:
|
||||
#
|
||||
# /native/usr/lib/crossdirect/armhf/gcc
|
||||
# -> /native/usr/bin/armv6-alpine-linux-muslgnueabihf-gcc
|
||||
#
|
||||
# When building packages in the armhf chroot, PATH will get prepended with
|
||||
# "/native/usr/lib/crossdirect/armhf". The end game is of course invoking the
|
||||
# cross compiler from the native chroot, running at native speed, whenever
|
||||
# calling the compiler from the foreign arch chroot. See crossdirect.c for
|
||||
# implementation details (llvm, fakeroot, rpath).
|
||||
|
||||
pkgname=crossdirect
|
||||
pkgver=1
|
||||
pkgrel=0
|
||||
pkgdesc="Wrappers to launch native cross compilers in foreign chroots"
|
||||
url="https://postmarketOS.org"
|
||||
arch="all"
|
||||
license="MIT"
|
||||
options=""
|
||||
source="crossdirect.c"
|
||||
|
||||
build() {
|
||||
cd "$srcdir"
|
||||
# Architectures and binaries
|
||||
_archs="x86_64 armhf armv7 aarch64"
|
||||
for _arch in $_archs; do
|
||||
[ "$_arch" == "$CARCH" ] && continue
|
||||
_hostspec="$(arch_to_hostspec $_arch)"
|
||||
$CC -o "crossdirect-$_arch" -static -DHOSTSPEC="\"$_hostspec\"" \
|
||||
crossdirect.c
|
||||
done
|
||||
}
|
||||
|
||||
package() {
|
||||
# Architectures and binaries
|
||||
_archs="x86_64 armhf armv7 aarch64"
|
||||
_bins="c++ cc cpp g++ gcc clang clang++"
|
||||
|
||||
# Iterate over architectures
|
||||
for _arch in $_archs; do
|
||||
[ "$_arch" == "$CARCH" ] && continue
|
||||
|
||||
# Put arch-specific crossdirect wrapper in arch-specific bin folder
|
||||
_bindir="$pkgdir/usr/lib/crossdirect/$_arch"
|
||||
_hostspec="$(arch_to_hostspec $_arch)"
|
||||
mkdir -p "$_bindir"
|
||||
cd "$_bindir"
|
||||
cp "$srcdir/crossdirect-$_arch" "./"
|
||||
|
||||
# Create compiler symlinks
|
||||
for _bin in $_bins; do
|
||||
ln -s "crossdirect-$_arch" "$_bin"
|
||||
ln -s "crossdirect-$_arch" "$_hostspec-$_bin"
|
||||
done
|
||||
done
|
||||
}
|
||||
sha512sums="12801031928103bd898a0d54a5c68b33da9bded10a3d145fdf5ce8b70eb0bbbcdd50764279004b6997d85d710fa581dc8b05aa5e0eb62d50c1054cc6d66db87f crossdirect.c"
|
77
cross/crossdirect/crossdirect.c
Normal file
77
cross/crossdirect/crossdirect.c
Normal file
|
@ -0,0 +1,77 @@
|
|||
// HOSTSPEC is defined at compile time, see APKBUILD
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <libgen.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <unistd.h>
|
||||
|
||||
void exit_userfriendly() {
|
||||
fprintf(stderr, "Please report this at: https://gitlab.com/postmarketOS/pmaports/issues\n");
|
||||
fprintf(stderr, "As a workaround, you can compile without crossdirect.\n");
|
||||
fprintf(stderr, "See 'pmbootstrap -h' for related options.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
// we have a max of four extra args ("-target", "HOSTSPEC", "--sysroot=/", "-Wl,-rpath-link=/lib:/usr/lib"), plus one ending null
|
||||
char* newargv[argc + 5];
|
||||
char* executableName = basename(argv[0]);
|
||||
char newExecutable[PATH_MAX];
|
||||
bool isClang = (strcmp(executableName, "clang") == 0 || strcmp(executableName, "clang++") == 0);
|
||||
bool startsWithHostSpec = (strncmp(HOSTSPEC, executableName, sizeof(HOSTSPEC) -1) == 0);
|
||||
|
||||
if (isClang || startsWithHostSpec) {
|
||||
snprintf(newExecutable, sizeof(newExecutable), "/native/usr/bin/%s", executableName);
|
||||
} else {
|
||||
snprintf(newExecutable, sizeof(newExecutable), "/native/usr/bin/" HOSTSPEC "-%s", executableName);
|
||||
}
|
||||
|
||||
char** newArgsPtr = newargv;
|
||||
*newArgsPtr++ = newExecutable;
|
||||
if (isClang) {
|
||||
*newArgsPtr++ = "-target";
|
||||
*newArgsPtr++ = HOSTSPEC;
|
||||
}
|
||||
*newArgsPtr++ = "--sysroot=/";
|
||||
bool addrpath = true;
|
||||
if (isClang) {
|
||||
// clang gives a warning if the rpath parameter is passed when linker isn't invoked.
|
||||
// to avoid this warning, only add if we're actually linking at least one library.
|
||||
addrpath = false;
|
||||
for (int i = 1; i < argc; i++) {
|
||||
char* arg = argv[i];
|
||||
if (strlen(arg) >= 2 && arg[0] == '-' && arg[1] == 'l') {
|
||||
addrpath = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (addrpath) {
|
||||
*newArgsPtr++ = "-Wl,-rpath-link=/lib:/usr/lib";
|
||||
}
|
||||
memcpy(newArgsPtr, argv + 1, sizeof(char*)*(argc - 1));
|
||||
newArgsPtr += (argc - 1);
|
||||
*newArgsPtr = NULL;
|
||||
|
||||
// new arguments prepared; now setup environmental vars
|
||||
setenv("LD_LIBRARY_PATH", "/native/lib:/native/usr/lib", true);
|
||||
char* ldPreload = getenv("LD_PRELOAD");
|
||||
if (ldPreload) {
|
||||
if (strcmp(ldPreload, "/usr/lib/libfakeroot.so") == 0) {
|
||||
setenv("LD_PRELOAD", "/native/usr/lib/libfakeroot.so", true);
|
||||
} else {
|
||||
fprintf(stderr, "ERROR: crossdirect: can't handle LD_PRELOAD: %s\n", ldPreload);
|
||||
exit_userfriendly();
|
||||
}
|
||||
}
|
||||
|
||||
if (execv(newExecutable, newargv) == -1) {
|
||||
fprintf(stderr, "ERROR: crossdirect: failed to execute %s: %s\n", newExecutable, strerror(errno));
|
||||
exit_userfriendly();
|
||||
}
|
||||
return 1;
|
||||
}
|
Loading…
Reference in a new issue