Skip to content

Commit

Permalink
Fix Nix cross-compilation by using callPackage properly. (#151)
Browse files Browse the repository at this point in the history
### What

I removed the call to `callPackage` in favor of using `pkgs` directly.
It seems this was a bad idea. I have undone this part of my refactor
and, I hope, made the Nix derivation clearer as a result.

I also added CI jobs for cross-compilation so this doesn't happen again.

### How

Yet more Nix. The key is using `pkgs.callPackage` with the `pkgs` from
_rust.nix_, rather than `import`, to specify the derivation.
  • Loading branch information
SamirTalwar authored Nov 6, 2023
1 parent cb0752c commit 927c903
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 48 deletions.
9 changes: 7 additions & 2 deletions .github/workflows/nix-build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ jobs:
nix-build:
name: nix build
runs-on: ubuntu-latest
strategy:
matrix:
target:
- x86_64-linux
- aarch64-linux
steps:
- name: Checkout 🛎️
uses: actions/checkout@v4
Expand All @@ -23,10 +28,10 @@ jobs:
authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}

- name: Build a binary with Nix
run: nix build --print-build-logs
run: nix build --print-build-logs '.#${{ matrix.target }}'

- name: Build a Docker image with Nix
run: nix build --print-build-logs '.#docker'
run: nix build --print-build-logs '.#docker-${{ matrix.target }}'

# scream into Slack if something goes wrong
- name: Report Status
Expand Down
31 changes: 11 additions & 20 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -30,32 +30,24 @@
rust = import ./nix/rust.nix {
inherit nixpkgs rust-overlay crane localSystem;
};

buildPackage = import ./nix/app.nix;
in
{
packages = {
# a binary for whichever is the local computer
default = buildPackage {
rust = import ./nix/rust.nix {
inherit nixpkgs rust-overlay crane localSystem;
};
};
default = rust.callPackage ./nix/app.nix { };

# cross compiler an x86_64 linux binary
x86_64-linux = buildPackage {
rust = import ./nix/rust.nix {
inherit nixpkgs rust-overlay crane localSystem;
crossSystem = "x86_64-linux";
};
};
x86_64-linux = (import ./nix/rust.nix {
inherit nixpkgs rust-overlay crane localSystem;
crossSystem = "x86_64-linux";
}).callPackage ./nix/app.nix
{ };
# cross compile a aarch64 linux binary
aarch64-linux = buildPackage {
rust = import ./nix/rust.nix {
inherit nixpkgs rust-overlay crane localSystem;
crossSystem = "aarch64-linux";
};
};
aarch64-linux = (import ./nix/rust.nix {
inherit nixpkgs rust-overlay crane localSystem;
crossSystem = "aarch64-linux";
}).callPackage ./nix/app.nix
{ };

# docker for local system
docker = pkgs.callPackage ./nix/docker.nix {
Expand Down Expand Up @@ -110,7 +102,6 @@
pkgs.pkg-config
pkgs.rnix-lsp
pkgs.skopeo
pkgs.nodePackages.prettier
rust.rustToolchain
] ++ (
pkgs.lib.optionals
Expand Down
51 changes: 26 additions & 25 deletions nix/app.nix
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
# This is a function that returns a derivation for the compiled Rust project.
{ rust }:
{ craneLib
, lib
, stdenv
, openssl
, libiconv
, pkg-config
, protobuf
, darwin
}:
let
inherit (rust) pkgs;

buildArgs = {
pname = "ndc-postgres";

Expand All @@ -13,36 +19,31 @@ let
isSourceFile = path: type:
isJsonFile path type
|| isSqlFile path type
|| rust.craneLib.filterCargoSources path type;
|| craneLib.filterCargoSources path type;
in
pkgs.lib.cleanSourceWith { src = rust.craneLib.path ./..; filter = isSourceFile; };
lib.cleanSourceWith { src = craneLib.path ./..; filter = isSourceFile; };

buildInputs = [
pkgs.openssl
] ++ pkgs.lib.optionals pkgs.stdenv.hostPlatform.isDarwin [
pkgs.libiconv
pkgs.darwin.apple_sdk.frameworks.Security
pkgs.darwin.apple_sdk.frameworks.SystemConfiguration
openssl
] ++ lib.optionals stdenv.hostPlatform.isDarwin [
libiconv
darwin.apple_sdk.frameworks.Security
darwin.apple_sdk.frameworks.SystemConfiguration
];

nativeBuildInputs = [
pkgs.pkg-config # required for non-static builds
pkgs.protobuf # required by opentelemetry-proto, a dependency of axum-tracing-opentelemetry
pkg-config # required for non-static builds
protobuf # required by opentelemetry-proto, a dependency of axum-tracing-opentelemetry
];
};

# Build the dependencies first.
cargoArtifacts = rust.craneLib.buildDepsOnly buildArgs;

# Then build the crate.
crate = rust.craneLib.buildPackage
(buildArgs // {
inherit cargoArtifacts;
doCheck = false;
});
cargoArtifacts = craneLib.buildDepsOnly buildArgs;
in
# Override the derivation to add cross-compilation and static linking environment variables.
crate.overrideAttrs (previous: rust.buildEnv // {
# We also have to override the `cargoArtifacts` derivation with the same changes.
cargoArtifacts = previous.cargoArtifacts.overrideAttrs (previous: rust.buildEnv);
})
# Then build the crate.
craneLib.buildPackage
(buildArgs // {
inherit cargoArtifacts;
doCheck = false;
cargoExtraArgs = "--locked --bin ${buildArgs.pname}";
})
14 changes: 13 additions & 1 deletion nix/rust.nix
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,16 @@ let
HOST_CC = "${pkgs.stdenv.cc.nativePrefix}cc";
};
in
{ inherit pkgs rustToolchain craneLib buildEnv; }
{
inherit rustToolchain;

callPackage = (package: args:
# Call the package, providing `craneLib` as an extra.
let crate = pkgs.callPackage package (args // { inherit craneLib; });
in
# Override the derivation to add cross-compilation environment variables.
crate.overrideAttrs (previous: buildEnv // {
# We also have to override the `cargoArtifacts` derivation with the same changes.
cargoArtifacts = previous.cargoArtifacts.overrideAttrs (previous: buildEnv);
}));
}

0 comments on commit 927c903

Please sign in to comment.