Code Monkey home page Code Monkey logo

cargo2nix's Introduction

cargo2nix

darwin & linux CI flakes supported latest release

Bring Nix dependency management to your Rust project!

  • Development Shell - knowing all the dependencies means easy creation of complete shells. Run nix develop or direnv allow in this repo and see!
  • Caching - CI & CD pipelines move faster when purity guarantees allow skipping more work!
  • Reproducibility - Pure builds. Access to all of nixpkgs for repeatable environment setup across multiple distributions and platforms

Run it now!

With nix (with flake support) installed, generate a Cargo.nix for your project:

# Use nix to get cargo2nix & rust toolchain on your path
nix develop github:cargo2nix/cargo2nix#bootstrap

# In directory with Cargo.toml & Cargo.lock files (cargo generate-lockfile)
cargo2nix

# Or skip the shell and run it directly
nix run github:cargo2nix/cargo2nix

# You'll need this in version control
git add Cargo.nix

Use what you generated!

To consume your new Cargo.nix, write a nix expression like that found in the hello world example.

A bare minimum flake.nix:

{
  inputs = {
    cargo2nix.url = "github:cargo2nix/cargo2nix/release-0.11.0";
    flake-utils.follows = "cargo2nix/flake-utils";
    nixpkgs.follows = "cargo2nix/nixpkgs";
  };

  outputs = inputs: with inputs;
    flake-utils.lib.eachDefaultSystem (system:
      let
        pkgs = import nixpkgs {
          inherit system;
          overlays = [cargo2nix.overlays.default];
        };

        rustPkgs = pkgs.rustBuilder.makePackageSet {
          rustVersion = "1.75.0";
          packageFun = import ./Cargo.nix;
        };

      in rec {
        packages = {
          # replace hello-world with your package name
          hello-world = (rustPkgs.workspace.hello-world {});
          default = packages.hello-world;
        };
      }
    );
}

For a more complete project with CI & CD mostly ready to go, check out Unixsocks or cargo2nix's own CI workflow.

Build with nix

# these must be in version control!
git add flake.nix Cargo.nix

nix build
...
...
...
./result-bin/bin/hello
hello world!

Check out our series of example projects which showcase how to use cargo2nix in more detail.

Development environment

In this repo, simply use nix develop or direnv allow. Even if you are on a bare NixOS system or fresh OSX environment with no dependencies or toolchains installed, you will have everything you need to run cargo build. See the devShell attribute in flake.nix to see how to prepare this kind of shell.

The workspaceShell function, created by makePackagSet accepts all the same options as the nix mkShell function.

Maintaining your project

In your flake, you can choose your cargo2nix version by changing the URL.

Flake URL Result
github:cargo2nix/cargo2nix/ latest release (check repo's default branch, release-0.11.0)
github:cargo2nix/cargo2nix/release-0.11.0 use a specific release
github:cargo2nix/cargo2nix/unstable latest features & fixes

Only use unstable for developing with the latest features. PR's against old releases can be accepted but no active support will be done. The default branch for this repo is updated whenever a new release tag is made. Only specific release branches are "stable."

Update your flake lock with the latest or a specific version of cargo2nix:

nix flake lock --update-input cargo2nix
nix flake lock --update-input cargo2nix --override-input cargo2nix github:cargo2nix/cargo2nix/?rev=d45481420482fa7d9b0a62836555e24ec07d93be

If you need newer versions of Rust or the flake-utils inputs, just specify them using url instead of follows.

Arguments to makePackageSet

The makePackageSet function from the overlay accepts arguments that adjust how the workspace is built. Only the packageFun argument is required. Cargo2nix's own flake.nix has more information.

  • rustVersion - is either a version string or YYYY-MM-DD date-string

  • rustChannel - "nightly" "beta" "stable"

  • rustProfile - "default" or "minimal" usually

  • extraRustComponents - ["clippy" "miri"] etc

  • workspaceSrc - override where the source is supplied relative to the Cargo.nix

  • rootFeatures - a list of foo/feature strings for workspace crate features

  • packageOverrides - control over the individual crate overrides used to make them compatible on some platforms, for example to tweak C lib consumption

  • target - setting an explicit target, useful when cross compiling to obtain a specific Rust target that doesn't align with the nixpkgs target

Contents of Package Set

rustPkgs contains all crates in the dependency graph and some extra conveniences for development. The workspace crates are also exposed via a workspace attribute.

rustPkgs.<registry>.<crate>.<version> is an example of a crate function path. Calling the function results in a completed derivation, which can be used as a flake output. They support all the normal behaviors such as override and overrideAttrs. See mkCrate.nix for the full set of arguments the crate function supports.

rustPkgs.workspace.<crate> are usually the packages you will use. The other paths look like:

rustPkgs."registry+https://github.com/rust-lang/crates.io-index".openssl."0.10.30"

rustPkgs.workspaceShell is a derivation using Nix's standard mkShell, embelished with information we learned from the dependencies and their overrides, enabling vanilla cargo build to work in a nix develop shell.

Overrides

This is for finished derivations, not for dependencies. Keep reading below for using makeOverride in the dependency tree.

workspaceShell and crates both support override and overrideAttrs like normal Nix derivations. This allows you to customize the workspace shell or a build step in your workspace crate very easily. See nix show-derivation and nix show-derivation #devShell for more information.

More Control

You can make overrides to packages in the dependency tree. See examples in overrides.nix. Overriding the buildPhase etc is possible for a single crate without modifying mkcrate.nix in cargo2nix directly. The output of nix show-derivation can be valuable when determining what the current output result is.

The most important function in cargo2nix source is mkcrate.nix because it's how we store information in dependents and replay them back when building dependents. It is vital for building crates in isolation.

How it works

  • The cargo2nix utility reads the Rust workspace configuration and Cargo.lock and generates nix expressions that encode some of the feature, platform, and target logic into a Cargo.nix

  • The cargo2nix Nixpkgs overlay consumes the Cargo.nix, feeding it what you pass to makePackageSet to provide workspace outputs you can expose in your nix flake

  • Because we know all of the dependencies, it's easy to create a shell from those dependencies as environment setup using the workspaceShell function and exposing the result in the devShell flake output

Building crates isolated from each other

Just like regular cargo builds, the Nix dependencies form a DAG, but purity means we only expose essential information to dependencies and manually invoke cargo. Communication from dependencies to dependents is handled by writing some extra outputs and then reading those outputs inside the next dependent build.

There's two broad categories of information that need to be transmitted when hand-building crates in isolation:

  • Global information

    • target such as x86_64-unknown-linux-gnu
    • cargo actions such as build or test
    • features which turn on optional dependencies & downstream features via logic in the Cargo.nix expressions

    This information is known before any of the crates are built. It's used at evaluation time to decide what will be built. See nix show-derivation results.

  • Propagated information

    Each dependency writes information such as linker flags alongside its rlib and other outputs. When the dependent is going to consume the dependency, it reads this information back.

Derivations are evaluated in Nix with global information available. During the build, rlibs and dependency information are propagated back up the DAG. Each derivation's build shell combines the linking, features, target, and other information. You can see how it's used in mkcrate.nix

Limitations implied by purity

Evaluation of nix derivations doesn't require building anything. If you want to build a specific variant of a crate in a workspace with Nix, we would have to know this when building all of its dependencies. This means certain behavior to switch features and optional dependencies on or off depends on what else is being built. By default cargo2nix will build crates as if all other crates in the workspace might be build. This can be somewhat controlled with the rootFeatures argument. (see rootFeatures in Cargo.nix). This actually improves caching but may rarely result in a long build for an unneeded dependency (which your workspace should put behind a non-default top-level feature). Cargo isn't any better at this aspect of caching vs rebuilding.

Common issues

  1. Flakes require flake.nix and Cargo.nix to be in version control. git add flake.nix Cargo.nix etc. Remember to keep them up to date! Before building the examples, you will usually need to update their pin of cargo2nix: nix flake lock --update-input cargo2nix or nix may complane about paths.

  2. Old versions of the cargo2nix.overlay usually cannot consume newer versions of the Cargo.nix that an updated cargo2nix will produce. Update your inputs with nix flake lock --update-input cargo2nix or nix build --update-input cargo2nix

  3. When building sys crates, build.rs scripts may themselves attempt to provide native dependencies that could be missing. See the overlay/overrides.nix for patterns of common solutions for fixing up specific deps.

    To provide your own override, pass a modified packageOverrides to pkgs.rustBuilder.makePackageSet:

      rustPkgs = pkgs.rustBuilder.makePackageSet {
        # ... required arguments not shown
      
        # Use the existing all list of overrides and append your override
        packageOverrides = pkgs: pkgs.rustBuilder.overrides.all ++ [
        
          # parentheses disambiguate each makeOverride call as a single list element
          (pkgs.rustBuilder.rustLib.makeOverride {
              name = "fantasy-zlib-sys";
              overrideAttrs = drv: {
                propagatedBuildInputs = drv.propagatedBuildInputs or [ ] ++ [
                  pkgs.zlib.dev
                ];
              };
          })
        ];
      };
  4. Each derivation function in rustBuilder.makePackageSet has it's outputs created within mkcrate.nix, using some bash functions in mkcrate-utils.sh. We try not to copy more than necessary to the outputs, but this also means sometimes skipping a necessary file. Each derivation is multiple output, using bin and out. The default output is bin and should contain just what's necessary at runtime, possibly linked to other files in the Nix store. This output si for installation into a Nix profile or shell. The out output contains all of this and extra information necessary for dependents to consume the crate, usually linking information, which will collide if you attempt to install several such derivations.

  5. Non-deterministic rustc or linker behavior can lead to binary-incompatible crates. Nix cannot protect from non-determinism, only impurity. Override your builds with preferLocalBuild = true; allowSubstitutes = false; for the affected package. This has been seen more often because of nondeterministic macros. See #184 for more information.

  6. Nixpkgs is a rolling release, and that means breakages occur but you have many potential successful versions to choose from. View the CI logs and check the flake.lock for rev information from recent successes. Update to a specific input version with:

     nix flake lock --override-input nixpkgs github:nixpgks/nixpkgs?rev=a284564b7f75ac4db73607db02076e8da9d42c9d
  7. Toml parsing / conversion issues Error: Cannot convert data to TOML (Invalid type <class 'NoneType'>)

    jq and remarshal are used to read & modify toml files in some cases. Lines of the form: [key."cfg(foo = \"a\", bar = \"b\"))".path] could produce breakage when jq output was fed back to remarshal. There are workarounds in place to catch many cases. See #149 for more information and report any newly found breakage until a total solution is in place.

  8. Git dependencies and crates from alternative Cargo registries rely on builtins.fetchGit to support fetching from private Git repositories. This means that such dependencies cannot be evaluated with restrict-eval applied.

    Also, if your Git dependency is tied to a Git branch, e.g. master, and you would like to force it to update on upstream changes, you should append --option tarball-ttl 0 to your nix-build command.

Declarative build debugging shell

You can load a nix shell for any crate derivation in the dependency tree. This is the same environment the cargo2nix overlay will build them in.

To do this, first find the .drv for your dependency by using, for example, nix show-derivation | grep colorify

nix show-derivation | rg -o "/nix.*crate.*colorify.*drv"
nix/store/whi3jprrpzlnvic9fsn5f69sddazp5sb-colorify-0.2.3.tar.gz

# ignore environment to remove your shell's impurities
nix develop --ignore-environment nix/store/whi3jprrpzlnvic9fsn5f69sddazp5sb-colorify-0.2.3.tar.gz

# the environment is now as it is when nix builds the package
echo $src 
nix/store/whi3jprrpzlnvic9fsn5f69sddazp5sb-colorify-0.2.3.tar.gz

# If you are working on a dependency and need the source (or a fresh copy) you
# can unpack the $src variable. Through nix stdenv, tar is available in pure 
# shells
mkdir debug
cp $src debug
cd debug
tar -xzfv whi3jprrpzlnvic9fsn5f69sddazp5sb-colorify-0.2.3.tar.gz
cd <unpacked source>

You will need to override your Cargo.toml and Cargo.lock in this shell, so make sure that you have them backed up if your are directly using your clone of your project instead of unpacking fresh sources like above.

Now you just need to run the $configurePhase and $buildPhase steps in order. You can find additional phases that may exist in overrides by running env | grep Phase

echo $configurePhase 
# runHook preConfigure runHook configureCargo runHook postConfigure

runHook preConfigure # usually does nothing
runHook findCrate
runHook configureCargo
runHook postConfigure # usually does nothing

echo $buildPhase
# runHook overrideCargoManifest runHook setBuildEnv runHook runCargo

runHook overrideCargoManifest  # This overrides your .cargo folder, e.g. for setting cross-compilers
runHook setBuildEnv  # This sets up linker flags for the `rustc` invocations
runHook runCargo

If runCargo succeeds, you will have a completed output ready for the (usually) less interesting $installPhase. If there's a problem, inspecting the env or reading the generated Cargo.lock etc should yield clues. If you've unpacked a fresh source and are using the --ignore-environment switch, everything is identical to how the overlay builds the crate, cutting out guess work.

Contributing

See Contributing for potentially more information.

  1. Fork this repository into the personal GitHub account
  2. Select the appropriate branch, release- for stable changes, unstable for breaking changes
  3. Make changes on the personal fork
  4. Make a Pull Request against this repository
  5. Allow maintainers to make changes to your pull request (there's a checkbox)
  6. Once the pull request has been approved, you will be thanked and observe your changes applied with authorship preserved (if we remember)

Credits

The design for the Nix overlay is inspired by the excellent work done by James Kay, which is described here and here. His source is available here. This work would have been impossible without these fantastic write-ups. Special thanks to James Kay!

License

cargo2nix is free and open source software distributed under the terms of the MIT License.

cargo2nix's People

Contributors

acristoffers avatar alarmak avatar alexis211 avatar antigravityla avatar caongocthai avatar chetanbhasin avatar darkkirb avatar dingxiangfei2009 avatar ebkalderon avatar eclairevoyant avatar edude03 avatar eupn avatar jmpunkt avatar jneem avatar marksisson avatar nerosnm avatar ollie-etl avatar onsails avatar philipstears avatar psionic-k avatar ryantm avatar snawaz avatar sphw avatar steveej avatar stites avatar superboum avatar torhovland avatar trha avatar vbrandl avatar workflow avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cargo2nix's Issues

Improve error message when Cargo.lock needs updating

When cargo2nix -f is run, it executes Cargo's dependency resolution algorithm in --locked mode, meaning that the Cargo.lock is treated as immutable. Normally, if the Cargo.lock is out of sync with the contents of the Cargo.toml (e.g. a crate version was bumped or a dependency was added or removed), Cargo will silently update the Cargo.lock whenever it is next invoked by the user. But when Cargo is run in locked mode, the application will exit early and prompt the user to update the lockfile explicitly instead.

Currently, the cargo2nix tool exits in this scenario with a crude and ungraceful panic:

$ cargo2nix -f
    Updating crates.io index
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: ErrorMessage { msg: "the lock file /home/user/foo/Cargo.lock needs to be updated but --locked was passed to prevent this" }', src/libcore/result.rs:999:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.

We should eliminate this unwrap() and handle the error properly, ideally printing some additional context describing how to update the Cargo.lock. In this case, the user would have to do one of the following:

  1. Running cargo build, cargo test, etc. at least once in the command-line.
  2. Running cargo update -p <crate>... to update the specific packages affected.

Cannot write Cargo.nix directly

I installed the latest version (0.8.2) of cargo2nix yesterday using nix-env -iA package -f https://github.com/tenx-tech/cargo2nix/tarball/master.

I cannot create Cargo.nix directly using cargo2nix -f. It panics with Invalid cross-device link (os error 18):

$ cargo2nix -f
error: could not write file to Cargo.nix

Caused by:
  failed to persist temporary file: Invalid cross-device link (os error 18)

As a workaround, cargo2nix -s > Cargo.nix worked for me.

I'm using Linux on a 5.5.9 Kernel using ext4 as filesystem.

Publish to crates.io

  • Update Cargo.toml to include required fields.
  • Setup CI to auto publish on new releases.

Add some sample projects

I believe we could improve the user experience a bit by providing a few sample Cargo crates and crate workspaces converted to use cargo2nix. This would provide useful examples for potential users looking to convert their projects, but might not know exactly how to get started with the instructions given in the README.

Example scenarios:

  1. Single crate (lib and/or bin, combination doesn't exactly matter to cargo2nix)
  2. Multi-crate workspace
  3. Crate with one or more feature flags
  4. Crate with extra directories to be included (e.g. a proto directory for Protobuf projects)
  5. Crate with test runner and some nativeBuildDependencies
  6. Crate with a custom crate override on a sub-dependency

Build dependencies are built with hostPlatformCpu and hostPlatformFeatures

We had an interesting issue related to my PR #119.

Everything built fine on our own build servers, and we got a nice CPU optimized asset out of the remote end. But then a customer tried to build it on their own machine and the build failed with SIGILL.

It transpires, that we've got the following dependency chain: our code -> clap -> indexmap, and it is the compilation of indexmap that was failing.

After some investigation, it turns out that indexmap uses a crate called autocfg as part of its build script:

https://github.com/bluss/indexmap/blob/master/build.rs#L4

So although the build script gets built with a different set of flags to crates, autocfg is just a regular crate and gets built with the same hostPlatformCpu and hostPlatformFeatures as any other crate, which then meant that the build script binary couldn't be run on the customer's build server because it didn't have those instruction sets.

I figured that was something worth having a conversation about.

One potential solution I could see is to have crates have both build and host variants in Cargo.nix and then having the buildDependencies refer to the build variant instead of the host variant.

I apologize if an issue isn't the right place to discuss this, if there's a better place, I'll happily discuss it there :)

profilesByName emitting doesn't escape strings

Howdy.

I tried adding:

[profile.release]
lto = "fat"

To my Cargo.toml, but when cargo2nix generates Cargo.nix, it emits:

   profilesByName = {
     release = builtins.fromTOML "lto = "fat"
 ";
   };

I'm unclear about the redundant new-line, but the main thing here is that the quotes inside of the TOML need escaping somehow, presumably before being passed to the template.

As a workaround, I'm able to use lto = true instead, but there are other potentially string-valued parameters that folks might want to change, for example the panic parameter.

Rewrite with Async/Await

Looks like async/await is stable in Rust 1.39.0. 🎊

There is a possibility that we can switch to async/await as well as std::future. This will depends on whether we want to switch to 1.39.0.

This can be assigned to me if ✋ is needed.

Optionally generate a minimal default.nix

Currently, the process for converting a crate to use cargo2nix for the first time is a very mechanical and repetitive transformation of the default.nix file included in this repo. We should provide the optional capability to generate a new default.nix for a project, similar to yarn2nix, for the sake of improving the user experience. Perhaps this could be achieved by adding a flag to cargo2nix gen, perhaps --new?

Committing generated code

My teammates are a bit reticent to commit what's essentially a generated file from a generated file. I can't explain to them why we shouldn't, so I figured I'd ask the maintainers, why do you commit the Cargo.nix in your repo when it could be generated from Cargo.lock?

Example '1-hello-world' not working

Hi I try to build the example '1-hello-world'.

I follow the README instructions and get this error on nix-build

nix-build
error: cannot update ref 'refs/heads/v0.9.0': trying to write non-commit object 50b861a95e0e69edddb651883a4df0b5286a0883 to branch 'refs/heads/v0.9.0'
error: program 'git' failed with exit code 1
# default.nix
{
  system ? builtins.currentSystem,
  nixpkgsMozilla ? builtins.fetchGit {
    url = https://github.com/mozilla/nixpkgs-mozilla;
    rev = "50bae918794d3c283aeb335b209efd71e75e3954";
  },
  cargo2nix ? builtins.fetchGit {
    url = https://github.com/cargo2nix/cargo2nix;
    ref = "v0.9.0";
  },
}:
let
  rustOverlay = import "${nixpkgsMozilla}/rust-overlay.nix";
  cargo2nixOverlay = import "${cargo2nix}/overlay";

  pkgs = import <nixpkgs> {
    inherit system;
    overlays = [ rustOverlay cargo2nixOverlay ];
  };

  rustPkgs = pkgs.rustBuilder.makePackageSet' {
    rustChannel = "stable";
    packageFun = import ./Cargo.nix;
  };
in
  rustPkgs.workspace.hello-world {}

Cargo.nix.TXT

Cargo.toml.TXT

Rust 1.47 - Cannot parse v2 Lockfile Format

So, the latest Rust version got pushed to stable last night, which includes a new lockfile format, and it breaks all our builds. We were able to fix it by replacing stable with 1.46.0, but that's not ideal.

The error we got was:
error: failed to parse lock file at: /build/bitflags-1.2.1/Cargo.lock

It wasn't just bitflags, there were several packages that broke, but that's just an example.

Update to latest cargo API encounters breaking changes

Updating the cargo dependency is mostly straightforward except changes to one method cargo2nix uses, cargo::ops::resolve_ws_with_opts because of the new arguments it accepts

https://docs.rs/cargo/0.44.0/cargo/ops/fn.resolve_ws_with_opts.html
https://docs.rs/cargo/0.41.0/cargo/ops/fn.resolve_ws_with_opts.html

Most of the changes happened in this PR
rust-lang/cargo#7820

Here's internal usages of those arguments:
https://github.com/rust-lang/cargo/search?q=HasDevUnits&unscoped_q=HasDevUnits
https://github.com/rust-lang/cargo/search?q=CompileKind&unscoped_q=CompileKind

I'm filing this issue because at a minimum, the API changes will block cargo2nix from using newer cargo features, meaning some projects with recent cargo features cannot be built with current cargo2nix

target_arch match in Cargo.nix

target_arch in Cargo.toml dependencies is converted to a comparison with hostPlatform.parsed.cpu.name, which is invalid for hostPlatforms whose arch name differs from rust expected naming, like "armv6l" or "armv7l".

Some kind of conversion from hostPlatform should be applied before passing as argument to packageFun.

Openssl configuration override necesary to build

This issue is worked around in #153 but there's no way that solution should be preferred if possible

The behavior observed without the fix is that the configuration is empty of any of the ossl111 etc that determine how openssl-sys builds. The result is a later failure to link against openssl

Test debug builds in CI

Our CI pipeline currently builds cargo2nix and our examples integration test suite in release mode only. As suggested in #125 (review), we should also check the integrity of debug builds in CI to catch any future regressions.

This can be done either by adding a dedicated Cargo project in examples which builds exclusively in debug mode, or ideally, by adding a release ? true parameter to each of the existing sample projects and build them all in both release and debug mode.

Provide shell completions for the CLI tool

It would be convenient if we could ship some bash, zsh, and fish shell completions for the cargo2nix code generation tool. We could maintain these shell completions ourselves, or ideally, we could switch to clap and/or structopt for argument parsing and generate these completions at build-time with a build.rs.

"Cannot convert data to toml"

Hello! I'm using cargo2nix for the first time - and indeed compiling a Rust program for the first time - and it's starting off great but I'm hitting some errors like this:

unpacking sources
unpacking source archive /nix/store/43ksm0c42cmsy0am22vv2nm4rkqwbddx-byteorder-1.3.4.tar.gz
source root is byteorder-1.3.4
setting SOURCE_DATE_EPOCH to timestamp 1581081480 of file byteorder-1.3.4/Cargo.toml
patching sources
configuring
building
Error: Cannot convert data to TOML (Invalid type <class 'NoneType'>)

and I'm wondering if someone could suggest a way to troubleshoot this?

Background links:

Thanks for any pointers!

Add pre and post-build hooks after compilation

It would be interesting if we could add optional preBuild and postBuild attributes which would allow for arbitrary shell commands to be run before and after compiling a crate. An example usage could be something like running cargo clippy after compilation, for example:

rustPkgs.workspace.foo { postBuild = "cargo clippy"; }

This would take advantage of the rustc wrapper that cargo2nix uses internally, which would leverage the cached crate derivations in the Nix store.

CC @snawaz @trha

Consider using builtins.fetchGit over nix-prefetch-git

We currently make use of fetchgitPrivate inside the overlay for fetching Git dependencies, but fetchgitPrivate has been removed from newer versions of Nixpkgs.

Since builtins.fetchGit exists since Nix 2.0 and is capable of fetching Git repos at evaluation time without needing a sha256 value, and it even works with private Git repos in much the same manner as fetchgitPrivate once did, there isn't much reason to stick with nix-prefetch-git anymore (source). We should probably drop our dependency on nix-prefetch-git and serde_json and use builtins.fetchGit in the overlay instead.

Note that this would be a breaking change to the overlay since as we would have to remove the sha256 argument from fetchCrateGit. This would require us to release a new minor version.

Improve localPatterns

Suggest splitting this:

    localPatterns = [
      ''^(src)(/.*)?''
      ''^(migrations)(/.*)?''
      ''^(proto)(/.*)?''
      ''[^/]*\.(rs|toml)$''
    ];

...into two lists of
includeLocalFiles
includeLocalDirs

Remove outdated sha256 argument from overlay

There seems to be a bug in the overlay in master regarding Git dependencies:

error: 'fetchCrateGit' at /nix/store/yzjjjwdxc451y6g5rlj17gqhm26wizb3-source/overlay/lib/fetch.nix:9:19 called without required argument 'sha256', at /Users/eyalkalderon/Documents/foo/Cargo.nix:2321:11

Looks like I forgot to remove the sha256 argument from the overlay in PR #124, and it wasn't caught in our integration test suite somehow. I'll fix that right away.

Provide more default values in overlay

Considering the high complexity of the default.nix referenced by most projects, it would be nice if we provided more default values in the cargo2nix overlay to reduce the initial boilerplate. Some examples include:

  1. Restoring <nixpkgs> as the default, if left unspecified. This used to be the default value, but was changed to help cross-compilation of cargo2nix specifically. The nixpkgs.nix isn't needed for projects using cargo2nix as a build system, so maybe the generated default.nix would simply use <nixpkgs> as the default (see #18).
  2. Importing the cargo2nix overlay could also re-export the nixpkgs-mozilla overlay, with the latest Rust stable selected as the default and aarch64-unknown-linux-gnu enabled, if left unspecified.
  3. Common patched dependencies such as openssl and macosFrameworks could be re-exported from the overlay, if needed.
  4. resolveResponse and rustPackagesWithResolve could have a default value for simple cases where manual resolution isn't necessary or impractical for a given project.

Any thoughts, @dingxiangfei2009?

Compilation with musl fails on NixOS 19.09.2166

Description

It appears that compilation of cargo2nix on NixOS 19.09.2166 fails when installing with nix-env but without --arg crossSystem null, defaulting the libc selection to musl. The command in question is:

# At the time of writing, `master` is at commit 29a9093
# Notice the lack of `--arg crossSystem null` here
nix-env -iA package -f https://github.com/tenx-tech/cargo2nix/tarball/master

The error seems to be coming from within the perl5.28.2-FCGI-0.78 builder, which looks like this:

Error output ``` building '/nix/store/qg4abdv40mj45w6x6n5dmmpy4wrkhi8-perl5.28.2-FCGI-0.78-x86_64-unknown-linux-musl.drv'... unpacking sources unpacking source archive /nix/store/n6zz3r5777ydfiv2lyjijvwdjv2j7qxz-FCGI-0.78.tar.gz source root is FCGI-0.78 setting SOURCE_DATE_EPOCH to timestamp 1457309258 of file FCGI-0.78/os_win32.c patching sources updateAutotoolsGnuConfigScriptsPhase configuring patching ./configure... patching ./eg/threaded.pl... patching ./eg/remote.pl... patching ./eg/echo.pl... Can't load module IO, dynamic loading not available in this perl (You may need to build a new perl executable which either supports dynamic loading or has the IO module statically linked into it.) at /nix/store/9jbxnmc146sh19x4ymkikyyava666m2a-perl-5.28.2-x86_64-unknown-linux-musl/lib/perl5/5.28.2/x86_64-linux/IO/Handle.pm line 268. Compilation failed in require at /nix/store/9jbxnmc146sh19x4ymkikyyava666m2a-perl-5.28.2-x86_64-unknown-linux-musl/lib/perl5/5.28.2/x86_64-linux/IO/Handle.pm line 268. BEGIN failed--compilation aborted at /nix/store/9jbxnmc146sh19x4ymkikyyava666m2a-perl-5.28.2-x86_64-unknown-linux-musl/lib/perl5/5.28.2/x86_64-linux/IO/Handle.pm line 268. Compilation failed in require at /nix/store/9jbxnmc146sh19x4ymkikyyava666m2a-perl-5.28.2-x86_64-unknown-linux-musl/lib/perl5/5.28.2/x86_64-linux/IO/Seekable.pm line 100. BEGIN failed--compilation aborted at /nix/store/9jbxnmc146sh19x4ymkikyyava666m2a-perl-5.28.2-x86_64-unknown-linux-musl/lib/perl5/5.28.2/x86_64-linux/IO/Seekable.pm line 100. Compilation failed in require at /nix/store/9jbxnmc146sh19x4ymkikyyava666m2a-perl-5.28.2-x86_64-unknown-linux-musl/lib/perl5/5.28.2/x86_64-linux/IO/File.pm line 132. BEGIN failed--compilation aborted at /nix/store/9jbxnmc146sh19x4ymkikyyava666m2a-perl-5.28.2-x86_64-unknown-linux-musl/lib/perl5/5.28.2/x86_64-linux/IO/File.pm line 132. Compilation failed in require at Makefile.PL line 5. BEGIN failed--compilation aborted at Makefile.PL line 5. builder for '/nix/store/qg4abdv40mj45w6x6n5dmmpy4wrkhi8-perl5.28.2-FCGI-0.78-x86_64-unknown-linux-musl.drv' failed with exit code 255 cannot build derivation '/nix/store/frss7dihaj45692z168zp3dsg0lcgbpl-git-2.22.0-x86_64-unknown-linux-musl.drv': 1 dependencies couldn't be built building '/nix/store/9jpk5ckr1zy4diq8am5qf5g53a0gf64f1-rust-std-1.37.0-x86_64-unknown-linux-musl.tar.xz.drv'... cannot build derivation '/nix/store/n4df028cb78pysqpw1d8ibw9ak6fc6mx-nix-prefetch-git-x86_64-unknown-linux-musl.drv': 1 dependencies couldn't be built cannot build derivation '/nix/store/xjswkwp96gnxzjfj0mqy1f79w6vlh92r-crate-cargo2nix-0.8.1-x86_64-unknown-linux-musl.drv': 1 dependencies couldn't be built error: build of '/nix/store/xjswkwp96gnxzjfj0mqy1f79w6vlh92r-crate-cargo2nix-0.8.1-x86_64-unknown-linux-musl.drv' failed ```

It appears that Nix is attempting to cross-compile not just cargo2nix to musl, but also nix-prefetch-git as well, which fails due to the FCGI Perl module failing to cross-compile.

It is not immediately clear whether this is an issue, since the instructions in the README specifically instruct users to install the cargo2nix tool with crossSystem set to null. Additionally, compilation of the cargo2nix codegen binary itself under musl isn't explicitly recommended nor supported, and the error isn't caused by a defect in the cargo2nix overlay either.

For that reason, I'm labeling this issue a question since we need to determine whether to consider this a bug or not.

Steps to reproduce

  • Download the official NixOS 19.09 demo VirtualBox appliance (link, SHA-256)
  • Load it into VirtualBox, VMware, or any hypervisor which supports the OVA format
  • Log in and launch a terminal
  • nix-env -iA package -f https://github.com/tenx-tech/cargo2nix/tarball/29a90937b3e30237245c71aa7dd0a09904ca7dd8

Git Deps Support Broken

First the Broken Parts

The overlay, necessary for consuming generated Cargo.nix currently contains broken references to fetchgitPrivate
https://github.com/tenx-tech/cargo2nix/blob/master/overlay/lib/fetch.nix#L11-L12

$ nix-channel --list
...
nixos https://nixos.org/channels/nixos-20.03

$ nix repl '<nixpkgs>'
nix-repl> buildPackages.fetchgitPrivate
error: attribute 'fetchgitPrivate' missing, at (string):1:1

fetchgitPrivate is actually dead in master nixpkgs

Crafting a Fix

There are three contexts to reconcile:

Cargo

Specifying dependencies from git repositories

Since we haven’t specified any other information, Cargo assumes that we intend to use the latest commit on the master branch to build our package. You can combine the git key with the rev, tag, or branch keys to specify something else.

Cargo lockfiles do not appear to include checksums for git dependencies.

Cargo2Nix

https://github.com/tenx-tech/cargo2nix/blob/master/templates/Cargo.nix.tera#L49-L55

Nix

fetchgit doesn't fetch at evaluation time
fetchGit doesn't accept a sha256 argument (this is being calculated by cargo2nix since it's not in the cargo docs.)
fetchFromGitHub will of course only work for Github

The most functionality will be covered by switching fetchGit. The downside is that the sha256 argument needs to be ignored and no integrity check will be performed. This sha256 pin & check may be possible for generic git, but the appropriate place for a fix would be upstream in nixpkgs, not in cargo2nix.

Tracking Integrity Issues

I attempted to contextualize the choices within the Rust community and found Boats discussing the update framework rust-lang/cargo#4768 I was unable to find an issue to add sha256 support to git fetchers generically in nixpkgs. Recommend adding tracking issues to this repo if other integrity check work is known.

Put intermediate files into separate dependency

This is the first issue focused on long-term improvements to architecture.

The various files that we write into the outputs in order to support later linking have negative effects on the generation of profiles and also on closure sizes as nix assumes that all these files that we need at link time etc are parts of output closures.

The bin target separation in #153 is basically a hack to address the symptom of this issue.

These files could be unique for some builds while having no effect at all on the actual outputs of dependencies, possibly resulting in duplication in the store?

Another issue we could be facing is taking on too much responsibility from cargo that may have been baked into earlier releases when other solutions in cargo meta data etc were not available. Libraries such as cargo-lock and guppy have come about and may solve some of the issues in a more lightweight manner

Use nixpkgs from cargo2nix flake by default

There's little reason to require the user to supply their own overlay pins while baking the Cargo.nix. It adds a lot of process overhead to simple packaging and in 99% of cases the right answer is to use the same overlay version as at the time of creating the Cargo.nix

Include Custom Directories in Build Sandbox

If a project depends on other files in the repository other than src, Cargo.* and any potential build scripts, e.g. a template directory, these are not included in the build sandbox and the build fails.

I prepared a testcase again (this time with everything pinned using niv): https://github.com/vbrandl/cargo2nix-ructe-testcase

It uses ructe for templating and the templates are located in the templates directory.

The build fails while evaluating the build.rs script.

Similar problems might happen when using tools like vergen to include e.g. the commit hash at compile time, since it needs at least .git and it's contents.

Is there a way to include some (or all) files in the repository inside the build sandbox?

I don't know if this is actually an issue with cargo2nix or with me not knowing enough about nix expressions...

Investigate import-from-derivation pattern

A common pattern used by several foo2nix tools is the import-from-derivation pattern.

In this pattern, users do not call cargo2nix -f directly and check in the resulting Cargo.nix into source control. Instead, a function inside the default.nix takes the top-level Cargo.toml and Cargo.lock as input and runs cargo2nix -f inside of a Nix derivation, vendoring the generated Cargo.nix into the Nix store. As long as the input Cargo.toml and Cargo.lock do not change, the command is not executed again.

Error building OpenSSL

I have a crate that depends on OpenSSL through git2 to be able to clone repositories via https.

When trying to build OpenSSL, nix-build fails with

<snip>
*** Installing runtime programs                                                                                                                                           
install apps/openssl -> /nix/store/6dgjjir56h5bjsjcvhbjy0kz4lzjiggn-openssl-1.1.1d/bin/openssl                                                                            
install ./tools/c_rehash -> /nix/store/6dgjjir56h5bjsjcvhbjy0kz4lzjiggn-openssl-1.1.1d/bin/c_rehash                                                                       
rm: cannot remove '/nix/store/6dgjjir56h5bjsjcvhbjy0kz4lzjiggn-openssl-1.1.1d/etc/ssl/misc': No such file or directory                                                    
builder for '/nix/store/ydyxwaq8zkqpq3pn63az1mbqaai45lvi-openssl-1.1.1d.drv' failed with exit code 1                                                                      
building '/nix/store/92l795axyqs3s8vc9828pj653k15zpcf-openssl-sys-0.9.54.tar.gz.drv'...                                                                                   
cannot build derivation '/nix/store/019pl8a07ys1nkkscm7l271743rxfflg-openssl.drv': 1 dependencies couldn't be built                                                       
cannot build derivation '/nix/store/vvin0c5x2yzqi36bmm38pgfl24qjry28-exports.sh.drv': 1 dependencies couldn't be built                                                    
cannot build derivation '/nix/store/361abpqh31fprx0jldn3kqbbgil87px7-openssl-sys-propagate-env.drv': 1 dependencies couldn't be built                                     
cannot build derivation '/nix/store/wmgmrzi2ixz26zmbw7zrvd8yrs5hs2rk-crate-git_test-0.1.0.drv': 1 dependencies couldn't be built                                          
error: build of '/nix/store/wmgmrzi2ixz26zmbw7zrvd8yrs5hs2rk-crate-git_test-0.1.0.drv' failed

I created a small testcase to reproduce the issue: https://github.com/vbrandl/cargo2nix-git2-testcase. It uses the current HEAD (e912ed483e980dfb4666ae0ed17845c4220e5e7c) of the mozilla overlay.

I tried building the same testcase using crate2nix, which build the project but resulted in runtime errors when executing the binary (nix-community/crate2nix#103)

Empty Cargo.nix file is generated upon panic

It appears that when cargo2nix -f is run against a crate workspace and Cargo aborts execution due to --locked (see #75), a zero-length Cargo.nix file is inadvertently produced. It seems that we call File::create() too early in the startup phase, creating an empty file that ends up being left behind after cargo2nix exits with an error.

Providing Rust Src for `RUST_SRC_PATH`

rust-lang/rust#73265 Evidently there's a path change coming up that will be reflected in a rust minor version. Also the srcs provided by the rust-src path are quite a bit different than the pkgs.rustPlatform.rustSrc attribute. The tarball that provides that src has about 1G of vendored sources in addition to rustc files themselves. Likely this causes Rust Analyzer not to work properly, as observed with completions for std when utilizing the provided RUST_SRC_PATH for cargo2nix.

The tarballs for 1.45 and 1.48 have ~20k Rust files while rust-src nix path contains only about 1k files. Clearly there's a different way to obtain a complete enough view of the source for rust analyzer to work.

Cannot compile zmq and zmq-sys

Perhaps this is related to, or the same as, #130.

Given the following repo and branch: https://github.com/bsima/rust-zmq/tree/cargo2nix-bug

We get error: couldn't read build/main.rs: No such file or directory (os error 2)

I believe the fix could be as simple as including the directory or file specified in the build directive from the Cargo.toml into the source tree when creating the derivation, but I'm not sure where this happens. If you can point me to the relevant code, I'd be happy to try and fix it.

I discovered this while trying to build a package that relies on tmq, which in turn relies on zmq. Maybe there is a way to fix this in the overlay, if so please advise, but I haven't been able to figure it out yet (aside: it would be helpful if overlay/lib/overrides.nix were exposed to the user, so I could just use your makeOverride function in my own overrides).

In any case, I would think that cargo2nix should be able to handle these kinds of local dependencies, so I'm filing this as a bug.

Full shell output

$ nix-build
these derivations will be built:
  /nix/store/c8rm5qxaxskgmv2mi538s8slb982pg03-crate-zmq-sys-0.11.0.drv
  /nix/store/f74yv9znnbicj2zw516ysf8l1n12ml57-crate-zmq-0.9.2.drv
building '/nix/store/c8rm5qxaxskgmv2mi538s8slb982pg03-crate-zmq-sys-0.11.0.drv'...
unpacking sources
unpacking source archive /nix/store/1sbmw2hab1bp3q4j7qh8nfzkk9kf8h92-source
source root is source
patching sources
configuring
building
   Compiling zmq-sys v0.11.0 (/private/var/folders/nk/rbcl1cjn7ljbgcfr04m_jyb40000gn/T/nix-build-crate-zmq-sys-0.11.0.drv-0/source)
{"reason":"compiler-message","package_id":"zmq-sys 0.11.0 (path+file:///private/var/folders/nk/rbcl1cjn7ljbgcfr04m_jyb40000gn/T/nix-build-crate-zmq-sys-0.11.0.drv-0/source)","target":{"kind":["custom-build"],"crate_types":["bin"],"name":"build-script-main","src_path":"/private/var/folders/nk/rbcl1cjn7ljbgcfr04m_jyb40000gn/T/nix-build-crate-zmq-sys-0.11.0.drv-0/source/build/main.rs","edition":"2015","doctest":false},"message":{"rendered":"error: couldn't read build/main.rs: No such file or directory (os error 2)\n\n","children":[],"code":null,"level":"error","message":"couldn't read build/main.rs: No such file or directory (os error 2)","spans":[]}}
{"reason":"compiler-message","package_id":"zmq-sys 0.11.0 (path+file:///private/var/folders/nk/rbcl1cjn7ljbgcfr04m_jyb40000gn/T/nix-build-crate-zmq-sys-0.11.0.drv-0/source)","target":{"kind":["custom-build"],"crate_types":["bin"],"name":"build-script-main","src_path":"/private/var/folders/nk/rbcl1cjn7ljbgcfr04m_jyb40000gn/T/nix-build-crate-zmq-sys-0.11.0.drv-0/source/build/main.rs","edition":"2015","doctest":false},"message":{"rendered":"error: aborting due to previous error\n\n","children":[],"code":null,"level":"error","message":"aborting due to previous error","spans":[]}}
{"reason":"build-finished","success":false}
error: could not compile `zmq-sys`.
To learn more, run the command again with --verbose.
builder for '/nix/store/c8rm5qxaxskgmv2mi538s8slb982pg03-crate-zmq-sys-0.11.0.drv' failed with exit code 101
cannot build derivation '/nix/store/f74yv9znnbicj2zw516ysf8l1n12ml57-crate-zmq-0.9.2.drv': 1 dependencies couldn't be built
error: build of '/nix/store/f74yv9znnbicj2zw516ysf8l1n12ml57-crate-zmq-0.9.2.drv' failed

Flake support

  • Build as a flake output #161
  • Include flake in project
  • Equip CI with nix version with flake support to maintain flakes

Add compile mode for cargo check

As mentioned in #92 (comment), we should add an option for compileMode = "check", which would correspond to cargo check. This would be useful for supporting other tools like Clippy in Nix expressions run in CI environments, for example.

To find what artifacts should be copied to the Nix store in a cargo check compile mode, we first generate a new crate with cargo new --bin foo and then check the contents of the target directory after each command (with a cargo clean in between each run).

cargo check

target
└── debug
    ├── build
    ├── deps
    │   ├── foo-3c902f3ce96f8337.d
    │   └── libfoo-3c902f3ce96f8337.rmeta
    ├── examples
    ├── incremental
    │   └── foo-2hoi7zn3kcata
    │       ├── s-flx0c62kz4-1uiqlpc-qmasrgjks254
    │       │   ├── dep-graph.bin
    │       │   ├── query-cache.bin
    │       │   └── work-products.bin
    │       └── s-flx0c62kz4-1uiqlpc.lock
    └── native

cargo check --release

target
└── release
    ├── build
    ├── deps
    │   ├── foo-67a189b0d138f374.d
    │   └── libfoo-67a189b0d138f374.rmeta
    ├── examples
    ├── incremental
    └── native

From this, it seems that the .d and .rmeta artifacts are of the most importance and should definitely be copied into the Nix store. Running cargo clippy and cargo clippy --release also produced identical results, which confirms that both check and clippy share the same cache and that the latter doesn't produce any additional artifacts.

The real question is how to expose the artifacts from the Nix store into the current build. For all other compile modes, we achieve this using a rustc wrapper which silently forwards vendored artifacts from the Nix store to the compiler. However, these artifacts aren't rlibs, so I assume this wrapper won't be able to help us here.

CC @trha, do you have any ideas?

Brief diversion about rmeta artifacts

According to this comment on rust-lang/cargo, it seems that both cargo build and cargo check produce .rmeta artifacts, but each contains slightly different data and aren't interchangeable at the time of writing.

We currently don't retain these.rmeta artifacts in derivations built with compileMode = "build" in cargo2nix. Crates seem to compile perfectly fine without them, so presumably either cargo or rustc is generating them on the fly if it has access to the source directory. Should we keep these .rmeta files in compileMode = "build" as well? It would seem a bit inconsistent for us to retain them in check mode but not in build mode.

Integration tests are not included in output

The officially supported method of producing test binaries in a cargo2nix project is to build the crate with compileMode = "test". Unfortunately, it appears that among the test binaries produced, any integration test binaries from the top-level tests directory are not included.

It seems that inline library tests, main.rs tests, and src/bin/* tests are included in the output, but integration tests from the tests directory are not. Like the other tests, the integration tests produced by Cargo are located in target/<host-triple>/<profile>/<test-name>-<hash>. I believe we should include these in the derivation output as well.

CI Improvements

Getting a lot of I/O noise in CI. it's a bit too flaky.

Also there is no cross compile smoke test. We have little warning when this is broken

Circle CI build logs are not visible to outside users

cargo2nix is an open source project with public CI builds hosted on CircleCI. I am able to view the build log without being logged in, and I can confirm from the dashboard that the cargo2nix workflow is configured to be public as a FOSS project.

Unfortunately, it seems that attempting to view a CircleCI build linked from GitHub leads to a redirect to CircleCI's new app experience, resulting in a "page not found" error. This is a bit annoying because it means that community contributors cannot view their own pull requests' build logs.

Depends on nix-prefetch-git implicitly

Current cargo2nix has an implicit runtime dependency on nix-prefetch-git for workspaces that need to pull in crates via git at least.

I would add it as propagatedBuildInput, but cross-compilation for nix-prefetch-git on musl64 is currently failing with some perl fu:

updateAutotoolsGnuConfigScriptsPhase                                                                             │Attempt to reload Scalar/Util.pm aborted.
patching ./t/write_default_maniskip.t...                                                                         │Compilation failed in require at /nix/store/kvadi9vl2alx6jy8hfbxr7ldccj184sc-perl-5.30.0-x86_64-unknown-linux-mu
Updating Autotools / GNU config script to a newer upstream version: ./build-aux/config.sub                       │sl/lib/perl5/5.30.0/x86_64-linux/Data/Dumper.pm line 304.
Updating Autotools / GNU config script to a newer upstream version: ./build-aux/config.guess                     │Couldn't run Build.PL: No such file or directory at lib/Module/Build/Compat.pm line 341.
patching ./t/PL_files.t...                                                                                       │cp lib/Test/Deep/Ref.pm blib/lib/Test/Deep/Ref.pm
configuring                                                                                                      │cp lib/Test/Deep/ArrayLength.pm blib/lib/Test/Deep/ArrayLength.pm
patching ./t/test_types.t...                                                                                     │cp lib/Test/Deep.pm blib/lib/Test/Deep.pm
patching ./t/files.t...                                                                                          │cp lib/Test/Deep/Boolean.pm blib/lib/Test/Deep/Boolean.pm
checking for x86_64-unknown-linux-musl-gcc... x86_64-unknown-linux-musl-gcc                                      │cp lib/Test/Deep/ArrayLengthOnly.pm blib/lib/Test/Deep/ArrayLengthOnly.pm
patching ./t/install.t...                                                                                        │cp lib/Test/Deep/Cache/Simple.pm blib/lib/Test/Deep/Cache/Simple.pm
Can't load module IO, dynamic loading not available in this perl.                                                │cp lib/Test/Deep/RefType.pm blib/lib/Test/Deep/RefType.pm
  (You may need to build a new perl executable which either supports                                             │cp lib/Test/Deep/HashKeysOnly.pm blib/lib/Test/Deep/HashKeysOnly.pm
  dynamic loading or has the IO module statically linked into it.)                                               │cp lib/Test/Deep/Array.pm blib/lib/Test/Deep/Array.pm
 at /nix/store/9jbxnmc146sh19x4ymkikyyava666m2a-perl-5.28.2-x86_64-unknown-linux-musl/lib/perl5/5.28.2/x86_64-lin│cp lib/Test/Deep/HashElements.pm blib/lib/Test/Deep/HashElements.pm
ux/IO/Handle.pm line 268.                                                                                        │cp lib/Test/Deep/ListMethods.pm blib/lib/Test/Deep/ListMethods.pm
Compilation failed in require at /nix/store/9jbxnmc146sh19x4ymkikyyava666m2a-perl-5.28.2-x86_64-unknown-linux-mus│cp lib/Test/Deep/RegexpRef.pm blib/lib/Test/Deep/RegexpRef.pm
l/lib/perl5/5.28.2/x86_64-linux/IO/Handle.pm line 268.                                                           │cp lib/Test/Deep/Stack.pm blib/lib/Test/Deep/Stack.pm
BEGIN failed--compilation aborted at /nix/store/9jbxnmc146sh19x4ymkikyyava666m2a-perl-5.28.2-x86_64-unknown-linux│cp lib/Test/Deep/Shallow.pm blib/lib/Test/Deep/Shallow.pm
-musl/lib/perl5/5.28.2/x86_64-linux/IO/Handle.pm line 268.                                                       │cp lib/Test/Deep/Isa.pm blib/lib/Test/Deep/Isa.pm
Compilation failed in require at /nix/store/9jbxnmc146sh19x4ymkikyyava666m2a-perl-5.28.2-x86_64-unknown-linux-mus│cp lib/Test/Deep/RegexpMatches.pm blib/lib/Test/Deep/RegexpMatches.pm
l/lib/perl5/5.28.2/x86_64-linux/IO/Seekable.pm line 100.                                                         │cp lib/Test/Deep/HashEach.pm blib/lib/Test/Deep/HashEach.pm
BEGIN failed--compilation aborted at /nix/store/9jbxnmc146sh19x4ymkikyyava666m2a-perl-5.28.2-x86_64-unknown-linux│cp lib/Test/Deep/MM.pm blib/lib/Test/Deep/MM.pm
-musl/lib/perl5/5.28.2/x86_64-linux/IO/Seekable.pm line 100.                                                     │x86_64-unknown-linux-musl-strip is /nix/store/gkq6rh8nj8i7prh4c9rawhwrk5g20cfx-x86_64-unknown-linux-musl-binutil
Compilation failed in require at /nix/store/9jbxnmc146sh19x4ymkikyyava666m2a-perl-5.28.2-x86_64-unknown-linux-mus│s-2.31.1/bin/x86_64-unknown-linux-musl-strip
l/lib/perl5/5.28.2/x86_64-linux/IO/File.pm line 132.                                                             │Removing empty /nix/store/q76nwhzd6v9b5j8kf2kchqn4b5yzsd93-perl5.30.0-Test-RequiresInternet-0.05-x86_64-unknown-
BEGIN failed--compilation aborted at /nix/store/9jbxnmc146sh19x4ymkikyyava666m2a-perl-5.28.2-x86_64-unknown-linux│linux-musl/share/man/ and (possibly) its parents
-musl/lib/perl5/5.28.2/x86_64-linux/IO/File.pm line 132.                                                         │patching script interpreter paths in /nix/store/ivw23rb4hk0mfl6smd37gqs7ak0dlwb0-perl5.30.0-IO-HTML-1.001-x86_64
Compilation failed in require at Makefile.PL line 5.                                                             │-unknown-linux-musl-devdoc
BEGIN failed--compilation aborted at Makefile.PL line 5.                                                         │cp lib/Test/Deep/All.pm blib/lib/Test/Deep/All.pm
configure flags: --disable-dependency-tracking --prefix=/nix/store/wbn67ycs6vnw2qddqh00jxfhwwysafzi-cpio-2.12-x86│cp lib/Test/Deep/RegexpVersion.pm blib/lib/Test/Deep/RegexpVersion.pm
_64-unknown-linux-musl --build=x86_64-unknown-linux-gnu --host=x86_64-unknown-linux-musl                         │builder for '/nix/store/khsym56j66s32ki1sgfqvpa0v36fcf5l-perl5.30.0-Module-Build-0.4229-x86_64-unknown-linux-mus
patching ./t/extend.t...                                                                                         │l.drv' failed with exit code 2
builder for '/nix/store/9kyibxdmp4nw8a9glvz79vg69ycqrhih-perl5.28.2-FCGI-0.78-x86_64-unknown-linux-musl.drv' fail│cannot build derivation '/nix/store/cb67anzy216wrqq5jl49azai6wad7pi4-perl5.30.0-HTML-TagCloud-0.38-x86_64-unknow
ed with exit code 255                                                                                            │n-linux-musl.drv': 1 dependencies couldn't be built
cannot build derivation '/nix/store/z4j738hxcnpmpa4m65k9xkz1bwjw5237-git-2.22.0-x86_64-unknown-linux-musl.drv': 1│cannot build derivation '/nix/store/n2986pg9s46mkhm866rcv7211bd99c85-git-2.23.0-x86_64-unknown-linux-musl.drv': 
 dependencies couldn't be built                                                                                  │1 dependencies couldn't be built
cannot build derivation '/nix/store/qvyg35knid1fb93iyjj0jl742jamyhkk-nix-prefetch-git-x86_64-unknown-linux-musl.d│cannot build derivation '/nix/store/g3q6c0wiiq4df7p0bz1wx86qskg18csa-nix-prefetch-git-x86_64-unknown-linux-musl.
rv': 1 dependencies couldn't be built                                                                            │drv': 1 dependencies couldn't be built
cannot build derivation '/nix/store/0iwsy3wlkd3ccaninza76a0m7kdbvjyp-crate-cargo2nix-0.3.0-x86_64-unknown-linux-m│error: build of '/nix/store/g3q6c0wiiq4df7p0bz1wx86qskg18csa-nix-prefetch-git-x86_64-unknown-linux-musl.drv' fai
usl.drv': 1 dependencies couldn't be built                                                                       │led
error: build of '/nix/store/0iwsy3wlkd3ccaninza76a0m7kdbvjyp-crate-cargo2nix-0.3.0-x86_64-unknown-linux-musl.drv'│ !  ~/c/t/cumbersell   std-nix-setup *~$…                               4m  Wed 30 Oct 2019 12:20:24 PM +08
 failed    

When I run nix-shell -p pkgsCross.musl64.nix-prefetch-git with no funky perl overrides on a fairly recent nixpkgs, I get this:

x86_64-unknown-linux-musl-strip is /nix/store/gkq6rh8nj8i7prh4c9rawhwrk5g20cfx-x86_64-unknown-linux-musl-binutils-2.31.1/bin/x86_64-unknown-linux-musl-strip
cp lib/Test/Deep/NoTest.pm blib/lib/Test/Deep/NoTest.pm
cp lib/Test/Deep/Hash.pm blib/lib/Test/Deep/Hash.pm
cp lib/Test/Deep/Any.pm blib/lib/Test/Deep/Any.pm
cp lib/Test/Deep/Blessed.pm blib/lib/Test/Deep/Blessed.pm
cp lib/Test/Deep/Regexp.pm blib/lib/Test/Deep/Regexp.pm
cp lib/Test/Deep/Obj.pm blib/lib/Test/Deep/Obj.pm
cp lib/Test/Deep/RegexpRefOnly.pm blib/lib/Test/Deep/RegexpRefOnly.pm
cp lib/Test/Deep/Methods.pm blib/lib/Test/Deep/Methods.pm
cp lib/Test/Deep/RegexpOnly.pm blib/lib/Test/Deep/RegexpOnly.pm
cp lib/Test/Deep/None.pm blib/lib/Test/Deep/None.pm
cp lib/Test/Deep/Ignore.pm blib/lib/Test/Deep/Ignore.pm
cp lib/Test/Deep/Set.pm blib/lib/Test/Deep/Set.pm
cp lib/Test/Deep/Number.pm blib/lib/Test/Deep/Number.pm
Removing empty /nix/store/inzrdszvd9n7lrl9ja4vp73cwiwsss4n-perl5.30.0-Test-NoWarnings-1.04-x86_64-unknown-linux-musl/share/man/ and (possibly) its parents
patching script interpreter paths in /nix/store/2ndkbbmigyb4b3nd837ac9j2smr081c9-perl5.30.0-Test-Needs-0.002006-x86_64-unknown-linux-musl-devdoc
checking for references to /tmp/nix-build-perl5.30.0-FCGI-ProcManager-0.28-x86_64-unknown-linux-musl.drv-0/ in /nix/store/5ijqhf0yy4jrzwv75c11z88pnr999fq6-perl5.30.0-FCGI-ProcManager-0.28-x86_64-unknown-linux-musl-devdoc...
Attempt to reload Scalar/Util.pm aborted.
Compilation failed in require at /nix/store/kvadi9vl2alx6jy8hfbxr7ldccj184sc-perl-5.30.0-x86_64-unknown-linux-musl/lib/perl5/5.30.0/x86_64-linux/Data/Dumper.pm line 304.
Couldn't run Build.PL: No such file or directory at lib/Module/Build/Compat.pm line 341.
cp lib/Test/Deep/Ref.pm blib/lib/Test/Deep/Ref.pm
cp lib/Test/Deep/ArrayLength.pm blib/lib/Test/Deep/ArrayLength.pm
cp lib/Test/Deep.pm blib/lib/Test/Deep.pm
cp lib/Test/Deep/Boolean.pm blib/lib/Test/Deep/Boolean.pm
cp lib/Test/Deep/ArrayLengthOnly.pm blib/lib/Test/Deep/ArrayLengthOnly.pm
cp lib/Test/Deep/Cache/Simple.pm blib/lib/Test/Deep/Cache/Simple.pm
cp lib/Test/Deep/RefType.pm blib/lib/Test/Deep/RefType.pm
cp lib/Test/Deep/HashKeysOnly.pm blib/lib/Test/Deep/HashKeysOnly.pm
cp lib/Test/Deep/Array.pm blib/lib/Test/Deep/Array.pm
cp lib/Test/Deep/HashElements.pm blib/lib/Test/Deep/HashElements.pm
cp lib/Test/Deep/ListMethods.pm blib/lib/Test/Deep/ListMethods.pm
cp lib/Test/Deep/RegexpRef.pm blib/lib/Test/Deep/RegexpRef.pm
cp lib/Test/Deep/Stack.pm blib/lib/Test/Deep/Stack.pm
cp lib/Test/Deep/Shallow.pm blib/lib/Test/Deep/Shallow.pm
cp lib/Test/Deep/Isa.pm blib/lib/Test/Deep/Isa.pm
cp lib/Test/Deep/RegexpMatches.pm blib/lib/Test/Deep/RegexpMatches.pm
cp lib/Test/Deep/HashEach.pm blib/lib/Test/Deep/HashEach.pm
cp lib/Test/Deep/MM.pm blib/lib/Test/Deep/MM.pm
x86_64-unknown-linux-musl-strip is /nix/store/gkq6rh8nj8i7prh4c9rawhwrk5g20cfx-x86_64-unknown-linux-musl-binutils-2.31.1/bin/x86_64-unknown-linux-musl-strip
Removing empty /nix/store/q76nwhzd6v9b5j8kf2kchqn4b5yzsd93-perl5.30.0-Test-RequiresInternet-0.05-x86_64-unknown-linux-musl/share/man/ and (possibly) its parents
patching script interpreter paths in /nix/store/ivw23rb4hk0mfl6smd37gqs7ak0dlwb0-perl5.30.0-IO-HTML-1.001-x86_64-unknown-linux-musl-devdoc
cp lib/Test/Deep/All.pm blib/lib/Test/Deep/All.pm
cp lib/Test/Deep/RegexpVersion.pm blib/lib/Test/Deep/RegexpVersion.pm
builder for '/nix/store/khsym56j66s32ki1sgfqvpa0v36fcf5l-perl5.30.0-Module-Build-0.4229-x86_64-unknown-linux-musl.drv' failed with exit code 2
cannot build derivation '/nix/store/cb67anzy216wrqq5jl49azai6wad7pi4-perl5.30.0-HTML-TagCloud-0.38-x86_64-unknown-linux-musl.drv': 1 dependencies couldn't be built
cannot build derivation '/nix/store/n2986pg9s46mkhm866rcv7211bd99c85-git-2.23.0-x86_64-unknown-linux-musl.drv': 1 dependencies couldn't be built
cannot build derivation '/nix/store/g3q6c0wiiq4df7p0bz1wx86qskg18csa-nix-prefetch-git-x86_64-unknown-linux-musl.drv': 1 dependencies couldn't be built
error: build of '/nix/store/g3q6c0wiiq4df7p0bz1wx86qskg18csa-nix-prefetch-git-x86_64-unknown-linux-musl.drv' failed

Generate Cargo2nix from remote source (without manual cloning)

Freezing a remote repo is kind of a pain. It would be preferable if Carog2nix was able to re-generate a fresh Cargo.nix without manually checking out the source being packaged. The cargo provided in the project shell should be sufficient (as a behavioral contract) to fetchGit etc and then cargo2nix -f with that source in a nix-build and then copy the Cargo.nix as the only output, finally checking the version like during a normal freeze.

Honor Cargo.toml "links" Attribute

Probably 95% of crate dependency failures on Linux are due to missing native deps that are trivially identifiable via the Cargo toml links field. Build.rs crates frequently attempt to build a library and an output might be yielded, but it's safe to say that the nixpkgs libs are almost always the better choice for reproducibility if only that. The link issue on #153 on mac didn't at first appear to be the type of issue that a simple override fixes, but it was, and this is very painful for users, manifesting as tricky failures to link rather than a compiler outright missing native sources.

https://doc.rust-lang.org/cargo/reference/manifest.html#the-links-field

I'm guessing most people don't want Cargo2nix for it's capability to do what cargo does but for it's potential to simplify / normalize the native deps issues that the links field was meant to help solve.

We can and should search for a package corresponding to links field declarations and just include that native dep automatically. Overrides in the overlay can then be opt-out

Write up tutorial for static resources example

Since #105 was merged, we need to write up a proper tutorial in a README.md which builds upon concepts introduced from the previous examples and also change the 2-bigger-project tutorial text to reference this new example project.

Dependency on `nix-prefetch-git` not included in PATH

Git dependencies depend on the nix-prefetch-git binary (available in nixpkgs) being included on the system path. cargo2nix relies on the end-user to do this themselves, otherwise it fails on projects with git dependencies.

This could be fixed with a makeWrapper derivation that includes nix-prefetch-git in the PATH when invoking cargo2nix.

Check version compatibility between cargo2nix and Cargo.nix

It'd be good to ensure that the imported cargo2nix is compatible with Cargo.nix of the project.

  • Cargo.nix exposes cargo2nixVersion (the version of cargo2nix which was used to generate this file). We could use this to ensure that the imported cargo2nix version is compatible, else it should fail with a good error message.

Compile errors when building tests for a crate that depends on its own library

You can check the example here: https://github.com/pikajude/cargo2nix/tree/circular-dep-demonstration/examples/4-circular-dependency

The dependency "graph" looks like lib-crate cfg(test) => util-crate => lib-crate (lib).

If you run nix-build examples/4-circular-dependency:

building
   Compiling lib-crate v0.1.0 (/build/lib-crate)
error[E0308]: mismatched types
 --> src/lib.rs:6:33
  |
6 |     assert_eq!(util_crate::show(&LibFoo), "Libfoo");
  |                                 ^^^^^^^ expected struct `lib_crate::LibFoo`, found struct `LibFoo`
  |
  = note: expected reference `&lib_crate::LibFoo`
             found reference `&LibFoo`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0308`.
error: could not compile `lib-crate`.

cargo2nix strips out all the dependency info from Cargo.toml when it builds crates, since the tool itself is the one managing dependency resolution. However, when building a crate like this, we can't prevent Cargo from discovering that lib-crate's source code is available alongside the tests, meaning that, even though the version we intend to use is already being picked up by the rustc wrapper, Cargo then recompiles the lib before building the tests.

The error above reads strangely but just means that it can't unify lib_crate-$metadata_for_lib::LibFoo with lib_crate-$metadata_for_test::LibFoo.

Add overlay to Nixpkgs

Considering the slim size, reasonable performance, and relative feature-completeness of cargo2nix at this point, we should probably consider submitting the cargo2nix overlay for inclusion in upstream Nixpkgs, similar to how node2nix and yarn2nix have done.

Improve Rust error handling

The original code for the cargo2nix CLI tool was a quick prototype and therefore does not properly handle errors with Result. We should refactor the main.rs and all associated modules to use proper error handling instead of panicking.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.