1pub mod build_type;
4pub mod builtins;
5pub mod ccache_variant;
6pub mod llvm_path;
7pub mod llvm_project;
8pub mod platforms;
9pub mod sanitizer;
10pub mod target_env;
11pub mod target_triple;
12pub mod utils;
13
14pub use self::build_type::BuildType;
15pub use self::llvm_path::LLVMPath;
16pub use self::platforms::Platform;
17
18use std::collections::HashSet;
19use std::path::{Path, PathBuf};
20use std::process::Command;
21pub use target_env::TargetEnv;
22pub use target_triple::TargetTriple;
23
24pub fn init(init_emscripten: bool) -> anyhow::Result<()> {
26 utils::check_presence("git")?;
27
28 if init_emscripten {
29 utils::install_emsdk()?;
30 }
31
32 let destination_path = PathBuf::from(LLVMPath::DIRECTORY_LLVM_SOURCE);
33 if destination_path.join(".git").exists() {
34 log::info!("LLVM submodule already initialized");
35 return Ok(());
36 }
37
38 utils::command(
39 Command::new("git").args(["submodule", "update", "--init", "--recursive"]),
40 "LLVM submodule initialization",
41 )?;
42
43 Ok(())
44}
45
46#[allow(clippy::too_many_arguments)]
51pub fn build(
52 build_type: BuildType,
53 target_env: TargetEnv,
54 targets: HashSet<Platform>,
55 llvm_projects: HashSet<llvm_project::LLVMProject>,
56 enable_rtti: bool,
57 default_target: Option<TargetTriple>,
58 enable_tests: bool,
59 enable_coverage: bool,
60 extra_args: &[String],
61 ccache_variant: Option<ccache_variant::CcacheVariant>,
62 enable_assertions: bool,
63 sanitizer: Option<sanitizer::Sanitizer>,
64 enable_valgrind: bool,
65) -> anyhow::Result<()> {
66 log::trace!("build type: {build_type:?}");
67 log::trace!("target env: {target_env:?}");
68 log::trace!("targets: {targets:?}");
69 log::trace!("llvm projects: {llvm_projects:?}");
70 log::trace!("enable rtti: {enable_rtti:?}");
71 log::trace!("default target: {default_target:?}");
72 log::trace!("eneable tests: {enable_tests:?}");
73 log::trace!("enable_coverage: {enable_coverage:?}");
74 log::trace!("extra args: {extra_args:?}");
75 log::trace!("sanitzer: {sanitizer:?}");
76 log::trace!("enable valgrind: {enable_valgrind:?}");
77
78 if !PathBuf::from(LLVMPath::DIRECTORY_LLVM_SOURCE).exists() {
79 log::error!(
80 "LLVM project source directory {} does not exist (run `revive-llvm --target-env {target_env} clone`)",
81 LLVMPath::DIRECTORY_LLVM_SOURCE
82 )
83 }
84
85 std::fs::create_dir_all(llvm_path::DIRECTORY_LLVM_TARGET.get().unwrap())?;
86
87 if cfg!(target_arch = "x86_64") {
88 if cfg!(target_os = "linux") {
89 if target_env == TargetEnv::MUSL {
90 platforms::x86_64_linux_musl::build(
91 build_type,
92 targets,
93 llvm_projects,
94 enable_rtti,
95 default_target,
96 enable_tests,
97 enable_coverage,
98 extra_args,
99 ccache_variant,
100 enable_assertions,
101 sanitizer,
102 enable_valgrind,
103 )?;
104 } else if target_env == TargetEnv::GNU {
105 platforms::x86_64_linux_gnu::build(
106 build_type,
107 targets,
108 llvm_projects,
109 enable_rtti,
110 default_target,
111 enable_tests,
112 enable_coverage,
113 extra_args,
114 ccache_variant,
115 enable_assertions,
116 sanitizer,
117 enable_valgrind,
118 )?;
119 } else if target_env == TargetEnv::Emscripten {
120 platforms::wasm32_emscripten::build(
121 build_type,
122 targets,
123 llvm_projects,
124 enable_rtti,
125 default_target,
126 enable_tests,
127 enable_coverage,
128 extra_args,
129 ccache_variant,
130 enable_assertions,
131 sanitizer,
132 enable_valgrind,
133 )?;
134 } else {
135 anyhow::bail!("Unsupported target environment for x86_64 and Linux");
136 }
137 } else if cfg!(target_os = "macos") {
138 platforms::x86_64_macos::build(
139 build_type,
140 targets,
141 llvm_projects,
142 enable_rtti,
143 default_target,
144 enable_tests,
145 enable_coverage,
146 extra_args,
147 ccache_variant,
148 enable_assertions,
149 sanitizer,
150 )?;
151 } else if cfg!(target_os = "windows") {
152 platforms::x86_64_windows_msvc::build(
153 build_type,
154 targets,
155 llvm_projects,
156 enable_rtti,
157 default_target,
158 enable_tests,
159 enable_coverage,
160 extra_args,
161 ccache_variant,
162 enable_assertions,
163 sanitizer,
164 )?;
165 } else {
166 anyhow::bail!("Unsupported target OS for x86_64");
167 }
168 } else if cfg!(target_arch = "aarch64") {
169 if cfg!(target_os = "linux") {
170 if target_env == TargetEnv::MUSL {
171 platforms::aarch64_linux_musl::build(
172 build_type,
173 targets,
174 llvm_projects,
175 enable_rtti,
176 default_target,
177 enable_tests,
178 enable_coverage,
179 extra_args,
180 ccache_variant,
181 enable_assertions,
182 sanitizer,
183 enable_valgrind,
184 )?;
185 } else if target_env == TargetEnv::GNU {
186 platforms::aarch64_linux_gnu::build(
187 build_type,
188 targets,
189 llvm_projects,
190 enable_rtti,
191 default_target,
192 enable_tests,
193 enable_coverage,
194 extra_args,
195 ccache_variant,
196 enable_assertions,
197 sanitizer,
198 enable_valgrind,
199 )?;
200 } else {
201 anyhow::bail!("Unsupported target environment for aarch64 and Linux");
202 }
203 } else if cfg!(target_os = "macos") {
204 if target_env == TargetEnv::Emscripten {
205 platforms::wasm32_emscripten::build(
206 build_type,
207 targets,
208 llvm_projects,
209 enable_rtti,
210 default_target,
211 enable_tests,
212 enable_coverage,
213 extra_args,
214 ccache_variant,
215 enable_assertions,
216 sanitizer,
217 enable_valgrind,
218 )?;
219 } else {
220 platforms::aarch64_macos::build(
221 build_type,
222 targets,
223 llvm_projects,
224 enable_rtti,
225 default_target,
226 enable_tests,
227 enable_coverage,
228 extra_args,
229 ccache_variant,
230 enable_assertions,
231 sanitizer,
232 )?;
233 }
234 } else {
235 anyhow::bail!("Unsupported target OS for aarch64");
236 }
237 } else {
238 anyhow::bail!("Unsupported target architecture");
239 }
240
241 crate::builtins::build(
242 build_type,
243 target_env,
244 default_target,
245 extra_args,
246 ccache_variant,
247 sanitizer,
248 )?;
249
250 Ok(())
251}
252
253pub fn clean() -> anyhow::Result<()> {
255 let remove_if_exists = |path: &Path| {
256 if !path.exists() {
257 return Ok(());
258 }
259 log::info!("deleting {}", path.display());
260 std::fs::remove_dir_all(path)
261 };
262
263 remove_if_exists(
264 llvm_path::DIRECTORY_LLVM_TARGET
265 .get()
266 .expect("target_env is always set because of the default value")
267 .parent()
268 .expect("target_env parent directory is target-llvm"),
269 )?;
270 remove_if_exists(&PathBuf::from(LLVMPath::DIRECTORY_EMSDK_SOURCE))?;
271
272 Ok(())
273}