shadow_build_common/
lib.rs1#![deny(unsafe_op_in_unsafe_fn)]
3
4use std::path::Path;
5
6pub struct ShadowBuildCommon {
7 deps: Option<system_deps::Dependencies>,
8 build_src_root: Box<Path>,
9 src_root: Box<Path>,
10}
11
12impl ShadowBuildCommon {
13 pub fn new(repo_root: &Path, system_deps: Option<system_deps::Dependencies>) -> Self {
14 let src_root = {
15 let mut p = repo_root.to_path_buf();
16 p.push("src");
17 p.into_boxed_path()
18 };
19
20 let build_src_root = {
21 let mut p = repo_root.to_path_buf();
22 p.push("build");
23 p.push("src");
24 p.into_boxed_path()
25 };
26
27 println!("cargo:rerun-if-changed=.");
30
31 Self {
32 deps: system_deps,
33 build_src_root,
34 src_root,
35 }
36 }
37
38 pub fn cc_build(&self, compiler: Compiler) -> cc::Build {
39 let mut b = cc::Build::new();
40 println!("cargo:rerun-if-env-changed=CC");
41 println!("cargo:rerun-if-env-changed=CXX");
42 println!("cargo:rerun-if-env-changed=CFLAGS");
43 println!("cargo:rerun-if-env-changed=CXXFLAGS");
44
45 match compiler {
47 Compiler::C => {
48 b.std("gnu11");
49 }
50 Compiler::CPP => {
51 b.cpp(true);
53 b.std("c++11");
54 }
55 }
56
57 b.define("_GNU_SOURCE", None)
61 .include(&*self.build_src_root)
62 .include(&*self.src_root)
63 .warnings(false)
66 .warnings_into_errors(false);
70
71 if let Some(deps) = &self.deps {
72 b.includes(deps.all_include_paths());
73 }
74
75 if let Some("true") = std::env::var("DEBUG").ok().as_deref() {
76 b.flag("-DDEBUG")
77 .flag("-Wunused-function");
81 } else {
82 b.flag("-DNDEBUG");
83 }
84
85 b
86 }
87
88 #[cfg(feature = "bindgen")]
89 pub fn bindgen_builder(&self) -> bindgen::Builder {
90 let mut builder = bindgen::Builder::default()
91 .parse_callbacks(Box::new(bindgen::CargoCallbacks::new()))
94 .clang_args(&[
95 &format!("-I{}", self.build_src_root.to_str().unwrap()),
96 &format!("-I{}", self.src_root.to_str().unwrap()),
97 "-D_GNU_SOURCE",
98 ])
99 .enable_function_attribute_detection();
101
102 if let Some(deps) = &self.deps {
103 for path in deps.all_include_paths() {
104 builder = builder.clang_args(&[format!("-I{}", path.to_str().unwrap())]);
105 }
106 }
107 builder
108 }
109
110 #[cfg(feature = "cbindgen")]
111 pub fn cbindgen_base_config(&self) -> cbindgen::Config {
112 let header = "
113/*
114 * The Shadow Simulator
115 * See LICENSE for licensing information
116 */
117// clang-format off";
118
119 cbindgen::Config {
120 language: cbindgen::Language::C,
121 line_length: 100,
122 documentation_style: cbindgen::DocumentationStyle::C99,
123 macro_expansion: cbindgen::MacroExpansionConfig {
124 bitflags: true,
125 },
126 header: Some(header.into()),
127 autogen_warning: Some(
128 "/* Warning, this file is autogenerated by cbindgen. Don't modify this manually. */"
129 .into(),
130 ),
131 enumeration: cbindgen::EnumConfig {
132 prefix_with_name: true,
133 rename_variants: cbindgen::RenameRule::ScreamingSnakeCase,
134 ..cbindgen::EnumConfig::default()
135 },
136 function: cbindgen::FunctionConfig {
137 must_use: Some("__attribute__((warn_unused_result))".into()),
138 no_return: Some("__attribute__((noreturn))".into()),
139 ..cbindgen::FunctionConfig::default()
140 },
141 export: cbindgen::ExportConfig {
142 rename: std::collections::HashMap::from([
143 ("timeval".into(), "struct timeval".into()),
144 ("timespec".into(), "struct timespec".into()),
145 ]),
146 item_types: vec![
148 cbindgen::ItemType::Enums,
149 cbindgen::ItemType::Constants,
150 cbindgen::ItemType::Globals,
151 cbindgen::ItemType::Structs,
152 cbindgen::ItemType::Unions,
153 cbindgen::ItemType::Typedefs,
154 cbindgen::ItemType::OpaqueItems,
155 cbindgen::ItemType::Functions,
156 ],
157 ..cbindgen::ExportConfig::default()
158 },
159 ..Default::default()
160 }
161 }
162}
163
164#[cfg(feature = "cbindgen")]
165pub trait CBindgenExt {
166 fn get_mut(&mut self) -> &mut cbindgen::Config;
167
168 fn add_opaque_types(&mut self, types: &[&str]) {
174 let c = self.get_mut();
175 if types.is_empty() {
176 return;
177 }
178 if c.after_includes.is_none() {
179 c.after_includes.replace("".into());
180 }
181 for t in types {
182 c.after_includes
183 .as_mut()
184 .unwrap()
185 .push_str(&format!("typedef struct {t} {t};\n"));
186 c.export.exclude.push((*t).into());
187 }
188 }
189}
190
191#[cfg(feature = "cbindgen")]
192impl CBindgenExt for cbindgen::Config {
193 fn get_mut(&mut self) -> &mut cbindgen::Config {
194 self
195 }
196}
197
198pub enum Compiler {
199 C,
200 CPP,
201}