A post-modern development environment.
0

Configure Feed

Select the types of activity you want to include in your feed.

Add icon to Windows executable (#9104)

* injecting the icon through a resource file, no extra deps

* formatted

* scripted rc compilation

* formatted and restructured

* simplified conditional func call

author
NitinKM
committer
GitHub
date (Jan 28, 2024, 6:31 PM +0900) commit 4ab70295 parent eb3c4e9f
+146
contrib/helix-256p.ico

This is a binary file and will not be displayed.

+146
helix-term/build.rs
··· 6 6 build_grammars(Some(std::env::var("TARGET").unwrap())) 7 7 .expect("Failed to compile tree-sitter grammars"); 8 8 } 9 + 10 + #[cfg(windows)] 11 + windows_rc::link_icon_in_windows_exe("../contrib/helix-256p.ico"); 12 + } 13 + 14 + #[cfg(windows)] 15 + mod windows_rc { 16 + use std::io::prelude::Write; 17 + use std::{env, io, path::Path, path::PathBuf, process}; 18 + 19 + pub(crate) fn link_icon_in_windows_exe(icon_path: &str) { 20 + let rc_exe = find_rc_exe().expect("Windows SDK is to be installed along with MSVC"); 21 + 22 + let output = env::var("OUT_DIR").expect("Env var OUT_DIR should have been set by compiler"); 23 + let output_dir = PathBuf::from(output); 24 + 25 + let rc_path = output_dir.join("resource.rc"); 26 + write_resource_file(&rc_path, icon_path).unwrap(); 27 + 28 + let resource_file = PathBuf::from(&output_dir).join("resource.lib"); 29 + compile_with_toolkit_msvc(rc_exe, resource_file, rc_path); 30 + 31 + println!("cargo:rustc-link-search=native={}", output_dir.display()); 32 + println!("cargo:rustc-link-lib=dylib=resource"); 33 + } 34 + 35 + fn compile_with_toolkit_msvc(rc_exe: PathBuf, output: PathBuf, input: PathBuf) { 36 + let mut command = process::Command::new(rc_exe); 37 + let command = command.arg(format!( 38 + "/I{}", 39 + env::var("CARGO_MANIFEST_DIR") 40 + .expect("CARGO_MANIFEST_DIR should have been set by Cargo") 41 + )); 42 + 43 + let status = command 44 + .arg(format!("/fo{}", output.display())) 45 + .arg(format!("{}", input.display())) 46 + .output() 47 + .unwrap(); 48 + 49 + println!( 50 + "RC Output:\n{}\n------", 51 + String::from_utf8_lossy(&status.stdout) 52 + ); 53 + println!( 54 + "RC Error:\n{}\n------", 55 + String::from_utf8_lossy(&status.stderr) 56 + ); 57 + } 58 + 59 + fn find_rc_exe() -> io::Result<PathBuf> { 60 + let find_reg_key = process::Command::new("reg") 61 + .arg("query") 62 + .arg(r"HKLM\SOFTWARE\Microsoft\Windows Kits\Installed Roots") 63 + .arg("/reg:32") 64 + .arg("/v") 65 + .arg("KitsRoot10") 66 + .output(); 67 + 68 + match find_reg_key { 69 + Err(find_reg_key) => { 70 + return Err(io::Error::new( 71 + io::ErrorKind::Other, 72 + format!("Failed to run registry query: {}", find_reg_key), 73 + )) 74 + } 75 + Ok(find_reg_key) => { 76 + if find_reg_key.status.code().unwrap() != 0 { 77 + return Err(io::Error::new( 78 + io::ErrorKind::Other, 79 + "Can not find Windows SDK", 80 + )); 81 + } else { 82 + let lines = String::from_utf8(find_reg_key.stdout) 83 + .expect("Should be able to parse the output"); 84 + let mut lines: Vec<&str> = lines.lines().collect(); 85 + let mut rc_exe_paths: Vec<PathBuf> = Vec::new(); 86 + lines.reverse(); 87 + for line in lines { 88 + if line.trim().starts_with("KitsRoot") { 89 + let kit: String = line 90 + .chars() 91 + .skip(line.find("REG_SZ").unwrap() + 6) 92 + .skip_while(|c| c.is_whitespace()) 93 + .collect(); 94 + 95 + let p = PathBuf::from(&kit); 96 + let rc = if cfg!(target_arch = "x86_64") { 97 + p.join(r"bin\x64\rc.exe") 98 + } else { 99 + p.join(r"bin\x86\rc.exe") 100 + }; 101 + 102 + if rc.exists() { 103 + println!("{:?}", rc); 104 + rc_exe_paths.push(rc.to_owned()); 105 + } 106 + 107 + if let Ok(bin) = p.join("bin").read_dir() { 108 + for e in bin.filter_map(|e| e.ok()) { 109 + let p = if cfg!(target_arch = "x86_64") { 110 + e.path().join(r"x64\rc.exe") 111 + } else { 112 + e.path().join(r"x86\rc.exe") 113 + }; 114 + if p.exists() { 115 + println!("{:?}", p); 116 + rc_exe_paths.push(p.to_owned()); 117 + } 118 + } 119 + } 120 + } 121 + } 122 + if rc_exe_paths.is_empty() { 123 + return Err(io::Error::new( 124 + io::ErrorKind::Other, 125 + "Can not find Windows SDK", 126 + )); 127 + } 128 + 129 + println!("{:?}", rc_exe_paths); 130 + let rc_path = rc_exe_paths.pop().unwrap(); 131 + 132 + let rc_exe = if !rc_path.exists() { 133 + if cfg!(target_arch = "x86_64") { 134 + PathBuf::from(rc_path.parent().unwrap()).join(r"bin\x64\rc.exe") 135 + } else { 136 + PathBuf::from(rc_path.parent().unwrap()).join(r"bin\x86\rc.exe") 137 + } 138 + } else { 139 + rc_path 140 + }; 141 + 142 + println!("Selected RC path: '{}'", rc_exe.display()); 143 + Ok(rc_exe) 144 + } 145 + } 146 + } 147 + } 148 + 149 + fn write_resource_file(rc_path: &Path, icon_path: &str) -> io::Result<()> { 150 + let mut f = std::fs::File::create(rc_path)?; 151 + writeln!(f, "{} ICON \"{}\"", 1, icon_path)?; 152 + 153 + Ok(()) 154 + } 9 155 }