urcu_src/
lib.rs

1#![doc = include_str!("../README.md")]
2
3pub trait BuildConfig {
4    fn cargo_link(&self, lib: &'static str);
5
6    fn configure_bindgen(&self, builder: bindgen::Builder) -> bindgen::Builder;
7
8    fn configure_cc<'a>(&'a self, builder: &'a mut cc::Build) -> &'a mut cc::Build;
9
10    fn default_bindgen(&self) -> bindgen::Builder {
11        self.configure_bindgen(bindgen::Builder::default())
12    }
13
14    fn default_cc(&self) -> cc::Build {
15        let mut builder = cc::Build::default();
16        self.configure_cc(&mut builder);
17        builder
18    }
19}
20
21#[cfg(feature = "static")]
22mod static_linking {
23    use std::path::PathBuf;
24    use std::str::FromStr;
25
26    use super::*;
27
28    pub struct StaticBuildConfig {
29        include_dir: Vec<PathBuf>,
30    }
31
32    impl StaticBuildConfig {
33        pub fn new() -> Self {
34            let build_dir = PathBuf::from_str(env!("BUILD_DIR")).unwrap();
35            let lib_dir = build_dir.join("lib");
36            let pkgconfig_dir = lib_dir.join("pkgconfig");
37
38            std::env::set_var("PKG_CONFIG_PATH", pkgconfig_dir);
39            println!("cargo:rustc-link-search=native={}", lib_dir.display());
40
41            Self {
42                include_dir: vec![build_dir.join("include")],
43            }
44        }
45
46        pub fn new_docrs() -> Self {
47            let include_dir = PathBuf::from_str(env!("CARGO_MANIFEST_DIR"))
48                .unwrap()
49                .join("vendor/include");
50
51            let out_dir = PathBuf::from_str(&std::env::var("OUT_DIR").unwrap())
52                .unwrap()
53                .join("urcu-src");
54
55            std::fs::create_dir_all(out_dir.join("urcu")).unwrap();
56
57            let _ = std::fs::copy(
58                include_dir.join("urcu/config.h.in"),
59                out_dir.join("urcu/config.h"),
60            );
61
62            Self {
63                include_dir: vec![include_dir, out_dir],
64            }
65        }
66    }
67
68    impl BuildConfig for StaticBuildConfig {
69        fn cargo_link(&self, lib: &'static str) {
70            println!("cargo:rustc-link-lib=static={}", lib);
71        }
72
73        fn configure_bindgen(&self, builder: bindgen::Builder) -> bindgen::Builder {
74            builder.clang_args(
75                self.include_dir
76                    .iter()
77                    .map(|dir| format!("-I{}", dir.display())),
78            )
79        }
80
81        fn configure_cc<'a>(&'a self, builder: &'a mut cc::Build) -> &'a mut cc::Build {
82            builder.includes(self.include_dir.clone())
83        }
84    }
85}
86
87#[cfg(not(feature = "static"))]
88mod dynamic_linking {
89    use super::*;
90
91    pub struct DynamicBuildConfig;
92
93    impl BuildConfig for DynamicBuildConfig {
94        fn cargo_link(&self, lib: &'static str) {
95            println!("cargo:rustc-link-lib={}", lib);
96        }
97
98        fn configure_bindgen(&self, builder: bindgen::Builder) -> bindgen::Builder {
99            builder
100        }
101
102        fn configure_cc<'a>(&'a self, builder: &'a mut cc::Build) -> &'a mut cc::Build {
103            builder
104        }
105    }
106}
107
108pub fn build_config() -> Box<dyn BuildConfig> {
109    #[cfg(feature = "static")]
110    return if std::env::var("DOCS_RS").is_ok() {
111        Box::new(static_linking::StaticBuildConfig::new_docrs())
112    } else {
113        Box::new(static_linking::StaticBuildConfig::new())
114    };
115
116    #[cfg(not(feature = "static"))]
117    return Box::new(dynamic_linking::DynamicBuildConfig);
118}