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 resource library creation on Windows with GNU toolchain. #12804

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
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
60 changes: 60 additions & 0 deletions helix-term/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ mod windows_rc {
use std::io::prelude::Write;
use std::{env, io, path::Path, path::PathBuf, process};

#[cfg(target_env = "msvc")]
pub(crate) fn link_icon_in_windows_exe(icon_path: &str) {
let rc_exe = find_rc_exe().expect("Windows SDK is to be installed along with MSVC");

Expand All @@ -32,6 +33,7 @@ mod windows_rc {
println!("cargo:rustc-link-lib=dylib=resource");
}

#[cfg(target_env = "msvc")]
fn compile_with_toolkit_msvc(rc_exe: PathBuf, output: PathBuf, input: PathBuf) {
let mut command = process::Command::new(rc_exe);
let command = command.arg(format!(
Expand All @@ -56,6 +58,7 @@ mod windows_rc {
);
}

#[cfg(target_env = "msvc")]
fn find_rc_exe() -> io::Result<PathBuf> {
let find_reg_key = process::Command::new("reg")
.arg("query")
Expand Down Expand Up @@ -144,6 +147,63 @@ mod windows_rc {
}
}

#[cfg(target_env = "gnu")]
pub(crate) fn link_icon_in_windows_exe(icon_path: &str) {
let windres_exe = PathBuf::from(r"windres.exe");
check_if_exe_works(&windres_exe).expect(
"Could not locate windres.exe binary from gnu toolkit in the PATH environment variable.",
);

let output = env::var("OUT_DIR").expect("Env var OUT_DIR should have been set by compiler");
let output_dir = PathBuf::from(output);

let rc_path = output_dir.join("resource.rc");
write_resource_file(&rc_path, icon_path).unwrap();

let resource_file = PathBuf::from(&output_dir).join("resource.lib");
compile_with_toolkit_gnu(windres_exe, resource_file, rc_path);

println!("cargo:rustc-link-search=native={}", output_dir.display());
println!("cargo:rustc-link-lib=dylib=resource");
}

#[cfg(target_env = "gnu")]
fn compile_with_toolkit_gnu(windres_exe: PathBuf, output: PathBuf, input: PathBuf) {
let mut command = process::Command::new(windres_exe);
let command = command.arg(format!(
"-I {}",
env::var("CARGO_MANIFEST_DIR")
.expect("CARGO_MANIFEST_DIR should have been set by Cargo")
));

let status = command
.arg(format!("--output={}", output.display()))
.arg(format!("{}", input.display()))
.output()
.unwrap();

println!(
"RC Output:\n{}\n------",
String::from_utf8_lossy(&status.stdout)
);
println!(
"RC Error:\n{}\n------",
String::from_utf8_lossy(&status.stderr)
);
}

#[cfg(target_env = "gnu")]
fn check_if_exe_works(exe: &PathBuf) -> Result<(), ()> {
let output = process::Command::new(exe)
.arg("--version") // Optional: You can pass an argument to check if the command is working
.output();

match output {
Ok(_) => Ok(()), // Command exists and ran successfully
Err(_) => Err(()), // Command failed to run
}
}

fn write_resource_file(rc_path: &Path, icon_path: &str) -> io::Result<()> {
let mut f = std::fs::File::create(rc_path)?;
writeln!(f, "{} ICON \"{}\"", 1, icon_path)?;
Expand Down