From 79b94624686bdf43a0518d6be7d5ad0e0274c0d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Thalheim?= Date: Tue, 20 Nov 2018 09:39:20 +0000 Subject: [PATCH] go_1_11: fix cross compilation --- pkgs/development/compilers/go/1.11.nix | 120 ++++++++++++------ .../go-modules/generic/default.nix | 19 ++- pkgs/top-level/all-packages.nix | 6 +- 3 files changed, 100 insertions(+), 45 deletions(-) diff --git a/pkgs/development/compilers/go/1.11.nix b/pkgs/development/compilers/go/1.11.nix index b1a26b2218d6..2f078abdb9aa 100644 --- a/pkgs/development/compilers/go/1.11.nix +++ b/pkgs/development/compilers/go/1.11.nix @@ -1,5 +1,6 @@ { stdenv, fetchFromGitHub, tzdata, iana-etc, go_bootstrap, runCommand, writeScriptBin -, perl, which, pkgconfig, patch, procps, pcre, cacert, llvm, Security, Foundation }: +, perl, which, pkgconfig, patch, procps, pcre, cacert, llvm, Security, Foundation +, buildPackages, targetPackages }: let @@ -7,12 +8,22 @@ let goBootstrap = runCommand "go-bootstrap" {} '' mkdir $out - cp -rf ${go_bootstrap}/* $out/ + cp -rf ${buildPackages.go_bootstrap}/* $out/ chmod -R u+w $out find $out -name "*.c" -delete cp -rf $out/bin/* $out/share/go/bin/ ''; + goarch = platform: { + "i686" = "386"; + "x86_64" = "amd64"; + "aarch64" = "arm64"; + "arm" = "arm"; + "armv5tel" = "arm"; + "armv6l" = "arm"; + "armv7l" = "arm"; + }.${platform.parsed.cpu.name} or (throw "Unsupported system"); + in stdenv.mkDerivation rec { @@ -26,13 +37,13 @@ stdenv.mkDerivation rec { sha256 = "0pk7pxfm3ij2ksdrg49jz501fr1d103zr4mjjwv821if9g279jc9"; }; - GOCACHE = "off"; - # perl is used for testing go vet nativeBuildInputs = [ perl which pkgconfig patch procps ]; buildInputs = [ cacert pcre ] ++ optionals stdenv.isLinux [ stdenv.cc.libc.out ] ++ optionals (stdenv.hostPlatform.libc == "glibc") [ stdenv.cc.libc.static ]; + + propagatedBuildInputs = optionals stdenv.isDarwin [ Security Foundation ]; hardeningDisable = [ "all" ]; @@ -126,62 +137,93 @@ stdenv.mkDerivation rec { substituteInPlace "src/cmd/link/internal/ld/lib.go" --replace dsymutil ${llvm}/bin/llvm-dsymutil ''; - GOOS = stdenv.hostPlatform.parsed.kernel.name; - GOARCH = { - "i686" = "386"; - "x86_64" = "amd64"; - "aarch64" = "arm64"; - "arm" = "arm"; - "armv5tel" = "arm"; - "armv6l" = "arm"; - "armv7l" = "arm"; - }.${stdenv.hostPlatform.parsed.cpu.name} or (throw "Unsupported system"); + GOOS = stdenv.targetPlatform.parsed.kernel.name; + GOARCH = goarch stdenv.targetPlatform; + # GOHOSTOS/GOHOSTARCH must match the building system, not the host system. + # Go will nevertheless build a for host system that we will copy over in + # the install phase. + GOHOSTOS = stdenv.buildPlatform.parsed.kernel.name; + GOHOSTARCH = goarch stdenv.buildPlatform; + + # {CC,CXX}_FOR_TARGET must be only set for cross compilation case as go expect those + # to be different from CC/CXX + CC_FOR_TARGET = if (stdenv.hostPlatform != stdenv.targetPlatform) then + "${targetPackages.stdenv.cc}/bin/${targetPackages.stdenv.cc.targetPrefix}cc" + else if (stdenv.buildPlatform != stdenv.targetPlatform) then + "${stdenv.cc.targetPrefix}cc" + else + null; + CXX_FOR_TARGET = if (stdenv.hostPlatform != stdenv.targetPlatform) then + "${targetPackages.stdenv.cc}/bin/${targetPackages.stdenv.cc.targetPrefix}c++" + else if (stdenv.buildPlatform != stdenv.targetPlatform) then + "${stdenv.cc.targetPrefix}c++" + else + null; + GOARM = toString (stdenv.lib.intersectLists [(stdenv.hostPlatform.parsed.cpu.version or "")] ["5" "6" "7"]); GO386 = 387; # from Arch: don't assume sse2 on i686 CGO_ENABLED = 1; - GOROOT_BOOTSTRAP = "${goBootstrap}/share/go"; # Hopefully avoids test timeouts on Hydra GO_TEST_TIMEOUT_SCALE = 3; - # The go build actually checks for CC=*/clang and does something different, so we don't - # just want the generic `cc` here. - CC = if stdenv.isDarwin then "clang" else "cc"; + # Indicate that we are running on build infrastructure + # Some tests assume things like home directories and users exists + GO_BUILDER_NAME = "nix"; - configurePhase = '' - # Indicate that we are running on build infrastructure - # Some tests assume things like home directories and users exists - export GO_BUILDER_NAME=nix + GOROOT_BOOTSTRAP="${goBootstrap}/share/go"; - mkdir -p $out/share/go/bin - export GOROOT=$out/share/go - export GOBIN=$GOROOT/bin - export PATH=$GOBIN:$PATH + postConfigure = '' + export GOCACHE=$TMPDIR/go-cache + # this is compiled into the binary + export GOROOT_FINAL=$out/share/go + + export PATH=$(pwd)/bin:$PATH + + # Independent from host/target, CC should produce code for the building system. + export CC=${buildPackages.stdenv.cc}/bin/cc ulimit -a ''; - installPhase = '' - runHook preInstall - cp -r . $GOROOT - ( cd $GOROOT/src && ./make.bash ) - runHook postInstall + postBuild = '' + (cd src && ./make.bash) ''; - doInstallCheck = true; - installCheckPhase = '' + doCheck = stdenv.hostPlatform == stdenv.targetPlatform; + + checkPhase = '' runHook preCheck - ( cd $GOROOT/src && ./run.bash --no-rebuild) + (cd src && ./run.bash --no-rebuild) runHook postCheck ''; - preFixup = '' - rm -r $out/share/go/pkg/bootstrap - rm -r $out/share/go/pkg/obj - ln -s $out/share/go/bin $out/bin + preInstall = '' + # Contains the wrong perl shebang when cross compiling, + # since it is not used for anything we can deleted as well. + rm src/regexp/syntax/make_perl_groups.pl + '' + (if (stdenv.buildPlatform != stdenv.hostPlatform) then '' + mv bin/*_*/* bin + rmdir bin/*_* + ${optionalString (!(GOHOSTARCH == GOARCH && GOOS == GOHOSTOS)) '' + rm -rf pkg/${GOHOSTOS}_${GOHOSTARCH} pkg/tool/${GOHOSTOS}_${GOHOSTARCH} + ''} + '' else if (stdenv.hostPlatform != stdenv.targetPlatform) then '' + rm -rf bin/*_* + ${optionalString (!(GOHOSTARCH == GOARCH && GOOS == GOHOSTOS)) '' + rm -rf pkg/${GOOS}_${GOARCH} pkg/tool/${GOOS}_${GOARCH} + ''} + '' else ""); + + installPhase = '' + runHook preInstall + mkdir -p $GOROOT_FINAL + cp -a bin pkg src lib misc api doc $GOROOT_FINAL + ln -s $GOROOT_FINAL/bin $out/bin + runHook postInstall ''; setupHook = ./setup-hook.sh; - disallowedReferences = [ go_bootstrap ]; + disallowedReferences = [ goBootstrap ]; meta = with stdenv.lib; { branch = "1.11"; diff --git a/pkgs/development/go-modules/generic/default.nix b/pkgs/development/go-modules/generic/default.nix index deebba5cfec8..6af5f72f2b73 100644 --- a/pkgs/development/go-modules/generic/default.nix +++ b/pkgs/development/go-modules/generic/default.nix @@ -1,5 +1,5 @@ { go, govers, lib, fetchgit, fetchhg, fetchbzr, rsync -, removeReferencesTo, fetchFromGitHub }: +, removeReferencesTo, fetchFromGitHub, stdenv }: { name, buildInputs ? [], nativeBuildInputs ? [], passthru ? {}, preFixup ? "" , shellHook ? "" @@ -80,7 +80,9 @@ go.stdenv.mkDerivation ( inherit name; nativeBuildInputs = [ removeReferencesTo go ] ++ (lib.optional (!dontRenameImports) govers) ++ nativeBuildInputs; - buildInputs = [ go ] ++ buildInputs; + buildInputs = buildInputs; + + inherit (go) GOOS GOARCH; configurePhase = args.configurePhase or '' runHook preConfigure @@ -167,7 +169,18 @@ go.stdenv.mkDerivation ( export NIX_BUILD_CORES=1 fi getGoDirs "" | xargs -n1 -P $NIX_BUILD_CORES bash -c 'buildGoDir install "$@"' -- - + '' + lib.optionalString (stdenv.hostPlatform != stdenv.buildPlatform) '' + # normalize cross-compiled builds w.r.t. native builds + ( + dir=$NIX_BUILD_TOP/go/bin/${go.GOOS}_${go.GOARCH} + if [[ -n "$(shopt -s nullglob; echo $dir/*)" ]]; then + mv $dir/* $dir/.. + fi + if [[ -d $dir ]]; then + rmdir $dir + fi + ) + '' + '' runHook postBuild ''; diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index b9bd6b1f5baa..78478a889bd4 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -13024,13 +13024,13 @@ with pkgs; ### DEVELOPMENT / GO MODULES buildGo19Package = callPackage ../development/go-modules/generic { - go = go_1_9; + go = buildPackages.go_1_9; }; buildGo110Package = callPackage ../development/go-modules/generic { - go = go_1_10; + go = buildPackages.go_1_10; }; buildGo111Package = callPackage ../development/go-modules/generic { - go = go_1_11; + go = buildPackages.go_1_11; }; buildGoPackage = buildGo111Package;