cargo_php_sys_build/
phpgen.rs1use std::collections::HashSet;
2use std::path::{Path, PathBuf};
3
4#[derive(Debug)]
5struct IgnoreMacros(HashSet<String>);
6
7impl bindgen::callbacks::ParseCallbacks for IgnoreMacros {
8 fn will_parse_macro(&self, name: &str) -> bindgen::callbacks::MacroParsingBehavior {
9 if self.0.contains(name) {
10 bindgen::callbacks::MacroParsingBehavior::Ignore
11 } else {
12 bindgen::callbacks::MacroParsingBehavior::Default
13 }
14 }
15}
16
17fn build_ignored_macros() -> IgnoreMacros {
18 IgnoreMacros(
19 vec![
20 "FP_INFINITE".into(),
21 "FP_NAN".into(),
22 "FP_NORMAL".into(),
23 "FP_SUBNORMAL".into(),
24 "FP_ZERO".into(),
25 "FP_INT_UPWARD".into(),
26 "FP_INT_DOWNWARD".into(),
27 "FP_INT_TOWARDZERO".into(),
28 "FP_INT_TONEARESTFROMZERO".into(),
29 "FP_INT_TONEAREST".into(),
30 "IPPORT_RESERVED".into(),
31 ]
32 .into_iter()
33 .collect(),
34 )
35}
36
37fn run_checks<T>(includes: T, check_path: &str)
38where
39 T: IntoIterator,
40 T::Item: AsRef<Path>,
41{
42 let check = cc::Build::new()
43 .file(check_path)
44 .includes(includes)
45 .expand();
46 let check = String::from_utf8(check).unwrap();
47
48 if check.contains("CHECK_DEBUG_ZEND_TRUE") {
49 println!("rustc-cfg=debug_zend");
50 }
51
52 if check.contains("CHECK_USING_ZTS_TRUE") {
53 println!("rustc-cfg=using_zts");
54 }
55}
56
57pub fn build_php(
58 bindings_rs: &PathBuf,
59 root_path: &PathBuf,
60 include_paths: &[&str],
61 wrapper_h: &PathBuf,
62 check_c_path: Option<&PathBuf>,
63) {
64 println!("cargo:rerun-if-changed={}", wrapper_h.to_str().unwrap());
65 let include_paths = include_paths
66 .iter()
67 .map(|v| {
68 root_path
69 .join(v)
70 .canonicalize()
71 .unwrap_or_else(|_| panic!("Include path not found : {:?}", root_path.join(v)))
72 })
73 .map(|v| String::from(v.to_str().unwrap()));
74
75 if let Some(p) = check_c_path {
76 println!("cargo:rerun-if-changed={}", p.to_str().unwrap());
77 run_checks(include_paths.clone(), p.to_str().unwrap());
78 }
79
80 let clang_args = include_paths.map(|v| format!("-I{}", v));
81
82 let bindings = bindgen::Builder::default()
83 .header(wrapper_h.to_str().unwrap())
84 .parse_callbacks(Box::new(build_ignored_macros()))
85 .layout_tests(true)
90 .allowlist_function(r"php_.*")
96 .allowlist_function(r"[_]?zend.*")
97 .allowlist_function(r".*zend")
98 .allowlist_type(r"zend.*")
99 .allowlist_type(r"ZEND.*")
100 .allowlist_var(r"[_]?zend.*")
101 .allowlist_var(r"[_]?ZEND.*")
102 .allowlist_var(r"php.*")
103 .allowlist_var(r"PHP.*")
104 .allowlist_var(r"[_]?is_.*")
105 .allowlist_var(r"[_]?IS_.*")
106 .allowlist_var(r"configure_.*")
107 .allowlist_var(r"CONFIGURE_.*")
108 .allowlist_var(r"gc_.*")
109 .allowlist_var(r"GC_.*")
110 .allowlist_var(r"using.*")
111 .allowlist_var(r"USING.*")
112 .allowlist_var(r"z_.*")
113 .allowlist_var(r"Z_.*")
114 .allowlist_var(r"zmsg")
115 .allowlist_var(r"ZMSG")
116 .allowlist_var(r"module.*")
117 .allowlist_var(r"MODULE.*")
118 .allowlist_var(r"hash_.*")
119 .allowlist_var(r"HASH_.*")
120 .allowlist_var(r"debug.*")
121 .allowlist_var(r"DEBUG.*")
122 .allowlist_var(r".*_globals")
123 .allowlist_var(r".*_GLOBALS")
124 .allowlist_var(r"module_registry")
125 .allowlist_var(r"MODULE_REGISTRY")
126 .allowlist_var(r"empty_fcall.*")
127 .allowlist_var(r"EMPTY_FCALL.*")
128 .allowlist_var(r"std_object_handlers")
129 .allowlist_var(r"STD_OBJECT_HANDLERS")
130 .allowlist_var(r".*zval.*")
131 .allowlist_var(r".*ZVAL.*")
132 .raw_line("#![allow(clippy::all)]") .raw_line("#![allow(non_upper_case_globals, non_camel_case_types, non_snake_case, clashing_extern_declarations)]\n")
134 .clang_args(clang_args)
135 .generate()
136 .expect("Unable to generate bindings");
137
138 bindings
139 .write_to_file(bindings_rs)
140 .expect("Couldn't write bindings!");
141}