build_vcxproj/
sample_builder.rs1use cc;
2use std::env;
3use std::collections::HashSet;
4use bitflags::bitflags;
5
6fn find_files(ptns: &[&str]) -> Vec<String> {
7 let mut rt = HashSet::new();
8 for ptn in ptns {
9 if ptn.starts_with("-") {
10 let ptn = &ptn[1..];
11 for f in glob::glob(ptn).unwrap().filter_map(Result::ok) {
12 rt.remove(&f);
13 }
14 } else {
15 for f in glob::glob(ptn).unwrap().filter_map(Result::ok) {
16 rt.insert(f);
17 }
18 }
19 }
20 rt.iter().map(|x| x.display().to_string()).collect()
21}
22
23#[cfg(target_os = "windows")]
24fn init_builder(is_debug: bool) -> cc::Build {
25 env::set_var("VSLANG", "1033");
26 let mut cxxb = cc::Build::new();
27 cxxb.cpp(true).std("c++20").flag("/EHsc").flag("/utf-8")
28 .flag("/D_CRT_SECURE_NO_WARNINGS")
29 .flag("/D_CRT_NONSTDC_NO_WARNINGS")
30 .flag("/DUNICODE").flag("/D_UNICODE").flag("/Zi").flag("/FS");
31 if is_debug {
32 cxxb.flag("/Od").flag("/RTC1").flag("/D_DEBUG");
33 } else {
34 cxxb.flag("/O2").flag("/DNDEBUG");
35 }
36 cxxb
37}
38#[cfg(not(target_os = "windows"))]
39fn init_builder(isdebug: bool) -> cc::Build {
40 let mut cxxb = cc::Build::new();
41 cxxb.cpp(true).std("c++20").flag("-Wall").flag("-Wextra")
42 .flag("-Wno-unused-parameter")
43 .flag("-Wno-unused-result")
44 .flag("-Wno-multichar")
45 .flag("-Wno-missing-field-initializers")
46 .flag("-Wno-unknown-pragmas")
47 .flag("-g");
48 if isdebug {
49 cxxb.flag("-O0");
50 } else {
51 cxxb.flag("-O2");
52 }
53 cxxb
54}
55
56bitflags! {
57 pub struct BuildOptions: u32 {
58 const BuildWithVCLib = 0b01;
59 const Dummy = 0b10;
60 }
61}
62
63
64#[allow(dead_code)]
65pub fn build<T>(projname: &str, headers: &[&str], sources: &[&str], incdirs:&[&str],
66 opt:BuildOptions, modify: T)
67 where T: FnOnce(&mut cc::Build)
68{
69 let srcfiles = find_files(sources);
70 for entry in &srcfiles {
71 println!("cargo:rerun-if-changed={}", entry);
72 }
73 for entry in find_files(headers) {
74 println!("cargo:rerun-if-changed={}", entry);
75 }
76
77 let from_vs = if opt.contains(BuildOptions::BuildWithVCLib) {
78 env::var("VisualStudioDir").map(|x| !x.is_empty()).unwrap_or(false)
79 } else {
80 false
81 };
82 let is_debug = env::var("PROFILE").map(|x| x == "debug").unwrap_or(false);
83 if from_vs {
84 if is_debug {
85 println!("cargo:rustc-link-arg-bins=/WHOLEARCHIVE:x64/Debug/{}.lib", projname);
86 println!("cargo:rerun-if-changed=x64/Debug/{}.lib", projname);
87 } else {
88 println!("cargo:rustc-link-arg-bins=/WHOLEARCHIVE:x64/Release/{}.lib", projname);
89 println!("cargo:rerun-if-changed=x64/Release/{}.lib", projname);
90 }
91 } else {
92 let mut new_incdirs = Vec::new();
93 for dir in incdirs {
94 let expanded_dir = if dir.starts_with("~") {
95 if let Ok(home) = env::var("HOME") {
96 dir.replacen("~", &home, 1)
97 } else {
98 dir.to_string()
99 }
100 } else {
101 dir.to_string()
102 };
103
104 if std::path::Path::new(&expanded_dir).exists() {
105 new_incdirs.push(expanded_dir);
106 }
107 }
108 crate::vcpkg::add_inc_paths(&mut new_incdirs);
109 let mut lib_dirs = Vec::new();
110 crate::vcpkg::add_lib_paths(is_debug, &mut lib_dirs);
111 for libdir in lib_dirs {
112 println!("cargo:rustc-link-search={}", libdir);
113 }
114 let mut cxxb = init_builder(is_debug);
115 cxxb.files(srcfiles);
116 cxxb.includes(&new_incdirs);
117 modify(&mut cxxb);
118 cxxb.compile(&format!("{}", projname));
119 }
120}