mirror of
https://github.com/danog/ext-php-rs.git
synced 2024-12-02 09:37:51 +01:00
e4deb1f93f
* Add PHP thread safety to build matrix * Revert "Add PHP thread safety to build matrix" This reverts commit 7de868e6b6e329b87c412af8daf61cba1a3e29c5. * Fixed arguments not being reconized by PHP * Added function to create interned Zend string * Changed statup/shutdown function types to Rust types Prevents users having to import from bindings * Added flags for classes * WIP: class builder * Added properties to classes * Added class constants * Added PHP base extensions Added class inheritance * Fixed memory leak with constants Created C wrapper which is compiled and linked in the `build.rs` script. In the process removed the `build_id()` function as now we can just export the macro via a function which is defined in `wrapper.c`. * Fixed lint issue * Added functions to set zval as different strings Regular strings, persistent strings and interned strings * Updated README with requirements * Fixed lint issues * Changed properties to use proper function * Free zend string when it is changed for a persistent one * WIP: overriding zend objects * Added comments to the top of modules. * Fixed some comments * Initialize hash map with initial size when converting from HashMap and Vec * Removed unused imports * WIP: object overrides * Added DerefMut implementation for ZendClassObject Tidied up lints that clippy was complaining about, removed debugging statements. * Fixed pointer dereference error in macro * Added missing comments for trait * All functions now take mutable references vs ptr Removed SetZval implementation for *mut Zval. Made bindings public, removed duplicate bindings. Fixed `create_object` handler not working. Note to self: smaller commits. * Showcase ability to use shared object * WIP: debugging property errors Changed `function` to `method` in classes Fixed doctest for `c_str` * Disabled class properties temporarily See #16 * Initialize args array with size
123 lines
4.3 KiB
Rust
123 lines
4.3 KiB
Rust
use std::{
|
|
collections::HashSet,
|
|
env,
|
|
path::{Path, PathBuf},
|
|
process::Command,
|
|
};
|
|
|
|
use bindgen::callbacks::{MacroParsingBehavior, ParseCallbacks};
|
|
use regex::{Captures, Regex};
|
|
|
|
extern crate bindgen;
|
|
|
|
// https://github.com/rust-lang/rust-bindgen/issues/687#issuecomment-450750547
|
|
#[derive(Debug)]
|
|
struct IgnoreMacros(HashSet<String>);
|
|
|
|
impl ParseCallbacks for IgnoreMacros {
|
|
fn will_parse_macro(&self, name: &str) -> MacroParsingBehavior {
|
|
if self.0.contains(name) {
|
|
MacroParsingBehavior::Ignore
|
|
} else {
|
|
MacroParsingBehavior::Default
|
|
}
|
|
}
|
|
}
|
|
|
|
const MIN_PHP_API_VER: u32 = 20200930;
|
|
const MAX_PHP_API_VER: u32 = 20200930;
|
|
|
|
fn main() {
|
|
// rerun if wrapper header is changed
|
|
println!("cargo:rerun-if-changed=src/wrapper/wrapper.h");
|
|
println!("cargo:rerun-if-changed=src/wrapper/wrapper.c");
|
|
|
|
// use php-config to fetch includes
|
|
let includes_cmd = Command::new("php-config")
|
|
.arg("--includes")
|
|
.output()
|
|
.expect("Unable to run `php-config`. Please ensure it is visible in your PATH.");
|
|
|
|
if !includes_cmd.status.success() {
|
|
let stderr = String::from_utf8(includes_cmd.stderr)
|
|
.unwrap_or_else(|_| String::from("Unable to read stderr"));
|
|
panic!("Error running `php-config`: {}", stderr);
|
|
}
|
|
|
|
// Ensure the PHP API version is supported.
|
|
// We could easily use grep and sed here but eventually we want to support Windows,
|
|
// so it's easier to just use regex.
|
|
let php_i_cmd = Command::new("php")
|
|
.arg("-i")
|
|
.output()
|
|
.expect("Unable to run `php -i`. Please ensure it is visible in your PATH.");
|
|
|
|
if !php_i_cmd.status.success() {
|
|
let stderr = String::from_utf8(includes_cmd.stderr)
|
|
.unwrap_or_else(|_| String::from("Unable to read stderr"));
|
|
panic!("Error running `php -i`: {}", stderr);
|
|
}
|
|
|
|
let php_i = String::from_utf8(php_i_cmd.stdout).expect("unabel to parse `php -i` stdout");
|
|
let php_api_regex = Regex::new(r"PHP API => ([0-9]+)").unwrap();
|
|
let api_ver: Vec<Captures> = php_api_regex.captures_iter(php_i.as_ref()).collect();
|
|
|
|
match api_ver.first() {
|
|
Some(api_ver) => match api_ver.get(1) {
|
|
Some(api_ver) => {
|
|
let api_ver: u32 = api_ver.as_str().parse().unwrap();
|
|
|
|
if api_ver < MIN_PHP_API_VER || api_ver > MAX_PHP_API_VER {
|
|
panic!("The current version of PHP is not supported. Current PHP API version: {}, requires a version between {} and {}", api_ver, MIN_PHP_API_VER, MAX_PHP_API_VER);
|
|
}
|
|
},
|
|
None => panic!("Unable to retrieve PHP API version from `php -i`. Please check the installation and ensure it is callable.")
|
|
},
|
|
None => panic!("Unable to retrieve PHP API version from `php -i`. Please check the installation and ensure it is callable.")
|
|
};
|
|
|
|
let includes =
|
|
String::from_utf8(includes_cmd.stdout).expect("unable to parse `php-config` stdout");
|
|
|
|
// Build `wrapper.c` and link to Rust.
|
|
cc::Build::new()
|
|
.file("src/wrapper/wrapper.c")
|
|
.includes(
|
|
str::replace(includes.as_ref(), "-I", "")
|
|
.split(' ')
|
|
.map(|path| Path::new(path)),
|
|
)
|
|
.compile("wrapper");
|
|
|
|
let ignore_math_h_macros = IgnoreMacros(
|
|
vec![
|
|
// math.h:914 - enum which uses #define for values
|
|
"FP_NAN".into(),
|
|
"FP_INFINITE".into(),
|
|
"FP_ZERO".into(),
|
|
"FP_SUBNORMAL".into(),
|
|
"FP_NORMAL".into(),
|
|
// math.h:237 - enum which uses #define for values
|
|
"FP_INT_UPWARD".into(),
|
|
"FP_INT_DOWNWARD".into(),
|
|
"FP_INT_TOWARDZERO".into(),
|
|
"FP_INT_TONEARESTFROMZERO".into(),
|
|
"FP_INT_TONEAREST".into(),
|
|
]
|
|
.into_iter()
|
|
.collect(),
|
|
);
|
|
|
|
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
|
|
bindgen::Builder::default()
|
|
.header("src/wrapper/wrapper.h")
|
|
.clang_args(includes.split(' '))
|
|
.parse_callbacks(Box::new(bindgen::CargoCallbacks))
|
|
.parse_callbacks(Box::new(ignore_math_h_macros))
|
|
.rustfmt_bindings(true)
|
|
.generate()
|
|
.expect("Unable to generate bindings for PHP")
|
|
.write_to_file(out_path.join("bindings.rs"))
|
|
.expect("Unable to write bindings file.");
|
|
}
|