/// A `clang` executable. #[derive(Clone, Debug)] pubstruct Clang { /// The path to this `clang` executable. pub path: PathBuf, /// The version of this `clang` executable if it could be parsed. pub version: Option<CXVersion>, /// The directories searched by this `clang` executable for C headers if /// they could be parsed. pub c_search_paths: Option<Vec<PathBuf>>, /// The directories searched by this `clang` executable for C++ headers if /// they could be parsed. pub cpp_search_paths: Option<Vec<PathBuf>>,
}
/// Returns a `clang` executable if one can be found. /// /// If the `CLANG_PATH` environment variable is set, that is the instance of /// `clang` used. Otherwise, a series of directories are searched. First, if /// a path is supplied, that is the first directory searched. Then, the /// directory returned by `llvm-config --bindir` is searched. On macOS /// systems, `xcodebuild -find clang` will next be queried. Last, the /// directories in the system's `PATH` are searched. /// /// ## Cross-compilation /// /// If target arguments are provided (e.g., `-target` followed by a target /// like `x86_64-unknown-linux-gnu`) then this method will prefer a /// target-prefixed instance of `clang` (e.g., /// `x86_64-unknown-linux-gnu-clang` for the above example). pubfn find(path: Option<&Path>, args: &[String]) -> Option<Clang> { iflet Ok(path) = env::var("CLANG_PATH") { let p = Path::new(&path); if p.is_file() && is_executable(p).unwrap_or(false) { return Some(Clang::new(p, args));
}
}
// Determine the cross-compilation target, if any.
letmut target = None; for i in0..args.len() { if args[i] == "-target" && i + 1 < args.len() {
target = Some(&args[i + 1]);
}
}
// Collect the paths to search for a `clang` executable in.
/// Returns the first match to the supplied glob patterns in the supplied /// directory if there are any matches. fn find(directory: &Path, patterns: &[&str]) -> Option<PathBuf> { // Escape the directory in case it contains characters that have special // meaning in glob patterns (e.g., `[` or `]`). let directory = iflet Some(directory) = directory.to_str() {
Path::new(&Pattern::escape(directory)).to_owned()
} else { return None;
};
for pattern in patterns { let pattern = directory.join(pattern).to_string_lossy().into_owned(); iflet Some(path) = glob::glob(&pattern).ok()?.filter_map(|p| p.ok()).next() { if path.is_file() && is_executable(&path).unwrap_or(false) { return Some(path);
}
}
}
None
}
#[cfg(unix)] fn is_executable(path: &Path) -> io::Result<bool> { use std::ffi::CString; use std::os::unix::ffi::OsStrExt;
/// Runs `llvm-config`, returning the `stdout` output if successful. fn run_llvm_config(arguments: &[&str]) -> Result<String, String> { let config = env::var("LLVM_CONFIG_PATH").unwrap_or_else(|_| "llvm-config".to_string());
run(&config, arguments).map(|(o, _)| o)
}
/// Parses a version number if possible, ignoring trailing non-digit characters. fn parse_version_number(number: &str) -> Option<c_int> {
number
.chars()
.take_while(|c| c.is_ascii_digit())
.collect::<String>()
.parse()
.ok()
}
/// Parses the version from the output of a `clang` executable if possible. fn parse_version(path: &Path) -> Option<CXVersion> { let output = run_clang(path, &["--version"]).0; let start = output.find("version ")? + 8; letmut numbers = output[start..].split_whitespace().next()?.split('.'); let major = numbers.next().and_then(parse_version_number)?; let minor = numbers.next().and_then(parse_version_number)?; let subminor = numbers.next().and_then(parse_version_number).unwrap_or(0);
Some(CXVersion {
Major: major,
Minor: minor,
Subminor: subminor,
})
}
/// Parses the search paths from the output of a `clang` executable if possible. fn parse_search_paths(path: &Path, language: &str, args: &[String]) -> Option<Vec<PathBuf>> { letmut clang_args = vec!["-E", "-x", language, "-", "-v"];
clang_args.extend(args.iter().map(|s| &**s)); let output = run_clang(path, &clang_args).1; let start = output.find("#include <...> search starts here:")? + 34; let end = output.find("End of search list.")?; let paths = output[start..end].replace("(framework directory)", "");
Some(
paths
.lines()
.filter(|l| !l.is_empty())
.map(|l| Path::new(l.trim()).into())
.collect(),
)
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.19 Sekunden
(vorverarbeitet am 2026-06-18)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.