cargo-bundle icon indicating copy to clipboard operation
cargo-bundle copied to clipboard

Can cargo-bundle bundle resources from a lib into a bin

Open andrewdavidmackenzie opened this issue 6 years ago • 6 comments

I'd like to have a set of resource files in a lib project, that then get installed as part of the .app bundle when a binary using that lib is built.

Is that possible? Thanks!

andrewdavidmackenzie avatar Feb 04 '18 21:02 andrewdavidmackenzie

This isn't currently possible, no. It's not immediately clear to me how it would work -- if this were a feature of cargo-bundle, how would non-cargo-bundled binaries depending on that library know how to find the resources?

Meanwhile, as a workaround, depending on what kinds of resources your library needs, you might consider using the std::include_bin! or std::include_str! macros to compile the resource files directly into the library.

mdsteele avatar Feb 04 '18 23:02 mdsteele

My idea is roughly this:

  • If a library has resources in it's folder tree but the binary built using the library is NOT bundled with cargo-bundler (just cargo let's say) then things would work as now. These files would NOT be included. Either the library and/or the binary would need to be written for the possibility of the files not being there (and either work differently, or fail gracefully). No worse than now, no? If you want bundled resources, you have to use a bundler...

  • if a library has resources in it's folder tree, and they are referenced in [package.metadata] in the library's Cargo.toml and the binary IS packaged with cargo-build, then they would be bundled with the binary and all works OK. (Optional to include a way in Cargo.toml of the binary to strip out resources from dependent libraries?)

  • if the binary also includes resources, then they would be bundled also, into a combined folder tree (with files from any dependant lib) in the resulting binary. Library resources would maybe need to be namespaced by lib name in the folder tree to avoid conflicts.

Get's a bit complicated I know....but it's either this, or we bake all files in as code using include_str!() and the like, to libs and binaries, and then write methods to navigate around and find them....kind of like a FileSystem :-)

Alternative Ideas: I guess I could look at creating a custom Framework (Mac OS) and bundling that? Not sure how it works on other OS....

andrewdavidmackenzie avatar Feb 05 '18 09:02 andrewdavidmackenzie

Any feedback on the idea @mdsteele ?

Thinking about my project, this is the cleanest way to achieve what I want to do, but given the complexity, I may need to bail and find another way to achieve it :-(

I guess we'd need to run cargo-bundle on all the dependencies (libs, workspace members) in the build (which is quite a big deal :-( ) and have those assets "bundled" (copied) into the output directory where the final build is done and cargo-bundle would create the final applicaiton bundle when the binary is finally built....

Either way I'll will do work on https://github.com/burtonageo/cargo-bundle/issues/42 as that's good for everyone.

andrewdavidmackenzie avatar Feb 07 '18 09:02 andrewdavidmackenzie

I looked into this a little more, and it might be doable:

  • It looks like Cargo.toml has an include field that allows crates to include extra files as part of the crate to be downloaded from crates.io.
  • For third-party commands (like cargo-bundle), Cargo sets a CARGO environment variable pointing to the cargo executable, which allows us to run other cargo subcommands.
  • The cargo metadata subcommand can get us info about the bundled binary's recursive dependencies, including manifest_path fields pointing to the Cargo.toml file for each dependency.
  • So, when running cargo-bundle for a binary, it could use cargo metadata to find the Cargo.toml files for every dependency, read each one to check for a package.metadata.bundle.resources field, follow those paths (relative to each Cargo.toml path) to find the resource files, and include them in the binary bundle.

Not sure how expensive all that is to do for every cargo-bundle invocation. It may be that we want this behavior to be off by default, with a [package.metadata.bundle] field to enable it.

mdsteele avatar Feb 07 '18 15:02 mdsteele

Wow! That's much more encouraging than I expected. I'd kind of given up....

Yes, some kind of "include subproject bundled files" flag would do it! Options like:

  • include all
  • exclude all
  • include a named list
  • exclude a named list

andrewdavidmackenzie avatar Feb 07 '18 22:02 andrewdavidmackenzie

Now that I've made progress on fixing the workspace awareness, I might be able to attack this in the next week or two (busy all next week).

Where the "included" files are bundled from ("target" directory) should follow the same logic as the non-workspace/workspace case I guess.

I guess that when building a library, the recursive bundling wouldn't need to be done (just let cargo "include" it's own files), as that can be deferred until a binary is built, and then it can do the whole dependency tree.

andrewdavidmackenzie avatar Feb 10 '18 20:02 andrewdavidmackenzie