1use cxx_llvm_build_common::prelude::*;
2use normpath::PathExt;
3use std::path::{Path, PathBuf};
4
5fn locate_clang_project_path(cargo_manifest_dir: &Path, llvm_project: &Path) -> BoxResult<PathBuf> {
6 let err =
7 Err("Failed to locate Clang project path. Try setting the `CLANG_PROJECT_PATH` environment variable.".into());
8
9 let mut should_ignore = false;
10
11 if let Some(clang_project) = get_path_from_env("CLANG_PROJECT_PATH", &mut should_ignore)? {
12 return Ok(clang_project);
13 }
14
15 if should_ignore {
16 return err;
17 }
18
19 let clang_project = llvm_project.join("clang");
20 if clang_project.exists() {
21 return Ok(clang_project);
22 }
23
24 let clang_project = PathBuf::from(cargo_manifest_dir).join("../../../clang");
25 if clang_project.exists() {
26 return Ok(clang_project.normalize()?.into_path_buf());
27 }
28
29 err
30}
31
32fn locate_clang_cmake_build_path(llvm_cmake_build: &Path, clang_project: &Path) -> BoxResult<PathBuf> {
33 let err = Err(
34 "Failed to locate Clang CMake build path. Try setting the `CLANG_CMAKE_BUILD_PATH` environment variable."
35 .into(),
36 );
37
38 let mut should_ignore = false;
39
40 if let Some(clang_cmake_build) = get_path_from_env("CLANG_CMAKE_BUILD_PATH", &mut should_ignore)? {
41 return Ok(clang_cmake_build);
42 }
43
44 if should_ignore {
45 return err;
46 }
47
48 let clang_cmake_build = llvm_cmake_build.join("tools/clang");
49 if clang_cmake_build.exists() {
50 return Ok(clang_cmake_build);
51 }
52
53 let clang_cmake_build = clang_project.join(PathBuf::from_iter([
54 "build",
55 &NINJA_BUILD_DIR(),
56 &format!("clang-{CMAKE_BUILD_TARGET}"),
57 ]));
58 if clang_cmake_build.exists() {
59 return Ok(clang_cmake_build);
60 }
61
62 err
63}
64
65pub struct Dirs {
66 pub clang_project: PathBuf,
67 pub clang_cmake_build: PathBuf,
68}
69
70impl Dirs {
71 pub fn new(cargo_pkg_name: &str, llvm_dirs: &cxx_llvm_build::Dirs) -> BoxResult<Self> {
72 let cargo_manifest_dir = PathBuf::from(std::env::var("CARGO_MANIFEST_DIR")?);
73 let cxx_llvm_build::Dirs {
74 llvm_project,
75 llvm_cmake_build,
76 ..
77 } = &llvm_dirs;
78 let clang_project = locate_clang_project_path(&cargo_manifest_dir, llvm_project)?;
79 println!(
80 "cargo:warning=[{cargo_pkg_name}]: Clang project path: \"{}\"",
81 clang_project.display()
82 );
83 let clang_cmake_build = locate_clang_cmake_build_path(llvm_cmake_build, &clang_project)?;
84 println!(
85 "cargo:warning=[{cargo_pkg_name}]: Clang CMake build path: \"{}\"",
86 clang_cmake_build.display()
87 );
88 let dirs = Dirs {
89 clang_project,
90 clang_cmake_build,
91 };
92 Ok(dirs)
93 }
94}
95
96pub fn cxx_build(
97 llvm_dirs: &cxx_llvm_build::Dirs,
98 clang_dirs: &Dirs,
99 rust_source_files: impl IntoIterator<Item = impl AsRef<Path>>,
100 files: impl IntoIterator<Item = impl AsRef<Path>>,
101 output: &str,
102) -> BoxResult<()> {
103 rustc_link_searches(llvm_dirs, clang_dirs);
104 cxx_build::bridges(rust_source_files)
105 .llvm_common_compiler()
106 .llvm_common_defines()
107 .llvm_common_flags()
108 .files(files)
109 .try_compile(output)?;
110 rustc_link_libs();
111 Ok(())
112}
113
114pub fn rustc_link_searches(_llvm_dirs: &cxx_llvm_build::Dirs, _clang_dirs: &Dirs) {
115}
116
117pub fn rustc_link_libs() {
118 println!("cargo:rustc-link-lib=static=clangIndex");
119 println!("cargo:rustc-link-lib=static=clangDependencyScanning");
120 println!("cargo:rustc-link-lib=static=clangCodeGen");
121 println!("cargo:rustc-link-lib=static=clangTooling");
122 println!("cargo:rustc-link-lib=static=clangFrontend");
123 println!("cargo:rustc-link-lib=static=clangCAS");
124 println!("cargo:rustc-link-lib=static=clangParse");
125 println!("cargo:rustc-link-lib=static=clangDriver");
126 println!("cargo:rustc-link-lib=static=clangSerialization");
127 println!("cargo:rustc-link-lib=static=clangSema");
128 println!("cargo:rustc-link-lib=static=clangEdit");
129 println!("cargo:rustc-link-lib=static=clangAnalysis");
130 println!("cargo:rustc-link-lib=static=clangAPINotes");
131 println!("cargo:rustc-link-lib=static=clangAST");
132 println!("cargo:rustc-link-lib=static=clangLex");
133 println!("cargo:rustc-link-lib=static=clangBasic");
134 cxx_llvm_build::rustc_link_libs();
135}