summaryrefslogtreecommitdiffstats
path: root/pkgs/rust/default.nix
blob: c26cf9de6354ed094e8f6598685351e2c6e4e391 (plain)
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
self: super:

let
  inherit (super) lib mylib;

  # Merges an override into attrs.  The override is attrs, or a function from
  # the original attrs to attrs, like the argument of nixpkgs' .override.
  applyOverride = override: attrs: attrs // lib.toFunction override attrs;

  explicitPackages =
    mylib.mapNixDir' (pname: path: path) [ ./. ];

  automaticPackages =
    let
      root = /home/tv/sync/src;
    in
    lib.optionalAttrs (builtins.pathExists root)
      (lib.mapAttrs (pname: _type: root + "/${pname}")
        (lib.filterAttrs
          (pname: type: type == "directory" && builtins.pathExists (root + "/${pname}/Cargo.toml"))
          (builtins.readDir root)));

  # callPackage adds override and overrideDerivation to the returned attrset,
  # which crate2nix-package.nix would reject as unexpected arguments.
  callArgs = path: builtins.removeAttrs (self.callPackage path {}) [ "override" "overrideDerivation" ];

  # A plan kept next to the package in hrm: pkgs/rust/<pname>/Cargo.json.
  # Settings in the package file itself take precedence.
  hrmPlan = path:
    lib.optionalAttrs (builtins.pathExists (path + "/Cargo.json")) {
      resolvedJson = path + "/Cargo.json";
    };

  # Checks the JSON plan against the checkout's Cargo.lock and Cargo.toml.
  # These come from dir, not src, because cleanCargoSource drops Cargo.lock
  # next to a Cargo.json.
  planChecks = dir:
    lib.optionalAttrs (builtins.pathExists (dir + "/Cargo.lock")) {
      cargoLock = dir + "/Cargo.lock";
    }
    // lib.optionalAttrs (builtins.pathExists (dir + "/Cargo.toml")) {
      cargoToml = dir + "/Cargo.toml";
    };
in

{
  # Builds a crate2nix workspace.
  crate2nixPackage = args: import ./lib/crate2nix-package.nix ({
    inherit applyOverride;
    pkgs = self;
  } // args);

  # Applied to our own crates: debug builds, but dependencies in release.
  rustDevCrateAttrs = args: {
    release = false;
    codegenUnits = 256;
    extraRustcOpts = args.extraRustcOpts or [] ++ [
      "-C debuginfo=line-tables-only"
      "-C link-arg=-fuse-ld=mold"
    ];
    nativeBuildInputs = args.nativeBuildInputs or [] ++ [ self.mold ];
  };

  # Builds a crate from rustCrateArgs.<pname> merged with an override: attrs,
  # or a function from the stored arguments to attrs, e.g.
  #   rustCrateWith "continuum" { features = [ "tor" ]; }
  # With {}, that's the package itself.
  rustCrateWith = pname: f:
    (self.crate2nixPackage (applyOverride f self.rustCrateArgs.${pname})).build;

  # crate2nixPackage arguments per package. Change them in a later overlay:
  #   self: super: {
  #     rustCrateArgs = super.rustCrateArgs // {
  #       continuum = super.rustCrateArgs.continuum // { resolvedJson = ./continuum.json; };
  #     };
  #   }
  rustCrateArgs =
    lib.mapAttrs (pname: path: hrmPlan path // callArgs path) explicitPackages
    //
    lib.mapAttrs
      (pname: dir: let
        src = self.cleanCargoSource pname dir;
      in
        if explicitPackages ? ${pname} then
          assert mylib.debug "pkgs/rust: overriding ${pname}.src with ${mylib.pretty dir}";
          hrmPlan explicitPackages.${pname} // callArgs explicitPackages.${pname} // { inherit src; } // planChecks dir
        else
          assert mylib.debug "pkgs/rust: automatic package ${pname} from ${mylib.pretty dir}";
          { name = pname; inherit src; } // planChecks dir
      )
      automaticPackages;

  # Copies a Cargo workspace into the store, leaving out what the build
  # doesn't need.
  cleanCargoSource = name: src: builtins.path {
    inherit name;
    path = src;
    filter = path: type:
      !builtins.any lib.id [
        (type == "directory" && builtins.elem (baseNameOf path) [ ".git" ".graveyard" ])
        # Cargo.json is the resolved lock.
        (type == "regular" && baseNameOf path == "Cargo.lock" && builtins.pathExists (builtins.dirOf path + "/Cargo.json"))
      ];
  };
}

//

lib.mapAttrs
  (pname: _path:
    assert mylib.debugIf (super ? ${pname}) "pkgs/rust: overriding ${pname}";
    self.rustCrateWith pname {})
  (explicitPackages // automaticPackages)