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 utils::apply_patches()?;
86
87 std::fs::create_dir_all(llvm_path::DIRECTORY_LLVM_TARGET.get().unwrap())?;
88
89 if cfg!(target_arch = "x86_64") {
90 if cfg!(target_os = "linux") {
91 if target_env == TargetEnv::MUSL {
92 platforms::x86_64_linux_musl::build(
93 build_type,
94 targets,
95 llvm_projects,
96 enable_rtti,
97 default_target,
98 enable_tests,
99 enable_coverage,
100 extra_args,
101 ccache_variant,
102 enable_assertions,
103 sanitizer,
104 enable_valgrind,
105 )?;
106 } else if target_env == TargetEnv::GNU {
107 platforms::x86_64_linux_gnu::build(
108 build_type,
109 targets,
110 llvm_projects,
111 enable_rtti,
112 default_target,
113 enable_tests,
114 enable_coverage,
115 extra_args,
116 ccache_variant,
117 enable_assertions,
118 sanitizer,
119 enable_valgrind,
120 )?;
121 } else if target_env == TargetEnv::Emscripten {
122 platforms::wasm32_emscripten::build(
123 build_type,
124 targets,
125 llvm_projects,
126 enable_rtti,
127 default_target,
128 enable_tests,
129 enable_coverage,
130 extra_args,
131 ccache_variant,
132 enable_assertions,
133 sanitizer,
134 enable_valgrind,
135 )?;
136 } else {
137 anyhow::bail!("Unsupported target environment for x86_64 and Linux");
138 }
139 } else if cfg!(target_os = "macos") {
140 platforms::x86_64_macos::build(
141 build_type,
142 targets,
143 llvm_projects,
144 enable_rtti,
145 default_target,
146 enable_tests,
147 enable_coverage,
148 extra_args,
149 ccache_variant,
150 enable_assertions,
151 sanitizer,
152 )?;
153 } else if cfg!(target_os = "windows") {
154 platforms::x86_64_windows_msvc::build(
155 build_type,
156 targets,
157 llvm_projects,
158 enable_rtti,
159 default_target,
160 enable_tests,
161 enable_coverage,
162 extra_args,
163 ccache_variant,
164 enable_assertions,
165 sanitizer,
166 )?;
167 } else {
168 anyhow::bail!("Unsupported target OS for x86_64");
169 }
170 } else if cfg!(target_arch = "aarch64") {
171 if cfg!(target_os = "linux") {
172 if target_env == TargetEnv::MUSL {
173 platforms::aarch64_linux_musl::build(
174 build_type,
175 targets,
176 llvm_projects,
177 enable_rtti,
178 default_target,
179 enable_tests,
180 enable_coverage,
181 extra_args,
182 ccache_variant,
183 enable_assertions,
184 sanitizer,
185 enable_valgrind,
186 )?;
187 } else if target_env == TargetEnv::GNU {
188 platforms::aarch64_linux_gnu::build(
189 build_type,
190 targets,
191 llvm_projects,
192 enable_rtti,
193 default_target,
194 enable_tests,
195 enable_coverage,
196 extra_args,
197 ccache_variant,
198 enable_assertions,
199 sanitizer,
200 enable_valgrind,
201 )?;
202 } else {
203 anyhow::bail!("Unsupported target environment for aarch64 and Linux");
204 }
205 } else if cfg!(target_os = "macos") {
206 if target_env == TargetEnv::Emscripten {
207 platforms::wasm32_emscripten::build(
208 build_type,
209 targets,
210 llvm_projects,
211 enable_rtti,
212 default_target,
213 enable_tests,
214 enable_coverage,
215 extra_args,
216 ccache_variant,
217 enable_assertions,
218 sanitizer,
219 enable_valgrind,
220 )?;
221 } else {
222 platforms::aarch64_macos::build(
223 build_type,
224 targets,
225 llvm_projects,
226 enable_rtti,
227 default_target,
228 enable_tests,
229 enable_coverage,
230 extra_args,
231 ccache_variant,
232 enable_assertions,
233 sanitizer,
234 )?;
235 }
236 } else {
237 anyhow::bail!("Unsupported target OS for aarch64");
238 }
239 } else {
240 anyhow::bail!("Unsupported target architecture");
241 }
242
243 crate::builtins::build(
244 build_type,
245 target_env,
246 default_target,
247 extra_args,
248 ccache_variant,
249 sanitizer,
250 )?;
251
252 Ok(())
253}
254
255pub fn clean() -> anyhow::Result<()> {
257 let remove_if_exists = |path: &Path| {
258 if !path.exists() {
259 return Ok(());
260 }
261 log::info!("deleting {}", path.display());
262 std::fs::remove_dir_all(path)
263 };
264
265 remove_if_exists(
266 llvm_path::DIRECTORY_LLVM_TARGET
267 .get()
268 .expect("target_env is always set because of the default value")
269 .parent()
270 .expect("target_env parent directory is target-llvm"),
271 )?;
272 remove_if_exists(&PathBuf::from(LLVMPath::DIRECTORY_EMSDK_SOURCE))?;
273
274 Ok(())
275}