cxx_llvm_build/
lib.rs

1use cxx_llvm_build_common::prelude::*;
2use normpath::PathExt;
3use std::path::{Path, PathBuf};
4
5fn locate_swift_project_path(cargo_manifest_dir: &Path) -> BoxResult<Option<PathBuf>> {
6    let mut should_ignore = false;
7
8    if let Some(swift_project) = get_path_from_env("SWIFT_PROJECT_PATH", &mut should_ignore)? {
9        return Ok(Some(swift_project));
10    }
11
12    if should_ignore {
13        return Ok(None);
14    }
15
16    let swift_project = PathBuf::from(cargo_manifest_dir).join("../../../swift-project");
17    if swift_project.exists() {
18        return Ok(Some(swift_project.normalize()?.into_path_buf()));
19    }
20
21    Ok(None)
22}
23
24fn locate_llvm_project_path(cargo_manifest_dir: &Path, swift_project: Option<&Path>) -> BoxResult<PathBuf> {
25    let err =
26        Err("Failed to locate LLVM project path. Try setting the `LLVM_PROJECT_PATH` environment variable.".into());
27
28    let mut should_ignore = false;
29
30    if let Some(llvm_project) = get_path_from_env("LLVM_PROJECT_PATH", &mut should_ignore)? {
31        return Ok(llvm_project);
32    }
33
34    if should_ignore {
35        return err;
36    }
37
38    if let Some(swift_project) = swift_project {
39        let llvm_project = swift_project.join("llvm-project");
40        if llvm_project.exists() {
41            return Ok(llvm_project);
42        }
43    }
44
45    let llvm_project = PathBuf::from(cargo_manifest_dir).join("../../../llvm-project");
46    if llvm_project.exists() {
47        return Ok(llvm_project.normalize()?.into_path_buf());
48    }
49
50    err
51}
52
53fn locate_llvm_cmake_build_path(swift_project: Option<&Path>, llvm_project: &Path) -> BoxResult<PathBuf> {
54    let err = Err(
55        "Failed to locate LLVM CMake build path. Try setting the `LLVM_CMAKE_BUILD_PATH` environment variable.".into(),
56    );
57
58    let mut should_ignore = false;
59
60    if let Some(llvm_cmake_build) = get_path_from_env("LLVM_CMAKE_BUILD_PATH", &mut should_ignore)? {
61        return Ok(llvm_cmake_build);
62    }
63
64    if should_ignore {
65        return err;
66    }
67
68    if let Some(swift_project) = swift_project {
69        let llvm_cmake_build = swift_project.join(PathBuf::from_iter([
70            "build",
71            &NINJA_BUILD_DIR(),
72            &format!("llvm-{CMAKE_BUILD_TARGET}"),
73        ]));
74        if llvm_cmake_build.exists() {
75            return Ok(llvm_cmake_build);
76        }
77    }
78
79    let llvm_cmake_build = llvm_project.join(PathBuf::from_iter([
80        "build",
81        &NINJA_BUILD_DIR(),
82        &format!("llvm-{CMAKE_BUILD_TARGET}"),
83    ]));
84    if llvm_cmake_build.exists() {
85        return Ok(llvm_cmake_build);
86    }
87
88    err
89}
90
91pub struct Dirs {
92    pub swift_project: Option<PathBuf>,
93    pub llvm_project: PathBuf,
94    pub llvm_cmake_build: PathBuf,
95}
96
97impl Dirs {
98    pub fn new(cargo_pkg_name: &str) -> BoxResult<Self> {
99        let cargo_manifest_dir = PathBuf::from(std::env::var("CARGO_MANIFEST_DIR")?);
100        let swift_project = locate_swift_project_path(&cargo_manifest_dir)?;
101        if let Some(swift_project) = swift_project.as_deref() {
102            println!(
103                "cargo:warning=[{cargo_pkg_name}]: Swift project path: \"{}\"",
104                swift_project.display()
105            );
106        }
107        let llvm_project = locate_llvm_project_path(&cargo_manifest_dir, swift_project.as_deref())?;
108        println!(
109            "cargo:warning=[{cargo_pkg_name}]: LLVM project path: \"{}\"",
110            llvm_project.display()
111        );
112
113        let llvm_cmake_build = locate_llvm_cmake_build_path(swift_project.as_deref(), &llvm_project)?;
114        println!(
115            "cargo:warning=[{cargo_pkg_name}]: LLVM CMake build path: \"{}\"",
116            llvm_cmake_build.display()
117        );
118        let dirs = Dirs {
119            swift_project,
120            llvm_project,
121            llvm_cmake_build,
122        };
123        Ok(dirs)
124    }
125}
126
127pub fn cxx_build(
128    llvm_dirs: &Dirs,
129    rust_source_files: impl IntoIterator<Item = impl AsRef<Path>>,
130    files: impl IntoIterator<Item = impl AsRef<Path>>,
131    output: &str,
132) -> BoxResult<()> {
133    rustc_link_searches(llvm_dirs);
134    cxx_build::bridges(rust_source_files)
135        .llvm_common_compiler()
136        .llvm_common_defines()
137        .llvm_common_flags()
138        .files(files)
139        .try_compile(output)?;
140    rustc_link_libs();
141    Ok(())
142}
143
144pub fn rustc_link_searches(llvm_dirs: &Dirs) {
145    println!(
146        "cargo:rustc-link-search={}",
147        llvm_dirs.llvm_cmake_build.join("lib").display()
148    );
149}
150
151pub fn rustc_link_libs() {
152    println!("cargo:rustc-link-lib=static=LLVMX86Disassembler");
153    println!("cargo:rustc-link-lib=static=LLVMARMDisassembler");
154    println!("cargo:rustc-link-lib=static=LLVMAArch64Disassembler");
155    println!("cargo:rustc-link-lib=static=LLVMPowerPCDisassembler");
156    println!("cargo:rustc-link-lib=static=LLVMSystemZDisassembler");
157    println!("cargo:rustc-link-lib=static=LLVMMipsDisassembler");
158    println!("cargo:rustc-link-lib=static=LLVMCoverage");
159    println!("cargo:rustc-link-lib=static=LLVMX86AsmParser");
160    println!("cargo:rustc-link-lib=static=LLVMARMAsmParser");
161    println!("cargo:rustc-link-lib=static=LLVMAArch64AsmParser");
162    println!("cargo:rustc-link-lib=static=LLVMPowerPCAsmParser");
163    println!("cargo:rustc-link-lib=static=LLVMSystemZAsmParser");
164    println!("cargo:rustc-link-lib=static=LLVMMipsAsmParser");
165    println!("cargo:rustc-link-lib=static=LLVMX86Info");
166    println!("cargo:rustc-link-lib=static=LLVMARMInfo");
167    println!("cargo:rustc-link-lib=static=LLVMAArch64Info");
168    println!("cargo:rustc-link-lib=static=LLVMPowerPCInfo");
169    println!("cargo:rustc-link-lib=static=LLVMSystemZInfo");
170    println!("cargo:rustc-link-lib=static=LLVMMipsInfo");
171    println!("cargo:rustc-link-lib=static=LLVMX86CodeGen");
172    println!("cargo:rustc-link-lib=static=LLVMARMCodeGen");
173    println!("cargo:rustc-link-lib=static=LLVMAArch64CodeGen");
174    println!("cargo:rustc-link-lib=static=LLVMPowerPCCodeGen");
175    println!("cargo:rustc-link-lib=static=LLVMSystemZCodeGen");
176    println!("cargo:rustc-link-lib=static=LLVMMipsCodeGen");
177    println!("cargo:rustc-link-lib=static=LLVMX86Desc");
178    println!("cargo:rustc-link-lib=static=LLVMARMDesc");
179    println!("cargo:rustc-link-lib=static=LLVMAArch64Desc");
180    println!("cargo:rustc-link-lib=static=LLVMPowerPCDesc");
181    println!("cargo:rustc-link-lib=static=LLVMSystemZDesc");
182    println!("cargo:rustc-link-lib=static=LLVMMipsDesc");
183    println!("cargo:rustc-link-lib=static=LLVMARMUtils");
184    println!("cargo:rustc-link-lib=static=LLVMAArch64Utils");
185    println!("cargo:rustc-link-lib=static=LLVMCFGuard");
186    println!("cargo:rustc-link-lib=static=LLVMAsmPrinter");
187    println!("cargo:rustc-link-lib=static=LLVMDebugInfoCodeView");
188    println!("cargo:rustc-link-lib=static=LLVMGlobalISel");
189    println!("cargo:rustc-link-lib=static=LLVMSelectionDAG");
190    println!("cargo:rustc-link-lib=static=LLVMCodeGen");
191    println!("cargo:rustc-link-lib=static=LLVMMCDisassembler");
192    println!("cargo:rustc-link-lib=static=LLVMLTO");
193    println!("cargo:rustc-link-lib=static=LLVMTarget");
194    println!("cargo:rustc-link-lib=static=LLVMObjCARCOpts");
195    println!("cargo:rustc-link-lib=static=LLVMScalarOpts");
196    println!("cargo:rustc-link-lib=static=LLVMInstrumentation");
197    println!("cargo:rustc-link-lib=static=LLVMipo");
198    println!("cargo:rustc-link-lib=static=LLVMLinker");
199    println!("cargo:rustc-link-lib=static=LLVMIRReader");
200    println!("cargo:rustc-link-lib=static=LLVMAsmParser");
201    println!("cargo:rustc-link-lib=static=LLVMScalarOpts");
202    println!("cargo:rustc-link-lib=static=LLVMVectorize");
203    println!("cargo:rustc-link-lib=static=LLVMAggressiveInstCombine");
204    println!("cargo:rustc-link-lib=static=LLVMInstCombine");
205    println!("cargo:rustc-link-lib=static=LLVMBitWriter");
206    println!("cargo:rustc-link-lib=static=LLVMPasses");
207    println!("cargo:rustc-link-lib=static=LLVMCoroutines");
208    println!("cargo:rustc-link-lib=static=LLVMTransformUtils");
209    println!("cargo:rustc-link-lib=static=LLVMAnalysis");
210    println!("cargo:rustc-link-lib=static=LLVMProfileData");
211    println!("cargo:rustc-link-lib=static=LLVMDebugInfoDWARF");
212    println!("cargo:rustc-link-lib=static=LLVMObject");
213    println!("cargo:rustc-link-lib=static=LLVMBitReader");
214    println!("cargo:rustc-link-lib=static=LLVMMCParser");
215    println!("cargo:rustc-link-lib=static=LLVMTextAPI");
216    println!("cargo:rustc-link-lib=static=LLVMWindowsDriver");
217    println!("cargo:rustc-link-lib=static=LLVMOption");
218    println!("cargo:rustc-link-lib=static=LLVMMC");
219    println!("cargo:rustc-link-lib=static=LLVMCore");
220    println!("cargo:rustc-link-lib=static=LLVMRemarks");
221    println!("cargo:rustc-link-lib=static=LLVMBitstreamReader");
222    println!("cargo:rustc-link-lib=static=LLVMBinaryFormat");
223    println!("cargo:rustc-link-lib=static=LLVMFrontendOpenMP");
224    println!("cargo:rustc-link-lib=static=LLVMCAS");
225    println!("cargo:rustc-link-lib=static=LLVMSupport");
226    println!("cargo:rustc-link-lib=static=LLVMDemangle");
227    println!("cargo:rustc-link-lib=ncurses");
228    println!("cargo:rustc-link-lib=z");
229}