From 56592ea2933c3ee837e28f593191924748db3142 Mon Sep 17 00:00:00 2001 From: Emery Hemingway Date: Fri, 5 Mar 2021 15:00:03 +0100 Subject: [PATCH] nim: cross-compilation fixes * Import with callPackages * Use buildPackages for building a cross-compiler * Patch-out potential conflicts in nim.cfg * Generate a configuration with toolchain detection * Build with strictDeps enabled --- pkgs/development/compilers/nim/default.nix | 382 ++++++++++-------- pkgs/development/compilers/nim/nim.cfg.patch | 70 ++++ .../development/tools/misc/nimlsp/default.nix | 2 +- pkgs/top-level/all-packages.nix | 5 +- 4 files changed, 285 insertions(+), 174 deletions(-) create mode 100644 pkgs/development/compilers/nim/nim.cfg.patch diff --git a/pkgs/development/compilers/nim/default.nix b/pkgs/development/compilers/nim/default.nix index 75b1a0f0020..676e35b06bb 100644 --- a/pkgs/development/compilers/nim/default.nix +++ b/pkgs/development/compilers/nim/default.nix @@ -1,22 +1,10 @@ # https://nim-lang.github.io/Nim/packaging.html +# https://nim-lang.org/docs/nimc.html -{ stdenv, lib, fetchurl, fetchgit, fetchFromGitHub, makeWrapper, gdb, openssl -, pcre, readline, boehmgc, sqlite, nim-unwrapped, nimble-unwrapped }: +{ lib, buildPackages, stdenv, fetchurl, fetchgit, fetchFromGitHub, makeWrapper +, openssl, pcre, readline, boehmgc, sqlite, nim-unwrapped }: let - version = "1.4.4"; - src = fetchurl { - url = "https://nim-lang.org/download/nim-${version}.tar.xz"; - sha256 = "03k642nnjca0s6jlbn1v4jld51mbkix97jli4ky74gqlxyfp4wvd"; - }; - - meta = with lib; { - description = "Statically typed, imperative programming language"; - homepage = "https://nim-lang.org/"; - license = licenses.mit; - maintainers = with maintainers; [ ehmry ]; - }; - parseCpu = platform: with platform; # Derive a Nim CPU identifier @@ -83,197 +71,251 @@ let nimHost = parsePlatform stdenv.hostPlatform; nimTarget = parsePlatform stdenv.targetPlatform; - wrapperInputs = rec { + bootstrapCompiler = stdenv.mkDerivation rec { + pname = "nim-bootstrap"; + version = "0.20.0"; - bootstrap = stdenv.mkDerivation rec { - pname = "nim-bootstrap"; - version = "0.20.0"; - - src = fetchgit { - # A Git checkout is much smaller than a GitHub tarball. - url = "https://github.com/nim-lang/csources.git"; - rev = "v" + version; - sha256 = "0i6vsfy1sgapx43n226q8m0pvn159sw2mhp50zm3hhb9zfijanis"; - }; - - enableParallelBuilding = true; - - installPhase = '' - runHook preInstall - install -Dt $out/bin bin/nim - runHook postInstall - ''; + src = fetchgit { + # A Git checkout is much smaller than a GitHub tarball. + url = "https://github.com/nim-lang/csources.git"; + rev = "v${version}"; + sha256 = "0i6vsfy1sgapx43n226q8m0pvn159sw2mhp50zm3hhb9zfijanis"; }; - unwrapped = stdenv.mkDerivation { - pname = "nim-unwrapped"; - inherit version src; - - buildInputs = [ boehmgc openssl pcre readline sqlite ]; - - patches = [ - ./NIM_CONFIG_DIR.patch - # Override compiler configuration via an environmental variable - - ./nixbuild.patch - # Load libraries at runtime by absolute path - ]; - - configurePhase = '' - runHook preConfigure - cp ${bootstrap}/bin/nim bin/ - echo 'define:nixbuild' >> config/nim.cfg - runHook postConfigure - ''; - - kochArgs = [ - "--cpu:${nimHost.cpu}" - "--os:${nimHost.os}" - "-d:release" - "-d:useGnuReadline" - ] ++ lib.optional (stdenv.isDarwin || stdenv.isLinux) - "-d:nativeStacktrace"; - - buildPhase = '' - runHook preBuild - local HOME=$TMPDIR - ./bin/nim c koch - ./koch boot $kochArgs --parallelBuild:$NIX_BUILD_CORES - ./koch toolsNoExternal $kochArgs --parallelBuild:$NIX_BUILD_CORES - runHook postBuild - ''; - - installPhase = '' - runHook preInstall - install -Dt $out/bin bin/* - ln -sf $out/nim/bin/nim $out/bin/nim - ./install.sh $out - runHook postInstall - ''; - - inherit meta; - }; - - nimble-unwrapped = stdenv.mkDerivation rec { - pname = "nimble-unwrapped"; - version = "0.13.1"; - - src = fetchFromGitHub { - owner = "nim-lang"; - repo = "nimble"; - rev = "v" + version; - sha256 = "1idb4r0kjbqv16r6bgmxlr13w2vgq5332hmnc8pjbxiyfwm075x8"; - }; - - nativeBuildInputs = [ nim-unwrapped ]; - buildInputs = [ openssl ]; - - nimFlags = [ "--cpu:${nimHost.cpu}" "--os:${nimHost.os}" "-d:release" ]; - - buildPhase = '' - runHook preBuild - HOME=$NIX_BUILD_TOP nim c $nimFlags src/nimble - runHook postBuild - ''; - - installPhase = '' - runHook preBuild - install -Dt $out/bin src/nimble - runHook postBuild - ''; - }; + enableParallelBuilding = true; + installPhase = '' + runHook preInstall + install -Dt $out/bin bin/nim + runHook postInstall + ''; }; - wrapped = let - nim' = nim-unwrapped; - nimble' = nimble-unwrapped; +in { + + nim-unwrapped = stdenv.mkDerivation rec { + pname = "nim-unwrapped"; + version = "1.4.4"; + strictDeps = true; + + src = fetchurl { + url = "https://nim-lang.org/download/nim-${version}.tar.xz"; + sha256 = "03k642nnjca0s6jlbn1v4jld51mbkix97jli4ky74gqlxyfp4wvd"; + }; + + buildInputs = [ boehmgc openssl pcre readline sqlite ]; + + patches = [ + ./NIM_CONFIG_DIR.patch + # Override compiler configuration via an environmental variable + + ./nixbuild.patch + # Load libraries at runtime by absolute path + ]; + + configurePhase = '' + runHook preConfigure + cp ${bootstrapCompiler}/bin/nim bin/ + echo 'define:nixbuild' >> config/nim.cfg + runHook postConfigure + ''; + + kochArgs = [ + "--cpu:${nimHost.cpu}" + "--os:${nimHost.os}" + "-d:release" + "-d:useGnuReadline" + ] ++ lib.optional (stdenv.isDarwin || stdenv.isLinux) "-d:nativeStacktrace"; + + buildPhase = '' + runHook preBuild + local HOME=$TMPDIR + ./bin/nim c koch + ./koch boot $kochArgs --parallelBuild:$NIX_BUILD_CORES + ./koch toolsNoExternal $kochArgs --parallelBuild:$NIX_BUILD_CORES + runHook postBuild + ''; + + installPhase = '' + runHook preInstall + install -Dt $out/bin bin/* + ln -sf $out/nim/bin/nim $out/bin/nim + ./install.sh $out + runHook postInstall + ''; + + meta = with lib; { + description = "Statically typed, imperative programming language"; + homepage = "https://nim-lang.org/"; + license = licenses.mit; + maintainers = with maintainers; [ ehmry ]; + }; + }; + + nimble-unwrapped = stdenv.mkDerivation rec { + pname = "nimble-unwrapped"; + version = "0.13.1"; + strictDeps = true; + + src = fetchFromGitHub { + owner = "nim-lang"; + repo = "nimble"; + rev = "v${version}"; + sha256 = "1idb4r0kjbqv16r6bgmxlr13w2vgq5332hmnc8pjbxiyfwm075x8"; + }; + + depsBuildBuild = [ nim-unwrapped ]; + buildInputs = [ openssl ]; + + nimFlags = [ "--cpu:${nimHost.cpu}" "--os:${nimHost.os}" "-d:release" ]; + + buildPhase = '' + runHook preBuild + HOME=$NIX_BUILD_TOP nim c $nimFlags src/nimble + runHook postBuild + ''; + + installPhase = '' + runHook preBuild + install -Dt $out/bin src/nimble + runHook postBuild + ''; + }; + + nim = let + nim' = buildPackages.nim-unwrapped; + nimble' = buildPackages.nimble-unwrapped; inherit (stdenv) targetPlatform; in stdenv.mkDerivation { name = "${targetPlatform.config}-nim-wrapper-${nim'.version}"; inherit (nim') version; preferLocalBuild = true; + strictDeps = true; nativeBuildInputs = [ makeWrapper ]; + patches = [ + ./nim.cfg.patch + # Remove configurations that clash with ours + ]; + unpackPhase = '' runHook preUnpack - tar xf ${nim'.src} nim-$version/config/nim.cfg + tar xf ${nim'.src} nim-$version/config cd nim-$version runHook postUnpack ''; dontConfigure = true; - wrapperArgs = [ - "--prefix PATH : ${lib.makeBinPath [ stdenv.cc gdb ]}:${ - placeholder "out" - }/bin" - "--prefix LD_LIBRARY_PATH : ${ - lib.makeLibraryPath [ stdenv.cc.libc openssl ] - }" - "--set NIM_CONFIG_PATH ${placeholder "out"}/etc/nim" - ''--set NIX_HARDENING_ENABLE "''${NIX_HARDENING_ENABLE/fortify}"'' - # Fortify hardening appends -O2 to gcc flags which is unwanted for unoptimized nim builds. - ]; - - buildPhase = with stdenv; - let - ccType = if cc.isGNU then - "gcc" - else if cc.isClang then - "clang" - else - abort "no Nim configuration available for ${cc.name}"; - in '' + buildPhase = + # Configure the Nim compiler to use $CC and $CXX as backends + # The compiler is configured by two configuration files, each with + # a different DSL. The order of evaluation matters and that order + # is not documented, so duplicate the configuration across both files. + '' runHook preBuild - cat >> config/nim.cfg << EOF + cat >> config/config.nims << WTF - define:nixbuild - os = ${nimTarget.os} - cpu = ${nimTarget.cpu} - cc = ${ccType} - EOF + switch("os", "${nimTarget.os}") + switch("cpu", "${nimTarget.cpu}") + switch("define", "nixbuild") - mkdir -p $out/bin $out/etc/nim - export cc=$CC - export cxx=$CXX - substituteAll config/nim.cfg $out/etc/nim/nim.cfg \ - --replace "cc = gcc" "" + # Configure the compiler using the $CC set by Nix at build time + import strutils + let cc = getEnv"CC" + if cc.contains("gcc"): + switch("cc", "gcc") + elif cc.contains("clang"): + switch("cc", "clang") + WTF - for binpath in ${nim'}/bin/nim?*; do - local binname=`basename $binpath` - makeWrapper \ - $binpath $out/bin/${targetPlatform.config}-$binname \ - $wrapperArgs - ln -s $out/bin/${targetPlatform.config}-$binname $out/bin/$binname - done + mv config/nim.cfg config/nim.cfg.old + cat > config/nim.cfg << WTF + os = "${nimTarget.os}" + cpu = "${nimTarget.cpu}" + define:"nixbuild" + WTF - makeWrapper \ - ${nim'}/nim/bin/nim $out/bin/${targetPlatform.config}-nim \ - $wrapperArgs - ln -s $out/bin/${targetPlatform.config}-nim $out/bin/nim + cat >> config/nim.cfg < config/nim.cfg.old + rm config/nim.cfg.old - makeWrapper \ - ${nim'}/bin/testament $out/bin/${targetPlatform.config}-testament \ - $wrapperArgs - ln -s $out/bin/${targetPlatform.config}-testament $out/bin/testament + cat >> config/nim.cfg << WTF - makeWrapper \ - ${nimble'}/bin/nimble $out/bin/${targetPlatform.config}-nimble \ - --suffix PATH : $out/bin - ln -s $out/bin/${targetPlatform.config}-nimble $out/bin/nimble + clang.cpp.exe %= "\$CXX" + clang.cpp.linkerexe %= "\$CXX" + clang.exe %= "\$CC" + clang.linkerexe %= "\$CC" + gcc.cpp.exe %= "\$CXX" + gcc.cpp.linkerexe %= "\$CXX" + gcc.exe %= "\$CC" + gcc.linkerexe %= "\$CC" + WTF runHook postBuild ''; - dontInstall = true; + wrapperArgs = [ + "--prefix PATH : ${lib.makeBinPath [ buildPackages.gdb ]}:${ + placeholder "out" + }/bin" + # Used by nim-gdb - meta = meta // { + "--prefix LD_LIBRARY_PATH : ${lib.makeLibraryPath [ openssl pcre ]}" + # These libraries may be referred to by the standard library. + # This is broken for cross-compilation because the package + # set will be shifted back by nativeBuildInputs. + + "--set NIM_CONFIG_PATH ${placeholder "out"}/etc/nim" + # Use the custom configuration + + ''--set NIX_HARDENING_ENABLE "''${NIX_HARDENING_ENABLE/fortify}"'' + # Fortify hardening appends -O2 to gcc flags which is unwanted for unoptimized nim builds. + ]; + + installPhase = '' + runHook preInstall + + mkdir -p $out/bin $out/etc + + cp -r config $out/etc/nim + + for binpath in ${nim'}/bin/nim?*; do + local binname=`basename $binpath` + makeWrapper \ + $binpath $out/bin/${targetPlatform.config}-$binname \ + $wrapperArgs + ln -s $out/bin/${targetPlatform.config}-$binname $out/bin/$binname + done + + makeWrapper \ + ${nim'}/nim/bin/nim $out/bin/${targetPlatform.config}-nim \ + $wrapperArgs + ln -s $out/bin/${targetPlatform.config}-nim $out/bin/nim + + makeWrapper \ + ${nim'}/bin/testament $out/bin/${targetPlatform.config}-testament \ + $wrapperArgs + ln -s $out/bin/${targetPlatform.config}-testament $out/bin/testament + + makeWrapper \ + ${nimble'}/bin/nimble $out/bin/${targetPlatform.config}-nimble \ + --suffix PATH : $out/bin + ln -s $out/bin/${targetPlatform.config}-nimble $out/bin/nimble + + runHook postInstall + ''; + + passthru = { + nim = nim'; + nimble = nimble'; + }; + + meta = nim'.meta // { description = nim'.meta.description + " (${targetPlatform.config} wrapper)"; - platforms = lib.platforms.unix; + platforms = with lib.platforms; unix ++ genode; }; }; -in wrapped // wrapperInputs +} diff --git a/pkgs/development/compilers/nim/nim.cfg.patch b/pkgs/development/compilers/nim/nim.cfg.patch new file mode 100644 index 00000000000..a95b672d1c1 --- /dev/null +++ b/pkgs/development/compilers/nim/nim.cfg.patch @@ -0,0 +1,70 @@ +diff --git a/config/nim.cfg b/config/nim.cfg +index a33a2f0a9..e069193ff 100644 +--- a/config/nim.cfg ++++ b/config/nim.cfg +@@ -8,26 +8,12 @@ + # Environment variables can be accessed like so: + # gcc.path %= "$CC_PATH" + +-cc = gcc +- + # additional options always passed to the compiler: + --parallel_build: "0" # 0 to auto-detect number of processors + + hint[LineTooLong]=off + #hint[XDeclaredButNotUsed]=off + +-# Examples of how to setup a cross-compiler: +- +-# Cross-compiling for Raspberry Pi. +-# (This compiler is available in gcc-arm-linux-gnueabihf package on Ubuntu) +-arm.linux.gcc.exe = "arm-linux-gnueabihf-gcc" +-arm.linux.gcc.linkerexe = "arm-linux-gnueabihf-gcc" +- +-# For OpenWRT, you will also need to adjust PATH to point to your toolchain. +-mips.linux.gcc.exe = "mips-openwrt-linux-gcc" +-mips.linux.gcc.linkerexe = "mips-openwrt-linux-gcc" +- +- + path="$lib/deprecated/core" + path="$lib/deprecated/pure" + path="$lib/pure/collections" +@@ -111,7 +97,7 @@ path="$lib/pure" + @end + + @if unix: +- @if not bsd or haiku: ++ @if not bsd or genode or haiku: + # -fopenmp + gcc.options.linker = "-ldl" + gcc.cpp.options.linker = "-ldl" +@@ -295,29 +281,6 @@ vcc.cpp.options.size = "/O1" + # Configuration for the Tiny C Compiler: + tcc.options.always = "-w" + +-# Configuration for the Genode toolchain +-@if genode: +- noCppExceptions # avoid std C++ +- tlsEmulation:on # no TLS segment register magic +- @if i386 or amd64: +- gcc.exe = "genode-x86-gcc" +- gcc.cpp.exe = "genode-x86-g++" +- gcc.cpp.linkerexe = "genode-x86-ld" +- @elif arm: +- gcc.exe = "genode-arm-gcc" +- gcc.cpp.exe = "genode-arm-g++" +- gcc.cpp.linkerexe = "genode-arm-ld" +- @elif arm64: +- gcc.exe = "genode-aarch64-gcc" +- gcc.cpp.exe = "genode-aarch64-g++" +- gcc.cpp.linkerexe = "genode-aarch64-ld" +- @elif riscv64: +- gcc.exe = "genode-riscv-gcc" +- gcc.cpp.exe = "genode-riscv-g++" +- gcc.cpp.linkerexe = "genode-riscv-ld" +- @end +-@end +- + @if arm or arm64: + --define:nimEmulateOverflowChecks + @end diff --git a/pkgs/development/tools/misc/nimlsp/default.nix b/pkgs/development/tools/misc/nimlsp/default.nix index 1919e26ddec..7f73fb9a1bc 100644 --- a/pkgs/development/tools/misc/nimlsp/default.nix +++ b/pkgs/development/tools/misc/nimlsp/default.nix @@ -31,7 +31,7 @@ stdenv.mkDerivation rec { export HOME=$TMPDIR nim -d:release -p:${astpatternmatching}/src -p:${jsonschema}/src \ c --threads:on -d:nimcore -d:nimsuggest -d:debugCommunication \ - -d:debugLogging -d:explicitSourcePath=${srcOnly nim.unwrapped} -d:tempDir=/tmp src/nimlsp + -d:debugLogging -d:explicitSourcePath=${srcOnly nim.passthru.nim} -d:tempDir=/tmp src/nimlsp ''; installPhase = '' diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index e502a21f217..10a530825ec 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -10907,9 +10907,8 @@ in muon = callPackage ../development/compilers/muon { }; - nim = callPackage ../development/compilers/nim { }; - nim-unwrapped = nim.unwrapped; - nimble-unwrapped = nim.nimble-unwrapped; + inherit (callPackages ../development/compilers/nim { }) + nim-unwrapped nimble-unwrapped nim; nrpl = callPackage ../development/tools/nrpl { };