compiler_llvm_builder/platforms/
aarch64_linux_musl.rs

1//!
2//! The ZKsync LLVM arm64 `linux-musl` builder.
3//!
4
5use crate::build_type::BuildType;
6use crate::ccache_variant::CcacheVariant;
7use crate::llvm_path::LLVMPath;
8use crate::llvm_project::LLVMProject;
9use crate::platforms::Platform;
10use crate::sanitizer::Sanitizer;
11use crate::target_triple::TargetTriple;
12use std::collections::HashSet;
13use std::path::Path;
14use std::process::Command;
15
16///
17/// The building sequence.
18///
19#[allow(clippy::too_many_arguments)]
20pub fn build(
21    build_type: BuildType,
22    targets: HashSet<Platform>,
23    llvm_projects: HashSet<LLVMProject>,
24    enable_rtti: bool,
25    default_target: Option<TargetTriple>,
26    enable_tests: bool,
27    enable_coverage: bool,
28    extra_args: Vec<String>,
29    ccache_variant: Option<CcacheVariant>,
30    enable_assertions: bool,
31    sanitizer: Option<Sanitizer>,
32    enable_valgrind: bool,
33    valgrind_options: Vec<String>,
34) -> anyhow::Result<()> {
35    crate::utils::check_presence("cmake")?;
36    crate::utils::check_presence("clang")?;
37    crate::utils::check_presence("clang++")?;
38    crate::utils::check_presence("lld")?;
39    crate::utils::check_presence("ninja")?;
40
41    let musl_name = "musl-1.2.3";
42    let musl_build = LLVMPath::musl_build(musl_name)?;
43    let musl_target = LLVMPath::musl_target()?;
44
45    let llvm_module_llvm = LLVMPath::llvm_module_llvm()?;
46    let llvm_host_module_llvm = LLVMPath::llvm_host_module_llvm()?;
47
48    let llvm_build_crt = LLVMPath::llvm_build_crt()?;
49    let llvm_target_crt = LLVMPath::llvm_target_crt()?;
50
51    let llvm_build_host = LLVMPath::llvm_build_host()?;
52    let llvm_target_host = LLVMPath::llvm_target_host()?;
53
54    let llvm_build_final = LLVMPath::llvm_build_final()?;
55    let llvm_target_final = LLVMPath::llvm_target_final()?;
56
57    if !LLVMPath::musl_source(musl_name)?.exists() {
58        crate::utils::download_musl(musl_name)?;
59    }
60    crate::platforms::shared::build_musl(musl_build.as_path(), musl_target.as_path())?;
61    build_crt(
62        targets.clone(),
63        llvm_host_module_llvm.as_path(),
64        llvm_build_crt.as_path(),
65        llvm_target_crt.as_path(),
66        ccache_variant,
67    )?;
68    build_host(
69        llvm_host_module_llvm.as_path(),
70        llvm_build_host.as_path(),
71        llvm_target_host.as_path(),
72        musl_target.as_path(),
73        llvm_target_crt.as_path(),
74        ccache_variant,
75    )?;
76    build_target(
77        build_type,
78        targets,
79        llvm_projects,
80        enable_rtti,
81        default_target,
82        llvm_module_llvm.as_path(),
83        llvm_build_final.as_path(),
84        llvm_target_final.as_path(),
85        musl_target.as_path(),
86        llvm_target_host.as_path(),
87        enable_tests,
88        enable_coverage,
89        extra_args,
90        ccache_variant,
91        enable_assertions,
92        sanitizer,
93        enable_valgrind,
94        valgrind_options,
95    )?;
96
97    Ok(())
98}
99
100///
101/// The `crt` building sequence.
102///
103fn build_crt(
104    mut targets: HashSet<Platform>,
105    source_directory: &Path,
106    build_directory: &Path,
107    target_directory: &Path,
108    ccache_variant: Option<CcacheVariant>,
109) -> anyhow::Result<()> {
110    targets.insert(Platform::AArch64);
111
112    crate::utils::command(
113        Command::new("cmake")
114            .args([
115                "-S",
116                source_directory.to_string_lossy().as_ref(),
117                "-B",
118                build_directory.to_string_lossy().as_ref(),
119                "-G",
120                "Ninja",
121                format!(
122                    "-DCMAKE_INSTALL_PREFIX='{}'",
123                    target_directory.to_string_lossy()
124                )
125                .as_str(),
126                "-DCMAKE_BUILD_TYPE='Release'",
127                "-DCMAKE_C_COMPILER='clang'",
128                "-DCMAKE_CXX_COMPILER='clang++'",
129                "-DLLVM_ENABLE_PROJECTS='compiler-rt'",
130                format!("-DLLVM_TARGETS_TO_BUILD='{}'", Platform::AArch64).as_str(),
131                "-DLLVM_DEFAULT_TARGET_TRIPLE='aarch64-unknown-linux-musl'",
132                "-DLLVM_BUILD_TESTS='Off'",
133                "-DLLVM_BUILD_RUNTIMES='Off'",
134                "-DLLVM_BUILD_UTILS='Off'",
135                "-DLLVM_INCLUDE_TESTS='Off'",
136                "-DLLVM_INCLUDE_RUNTIMES='Off'",
137                "-DLLVM_INCLUDE_UTILS='Off'",
138                "-DCOMPILER_RT_DEFAULT_TARGET_ARCH='aarch64'",
139                "-DCOMPILER_RT_BUILD_CRT='On'",
140                "-DCOMPILER_RT_BUILD_BUILTINS='On'",
141                "-DCOMPILER_RT_BUILD_SANITIZERS='Off'",
142                "-DCOMPILER_RT_BUILD_XRAY='Off'",
143                "-DCOMPILER_RT_BUILD_LIBFUZZER='Off'",
144                "-DCOMPILER_RT_BUILD_PROFILE='Off'",
145                "-DCOMPILER_RT_BUILD_MEMPROF='Off'",
146                "-DCOMPILER_RT_BUILD_ORC='Off'",
147            ])
148            .args(crate::platforms::shared::SHARED_BUILD_OPTS)
149            .args(crate::platforms::shared::shared_build_opts_ccache(
150                ccache_variant,
151            )),
152        "CRT building cmake",
153    )?;
154
155    crate::utils::command(
156        Command::new("ninja")
157            .arg("-C")
158            .arg(build_directory)
159            .arg("install-crt"),
160        "CRT building ninja",
161    )?;
162
163    Ok(())
164}
165
166///
167/// The host toolchain building sequence.
168///
169fn build_host(
170    source_directory: &Path,
171    build_directory: &Path,
172    target_directory: &Path,
173    musl_target_directory: &Path,
174    crt_target_directory: &Path,
175    ccache_variant: Option<CcacheVariant>,
176) -> anyhow::Result<()> {
177    crate::utils::command(
178        Command::new("cmake")
179            .args([
180                "-S",
181                source_directory.to_string_lossy().as_ref(),
182                "-B",
183                build_directory.to_string_lossy().as_ref(),
184                "-G",
185                "Ninja",
186                format!(
187                    "-DDEFAULT_SYSROOT='{}'",
188                    musl_target_directory.to_string_lossy()
189                )
190                .as_str(),
191                "-DLINKER_SUPPORTS_COLOR_DIAGNOSTICS=0",
192                format!(
193                    "-DCMAKE_INSTALL_PREFIX='{}'",
194                    target_directory.to_string_lossy()
195                )
196                .as_str(),
197                "-DCMAKE_BUILD_TYPE='Release'",
198                "-DCMAKE_C_COMPILER='clang'",
199                "-DCMAKE_CXX_COMPILER='clang++'",
200                "-DCLANG_DEFAULT_CXX_STDLIB='libc++'",
201                "-DCLANG_DEFAULT_RTLIB='compiler-rt'",
202                "-DLLVM_DEFAULT_TARGET_TRIPLE='aarch64-unknown-linux-musl'",
203                "-DLLVM_TARGETS_TO_BUILD='AArch64'",
204                "-DLLVM_BUILD_TESTS='Off'",
205                "-DLLVM_BUILD_UTILS='Off'",
206                "-DLLVM_INCLUDE_TESTS='Off'",
207                "-DLLVM_INCLUDE_UTILS='Off'",
208                "-DLLVM_ENABLE_PROJECTS='clang;lld'",
209                "-DLLVM_ENABLE_RUNTIMES='compiler-rt;libcxx;libcxxabi;libunwind'",
210                "-DLIBCXX_CXX_ABI='libcxxabi'",
211                "-DLIBCXX_HAS_MUSL_LIBC='On'",
212                "-DLIBCXX_ENABLE_SHARED='Off'",
213                "-DLIBCXX_ENABLE_STATIC='On'",
214                "-DLIBCXX_ENABLE_STATIC_ABI_LIBRARY='On'",
215                "-DLIBCXXABI_ENABLE_SHARED='Off'",
216                "-DLIBCXXABI_ENABLE_STATIC='On'",
217                "-DLIBCXXABI_ENABLE_STATIC_UNWINDER='On'",
218                "-DLIBCXXABI_USE_LLVM_UNWINDER='On'",
219                "-DLIBCXXABI_USE_COMPILER_RT='On'",
220                "-DLIBUNWIND_ENABLE_STATIC='On'",
221                "-DLIBUNWIND_ENABLE_SHARED='Off'",
222                "-DCOMPILER_RT_BUILD_CRT='On'",
223                "-DCOMPILER_RT_BUILD_SANITIZERS='Off'",
224                "-DCOMPILER_RT_BUILD_XRAY='Off'",
225                "-DCOMPILER_RT_BUILD_LIBFUZZER='Off'",
226                "-DCOMPILER_RT_BUILD_PROFILE='On'",
227                "-DCOMPILER_RT_BUILD_MEMPROF='Off'",
228                "-DCOMPILER_RT_BUILD_ORC='Off'",
229                "-DCOMPILER_RT_DEFAULT_TARGET_ARCH='aarch64'",
230                "-DCOMPILER_RT_DEFAULT_TARGET_ONLY='On'",
231            ])
232            .args(crate::platforms::shared::SHARED_BUILD_OPTS)
233            .args(crate::platforms::shared::shared_build_opts_ccache(
234                ccache_variant,
235            )),
236        "LLVM host building cmake",
237    )?;
238
239    let mut crt_lib_directory = crt_target_directory.to_path_buf();
240    crt_lib_directory.push("lib/");
241
242    let mut build_lib_directory = build_directory.to_path_buf();
243    build_lib_directory.push("lib/");
244
245    let copy_options = fs_extra::dir::CopyOptions {
246        overwrite: true,
247        copy_inside: true,
248        content_only: true,
249        ..Default::default()
250    };
251    fs_extra::dir::copy(crt_lib_directory, build_lib_directory, &copy_options)?;
252
253    crate::utils::command(
254        Command::new("ninja")
255            .arg("-C")
256            .arg(build_directory)
257            .arg("install"),
258        "LLVM host building ninja",
259    )?;
260
261    Ok(())
262}
263
264///
265/// The target toolchain building sequence.
266///
267#[allow(clippy::too_many_arguments)]
268fn build_target(
269    build_type: BuildType,
270    targets: HashSet<Platform>,
271    llvm_projects: HashSet<LLVMProject>,
272    enable_rtti: bool,
273    default_target: Option<TargetTriple>,
274    source_directory: &Path,
275    build_directory: &Path,
276    target_directory: &Path,
277    musl_target_directory: &Path,
278    host_target_directory: &Path,
279    enable_tests: bool,
280    enable_coverage: bool,
281    extra_args: Vec<String>,
282    ccache_variant: Option<CcacheVariant>,
283    enable_assertions: bool,
284    sanitizer: Option<Sanitizer>,
285    enable_valgrind: bool,
286    valgrind_options: Vec<String>,
287) -> anyhow::Result<()> {
288    let mut clang_path = host_target_directory.to_path_buf();
289    clang_path.push("bin/clang");
290
291    let mut clang_cxx_path = host_target_directory.to_path_buf();
292    clang_cxx_path.push("bin/clang++");
293
294    crate::utils::command(
295        Command::new("cmake")
296            .args([
297                "-S",
298                source_directory.to_string_lossy().as_ref(),
299                "-B",
300                build_directory.to_string_lossy().as_ref(),
301                "-G",
302                "Ninja",
303                "-DBUILD_SHARED_LIBS='Off'",
304                "-DLINKER_SUPPORTS_COLOR_DIAGNOSTICS=0",
305                format!(
306                    "-DCMAKE_INSTALL_PREFIX='{}'",
307                    target_directory.to_string_lossy()
308                )
309                .as_str(),
310                format!("-DCMAKE_BUILD_TYPE='{build_type}'").as_str(),
311                format!("-DCMAKE_C_COMPILER='{}'", clang_path.to_string_lossy()).as_str(),
312                format!(
313                    "-DCMAKE_CXX_COMPILER='{}'",
314                    clang_cxx_path.to_string_lossy()
315                )
316                .as_str(),
317                "-DCMAKE_FIND_LIBRARY_SUFFIXES='.a'",
318                "-DCMAKE_BUILD_WITH_INSTALL_RPATH=1",
319                "-DCMAKE_EXE_LINKER_FLAGS='-fuse-ld=lld -static'",
320                format!(
321                    "-DLLVM_TARGETS_TO_BUILD='{}'",
322                    targets
323                        .into_iter()
324                        .map(|platform| platform.to_string())
325                        .collect::<Vec<String>>()
326                        .join(";")
327                )
328                .as_str(),
329                format!(
330                    "-DLLVM_ENABLE_PROJECTS='{}'",
331                    llvm_projects
332                        .into_iter()
333                        .map(|project| project.to_string())
334                        .collect::<Vec<String>>()
335                        .join(";")
336                )
337                .as_str(),
338            ])
339            .args(crate::platforms::shared::shared_build_opts_default_target(
340                default_target,
341            ))
342            .args(crate::platforms::shared::SHARED_BUILD_OPTS)
343            .args(crate::platforms::shared::SHARED_BUILD_OPTS_NOT_MUSL)
344            .args(crate::platforms::shared::shared_build_opts_werror())
345            .args(crate::platforms::shared::shared_build_opts_tests(
346                enable_tests,
347            ))
348            .args(crate::platforms::shared::shared_build_opts_coverage(
349                enable_coverage,
350            ))
351            .args(extra_args)
352            .args(crate::platforms::shared::shared_build_opts_ccache(
353                ccache_variant,
354            ))
355            .args(crate::platforms::shared::shared_build_opts_assertions(
356                enable_assertions,
357            ))
358            .args(crate::platforms::shared::shared_build_opts_rtti(
359                enable_rtti,
360            ))
361            .args(crate::platforms::shared::shared_build_opts_sanitizers(
362                sanitizer,
363            ))
364            .args(crate::platforms::shared::shared_build_opts_valgrind(
365                enable_valgrind,
366                valgrind_options,
367            )),
368        "LLVM target building cmake",
369    )?;
370
371    crate::utils::ninja(build_directory)?;
372
373    let mut musl_lib_directory = musl_target_directory.to_path_buf();
374    musl_lib_directory.push("lib/");
375
376    let mut host_lib_directory = host_target_directory.to_path_buf();
377    host_lib_directory.push("lib/aarch64-unknown-linux-musl/");
378
379    let mut target_lib_directory = target_directory.to_path_buf();
380    target_lib_directory.push("lib/");
381
382    let copy_options = fs_extra::dir::CopyOptions {
383        overwrite: true,
384        copy_inside: true,
385        content_only: true,
386        ..Default::default()
387    };
388    fs_extra::dir::copy(
389        musl_lib_directory,
390        target_lib_directory.as_path(),
391        &copy_options,
392    )?;
393    fs_extra::dir::copy(
394        host_lib_directory,
395        target_lib_directory.as_path(),
396        &copy_options,
397    )?;
398
399    Ok(())
400}