1pub mod build_type;
6pub mod ccache_variant;
7pub mod llvm_path;
8pub mod llvm_project;
9pub mod lock;
10pub mod platforms;
11pub mod sanitizer;
12pub mod target_env;
13pub mod target_triple;
14pub mod utils;
15
16pub use self::build_type::BuildType;
17pub use self::llvm_path::LLVMPath;
18pub use self::lock::Lock;
19pub use self::platforms::Platform;
20pub use self::target_triple::TargetTriple;
21
22use std::collections::HashSet;
23use std::path::PathBuf;
24use std::process::Command;
25
26pub fn clone_host() -> anyhow::Result<()> {
30 let destination_path = PathBuf::from(LLVMPath::DIRECTORY_LLVM_HOST_SOURCE);
31 if destination_path.exists() {
32 eprintln!(
33 "The host repository is already cloned at {:?}. Skipping...",
34 destination_path
35 );
36 return Ok(());
37 }
38
39 utils::command(
40 Command::new("git").args([
41 "clone",
42 "--depth",
43 "1",
44 "--branch",
45 utils::LLVM_HOST_SOURCE_TAG,
46 utils::LLVM_HOST_SOURCE_URL,
47 destination_path.to_string_lossy().as_ref(),
48 ]),
49 "LLVM host repository cloning",
50 )?;
51
52 Ok(())
53}
54
55pub fn clone(lock: Lock, deep: bool, target_env: target_env::TargetEnv) -> anyhow::Result<()> {
59 utils::check_presence("git")?;
60
61 if cfg!(target_os = "linux") && target_env == target_env::TargetEnv::MUSL {
63 clone_host()?;
64 }
65
66 let destination_path = PathBuf::from(LLVMPath::DIRECTORY_LLVM_SOURCE);
67 if destination_path.exists() {
68 anyhow::bail!(
69 "The repository is already cloned at {:?}. Use `checkout` instead",
70 destination_path
71 );
72 }
73
74 let mut clone_args = vec!["clone", "--branch", lock.branch.as_str()];
75 if !deep {
76 clone_args.push("--depth");
77 clone_args.push("1");
78 }
79
80 utils::command(
81 Command::new("git")
82 .args(clone_args)
83 .arg(lock.url.as_str())
84 .arg(destination_path.to_string_lossy().as_ref()),
85 "LLVM repository cloning",
86 )?;
87
88 if let Some(r#ref) = lock.r#ref {
89 utils::command(
90 Command::new("git")
91 .args(["checkout", r#ref.as_str()])
92 .current_dir(destination_path.to_string_lossy().as_ref()),
93 "LLVM repository commit checking out",
94 )?;
95 }
96
97 Ok(())
98}
99
100pub fn checkout(lock: Lock, force: bool) -> anyhow::Result<()> {
104 let destination_path = PathBuf::from(LLVMPath::DIRECTORY_LLVM_SOURCE);
105
106 utils::command(
107 Command::new("git")
108 .current_dir(destination_path.as_path())
109 .args(["fetch", "--all", "--tags"]),
110 "LLVM repository data fetching",
111 )?;
112
113 if force {
114 utils::command(
115 Command::new("git")
116 .current_dir(destination_path.as_path())
117 .args(["clean", "-d", "-x", "--force"]),
118 "LLVM repository cleaning",
119 )?;
120 }
121
122 utils::command(
123 Command::new("git")
124 .current_dir(destination_path.as_path())
125 .args(["checkout", "--force", lock.branch.as_str()]),
126 "LLVM repository data pulling",
127 )?;
128
129 if let Some(r#ref) = lock.r#ref {
130 let mut checkout_command = Command::new("git");
131 checkout_command.current_dir(destination_path.as_path());
132 checkout_command.arg("checkout");
133 if force {
134 checkout_command.arg("--force");
135 }
136 checkout_command.arg(r#ref);
137 utils::command(&mut checkout_command, "LLVM repository checking out")?;
138 }
139
140 Ok(())
141}
142
143#[allow(clippy::too_many_arguments)]
150pub fn build(
151 build_type: BuildType,
152 target_env: target_env::TargetEnv,
153 targets: HashSet<Platform>,
154 llvm_projects: HashSet<llvm_project::LLVMProject>,
155 enable_rtti: bool,
156 default_target: Option<TargetTriple>,
157 enable_tests: bool,
158 enable_coverage: bool,
159 extra_args: Vec<String>,
160 ccache_variant: Option<ccache_variant::CcacheVariant>,
161 enable_assertions: bool,
162 sanitizer: Option<sanitizer::Sanitizer>,
163 enable_valgrind: bool,
164 valgrind_options: Vec<String>,
165) -> anyhow::Result<()> {
166 std::fs::create_dir_all(LLVMPath::DIRECTORY_LLVM_TARGET)?;
167
168 if cfg!(target_arch = "x86_64") {
169 if cfg!(target_os = "linux") {
170 if target_env == target_env::TargetEnv::MUSL {
171 platforms::x86_64_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 valgrind_options,
185 )?;
186 } else if target_env == target_env::TargetEnv::GNU {
187 platforms::x86_64_linux_gnu::build(
188 build_type,
189 targets,
190 llvm_projects,
191 enable_rtti,
192 default_target,
193 enable_tests,
194 enable_coverage,
195 extra_args,
196 ccache_variant,
197 enable_assertions,
198 sanitizer,
199 enable_valgrind,
200 valgrind_options,
201 )?;
202 } else {
203 anyhow::bail!("Unsupported target environment for x86_64 and Linux");
204 }
205 } else if cfg!(target_os = "macos") {
206 platforms::x86_64_macos::build(
207 build_type,
208 targets,
209 llvm_projects,
210 enable_rtti,
211 default_target,
212 enable_tests,
213 enable_coverage,
214 extra_args,
215 ccache_variant,
216 enable_assertions,
217 sanitizer,
218 )?;
219 } else if cfg!(target_os = "windows") {
220 platforms::x86_64_windows_gnu::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 } else {
234 anyhow::bail!("Unsupported target OS for x86_64");
235 }
236 } else if cfg!(target_arch = "aarch64") {
237 if cfg!(target_os = "linux") {
238 if target_env == target_env::TargetEnv::MUSL {
239 platforms::aarch64_linux_musl::build(
240 build_type,
241 targets,
242 llvm_projects,
243 enable_rtti,
244 default_target,
245 enable_tests,
246 enable_coverage,
247 extra_args,
248 ccache_variant,
249 enable_assertions,
250 sanitizer,
251 enable_valgrind,
252 valgrind_options,
253 )?;
254 } else if target_env == target_env::TargetEnv::GNU {
255 platforms::aarch64_linux_gnu::build(
256 build_type,
257 targets,
258 llvm_projects,
259 enable_rtti,
260 default_target,
261 enable_tests,
262 enable_coverage,
263 extra_args,
264 ccache_variant,
265 enable_assertions,
266 sanitizer,
267 enable_valgrind,
268 valgrind_options,
269 )?;
270 } else {
271 anyhow::bail!("Unsupported target environment for aarch64 and Linux");
272 }
273 } else if cfg!(target_os = "macos") {
274 platforms::aarch64_macos::build(
275 build_type,
276 targets,
277 llvm_projects,
278 enable_rtti,
279 default_target,
280 enable_tests,
281 enable_coverage,
282 extra_args,
283 ccache_variant,
284 enable_assertions,
285 sanitizer,
286 )?;
287 } else {
288 anyhow::bail!("Unsupported target OS for aarch64");
289 }
290 } else {
291 anyhow::bail!("Unsupported target architecture");
292 }
293
294 Ok(())
295}
296
297pub fn clean() -> anyhow::Result<()> {
301 std::fs::remove_dir_all(PathBuf::from(LLVMPath::DIRECTORY_LLVM_TARGET))?;
302 Ok(())
303}