From 42e2fab6bc3dcbeea9d557c4eba2508e50abea18 Mon Sep 17 00:00:00 2001 From: Ivan Petkov Date: Thu, 5 Jan 2023 04:46:43 +0000 Subject: [PATCH] Make it easier to build workspaces not at source root (#212) --- CHANGELOG.md | 4 ++++ checks/default.nix | 8 +++++++ checks/workspace-not-at-root/README.md | 1 + .../workspace/Cargo.lock | 19 +++++++++++++++++ .../workspace/Cargo.toml | 4 ++++ .../workspace/hello/Cargo.toml | 4 ++++ .../workspace/hello/src/lib.rs | 3 +++ .../workspace/print/Cargo.toml | 8 +++++++ .../workspace/print/src/main.rs | 3 +++ .../workspace/world/Cargo.toml | 4 ++++ .../workspace/world/src/lib.rs | 3 +++ docs/SUMMARY.md | 1 + docs/faq/workspace-not-at-source-root.md | 21 +++++++++++++++++++ lib/buildDepsOnly.nix | 14 +------------ lib/crateNameFromCargoToml.nix | 18 +++++++++++----- 15 files changed, 97 insertions(+), 18 deletions(-) create mode 100644 checks/workspace-not-at-root/README.md create mode 100644 checks/workspace-not-at-root/workspace/Cargo.lock create mode 100644 checks/workspace-not-at-root/workspace/Cargo.toml create mode 100644 checks/workspace-not-at-root/workspace/hello/Cargo.toml create mode 100644 checks/workspace-not-at-root/workspace/hello/src/lib.rs create mode 100644 checks/workspace-not-at-root/workspace/print/Cargo.toml create mode 100644 checks/workspace-not-at-root/workspace/print/src/main.rs create mode 100644 checks/workspace-not-at-root/workspace/world/Cargo.toml create mode 100644 checks/workspace-not-at-root/workspace/world/src/lib.rs create mode 100644 docs/faq/workspace-not-at-source-root.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 8fd80ce..7a20263 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## Unreleased +### Changed +* Documented and made it easier to build a cargo workspace located in a + subdirectory of the source root + ### Fixed * Previously compiled build scripts now maintain their executable bit when inherited diff --git a/checks/default.nix b/checks/default.nix index d3adf4c..3ead31f 100644 --- a/checks/default.nix +++ b/checks/default.nix @@ -363,6 +363,14 @@ in pname = "workspace-inheritance"; }; + # https://github.com/ipetkov/crane/issues/209 + workspaceRootNotAtSourceRoot = myLib.buildPackage { + src = myLib.cleanCargoSource ./workspace-not-at-root; + sourceRoot = "source/workspace"; + cargoLock = ./workspace-not-at-root/workspace/Cargo.lock; + cargoToml = ./workspace-not-at-root/workspace/Cargo.toml; + }; + workspaceRoot = myLib.buildPackage { src = myLib.cleanCargoSource ./workspace-root; pname = "workspace-root"; diff --git a/checks/workspace-not-at-root/README.md b/checks/workspace-not-at-root/README.md new file mode 100644 index 0000000..1b8be1f --- /dev/null +++ b/checks/workspace-not-at-root/README.md @@ -0,0 +1 @@ +Example project where the cargo workspace root is not at the source root diff --git a/checks/workspace-not-at-root/workspace/Cargo.lock b/checks/workspace-not-at-root/workspace/Cargo.lock new file mode 100644 index 0000000..65b07e1 --- /dev/null +++ b/checks/workspace-not-at-root/workspace/Cargo.lock @@ -0,0 +1,19 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "hello" +version = "0.1.0" + +[[package]] +name = "print" +version = "0.1.0" +dependencies = [ + "hello", + "world", +] + +[[package]] +name = "world" +version = "0.1.0" diff --git a/checks/workspace-not-at-root/workspace/Cargo.toml b/checks/workspace-not-at-root/workspace/Cargo.toml new file mode 100644 index 0000000..44033c4 --- /dev/null +++ b/checks/workspace-not-at-root/workspace/Cargo.toml @@ -0,0 +1,4 @@ +[workspace] +# NB: hello and world are intentionally left out cargo will +# promote them to members since they are listed as path deps +members = ["print"] diff --git a/checks/workspace-not-at-root/workspace/hello/Cargo.toml b/checks/workspace-not-at-root/workspace/hello/Cargo.toml new file mode 100644 index 0000000..60a3916 --- /dev/null +++ b/checks/workspace-not-at-root/workspace/hello/Cargo.toml @@ -0,0 +1,4 @@ +[package] +name = "hello" +version = "0.1.0" +edition = "2021" diff --git a/checks/workspace-not-at-root/workspace/hello/src/lib.rs b/checks/workspace-not-at-root/workspace/hello/src/lib.rs new file mode 100644 index 0000000..8fd0518 --- /dev/null +++ b/checks/workspace-not-at-root/workspace/hello/src/lib.rs @@ -0,0 +1,3 @@ +pub fn hello() -> &'static str { + "hello" +} diff --git a/checks/workspace-not-at-root/workspace/print/Cargo.toml b/checks/workspace-not-at-root/workspace/print/Cargo.toml new file mode 100644 index 0000000..c81adea --- /dev/null +++ b/checks/workspace-not-at-root/workspace/print/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "print" +version = "0.1.0" +edition = "2021" + +[dependencies] +hello = { version = "*", path = "../hello" } +world = { version = "*", path = "../world" } diff --git a/checks/workspace-not-at-root/workspace/print/src/main.rs b/checks/workspace-not-at-root/workspace/print/src/main.rs new file mode 100644 index 0000000..4e560bf --- /dev/null +++ b/checks/workspace-not-at-root/workspace/print/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + println!("{}, {}", hello::hello(), world::world()); +} diff --git a/checks/workspace-not-at-root/workspace/world/Cargo.toml b/checks/workspace-not-at-root/workspace/world/Cargo.toml new file mode 100644 index 0000000..deb61af --- /dev/null +++ b/checks/workspace-not-at-root/workspace/world/Cargo.toml @@ -0,0 +1,4 @@ +[package] +name = "world" +version = "0.1.0" +edition = "2021" diff --git a/checks/workspace-not-at-root/workspace/world/src/lib.rs b/checks/workspace-not-at-root/workspace/world/src/lib.rs new file mode 100644 index 0000000..45475d5 --- /dev/null +++ b/checks/workspace-not-at-root/workspace/world/src/lib.rs @@ -0,0 +1,3 @@ +pub fn world() -> &'static str { + "world!" +} diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md index f611275..758df35 100644 --- a/docs/SUMMARY.md +++ b/docs/SUMMARY.md @@ -27,3 +27,4 @@ * [Building a subset of a workspace](./faq/build-workspace-subset.md) * [Trouble building when using `include_str!` (or including other non-rust files)](./faq/building-with-non-rust-includes.md) * [Dealing with sandbox-unfriendly build scripts](./faq/sandbox-unfriendly-build-scripts.md) + * [Cargo.toml is not at the source root](./faq/workspace-not-at-source-root.md) diff --git a/docs/faq/workspace-not-at-source-root.md b/docs/faq/workspace-not-at-source-root.md new file mode 100644 index 0000000..24a5185 --- /dev/null +++ b/docs/faq/workspace-not-at-source-root.md @@ -0,0 +1,21 @@ +## Cargo workspace root (Cargo.toml) is not at the root of the derivation's source + +Most cargo projects have their `Cargo.toml` at the root of the source, but it's +still possible to build a project where the `Cargo.toml` file is nested in a +deeper directory: + +```nix +# Assuming that we have the following directory structure: +# ./flake.nix +# ./flake.lock +# ./nested +# ./nested/Cargo.toml +# ./nested/Cargo.lock +# ./nested/src/*.rs +craneLib.buildPackage { + src = myLib.cleanCargoSource ./.; + sourceRoot = "source/nested"; # Needs to start with "source/" by default + cargoLock = ./nested/Cargo.lock; + cargoToml = ./nested/Cargo.toml; +} +``` diff --git a/lib/buildDepsOnly.nix b/lib/buildDepsOnly.nix index afbec0c..7d987c6 100644 --- a/lib/buildDepsOnly.nix +++ b/lib/buildDepsOnly.nix @@ -23,24 +23,12 @@ let "dummySrc" ]; - throwMsg = throw '' - unable to find Cargo.toml and Cargo.lock at ${path}. please ensure one of the following: - - a Cargo.toml and Cargo.lock exists at the root of the source directory of the derivation - - set `cargoArtifacts = buildDepsOnly { src = ./some/path/to/cargo/root; }` - - set `cargoArtifacts = null` to skip reusing cargo artifacts altogether - ''; - # Run tests by default to ensure we cache any dev-dependencies doCheck = args.doCheck or true; cargoCheckExtraArgs = args.cargoCheckExtraArgs or (if doCheck then "--all-targets" else ""); - path = args.src or throwMsg; - cargoToml = path + "/Cargo.toml"; - dummySrc = args.dummySrc or - (if builtins.pathExists cargoToml - then mkDummySrc args - else throwMsg); + dummySrc = args.dummySrc or (mkDummySrc args); in mkCargoDerivation (cleanedArgs // { inherit doCheck; diff --git a/lib/crateNameFromCargoToml.nix b/lib/crateNameFromCargoToml.nix index 9804e6c..5548974 100644 --- a/lib/crateNameFromCargoToml.nix +++ b/lib/crateNameFromCargoToml.nix @@ -3,13 +3,21 @@ args: let - src = args.src or (throw '' - unable to infer crate name and version. Please make sure the src directory - contains a valid Cargo.toml file, or consider setting a derivation name explicitly - ''); + throwMsg = throw '' + unable to infer crate name and version. please ensure one of the following: + - a Cargo.toml exists at the root of the source directory of the derivation + - `cargoToml` is set to a path to the package's Cargo.toml + - `cargoTomlContents` is set to the contents of the package's Cargo.toml + - `pname` and `version` are explicitly set + ''; + src = args.src or throwMsg; cargoToml = args.cargoToml or (args.src + "/Cargo.toml"); - cargoTomlContents = args.cargoTomlContents or (builtins.readFile cargoToml); + cargoTomlContents = args.cargoTomlContents or ( + if builtins.pathExists cargoToml + then builtins.readFile cargoToml + else throwMsg + ); toml = builtins.fromTOML cargoTomlContents; in