xref: /third_party/rust/crates/cxx/gen/build/src/paths.rs (revision 33d722a9)
1use crate::error::Result;
2use crate::gen::fs;
3use std::ffi::OsStr;
4use std::path::{Component, Path, PathBuf};
5
6pub(crate) fn manifest_dir() -> Result<PathBuf> {
7    crate::env_os("CARGO_MANIFEST_DIR").map(PathBuf::from)
8}
9
10pub(crate) fn out_dir() -> Result<PathBuf> {
11    crate::env_os("OUT_DIR").map(PathBuf::from)
12}
13
14// Given a path provided by the user, determines where generated files related
15// to that path should go in our out dir. In particular we don't want to
16// accidentally write generated code upward of our out dir, even if the user
17// passed a path containing lots of `..` or an absolute path.
18pub(crate) fn local_relative_path(path: &Path) -> PathBuf {
19    let mut rel_path = PathBuf::new();
20    for component in path.components() {
21        match component {
22            Component::Prefix(_) | Component::RootDir | Component::CurDir => {}
23            Component::ParentDir => drop(rel_path.pop()), // noop if empty
24            Component::Normal(name) => rel_path.push(name),
25        }
26    }
27    rel_path
28}
29
30pub(crate) trait PathExt {
31    fn with_appended_extension(&self, suffix: impl AsRef<OsStr>) -> PathBuf;
32}
33
34impl PathExt for Path {
35    fn with_appended_extension(&self, suffix: impl AsRef<OsStr>) -> PathBuf {
36        let mut file_name = self.file_name().unwrap().to_owned();
37        file_name.push(suffix);
38        self.with_file_name(file_name)
39    }
40}
41
42#[cfg(unix)]
43pub(crate) use self::fs::symlink_file as symlink_or_copy;
44
45#[cfg(windows)]
46pub(crate) fn symlink_or_copy(
47    original: impl AsRef<Path>,
48    link: impl AsRef<Path>,
49) -> fs::Result<()> {
50    // Pre-Windows 10, symlinks require admin privileges. Since Windows 10, they
51    // require Developer Mode. If it fails, fall back to copying the file.
52    let original = original.as_ref();
53    let link = link.as_ref();
54    if fs::symlink_file(original, link).is_err() {
55        fs::copy(original, link)?;
56    }
57    Ok(())
58}
59
60#[cfg(not(any(unix, windows)))]
61pub(crate) fn symlink_or_copy(
62    original: impl AsRef<Path>,
63    copy: impl AsRef<Path>,
64) -> fs::Result<()> {
65    fs::copy(original, copy)?;
66    Ok(())
67}
68