1#![doc = include_str!("../README.md")]
2
3use std::{env, path::PathBuf, process::Command};
4
5const VC_LTL_VERSION: &'static str = "5.2.2";
6const YY_THUNKS_VERSION: &'static str = "1.1.7";
7
8pub fn thunk() {
10 let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap();
11 let target_env = env::var("CARGO_CFG_TARGET_ENV").unwrap();
12
13 if target_os != "windows" || target_env != "msvc" {
14 println!("cargo::warning=Skipped! Only Windows(MSVC) is supported!");
15 return;
16 }
17
18 let target_arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap();
19 let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
20
21 let vc_ltl_arch = if target_arch == "x86" { "Win32" } else { "x64" };
23 let vc_ltl_platform = if cfg!(feature = "xp") {
24 if vc_ltl_arch == "Win32" {
25 "5.1.2600.0"
26 } else {
27 "5.2.3790.0"
28 }
29 } else if cfg!(feature = "vista") || cfg!(feature = "win7") {
30 "6.0.6000.0"
31 } else if cfg!(feature = "win8") {
32 "6.2.9200.0"
33 } else if cfg!(feature = "win10_10240") {
34 "10.0.10240.0"
35 } else if cfg!(feature = "win10_19041") {
36 "10.0.19041.0"
37 } else if cfg!(feature = "vc_ltl_only") {
38 "6.0.6000.0"
39 } else {
40 println!("cargo::warning=VC-LTL5 Skipped: Nothing to do!");
41 return;
42 };
43
44 let vc_ltl = get_or_download(
45 "VC_LTL",
46 "VC_LTL_URL",
47 &format!(
48 "https://github.com/Chuyu-Team/VC-LTL5/releases/download/v{}/VC-LTL-Binary.7z",
49 VC_LTL_VERSION
50 ),
51 &out_dir,
52 &format!("VC-LTL-{}", VC_LTL_VERSION),
53 );
54
55 let vc_ltl_path = vc_ltl.join(&format!(
56 "TargetPlatform/{}/lib/{}",
57 vc_ltl_platform, vc_ltl_arch
58 ));
59
60 println!("cargo::rustc-link-search={}", vc_ltl_path.to_string_lossy());
61 println!(
62 "cargo::warning=VC-LTL5 Enabled: {}({})",
63 vc_ltl_platform, vc_ltl_arch
64 );
65
66 let yy_thunks_arch = if target_arch == "x86" { "x86" } else { "x64" };
68 let yy_thunks_platform = if cfg!(feature = "xp") {
69 "WinXP"
70 } else if cfg!(feature = "vista") {
71 "Vista"
72 } else if cfg!(feature = "win7") {
73 "Win7"
74 } else if cfg!(feature = "win8") {
75 "Win8"
76 } else if cfg!(feature = "win10_10240") {
77 "Win10.0.10240"
78 } else if cfg!(feature = "win10_19041") {
79 "Win10.0.19041"
80 } else {
81 println!("cargo::warning=YY-Thunks Skipped: Nothing to do!!");
82 return;
83 };
84
85 let yy_thunks = get_or_download(
86 "YY_THUNKS",
87 "YY_THUNKS_URL",
88 &format!(
89 "https://github.com/Chuyu-Team/YY-Thunks/releases/download/v{}/YY-Thunks-Objs.zip",
90 YY_THUNKS_VERSION
91 ),
92 &out_dir,
93 &format!("YY-Thunks-{}", YY_THUNKS_VERSION),
94 );
95
96 let yy_thunks = yy_thunks.join(format!(
97 "objs/{}/YY_Thunks_for_{}.obj",
98 yy_thunks_arch, yy_thunks_platform
99 ));
100
101 println!("cargo::rustc-link-arg={}", yy_thunks.to_string_lossy());
102 println!(
103 "cargo::warning=YY-Thunks Enabled: {}({})",
104 yy_thunks_platform, yy_thunks_arch
105 );
106
107 if cfg!(feature = "lib") {
109 println!("cargo::warning=Lib Mode Enabled!");
110 return;
111 }
112
113 let os_version = if cfg!(feature = "xp") {
115 if target_arch == "x86" {
116 ",5.01"
117 } else {
118 ",5.02"
119 }
120 } else {
121 ""
122 };
123
124 if cfg!(feature = "subsystem_windows") && env::var("PROFILE").unwrap() != "debug" {
125 println!("cargo::rustc-link-arg=/SUBSYSTEM:WINDOWS{}", os_version);
126 println!("cargo::rustc-link-arg=/ENTRY:mainCRTStartup");
127 println!("cargo::warning=Subsystem is set to WINDOWS");
128 } else {
129 println!("cargo::rustc-link-arg=/SUBSYSTEM:CONSOLE{}", os_version);
130 }
131}
132
133fn get_or_download(
134 env_path: &str,
135 env_url: &str,
136 default_url: &str,
137 out_dir: &PathBuf,
138 unpack_name: &str,
139) -> PathBuf {
140 if let Ok(env_path) = env::var(env_path) {
141 PathBuf::from(env_path)
142 } else {
143 let unpack_dir = out_dir.join(unpack_name);
144
145 if unpack_dir.exists() {
147 return unpack_dir;
148 }
149
150 let url = if let Ok(env_url) = env::var(env_url) {
151 PathBuf::from(env_url)
152 } else {
153 PathBuf::from(default_url)
154 };
155
156 let curl_status = Command::new("curl")
157 .args(["-LOkf", url.to_str().unwrap()])
158 .current_dir(out_dir)
159 .status()
160 .expect("Curl is needed to download binaries!");
161
162 if !curl_status.success() {
163 panic!("Download libraries from {:?} failed", url)
164 }
165
166 let extract_status = Command::new("7z")
167 .args([
168 "x",
169 "-aoa",
170 url.file_name().unwrap().to_str().unwrap(),
171 &format!("-o{}", unpack_name),
172 ])
173 .current_dir(out_dir)
174 .status()
175 .expect("7z is needed to unpack libraries!");
176
177 if !extract_status.success() {
178 panic!("Unpack YY-Thunks failed!")
179 }
180
181 unpack_dir
182 }
183}