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}