cxx_clang_build/
lib.rs

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}