Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for library crates with multiple binaries #8

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 60 additions & 14 deletions lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -616,13 +616,13 @@ impl WindowsResource {
self
}

fn compile_with_toolkit_gnu<'a>(&self, input: &'a str, output_dir: &'a str) -> io::Result<()> {
fn compile_with_toolkit_gnu<'a>(&self, input: &'a str, output_dir: &'a str, binary: Option<&'a str>) -> io::Result<()> {
let target_env = std::env::var("CARGO_CFG_TARGET_ENV").unwrap();

let output = PathBuf::from(output_dir).join(if target_env == "msvc" {
"resource.lib"
format!("{}.lib", binary.unwrap_or("resource"))
} else {
"resource.o"
format!("{}.o", binary.unwrap_or("resource"))
});
let input = PathBuf::from(input);
let status = process::Command::new(&self.windres_path)
Expand All @@ -639,7 +639,7 @@ impl WindowsResource {
}

if target_env == "gnu" {
let libname = PathBuf::from(output_dir).join("libresource.a");
let libname = PathBuf::from(output_dir).join(format!("lib{}.a", binary.unwrap_or("resource")));
let status = process::Command::new(&self.ar_path)
.current_dir(&self.toolkit_path)
.arg("rsc")
Expand All @@ -657,12 +657,34 @@ impl WindowsResource {
println!("cargo:rustc-link-search=native={}", output_dir);

if target_env == "msvc" {
println!("cargo:rustc-link-lib=dylib=resource");
match binary {
None => {
println!("cargo:rustc-link-lib=dylib=resource");
}
Some(binary) => {
println!("cargo:rustc-link-arg-bin={}={}.lib", binary, binary);
}
}
} else {
if version_check::is_min_version("1.61.0").unwrap_or(true) {
println!("cargo:rustc-link-lib=static:+whole-archive=resource");
match binary {
None => {
println!("cargo:rustc-link-lib=static:+whole-archive=resource");
}
Some(binary) => {
println!("cargo:rustc-link-arg-bin={}=--whole-archive", binary);
println!("cargo:rustc-link-arg-bin={}={}.o", binary, binary);
}
}
} else {
println!("cargo:rustc-link-lib=static=resource");
match binary {
None => {
println!("cargo:rustc-link-lib=static=resource");
}
Some(binary) => {
println!("cargo:rustc-link-arg-bin={}={}.o", binary, binary);
}
}
}
}

Expand All @@ -679,8 +701,25 @@ impl WindowsResource {
/// `cargo:rustc-link-lib=` and `cargo:rustc-link-search` on the console,
/// so that the cargo build script can link the compiled resource file.
pub fn compile(&self) -> io::Result<()> {
self.compile_internal(None)
}

/// Run the resource compiler for a specific binary.
///
/// This function generates a resource file from the settings or
/// uses an existing resource file and passes it to the resource compiler
/// of your toolkit.
///
/// Furthermore we will print the correct statements for
/// `cargo:rustc-link-arg-bin=` and `cargo:rustc-link-search` on the console,
/// so that the cargo build script can link the compiled resource file for the desired binary.
pub fn compile_for(&self, binary: &str) -> io::Result<()> {
self.compile_internal(Some(binary))
}

fn compile_internal(&self, binary: Option<&str>) -> io::Result<()> {
let output = PathBuf::from(&self.output_directory);
let rc = output.join("resource.rc");
let rc = output.join(format!("{}.rc", binary.unwrap_or("resource")));
if self.rc_file.is_none() {
self.write_resource_file(&rc)?;
}
Expand All @@ -691,13 +730,13 @@ impl WindowsResource {
};

#[cfg(not(target_os = "windows"))]
return self.compile_with_toolkit_gnu(rc.as_str(), &self.output_directory);
return self.compile_with_toolkit_gnu(rc.as_str(), &self.output_directory, binary);
#[cfg(target_os = "windows")]
{
let target_env = std::env::var("CARGO_CFG_TARGET_ENV").unwrap();
match target_env.as_str() {
"gnu" => self.compile_with_toolkit_gnu(rc.as_str(), &self.output_directory),
"msvc" => self.compile_with_toolkit_msvc(rc.as_str(), &self.output_directory),
"gnu" => self.compile_with_toolkit_gnu(rc.as_str(), &self.output_directory, binary),
"msvc" => self.compile_with_toolkit_msvc(rc.as_str(), &self.output_directory, binary),
_ => Err(io::Error::new(
io::ErrorKind::Other,
"Can only compile resource file when target_env is \"gnu\" or \"msvc\"",
Expand All @@ -706,7 +745,7 @@ impl WindowsResource {
}
}

fn compile_with_toolkit_msvc<'a>(&self, input: &'a str, output_dir: &'a str) -> io::Result<()> {
fn compile_with_toolkit_msvc<'a>(&self, input: &'a str, output_dir: &'a str, binary: Option<&str>) -> io::Result<()> {
let rc_exe = PathBuf::from(&self.toolkit_path).join("rc.exe");
let rc_exe = if !rc_exe.exists() {
if cfg!(target_arch = "x86_64") {
Expand All @@ -718,7 +757,7 @@ impl WindowsResource {
rc_exe
};
println!("Selected RC path: '{}'", rc_exe.display());
let output = PathBuf::from(output_dir).join("resource.lib");
let output = PathBuf::from(output_dir).join(format!("{}.lib", binary.unwrap_or("resource")));
let input = PathBuf::from(input);
let mut command = process::Command::new(&rc_exe);
let command = command.arg(format!("/I{}", env::var("CARGO_MANIFEST_DIR").unwrap()));
Expand Down Expand Up @@ -751,7 +790,14 @@ impl WindowsResource {
}

println!("cargo:rustc-link-search=native={}", output_dir);
println!("cargo:rustc-link-lib=dylib=resource");
match binary {
None => {
println!("cargo:rustc-link-lib=dylib=resource");
}
Some(binary) => {
println!("cargo:rustc-link-arg-bin={}={}.lib", binary, binary);
}
}
Ok(())
}
}
Expand Down
2 changes: 2 additions & 0 deletions multi_binary_example/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/target
/Cargo.lock
18 changes: 18 additions & 0 deletions multi_binary_example/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[package]
name = "multi_binary_example"
description = "Winres - example script for a library with 2 binaries"
version = "0.1.0"
edition = "2021"

[lib]
crate-type = ["rlib"]

[build-dependencies]
tauri-winres = { path = ".." }

[[bin]]
name = "a"

[[bin]]
name = "example-b"
path = "src/bin/b.rs"
23 changes: 23 additions & 0 deletions multi_binary_example/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
use std::error::Error;

fn main() -> Result<(), Box<dyn Error>> {
if std::env::var("CARGO_CFG_TARGET_OS").unwrap() == "windows" {
// Do not do this
// This will cause the binaries to fail building with the below error:
// "fatal error CVT1100: duplicate resource"

// let lib_res = tauri_winres::WindowsResource::new();
// lib_res.compile()?;

// Binary target with name "a"
let mut a_res = tauri_winres::WindowsResource::new();
a_res.set("FileDescription", "multi_binary_example - example A");
a_res.compile_for("a")?;

// Binary target with name "example-b"
let mut b_res = tauri_winres::WindowsResource::new();
b_res.set("FileDescription", "multi_binary_example - example B");
b_res.compile_for("example-b")?;
}
Ok(())
}
3 changes: 3 additions & 0 deletions multi_binary_example/src/bin/a.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
fn main() {
println!("2 + 2 is {}", multi_binary_example::add(2, 2));
}
3 changes: 3 additions & 0 deletions multi_binary_example/src/bin/b.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
fn main() {
println!("Example B");
}
3 changes: 3 additions & 0 deletions multi_binary_example/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pub fn add(left: usize, right: usize) -> usize {
left + right
}