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}