about summary refs log tree commit diff
path: root/pkgs/build-support/rust/hooks/default.nix
blob: 9989e582d2e9ad82e297d6d474e965f60090b384 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
{ buildPackages
, callPackage
, cargo
, cargo-nextest
, clang
, lib
, makeSetupHook
, maturin
, rust
, rustc
, stdenv
, target ? rust.toRustTargetSpec stdenv.hostPlatform
}:

let
  targetIsJSON = lib.hasSuffix ".json" target;

  # see https://github.com/rust-lang/cargo/blob/964a16a28e234a3d397b2a7031d4ab4a428b1391/src/cargo/core/compiler/compile_kind.rs#L151-L168
  # the "${}" is needed to transform the path into a /nix/store path before baseNameOf
  shortTarget = if targetIsJSON then
      (lib.removeSuffix ".json" (builtins.baseNameOf "${target}"))
    else target;
  ccForBuild = "${buildPackages.stdenv.cc}/bin/${buildPackages.stdenv.cc.targetPrefix}cc";
  cxxForBuild = "${buildPackages.stdenv.cc}/bin/${buildPackages.stdenv.cc.targetPrefix}c++";
  ccForHost = "${stdenv.cc}/bin/${stdenv.cc.targetPrefix}cc";
  cxxForHost = "${stdenv.cc}/bin/${stdenv.cc.targetPrefix}c++";
  rustBuildPlatform = rust.toRustTarget stdenv.buildPlatform;
  rustTargetPlatform = rust.toRustTarget stdenv.hostPlatform;
  rustTargetPlatformSpec = rust.toRustTargetSpec stdenv.hostPlatform;
in {
  cargoBuildHook = callPackage ({ }:
    makeSetupHook {
      name = "cargo-build-hook.sh";
      deps = [ cargo ];
      substitutions = {
        inherit ccForBuild ccForHost cxxForBuild cxxForHost
          rustBuildPlatform rustTargetPlatform rustTargetPlatformSpec;
      };
    } ./cargo-build-hook.sh) {};

  cargoCheckHook = callPackage ({ }:
    makeSetupHook {
      name = "cargo-check-hook.sh";
      deps = [ cargo ];
      substitutions = {
        inherit rustTargetPlatformSpec;
      };
    } ./cargo-check-hook.sh) {};

  cargoInstallHook = callPackage ({ }:
    makeSetupHook {
      name = "cargo-install-hook.sh";
      deps = [ ];
      substitutions = {
        inherit shortTarget;
      };
    } ./cargo-install-hook.sh) {};

  cargoNextestHook = callPackage ({ }:
    makeSetupHook {
      name = "cargo-nextest-hook.sh";
      deps = [ cargo cargo-nextest ];
      substitutions = {
        inherit rustTargetPlatformSpec;
      };
    } ./cargo-nextest-hook.sh) {};

  cargoSetupHook = callPackage ({ }:
    makeSetupHook {
      name = "cargo-setup-hook.sh";
      deps = [ ];
      substitutions = {
        defaultConfig = ../fetchcargo-default-config.toml;

        # Specify the stdenv's `diff` by abspath to ensure that the user's build
        # inputs do not cause us to find the wrong `diff`.
        diff = "${lib.getBin buildPackages.diffutils}/bin/diff";

        # We want to specify the correct crt-static flag for both
        # the build and host platforms. This is important when the wanted
        # value for crt-static does not match the defaults in the rustc target,
        # like for pkgsMusl or pkgsCross.musl64; Upstream rustc still assumes
        # that musl = static[1].
        #
        # By default, Cargo doesn't apply RUSTFLAGS when building build.rs
        # if --target is passed, so the only good way to set crt-static for
        # build.rs files is to use the unstable -Zhost-config Cargo feature.
        # This allows us to specify flags that should be passed to rustc
        # when building for the build platform. We also need to use
        # -Ztarget-applies-to-host, because using -Zhost-config requires it.
        #
        # When doing this, we also have to specify the linker, or cargo
        # won't pass a -C linker= argument to rustc.  This will make rustc
        # try to use its default value of "cc", which won't be available
        # when cross-compiling.
        #
        # [1]: https://github.com/rust-lang/compiler-team/issues/422
        cargoConfig = ''
          [host]
          "linker" = "${ccForBuild}"
          "rustflags" = [ "-C", "target-feature=${if stdenv.buildPlatform.isStatic then "+" else "-"}crt-static" ]

          [target."${shortTarget}"]
          "linker" = "${ccForHost}"
          "rustflags" = [ "-C", "target-feature=${if stdenv.hostPlatform.isStatic then "+" else "-"}crt-static" ]

          [unstable]
          host-config = true
          target-applies-to-host = true
        '';

        # https://github.com/NixOS/nixpkgs/issues/201254
        aarch64LinuxGccWorkaround = lib.optionalString (stdenv.isLinux && stdenv.isAarch64 && stdenv.cc.isGNU) "-lgcc";
      };
    } ./cargo-setup-hook.sh) {};

  maturinBuildHook = callPackage ({ }:
    makeSetupHook {
      name = "maturin-build-hook.sh";
      deps = [ cargo maturin rustc ];
      substitutions = {
        inherit ccForBuild ccForHost cxxForBuild cxxForHost
          rustBuildPlatform rustTargetPlatform rustTargetPlatformSpec;
      };
    } ./maturin-build-hook.sh) {};

    bindgenHook = callPackage ({}: makeSetupHook {
      name = "rust-bindgen-hook";
      substitutions = {
        libclang = clang.cc.lib;
        inherit clang;
      };
    }
    ./rust-bindgen-hook.sh) {};
}