aboutsummaryrefslogtreecommitdiff
path: root/flake.nix
blob: 014898a3a5111ece646c886fcf0e3bcb02e92ff5 (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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
{
  description =
    "Garage, an S3-compatible distributed object store for self-hosted deployments";

  # Cross-compilation logic from here:
  # https://mediocregopher.com/posts/x-compiling-rust-with-nix
  # Thank you so much!!

  # Nixpkgs 24.11 as of 2025-01-12 has rustc v1.82
  inputs.nixpkgs.url =
    "github:NixOS/nixpkgs/7c4869c47090dd7f9f1bdfb49a22aea026996815";

  inputs.flake-compat.url = "github:nix-community/flake-compat";

  inputs.fenix.url = "github:nix-community/fenix";
  inputs.naersk.url = "github:nix-community/naersk/master";

  outputs = { self, nixpkgs, fenix, naersk, ... }:
   let
      buildTargets = {
        "x86_64-linux" = {
          crossSystemConfig = "x86_64-unknown-linux-musl";
          rustTarget = "x86_64-unknown-linux-musl";
        };

        "i686-linux" = {
          crossSystemConfig = "i686-unknown-linux-musl";
          rustTarget = "i686-unknown-linux-musl";
        };

        "aarch64-linux" = {
          crossSystemConfig = "aarch64-unknown-linux-musl";
          rustTarget = "aarch64-unknown-linux-musl";
        };

        # Old Raspberry Pi's
        "armv6l-linux" = {
          crossSystemConfig = "armv6l-unknown-linux-musleabihf";
          rustTarget = "arm-unknown-linux-musleabihf";
        };
      };

      # eachSystem [system] (system: ...)
      #
      # Returns an attrset with a key for every system in the given array, with
      # the key's value being the result of calling the callback with that key.
      eachSystem = supportedSystems: callback: builtins.foldl'
        (overall: system: overall // { ${system} = callback system; })
        {}
        supportedSystems;

      # eachCrossSystem [system] (buildSystem: targetSystem: ...)
      #
      # Returns an attrset with a key "$buildSystem.cross-$targetSystem" for
      # every combination of the elements of the array of system strings. The
      # value of the attrs will be the result of calling the callback with each
      # combination.
      #
      # There will also be keys "$system.default", which are aliases of
      # "$system.cross-$system" for every system.
      #
      eachCrossSystem = supportedSystems: callback:
        eachSystem supportedSystems (buildSystem: builtins.foldl'
            (inner: targetSystem: inner // {
              "cross-${targetSystem}" = callback buildSystem targetSystem;
            })
            { default = callback buildSystem buildSystem; }
            supportedSystems
        );

      mkPkgs = buildSystem: targetSystem: import nixpkgs ({
        system = buildSystem;
      } // (if targetSystem == null then {} else {
        # The nixpkgs cache doesn't have any packages where cross-compiling has
        # been enabled, even if the target platform is actually the same as the
        # build platform (and therefore it's not really cross-compiling). So we
        # only set up the cross-compiling config if the target platform is
        # different.
        crossSystem.config = buildTargets.${targetSystem}.crossSystemConfig;
      }));

    in {
      packages = eachCrossSystem
        (builtins.attrNames buildTargets)
        (buildSystem: targetSystem: let
          pkgs = mkPkgs buildSystem null;
          pkgsCross = mkPkgs buildSystem targetSystem;
          rustTarget = buildTargets.${targetSystem}.rustTarget;

          # TODO I'd prefer to use the toolchain file
          # https://github.com/nix-community/fenix/issues/123
          #toolchain = fenix.packages.${buildSystem}.fromToolchainFile {
          #  file = ./rust-toolchain.toml;
          #  sha256 = "sha256-LU4C/i+maIOqBZagUaXpFyWZyOVfQ3Ah5/JTz7v6CG4=";
          #};

          fenixPkgs = fenix.packages.${buildSystem};

          mkToolchain = fenixPkgs: fenixPkgs.toolchainOf {
			# TODO change compiler to stable
            channel = "1.77";
            sha256 = "sha256-7QfkHty6hSrgNM0fspycYkRcB82eEqYa4CoAJ9qA3tU=";
          };

          toolchain = fenixPkgs.combine [
            (mkToolchain fenixPkgs).rustc
            (mkToolchain fenixPkgs).cargo
            (mkToolchain fenixPkgs.targets.${rustTarget}).rust-std
          ];

          buildPackageAttrs = if
            builtins.hasAttr "makeBuildPackageAttrs" buildTargets.${targetSystem}
          then
            buildTargets.${targetSystem}.makeBuildPackageAttrs pkgsCross
          else
            {};

          naersk-lib = pkgs.callPackage naersk {
            cargo = toolchain;
            rustc = toolchain;
          };

        in
          naersk-lib.buildPackage (buildPackageAttrs // rec {
            name = "garage";
            pname = "garage";
            src = ./.;
            strictDeps = true;
            doCheck = false;
            release = false;    # for now

	        # TODO co uld be removed	?
            OPENSSL_STATIC = "1";
            OPENSSL_LIB_DIR = "${pkgsCross.pkgsStatic.openssl.out}/lib";
            OPENSSL_INCLUDE_DIR = "${pkgsCross.pkgsStatic.openssl.dev}/include";

	        # TODO co uld be removed	?
            # Required because ring crate is special. This also seems to have
            # fixed some issues with the x86_64-windows cross-compile :shrug:
            TARGET_CC = "${pkgsCross.stdenv.cc}/bin/${pkgsCross.stdenv.cc.targetPrefix}cc";

            CARGO_BUILD_TARGET = rustTarget;
            CARGO_BUILD_RUSTFLAGS = [
              "-C" "target-feature=+crt-static"

              # -latomic is required to build openssl-sys for armv6l-linux, but
              # it doesn't seem to hurt any other builds.
              "-C" "link-args=-static -latomic"

              # https://github.com/rust-lang/cargo/issues/4133
              "-C" "linker=${TARGET_CC}"
            ];
          })
        );
    };
}