nix-community / crate2nix

rebuild only changed crates in CI with crate2nix and nix
https://nix-community.github.io/crate2nix/
Apache License 2.0
335 stars 82 forks source link

Respect cargo profiles / enable debug info in release mode #345

Open Ten0 opened 2 months ago

Ten0 commented 2 months ago

I'm trying to get my workspace to compile with debug info in release mode.

My Cargo.toml has the following:

[profile.release]
debug = 1

however that seems to be ignored when using crate2nix.

Solving

The documentation of buildRustCrate suggests that extraRustcOpts can be used (source code), however transposing it to crate2nix doesn't work:

            buildRustCrateForPkgs = pkgs: pkgs.buildRustCrate.override {
              extraRustcOpts = "-C debuginfo=1";
            };

yields the following error:

       error: function 'anonymous lambda' called with unexpected argument 'extraRustcOpts'
       at /nix/store/zaza7mgggz4m5h6z18kajabf4wciaj47-source/pkgs/build-support/rust/build-rust-crate/default.nix:7:1

That is because extraRustOpts can't be specified at a global level: https://github.com/NixOS/nixpkgs/blob/30d044f8235dbd03675bef6e2b59e1c8a94e2c51/pkgs/build-support/rust/build-rust-crate/default.nix#L7 It can only be specified at a crate level: https://github.com/NixOS/nixpkgs/blob/30d044f8235dbd03675bef6e2b59e1c8a94e2c51/pkgs/build-support/rust/build-rust-crate/default.nix#L180

=> It looks like in order to be able to respect cargo profiles, or at least give an interface that allows users to easily override rust flags at the buildRustCrateForPkgs level, one would need to PR something into nixpkgs so that one can propagate arguments from there.

It looks like as a workaround, one may override the crates one by one through the defaultCrateOverrides mechanism, but that requires re-mentioning every crate in there.

It seems that this may also be a first step towards ~fixing #338.

Ten0 commented 2 months ago

Current workaround:

{ pkgs, lib, cargoNix }:

let
  defaultOrOverrides = pkgs.defaultCrateOverrides;

  # Enable debuginfo on all known crates. Unfortunately this has to be overridden on a per-crate basis,
  # and we can only do this by looking up crates list from cargoNix.internal.
  # The fact this is so complex is tracked by https://github.com/nix-community/crate2nix/issues/345
  withDebugInfo = defaultOrOverrides // (
    builtins.listToAttrs
      (builtins.map
        (crate:
          let
            crateName = crate.crateName;
            defaultOverride = defaultOrOverrides.${crateName} or (crate: { });
          in
          {
            name = crateName;
            value = crate: (
              let defaultOverrideApplied = defaultOverride crate;
              in
              defaultOverrideApplied // {
                extraRustcOpts = (defaultOverrideApplied.extraRustcOpts or [ ]) ++ [ "-C debuginfo=1" ];
                extraRustcOptsForBuildRs = (defaultOverrideApplied.extraRustcOptsForBuildRs or [ ]) ++ [ "-C debuginfo=1" ];
              }
            );
          }
        )
        (builtins.attrValues cargoNix.internal.crates))
  );
in
withDebugInfo

note the use of .internal to get the list of all crates, that we can then build the crateOverrides with.