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