-
Notifications
You must be signed in to change notification settings - Fork 2.6k
--artifact-dir
(nee --out-dir
) Tracking Issue
#6790
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
I find this feature very helpful, since I get output in a directory named like this However, it doesn't seem that OUT_DIR environment variable is set to the value of |
+1 on this issue. I have a program that uses a template directory for rust compilation and would like to now have to recompile everything. Yes I could symlink all the folders within target, but it would be nicer to be able to specify the binary output path. I'm not sure why this is such an overlooked issue. |
When will this feature be available in the stable release? It would greatly simplify my build/CI pipeline. |
+1 on this. This greatly improves the workflow on our CI, and we'd like to avoid using a nightly compiler just for this. What needs to happen for this to move forward? |
This issue makes nmattia/naersk unusable on stable rust. (another build system issue) |
This would streamline some of my Dockerfiles and build scripts quite nicely. |
Is there a reason this doesn't work with |
I just published a crate called cargo-out-dir to crates.io, which can ease some of the frustration while we wait for this to stabilize. All it does is print out the current' crate's out directory, as determined by running
|
Another potential use case for out-dir is making
in order for native APIs like (the moral equivalent of) But in this case it would be more helpful to be able to put |
|
I run into this regularly (multiple times a year), and I am not the only one. At the moment, people hard-code
Cargo's current file handling is unfortunate, and stabilizing this value would help a lot. Specifically, all temporary build files should be freely movable to an external directory, while the build outputs (i.e. the binaries or shared objects) should land in a fixed path for easy packaging. (In an ideal world, Related: #6100 (comment) |
@piegamesde exactly, I'm used to having |
Why is it still unstable?
|
The key scenario for this is integrating with other build systems, especially where you are cross-compiling: since Cargo will place the build artifacts into a target-triple directory, you need to teach the outer build system about Rust's target-triples so that you know where to look to find the build artifacts. I'd mostly be happy if there was an option to suppress the target-triple directory (and the |
...? But in that case you need to have invoked them using |
Just from experience with various (non-embedded) CI and embedded build systems, it's often easier to determine a path for the binary artifacts early and up-front and then use that everywhere, than try to reverse engineer your build tool's scheme for placement. Especially if there's no agreement that the build tool's placement will remain stable. Consider also that with CI/CD you're configuring things in YAML, so no functions to call like There may be more concrete reasons too, that's just what came to mind. |
CI configuration languages generally accept variables, indeed this is virtually required for making a CI matrix work. And in a project I have recently been working on which requires constructing a custom build system, I made it so cargo is always invoked with a |
One problematic use case I ran into was with some application that was built with Meson. The problem is that it just copied |
You might know the target triple within the Rust project, but if you are wrapping calls to Cargo from another build system then there are likely other non-Rust projects in that build system that are unaware of Rust's target triples. It's much easier in a build system to assume that the built artifact is Things only get worse if a project can customize its target triple: it might be trivial to create some Make/CMake function to generate the target triple based on the target architecture of the build, but if an individual project can customize that triple (e.g., MUSL vs GNU, MSVC vs GNU, or using a |
As a practical example, this is a problem when one builds and packages mdcat - besides the binary $ git clone https://codeberg.org/flausch/mdcat
$ cargo fetch --locked
$ cargo build --frozen --release --target-dir=target
$ ls target/release/mdcat
target/release/mdcat
$ ls -d target/release/build/mdcat-*
target/release/build/mdcat-2a83e790d2b3f7a6 target/release/build/mdcat-7decb70a642f31fb
$ find target/release/build -type d -path "target/release/build/mdcat-*/out"
target/release/build/mdcat-7decb70a642f31fb
$ ls target/release/build/mdcat-7decb70a642f31fb/out
completions _mdcat mdcat.bash mdcat.fish _mdcat.ps1 |
I need this Not a fan of how the flag is teased in non-nightly cargo's help menu, only to bail when invoked. Don't bother me. Either let me use the flag, or at least drop it from the CLI documentation. Alternatively, I could use nightly, and require my users to use nightly. For DevOps users and other fans of pinned, immutable versions, nightly is not a valid option. Alternatively, I would have less need for this feature if cargo simply nested binary artifacts in a more archive amenable tree structure, like Alternatively, one could write a custom shell script to accomplish this. But that wouldn't work very well across all Rust projects, and it would needlessly restrict Windows devs, and proper robust shell programming is rather a dark art, and shell scripts substantially depart from the Rust ecosystem. Alternatively, one could configure archive commands to strip out the junk sibling files, but that's a maintenance nightmare, as cargo will surely (as any package manager reasonably would) introduce additional file patterns in the build tree internal directory over time. Alternatively, one could configure archive commands to look exclusively for file patterns matching I don't want to get too involved with low level details of cargo internal build files. I just want more reasonable defaults. Or failing that, landing |
Here's a recap of the unresolved questions:
Over the years, many people in that issue thread have proposed their dissatisfaction with
Still relevant and will need to be solved.
See above for all the developers who want this to be added. An important use case is being able to directly output artifacts where you want them, without having to know where the target directory is or copy out of it as an extra step. Figuring out the former is complicated by the A couple pain points with the current situation seem to be knowing whether to reach into the
Solved by renaming to As I noted above, #7493 is also a blocker that will need to be resolved before we can stabilize this flag. |
Per discussion in rust-lang#6790. The --out-dir CLI option and out-dir config option are often confused with the OUT_DIR environment variable, when the two serve very different purposes (the former tells Cargo where to copy build artifacts to, whereas the OUT_DIR environment variable is set *by* Cargo to tell build scripts where to place their generated intermediate artifacts). Renaming the option to something less confusing is a prerequisite to stabilizing it.
Per discussion in rust-lang#6790. The --out-dir CLI option and out-dir config option are often confused with the OUT_DIR environment variable, when the two serve very different purposes (the former tells Cargo where to copy build artifacts to, whereas the OUT_DIR environment variable is set *by* Cargo to tell build scripts where to place their generated intermediate artifacts). Renaming the option to something less confusing is a prerequisite to stabilizing it.
Rename --out-dir to --artifact-dir Progress towards unblocking #6790. Renames the experimental `--out-dir` argument to `--artifact-dir`, both to reflect that it's where the final build *artifacts* will be copied to, and to avoid confusion with the `OUT_DIR` environment variable which serves an entirely different purpose. For transition purposes, `--out-dir` argument and `out-dir` config key will still work with a deprecation message encouraging the use of the new arg and config key. ### Rationale A lot of people seem to be confused by the naming of the `--out-dir` argument, and are misled into thinking it serves the same purpose as the `OUT_DIR` environment variable: > [However, it doesn't seem that OUT_DIR environment variable is set to the value of --out-dir when build.rs is executed.](#6790 (comment)) > [I understand that the worry is that there could be confusion between --out-dir for cargo and the environment variable OUT_DIR for build.rs, but doesn't it mean exactly the same in both cases?](#6790 (comment)) > [--out-dir: Things will be built into $PWD/target as normal, but copies some of the artifacts into the directory specified by out-dir (not a profile specific subdirectory). Unstable flag, added in March 2018. cargo build --out-dir #5203 Ability to specify output artifact name #4875. **Mimicks the behavior of OUT_DIR.**](#6100 (comment)) > [I recently had a couple of people express an interest in --out-dir being stabilized and from my initial digging it seems like what they may actually want is to switch to OUT_DIR, which is already stable.](#6100 (comment))
--artifact-dir
(nee --out-dir
) Tracking Issue
That is not sufficient reason to ignore those concerns. However, since then (besides team members rotating)
Looking at those, I agree with #6100 (comment) that having
What would be important for organizing all of the use cases is to understand what is in or out of scope (or if we need more, lower level knobs as mentioned). e.g. #6100 (comment)
A feature may sound like it works for one person or it may indeed work for one person but we need to consider the overall ecosystem and "where will this lead" both in terms of second order effects (not concerned about that here) and what will people find lacking and ask to have changed or extended. We don't have to solve everyone's problem but we need to have a rough idea of what the future is to make sure we are solving the right problems. For me, I'm less concerned with #6100 for this flag but whether we'll need several additional flags after this because we didn't quite solve the right problem. |
I think that to a large extent, the need being addressed can be split into two parts:
The "certain build artifacts" can also be split into two parts:
By way of example, I have recently been trying to implement fine-grained code coverage reporting in CI on a Rust project. It is necessary to tell the coverage tools where both the coverage instrumented binary artifacts are, and where the coverage data is. The latter can be controlled through environment variables, so perhaps we can ignore that. But the former is extremely hard right now.
So to simply generate the command lines for a coverage tool in CI, I need to implement this logic in CI or a build script. I can't just have I also can't just use the JSON output of Cargo because there is no part of that that gives me the base directory, only the full path to each individual artifact. The base directory is required eg. for most instrumentation analysis tools, for caching and storing artifacts consistently, and because the full list might actually be too long for many shells' limit on environment variables. So I need to implement a more complex mapping that duplicates Cargo's internal artifact directory construction logic. In shell script. Or the CI config syntax. Or another build script language. This is undesirable because:
This is not just an issue for code coverage. This applies to:
Now consider that if I were just able to predict (or extract from Cargo's output) where artifacts will end up, I can effectively meet "the need to control where certain build artifacts will be placed" by writing I'll also preempt the argument that there are tools that abstract this away for some of the use cases I mention eg. In the last four years of using Rust in earnest and trying to do novel things related to code quality, instrumentation and testing, I just keep running up against this. I don't mean this as a kind of pressure to just "get it done", because I respect (a) Cargo's commitment to quality of API and (b) the fact that (veeery much like the |
rust and cargo has so many flags and environment variables, which i find quite confusing. there are legacy tools which have a logic variable naming, like cmake: https://cmake.org/cmake/help/v3.0/manual/cmake-variables.7.html, it has a couple of directories, but for profiles it operates with postfixes. for building, the default cmake is very simple. either change directory and build, or call if you want to have a more modern example, bazel has the following: https://bazel.build/remote/output-directories. it is designed for buils on a cluster, and extreme reuse of build artifacts. therefor i woudl support a design ... if the designer would be prepared to remove 90% of the existing varialbes would be already a huge advancement :) my personal opinion of course - just coming from my current frustration of hours of build time of COSMIC desktop because it recompiles the same libraries again and again. |
So I need to catch up on some things earlier in the thread but needed to record some thoughts real quick. Someone brought up multi-target builds ( While I don't dig into the blockers for this, #14125 (comment) explores a potential cohesive picture of what we should be doing |
Summary: It was renamed long time ago: rust-lang/cargo#6790 Differential Revision: D66011214
Summary: It was renamed long time ago: rust-lang/cargo#6790 Differential Revision: D66011214
Summary: It was renamed long time ago: rust-lang/cargo#6790 Differential Revision: D66011214
Summary: It was renamed long time ago: rust-lang/cargo#6790 Differential Revision: D66011214
Summary: It was renamed long time ago: rust-lang/cargo#6790 Differential Revision: D66011214
Summary: It was renamed long time ago: rust-lang/cargo#6790 Reviewed By: iguridi Differential Revision: D66011214
Summary: It was renamed long time ago: rust-lang/cargo#6790 Reviewed By: iguridi Differential Revision: D66011214
Summary: It was renamed long time ago: rust-lang/cargo#6790 Reviewed By: iguridi Differential Revision: D66011214 fbshipit-source-id: ebf63bc0c05e78b0b853ff58161e9a28acc45bf4
Can this also copy the corresponding dependency file (
I hope this answers that question. We're building the same binary, same profile and target, but different flags, resulting in different artifacts but with the same file name in the same output directory. I suppose there's related, nagging concern there, that if this is just a copy step from the canonical artifact dir under |
For what it's worth, I think it's very important to prioritize this issue. Because cargo's target directories are nested and are basically impossible to predict, it makes it hard to integrate crates into existing C or C++ projects.
I saw earlier in this thread that a design philosophy was "Cargo should work well with just Cargo" and I think that will ultimately harm Rust's adoption in industry. In the real world, we will need to do stuff like this and I don't think |
## What does this PR try to resolve? This PR adds a new `build.build-dir` configuration option that was proposed in #14125 (comment) This new config option allows the user to specify a directory where intermediate build artifacts should be stored. I have shortened it to just `build-dir` from `target-build-dir`, although naming is still subject to change. ### What is a final artifact vs an intermediate build artifact #### Final artifacts These are the files that end users will typically want to access directly or indirectly via a third party tool. * binary executable for bin crates * binary executable for examples * `.crate` files output from `cargo package` * [depinfo files](https://doc.rust-lang.org/cargo/reference/build-cache.html#dep-info-files) (`.d` files) for third party build-system integrations (see https://github.com/rust-lang/cargo/blob/master/src/cargo/core/compiler/fingerprint/mod.rs#L194) * `cargo doc` output (html/css/js/etc) * Cargo's [`--timings`](https://doc.rust-lang.org/cargo/reference/timings.html) HTML report #### Intermediate build artifact, caches, and state These are files that are used internally by Cargo/Rustc during the build process * other depinfo files (generated by rustc, fingerprint, etc. See https://github.com/rust-lang/cargo/blob/master/src/cargo/core/compiler/fingerprint/mod.rs#L164) * rlibs and debug info from dependencies * build script `OUT_DIR` * output from proc macros (previously stored in `target/build`) * [incremental build](https://doc.rust-lang.org/rustc/codegen-options/index.html#incremental) output from rustc * fingerprint files used by Cargo for rebuild detection * scratchpad used for `cargo package` verify step * Cache of rustc invocations (`.rustc_info.json`) * "pre and non uplifted" binary executables. (ie. bins for `examples` that contain the hash in the name, bins for `benches`, proc macros, build scripts) * `CARGO_TARGET_TMPDIR` files (see rational for this [here](#14125 (comment))) * [future-incompat-report](https://doc.rust-lang.org/cargo/reference/future-incompat-report.html)'s `.future-incompat-report.json` file ## Feature Gating Strategy We are following the "Ignore the feature that is used without a gate" approach as described [here](https://doc.rust-lang.org/nightly/nightly-rustc/cargo/core/features/index.html). The rational for this is: The `build.build-dir` is likely going to be set by by users "globally" (ie. `$CARGO_HOME/config.toml`) to set a shared build directory to reduce rebuilding dependencies. For users that multiple cargo versions having having an error would be disrupted. The fallback behavior is to revert to the behavior of the current stable release (building in `$CARGO_TARGET_DIR`) ## Testing Strategy * We have the existing Cargo testsuite to be sure we do not introduce regressions. * I have also run the testsuite locally with the cli flag remove to verify all tests pass with the default build dir (which falls back to the target dir) * For testing thus far, I have been using small hello world project with a few dependencies like `rand` to verify files are being output to the correct directory. * When this PR is closer to merging, I plan to test with some larger projects with more dependencies, build scripts, ect. * Other testing recommendations are welcome 🙇 ## How should we test and review this PR? This is probably best reviewed commit by commit. I documented each commit. I tied to follow the atomic commits recommendation in the Cargo contributors guide, but I split out some commits for ease of review. (Otherwise I think this would have ended up being 1 or 2 large commits 😅) ## Questions - [x] What is the expected behavior of `cargo clean`? * At the time of writing it only cleans `target` and does not impact the build-dir but this is easily changable. * Answer: See #15104 (comment) - [x] When using `cargo package` are was expecting just the `.crate` file to be in `target` while all other output be stored in `build.build-dir`? Not sure if we consider things like `Cargo.toml`, ` Cargo.toml.orig`, `.cargo_vcs_info.json` part of the user facing interface. * Current consensus is that only `.crate` is considered a final artifact - [x] Where should `cargo doc` output go? HTML/JS for many crates can be pretty large. Moving to the build-dir would help reduce duplication if we find the that acceptable. For `cargo doc --open` this is not a problem but may be problematic for other use cases? * Answer: #15104 (comment) - [x] Are bins generated from `benches` considered final artifacts? * Since bins from `examples` are considered final artifacts, it seems natural that `benches` should also be considered final artifacts. However, unlike `examples` the `benches` bins are stored in `target/{profile}/deps` instead of a dedicated directory (like `target/{profile}/examples`). We could move them into a dedicated directory (`target/{profile}/benches`) but that mean would also be changing the structure of the `target` directory which feels out of scope for this change. If we decide that `benches` are final artifacts, it would probably be better to consider that changes as part of #6790 * Answer: #15104 (comment) - [ ] [Do we want to include a `CARGO_BUILD_DIR` shortcut env var?](#15104 (comment)) * The current commit (2af0c91) has included the `CARGO_BUILD_DIR` shortcut. This can be removed before merging if there a good reason to. ## TODO - Implementation - [x] Add support in `cargo clean` - [ ] ~~Implement templating for `build.build-dir`~~ * Will implement in a follow up PR [as suggested](#15104 (comment)) - [x] Fix issue with `target/examples` still containing "pre-uplifted" binaries - [x] Verify `build-dir` with non-bin crate types - Prepare for review - [x] Clean up/improve docs - [x] Review tests and add more as needed - [x] Fix tests in CI (Windows is currently failing) - [x] Clean up commits - [ ] Resolve remaining questions - [x] Request review
Note: this was renamed from
--out-dir
to--artifact-dir
in #13809Original issue: #4875Nightly: --out-dir
Implementation PR: #5203
Documentation: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#artifact-dir
Issues: Z-out-dir
Summary
Adds
--artifact-dir=PATH
flag tocargo build
to specify a directory to place final artifacts.Tasks:
--out-dir
Unresolved questions
--target <one> --target <two>
)--out-dir
justified or can we find another way of accomplishing it? #6100 — concern about similarity with--target-dir
, proliferation of flags--out-dir
(Rename --out-dir to --artifact-dir #13809)build.rs
sOUT_DIR
(depends on ifbuild.rs
is generating intermediate or final artifacts) (Rename --out-dir to --artifact-dir #13809)The text was updated successfully, but these errors were encountered: