A Cargo
build script library to handle compilation and inclusion of Windows resources
in the most resilient fashion imaginable
In your build script, assuming the resource file is called checksums.rc
:
extern crate embed_resource;
fn main() {
// Compile and link checksums.rc
embed_resource::compile("checksums.rc", embed_resource::NONE).manifest_optional().unwrap();
// Or, to select a resource file for each binary separately
embed_resource::compile_for("assets/poke-a-mango.rc", &["poke-a-mango", "poke-a-mango-installer"], &["VERSION=\"0.5.0\""]).manifest_required().unwrap();
embed_resource::compile_for("assets/uninstaller.rc", &["unins001"], embed_resource::NONE).manifest_required().unwrap();
}
Use .manifest_optional().unwrap()
if the manifest is cosmetic (like an icon).
Use .manifest_required().unwrap()
if the manifest is required (security, entry point, &c.).
Courtesy of @jpoles1.
The following steps are used to embed a manifest in your compiled rust .exe file. In this example the manifest will cause admin permissions to be requested for the final executable:
- Add the following to your cargo.toml:
[build-dependencies]
embed-resource = "2.5"
- In your project root directory, add a file named
build.rs
with the following:
extern crate embed_resource;
fn main() {
embed_resource::compile("app-name-manifest.rc", embed_resource::NONE).manifest_optional().unwrap();
}
- In your project root directory, add a file named
app-name-manifest.rc
with the following:
#define RT_MANIFEST 24
1 RT_MANIFEST "app-name.exe.manifest"
- In your project root directory, add a file named
app-name.exe.manifest
with the following:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="requireAdministrator" uiAccess="false"/>
</requestedPrivileges>
</security>
</trustInfo>
</assembly>
- Build your project!
If no cargo:rerun-if-changed
annotations are generated, Cargo scans the entire build root by default.
Because the first step in building a manifest is an unspecified C preprocessor step with-out the ability to generate the equivalent of cc -MD
, we do not output said annotation.
If scanning is prohibitively expensive, or you have something else that generates the annotations, you may want to spec the full non-system dependency list for your manifest manually, so:
println!("cargo:rerun-if-changed=app-name-manifest.rc");
embed_resource::compile("app-name-manifest.rc", embed_resource::NONE).manifest_optional().unwrap();
for the above example (cf. #41).
Add embed_resource::NONE
as the last argument to embed_resource::compile()
and embed_resource::compile_for()
.
Add .manifest_optional().unwrap()
or .manifest_required().unwrap()
to all embed_resource::compile()
and embed_resource::compile_for*()
calls.
CompilationResult
is #[must_use]
so should be highlighted automatically.
Embed-resource <3.x always behaves like .manifest_optional().unwrap()
.
In chronological order:
@liigo -- persistency in pestering me and investigating problems where I have failed
@mzji -- MSVC lab rat
@TheCatPlusPlus -- knowledge and providing first iteration of manifest-embedding code
@azyobuzin -- providing code for finding places where RC.EXE could hide
@retep998 -- fixing MSVC support
@SonnyX -- Windows cross-compilation support and testing
@MSxDOS -- finding and supplying RC.EXE its esoteric header include paths
@roblabla -- cross-compilation to Windows MSVC via LLVM-RC
To all who support further development on Patreon, in particular:
- ThePhD
- Embark Studios
- Lars Strojny
- EvModder