4 releases (2 breaking)
0.3.0 | Aug 4, 2024 |
---|---|
0.2.0 | May 29, 2024 |
0.1.1 | Jan 14, 2024 |
0.1.0 | Dec 20, 2023 |
#728 in Filesystem
454 downloads per month
14KB
61 lines
Omnicopy_to_output
Provides a generalized implementation for a "post build copy" operation, which isn't well-supported in rust at time of writing. This crate is inspired by https://github.com/prenwyn/copy_to_output, but implements more managed helpers + addresses some of the missing scenarios (again, at time of writing).
If any scenarios are missing, please contribute!
See docs.rs for full details.
License
This project is licensed under either of
at your option.
The SPDX license identifier for this project is MIT OR Apache-2.0
.
lib.rs
:
Provides a generalized implementation for a "post build copy" operation, which isn't well-supported in rust at time of writing. This crate is inspired by https://github.com/prenwyn/copy_to_output, but implements more managed helpers + addresses some of the missing scenarios (again, at time of writing).
As the name implies, the goal here is to provide coverage for all possible build scenarios as a stand-in until (if) there is a native solution in the rust tooling. If anything is missing, please contribute!
Examples
-
Use in
build.rs
with automatic discovery.Path is relative to project root. If your resources are in your project, cargo will automatically detect changes and invalidate the cache as needed.
use omnicopy_to_output::copy_to_output; fn main() { // Copy everything recursively from the res folder and place into output. copy_to_output("res").expect("Could not copy"); }
-
Use in
build.rs
with custom target (e.g. if your have different shared libraries for debug).Note, if you used both your builds will fail. Each target directory only exists when that build is run. A full example would have conditional logic.
use omnicopy_to_output::copy_to_output_for_profile; fn main() { // Manually specify the profile (i.e. env:PROFILE) copy_to_output_for_profile("res/foo.dll", "release").expect("Could not copy"); copy_to_output_for_profile("res/food.dll", "debug").expect("Could not copy"); }
-
Invalidate Cache for external resources
Large resources may not exist in your project. We can still copy those to output, but cargo will not detect changes and invalidate the cache. Emitting cargo:rerun-if-changed instructions will inform cargo these files exist, but then will change cache invalidation to only what you specify. Note, as soon as you do this in one place the default "anything in package" rules no longer apply. This is something you ideally are configuring anyway though.
use omnicopy_to_output::{copy_to_output, cargo_rerun_if_changed}; fn main() { let path_to_large_resources = "/path/to/large/resources"; cargo_rerun_if_changed(path_to_large_resources); copy_to_output(path_to_large_resources).expect("Could not copy"); }
Scenario Coverage
Key motivations for the original fork were supporting workspaces + managed experience for cargo cache instructions.
We support accommodating:
- Build types (e.g. retail vs test; integration tests see files)
- cargo::CompileKind
- Target
- Cross compilation (special case target)
- Workspace or single crate build
Considerations
This is in lieu of a better solution from cargo directly. In particular, it's worth noting that build scripts should not modify any files outside the OUT_DIR directory. We're not modifying, but it's still not necessarily in the "spirit" of the instructions.
How it Works
To locate the target directory, we must know the project root and the target.
- Determine if the output directory was overridden with
env:CARGO_TARGET_DIR
- If yes, use that path directly
- If not, the path will default to
{workspace_root}/target
which we determine using project_root.
- Determine which
CompileKind
is used. Cargo doesn't expose this directly. This crate is intended to be used in build scripts. Cargo providesenv:OUT_DIR
for build scripts. This isn't where we want to place these assets, but it does allow us to infer theCompileKind
. If the triple + profile ({target}/{profile}
) appears in the path, thenCompileKind::Target
was used. Otherwise,CompileKind::Host
was used. Profile comes fromenv:Profile
and target from build_target::target_triple.- For
CompileKind::Host
we concatenate/{profile}
- For
CompileKind::Target
we concatenate/{target}/{profile}
- For
Dependencies
~255KB