#cargo-build #cargo #tool #root-directory

omnicopy_to_output

Generalized post build copy to place files in output directory

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

Download history 273/week @ 2024-07-02 199/week @ 2024-07-09 135/week @ 2024-07-16 131/week @ 2024-07-23 238/week @ 2024-07-30 234/week @ 2024-08-06 145/week @ 2024-08-13 191/week @ 2024-08-20 166/week @ 2024-08-27 229/week @ 2024-09-03 257/week @ 2024-09-10 103/week @ 2024-09-17 148/week @ 2024-09-24 84/week @ 2024-10-01 98/week @ 2024-10-08 94/week @ 2024-10-15

454 downloads per month

MIT/Apache

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:

githubcrates-iodocs-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.

  1. 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.
  2. Determine which CompileKind is used. Cargo doesn't expose this directly. This crate is intended to be used in build scripts. Cargo provides env:OUT_DIR for build scripts. This isn't where we want to place these assets, but it does allow us to infer the CompileKind. If the triple + profile ({target}/{profile}) appears in the path, then CompileKind::Target was used. Otherwise, CompileKind::Host was used. Profile comes from env:Profile and target from build_target::target_triple.
    • For CompileKind::Host we concatenate /{profile}
    • For CompileKind::Target we concatenate /{target}/{profile}

Dependencies

~255KB