Skip to content

rustc with musl target #71195

@nmattia

Description

@nmattia

Project description

I would love to have a rustc version that compiles static binaries on Linux.

I've hacked one together:

commit 67cf46e3a914f9d89a6b367e261b3d33ecbf5dc5
Author: Nicolas Mattia <[email protected]>
Date:   Tue Oct 15 17:25:55 2019 +0200

    wip

diff --git a/pkgs/development/compilers/rust/rustc.nix b/pkgs/development/compilers/rust/rustc.nix
index 430d22f7653..069fe08c6da 100644
--- a/pkgs/development/compilers/rust/rustc.nix
+++ b/pkgs/development/compilers/rust/rustc.nix
@@ -4,6 +4,9 @@
 , pkgconfig, openssl
 , which, libffi
 , withBundledLLVM ? false
+, pkgsStatic
+, musl
+, runCommand
 }:
 
 let
@@ -51,41 +54,45 @@ in stdenv.mkDerivation rec {
   # We need rust to build rust. If we don't provide it, configure will try to download it.
   # Reference: https://github.com/rust-lang/rust/blob/master/src/bootstrap/configure.py
   configureFlags = let
-    setBuild  = "--set=target.${stdenv.buildPlatform.config}";
-    setHost   = "--set=target.${stdenv.hostPlatform.config}";
-    setTarget = "--set=target.${stdenv.targetPlatform.config}";
-    ccForBuild  = "${pkgsBuildBuild.targetPackages.stdenv.cc}/bin/${pkgsBuildBuild.targetPackages.stdenv.cc.targetPrefix}cc";
-    cxxForBuild = "${pkgsBuildBuild.targetPackages.stdenv.cc}/bin/${pkgsBuildBuild.targetPackages.stdenv.cc.targetPrefix}c++";
-    ccForHost  = "${pkgsBuildHost.targetPackages.stdenv.cc}/bin/${pkgsBuildHost.targetPackages.stdenv.cc.targetPrefix}cc";
-    cxxForHost = "${pkgsBuildHost.targetPackages.stdenv.cc}/bin/${pkgsBuildHost.targetPackages.stdenv.cc.targetPrefix}c++";
-    ccForTarget  = "${pkgsBuildTarget.targetPackages.stdenv.cc}/bin/${pkgsBuildTarget.targetPackages.stdenv.cc.targetPrefix}cc";
-    cxxForTarget = "${pkgsBuildTarget.targetPackages.stdenv.cc}/bin/${pkgsBuildTarget.targetPackages.stdenv.cc.targetPrefix}c++";
+    ccGlibc  = "${pkgsBuildBuild.targetPackages.stdenv.cc}/bin/${pkgsBuildBuild.targetPackages.stdenv.cc.targetPrefix}cc";
+    cxxGlibc = "${pkgsBuildBuild.targetPackages.stdenv.cc}/bin/${pkgsBuildBuild.targetPackages.stdenv.cc.targetPrefix}c++";
+
+    # the musl-enabled GCC and G++
+    ccMusl  = "${pkgsStatic.stdenv.cc}/bin/${pkgsStatic.stdenv.cc.targetPrefix}cc";
+    cxxMusl = "${pkgsStatic.stdenv.cc}/bin/${pkgsStatic.stdenv.cc.targetPrefix}c++";
+    muslRoot =
+      let libunwind = pkgsStatic.llvmPackages_9.libunwind.override
+            { enableShared = false; };
+      in
+      runCommand "musl-root" {}
+    ''
+      mkdir -p $out
+      cp -r ${musl}/* $out
+      chmod +w $out/lib
+      cp ${libunwind}/lib/* $out/lib
+    '';
   in [
     "--release-channel=stable"
     "--set=build.rustc=${rustPlatform.rust.rustc}/bin/rustc"
     "--set=build.cargo=${rustPlatform.rust.cargo}/bin/cargo"
     "--enable-rpath"
     "--enable-vendor"
-    "--build=${stdenv.buildPlatform.config}"
-    "--host=${stdenv.hostPlatform.config}"
-    "--target=${stdenv.targetPlatform.config}"
+    "--build=x86_64-unknown-linux-gnu"
+    "--host=x86_64-unknown-linux-gnu"
+    "--target=x86_64-unknown-linux-musl"
 
-    "${setBuild}.cc=${ccForBuild}"
-    "${setHost}.cc=${ccForHost}"
-    "${setTarget}.cc=${ccForTarget}"
+    "--set=target.x86_64-unknown-linux-gnu.cc=${ccGlibc}"
+    "--set=target.x86_64-unknown-linux-gnu.linker=${ccGlibc}"
+    "--set=target.x86_64-unknown-linux-gnu.cxx=${cxxGlibc}"
 
-    "${setBuild}.linker=${ccForBuild}"
-    "${setHost}.linker=${ccForHost}"
-    "${setTarget}.linker=${ccForTarget}"
+    "--set=target.x86_64-unknown-linux-musl.cc=${ccMusl}"
+    "--set=target.x86_64-unknown-linux-musl.linker=${ccMusl}"
+    "--set=target.x86_64-unknown-linux-musl.cxx=${cxxMusl}"
 
-    "${setBuild}.cxx=${cxxForBuild}"
-    "${setHost}.cxx=${cxxForHost}"
-    "${setTarget}.cxx=${cxxForTarget}"
+    "--set=target.x86_64-unknown-linux-musl.musl-root=${muslRoot}"
   ] ++ optional (!withBundledLLVM) [
     "--enable-llvm-link-shared"
-    "${setBuild}.llvm-config=${llvmSharedForBuild}/bin/llvm-config"
-    "${setHost}.llvm-config=${llvmSharedForHost}/bin/llvm-config"
-    "${setTarget}.llvm-config=${llvmSharedForTarget}/bin/llvm-config"
+    "--set=target.x86_64-unknown-linux-gnu.llvm-config=${llvmSharedForBuild}/bin/llvm-config"
   ] ++ optional stdenv.isLinux [
     "--enable-profiler" # build libprofiler_builtins
   ];
@@ -132,7 +139,7 @@ in stdenv.mkDerivation rec {
 
   # remove references to llvm-config in lib/rustlib/x86_64-unknown-linux-gnu/codegen-backends/librustc_codegen_llvm-llvm.so
   # and thus a transitive dependency on ncurses
-  postInstall = ''
+  postInstall = optionalString (!withBundledLLVM) ''
     find $out/lib -name "*.so" -type f -exec remove-references-to -t ${llvmShared} '{}' '+'
   '';
 

The idea is that I really, really don't want to go through the pkgsCross infrastructure as this involves using a regular rustc (pkgsBuild) but then build two static rustcs (pkgsHost + pkgsTarget) when using pkgsStatic (not even sure this is possible). Instead I'd rather just instruct the rustc build system to build an extra target (i.e. stdlib) targetting musl. The above works well (modulo the withBundledLLVM which I've always set to true so far).

Would love to hear your thoughts @dtzWill @matthewbauer .

Metadata

Metadata

Assignees

No one assigned

    Labels

    0.kind: enhancementAdd something new6.topic: muslRunning or building packages with musl libc6.topic: rustGeneral-purpose programming language emphasizing performance, type safety, and concurrency.6.topic: staticStatic builds (e.g. pkgsStatic)

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions