{"id":13647671,"url":"https://github.com/oxalica/nocargo","last_synced_at":"2025-04-06T18:15:56.936Z","repository":{"id":41459253,"uuid":"375423852","full_name":"oxalica/nocargo","owner":"oxalica","description":"[alpha] Build Rust crates with Nix Build System.","archived":false,"fork":false,"pushed_at":"2024-03-08T00:12:39.000Z","size":351,"stargazers_count":158,"open_issues_count":10,"forks_count":8,"subscribers_count":7,"default_branch":"main","last_synced_at":"2025-03-30T16:12:29.655Z","etag":null,"topics":["cargo","nix","rust"],"latest_commit_sha":null,"homepage":"","language":"Nix","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/oxalica.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE-MIT","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-06-09T16:38:38.000Z","updated_at":"2025-03-27T04:43:30.000Z","dependencies_parsed_at":"2024-01-14T10:29:21.045Z","dependency_job_id":"dddbe35a-d13f-4410-9b42-55894930ebd0","html_url":"https://github.com/oxalica/nocargo","commit_stats":{"total_commits":125,"total_committers":3,"mean_commits":"41.666666666666664","dds":"0.016000000000000014","last_synced_commit":"43c6f9e71372283285c11eaaa79905570a65f1cc"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oxalica%2Fnocargo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oxalica%2Fnocargo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oxalica%2Fnocargo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oxalica%2Fnocargo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/oxalica","download_url":"https://codeload.github.com/oxalica/nocargo/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247526764,"owners_count":20953143,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cargo","nix","rust"],"created_at":"2024-08-02T01:03:42.025Z","updated_at":"2025-04-06T18:15:56.908Z","avatar_url":"https://github.com/oxalica.png","language":"Nix","funding_links":[],"categories":["Nix","Programming Languages"],"sub_categories":[],"readme":"# nocargo: Cargo in Nix\n\n🚧 *This project is under development and is not ready for production yet. APIs are subjects to change.*\n\nBuild Rust crates with *Nix Build System*.\n- **No IFDs** (import-from-derivation). See [meme](https://gist.github.com/oxalica/d3b1251eb29d10e6f3cb2005167ddcd9).\n- No `cargo` dependency during building. Only `rustc`.\n- No need for hash prefetching or code generation[^no-code-gen].\n- Crate level caching, globally shared.\n- [nixpkgs] integration for non-Rust dependencies.\n\n[^no-code-gen]: Initial template generation and `Cargo.lock` updatin don't count for \"code generation\". The former is optional, and the latter is indeed not \"code\".\n\n\u003cdetails\u003e\n\u003csummary\u003eFeature checklist\u003c/summary\u003e\n\n- Binary cache\n  - [x] Top 256 popular crate versions with default features\n- Nix library\n  - [ ] Non-flake support.\n  - [x] `[workspace]`\n    - [x] `members`\n    - [ ] Auto-`members`\n    - [x] `excludes`\n      FIXME: Buggy.\n  - [ ] `resolver`\n        Currently has custom resolution algorithm, more like v2.\n  - [x] `links`\n  - [x] `[profile]`\n  - [x] `[{,dev-,build-}dependencies]`\n  - [x] `[features]`\n    - [x] Overriding API\n  - [x] `[target.\u003ccfg\u003e.dependencies]`\n  - [x] `[patch]`\n        Automatically supported. Since the dependency graph `Cargo.lock` currently relies on `cargo`'s generation.\n  - [ ] Cross-compilation.\n        FIXME: Buggy with proc-macros.\n- `noc` helper\n  - [x] `noc init`: Initial template `flake.nix` generation\n    - Dependency kinds\n      - [ ] `registry`\n      - [x] `registry-index`\n      - [x] `git`\n      - [x] `path` inside workspace\n      - [ ] `path` outside workspace\n    - Target detection\n      - [ ] Library\n            FIXME: Assume to always exist.\n      - [x] Binary\n      - [ ] Test\n      - [ ] Bench\n      - [ ] Example\n  - [ ] `Cargo.lock` generation and updating\n\n\u003c/details\u003e\n\n## Start with Nix flake\n\n1. (Optional) Add binary substituters for pre-built popular crates, by either\n   - Install `cachix` and run `cachix use nocargo` ([see more detail about `cachix`](https://app.cachix.org/cache/nocargo)), or\n   - Manually add substituter `https://nocargo.cachix.org` with public key `nocargo.cachix.org-1:W6jkp5htZBA1tUdU8XHLaD7zBrIFnor0MsLhHgrJeHk=`\n1. Enter the root directory of your rust workspace or package. Currently, you should have `Cargo.lock` already created by `cargo`.\n1. Run `nix run github:oxalica/nocargo init` to generate `flake.nix`. Or write it by hand by following [the next section](#example-flake.nix-structure).\n1. Check flake outputs with `nix flake show`. Typically, the layout would be like,\n   ```\n   └───packages\n       └───x86_64-linux\n           ├───default: package 'rust_mypkg1-0.1.0'           # The \"default\" package. For workspace, it's the top-level one if exists.\n           ├───mypkg1: package 'rust_mypkg1-0.1.0'            # Crate `mypkg1` with `release` profile.\n           ├───mypkg1-dev: package 'rust_mypkg1-debug-0.1.0'  # Crate `mypkg1` with `dev` profile.\n           ├───mypkg2: package 'rust_mypkg2-0.1.0'            # etc.\n           └───mypkg2-dev: package 'rust_mypkg2-debug-0.1.0'\n   ```\n1. Run `nix build .#\u003cpkgname\u003e` to build your package. Built binaries (if any) will be placed in `./result/bin`, and the library will be in `./result/lib`.\n1. Have fun!\n\n## Example `flake.nix` structure for reference \n\nA template `flake.nix` with common setup are below. It's mostly the same as the generated one, except that the helper `noc` will scan the workspace and discover all external registries and git dependencies for you.\n\n```nix\n{\n  description = \"My Rust packages\";\n\n  inputs = {\n    nixpkgs.url = \"github:NixOS/nixpkgs\";\n    flake-utils.url = \"github:numtide/flake-utils\";\n    nocargo = {\n      url = \"github:oxalica/nocargo\";\n      inputs.nixpkgs.follows = \"nixpkgs\";\n\n      # See below.\n      # inputs.registry-crates-io.follows = \"registry-crates-io\";\n    };\n\n    # Optionally, you can explicitly import crates.io-index here.\n    # So you can `nix flake update` at any time to get cutting edge version of crates,\n    # instead of waiting `nocargo` to dump its dependency.\n    # Otherwise, you can simply omit this to use the locked registry from `nocargo`,\n    # which is updated periodically.\n    # registry-crates-io = { url = \"github:rust-lang/crates.io-index\"; flake = false; };\n  };\n\n  outputs = { nixpkgs, flake-utils, nocargo, ... }@inputs:\n    flake-utils.lib.eachSystem [ \"x86_64-linux\" ] (system:\n      let\n        # The entry API to make Nix derivations from your Rust workspace or package.\n        # The output of it consists of profile names, like `release` or `dev`, each of which is\n        # a attrset of all member package derivations keyed by their package names.\n        ws = nocargo.lib.${system}.mkRustPackageOrWorkspace {\n          # The root directory, which contains `Cargo.lock` and top-level `Cargo.toml`\n          # (the one containing `[workspace]` for workspace).\n          src = ./.;\n\n          # If you use registries other than crates.io, they should be imported in flake inputs,\n          # and specified here. Note that registry should be initialized via `mkIndex`,\n          # with an optional override.\n          extraRegistries = {\n            # \"https://example-registry.org\" = nocargo.lib.${system}.mkIndex inputs.example-registry {};\n          };\n\n          # If you use crates from git URLs, they should be imported in flake inputs,\n          # and specified here.\n          gitSrcs = {\n            # \"https://github.com/some/repo\" = inputs.example-git-source;\n          };\n\n          # If some crates in your dependency closure require packages from nixpkgs.\n          # You can override the argument for `stdenv.mkDerivation` to add them.\n          #\n          # Popular `-sys` crates overrides are maintained in `./crates-io-override/default.nix`\n          # to make them work out-of-box. PRs are welcome.\n          buildCrateOverrides = with nixpkgs.legacyPackages.${system}; {\n            # Use package id format `pkgname version (registry)` to reference a direct or transitive dependency.\n            \"zstd-sys 2.0.1+zstd.1.5.2 (registry+https://github.com/rust-lang/crates.io-index)\" = old: {\n              nativeBuildInputs = [ pkg-config ];\n              propagatedBuildInputs = [ zstd ];\n            };\n\n            # Use package name to reference local crates.\n            \"mypkg1\" = old: {\n              nativeBuildInputs = [ git ];\n            };\n          };\n\n          # We use the rustc from nixpkgs by default.\n          # But you can override it, for example, with a nightly version from https://github.com/oxalica/rust-overlay\n          # rustc = rust-overlay.packages.${system}.rust-nightly_2022-07-01;\n        };\n      in rec {\n        # For convenience, we hoist derivations of `release` and `dev` profile for easy access,\n        # with `dev` packages postfixed by `-dev`.\n        # You can export different packages of your choice.\n        packages = ws.release\n          // nixpkgs.lib.mapAttrs' (name: value: { name = \"${name}-dev\"; inherit value; }) ws.dev\n          // {\n            # The \"default\" features are turned on by default.\n            # You can `override` the library derivation to enable a different set of features.\n            # Explicit overriding will disable \"default\", unless you manually include it.\n            mypkg1-with-custom-features = (ws.release.mypkg1.override {\n              # Enables two features (and transitive ones), and disables \"default\".\n              features = [ \"feature1\" \"feature2\" ]; \n            }).bin;\n          };\n      });\n}\n```\n\n## FAQ\n\n### Comparison with [cargo2nix] and [naersk]?\n\nMain differences are already clarified [on the top](#nocargo%3A-cargo-in-nix).\n\n`nocargo` is inspired by `cargo2nix` and `buildRustCrate` in `nixpkgs`. We are more like `cargo2nix` while the generation part is implemented by pure Nix, but less like `naersk` which is a wrapper to call `cargo` to build the package inside derivations.\n\nIn other words, we and `cargo2nix` use Nix as a *Build System*, while `nearsk` use Nix as a *Package Manager* or *Packager*.\n\n\u003cdetails\u003e\n\u003csummary\u003e\nDetail comparison of nocargo, cargo2nix/buildRustCrate, naersk and buildRustPackage\n\n\u003c/summary\u003e\n\n| | nocargo | [cargo2nix]/`buildRustCrate` | [naersk] | `buildRustPackage` |\n|-|-|-|-|-|\n| Depend on `cargo` | Updating `Cargo.lock` | Updating \u0026 generating \u0026 building | Updating \u0026 vendoring \u0026 building | Building |\n| Derivation granularity | Per crate | Per crate | Per package + one dependency closure | All in one |\n| Crate level sharing | ✔️ | ✔️ | ✖ | ✖ |\n| Binary substitution per crate | ✔️ | Not implemented | ✖ | ✖ |\n| Code generation | ✖ | ✔️ | ✖ | ✖ |\n| Edit workspace \u0026 rebuild | Rebuild leaf crates | Rebuild leaf crates | Rebuild leaf crates | Refetch and rebuild all crates |\n| Edit dependencies \u0026 rebuild | Rebuild changed crates (refetch if needed) | Refetch, regenerate and rebuild changed crates | Refetch and rebuild all crates | Refetch and rebuild all crates |\n| Offline rebuild as long as | Not adding unfetched crate dependency | Not adding unfetched crate dependency | Not changing any dependencies | ✖ |\n\n\u003c/details\u003e\n\n### But why pure Nix build system?\n\n- Sharing through fine-grained derivations between all projects, not just in one workspace.\n- Binary substitution per crate.\n  No need for global `target_dir`/`CARGO_TARGET_DIR` or [sccache].\n- Easy `nixpkgs` integration for non-Rust package dependencies, cross-compilation (planned) and package overriding.\n- More customizability: per-crate `rustc` flags tweaking, arbitrary crate patching, force dynamic linking and more.\n\n### Can I really throw away `cargo`?\n\nSorry, currently no. :crying_cat_face: Updating of `Cargo.lock` still relies on `cargo`.\nThis can happen when creating a new project or changing dependencies.\nWe are mainly using `cargo`'s SAT solver to pin down the dependency graph.\n\nIt's *possible* to implement it ourselves, but not yet, due to the complexity.\n\n## License\n\nMIT Licensed.\n\n[nixpkgs]: https://github.com/NixOS/nixpkgs\n[naersk]: https://github.com/nix-community/naersk\n[cargo2nix]: https://github.com/cargo2nix/cargo2nix\n[sccache]: https://github.com/mozilla/sccache\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foxalica%2Fnocargo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Foxalica%2Fnocargo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foxalica%2Fnocargo/lists"}