Where to put asset files for application?

Ref: Reference asset files from a test

Where do you put asset files? Icons, data, etc. that ship with the application?
That suggests looking for files relative to CARGO_MANIFEST_DIR. That's fine for tests. But when you finally package up an executable, where should the asset files go? Any portable solutions? Options:

  • Subdirectory in the same directory as the executable file. This is common for programs installed by unzipping and running, but not for Windows installers, .deb files, etc. It's a bit inconvenient for testing, because cargo will generate outputs in target/debug, target/PLATFORMNAME/release, etc.

  • Look in Executable dir, then CARGO_MANIFEST_DIR. This lets you test.

  • None of the paths from the directories crate seem useful. It would be nice to have asset_dir as an output from directories, but that has to be coordinated with whatever makes the install bundle.

Most solutions to this problem seem to involve some kludge such as having the main program be a shell script which sets paths, or Windows registry keys, or whatever you do on Mac.

If someone ever gets the cargo bundler working on more platforms, there will be a need for some way for it to communicate its placement choices to the program. cargo bundler needs attention from a Windows expert. Mac works, and .deb wouldn't be too hard to fix, but cranking out Windows installers requires arcane knowledge.

I doubt there's a good answer for this yet, but it's one of those cross-platform headaches worth pounding on.

3 Likes

One option, assuming you are not interested in swapping out assets without rebuilding, is to embed the assets inside the binary with include_bytes and/or include_str.

I've done that for some small icons, but some of the assets are too big and not needed resident in memory.

In that case, I don’t have a better suggestion than just using a path relative to the executable, and working around the test inconvenience by setting the path with #[cfg(test)] and similar things.

1 Like

Yeah, there's no standard for this. Paths relative to std::env::current_exe() are not too bad, but if you want to be a good citizen on each platform, you need platform-specific bundling/installers.

2 Likes

If you are referring to Tauri's bundler then cargo tauri build should be all you need. We currently use it to generate Linux, MacOS, and Windows installers for our Tauri app in CI.

Generally, this will be specific to your installer. Tauri has a bundle.resources array which lets you make sure certain files will be available when installed.

For data, take a look at the new Fetch-Data crate. It allows both tests and examples to download only the data they need. Users can run examples without downloading all data files.

I use it in the Bed-Reader crate to define a handy sample_file function:

use fetch_data::sample_file;

let path = sample_file("small.fam")?;
println!("{}", std::fs::metadata(path)?.len()); // Prints 85

Behind the scenes, it uses a file cache and a registry of URLs and hashes. It is inspired by and has some compatibility with the very popular Pooch Python package.

The Tauri bundler seems to be set up mostly for building web apps. There's a whole Tauri ecosystem. It's an entire framework.

Tauri isn't doing the bundling, Tauri uses Wix to do that work, so you have to have some Wix tools installed. Those only run on Windows, and need various DLLs. What it really does is run "light.exe" and "candle.exe" from Wix v3. Wix is now at version 4, and those programs have been subsumed into a bigger "wix.exe".

Wix does a lot. Too much, really. "For example, WiX can install IIS web sites, create SQL Server databases, and register exceptions in the Windows Firewall, among others." It packages your program with something called "Burn", which apparently runs during installation. The way this works, I think, is that something generates XML files which are compiled by "candle.exe" into some DLL that goes into the installer to be executed at install time by Wix's "burn". You're buying into a big ecosystem. And all that stuff has to run on Windows to build for Windows.

I'm in a different Rust ecosystem - Rend3/Egui/Winit/Rfd/WGPU/Vulkan. I can generate good GUI executables without actually using a Windows system. Even all the 3D stuff works. But as yet I can't package the binaries and support files for installation.

Every Windows installer maker tool I can find seems to come with a huge amount of excess baggage. Microsoft's newer tools are now either cloud based or node-locked, and only run on licensed Windows systems.

1 Like

OK, current plan: have program look for the asset directory first in the directory of the executable, then look in CARGO_MANIFEST_DIR.

Longer term: try to find someone into Windows installers to finish up cargo bundler in a portable way.

Incidentally, 7-zip (7zz on Linux) can unpack .msi fles. Not that it helps much. They're an archive of obscure binary Microsoft data formats.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.