diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6824dd7..d4de9ce 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -32,6 +32,7 @@ jobs: uses: actions-rs/toolchain@v1 with: toolchain: ${{ matrix.rust-toolchain }} + override: true - name: Setup LLVM & Clang uses: KyleMayes/install-llvm-action@v1 with: @@ -42,12 +43,10 @@ jobs: with: mdbook-version: latest - name: Build - uses: actions-rs/cargo@v1 env: LIBCLANG_PATH: ${{ runner.temp }}/llvm-${{ matrix.llvm }}/lib - with: - command: build - args: --release --features alloc,closure + EXT_PHP_RS_TEST: + run: cargo build --release --features alloc,closure - name: Test guide examples run: | mdbook test guide -L target/release/deps diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 43bb51e..5d8226e 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -28,6 +28,7 @@ jobs: uses: actions-rs/toolchain@v1 with: toolchain: ${{ matrix.rust-toolchain }} + override: true - name: Setup LLVM & Clang uses: KyleMayes/install-llvm-action@v1 with: @@ -41,7 +42,7 @@ jobs: env: LIBCLANG_PATH: ${{ runner.temp }}/llvm-${{ matrix.llvm }}/lib RUSTDOCFLAGS: --cfg docs - run: cargo +nightly doc --release + run: cargo --release - name: Build guide run: | mdbook build guide diff --git a/build.rs b/build.rs index 90904d3..a852649 100644 --- a/build.rs +++ b/build.rs @@ -3,10 +3,11 @@ use std::{ env, path::{Path, PathBuf}, process::Command, + str, }; use bindgen::callbacks::{MacroParsingBehavior, ParseCallbacks}; -use regex::{Captures, Regex}; +use regex::Regex; extern crate bindgen; @@ -53,28 +54,23 @@ fn main() { .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")); + let stderr = str::from_utf8(&includes_cmd.stderr).unwrap_or("Unable to read stderr"); panic!("Error running `php -i`: {}", stderr); } - let php_i = String::from_utf8(php_i_cmd.stdout).expect("unable to parse `php -i` stdout"); - let php_api_regex = Regex::new(r"PHP API => ([0-9]+)").unwrap(); - let api_ver: Vec = php_api_regex.captures_iter(php_i.as_ref()).collect(); + let api_ver = Regex::new(r"PHP API => ([0-9]+)") + .unwrap() + .captures_iter( + str::from_utf8(&php_i_cmd.stdout).expect("Unable to parse `php -i` stdout as UTF-8"), + ) + .next() + .and_then(|ver| ver.get(1)) + .and_then(|ver| ver.as_str().parse::().ok()) + .expect("Unable to retrieve PHP API version from `php -i`."); - 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.") - }; + 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); + } let includes = String::from_utf8(includes_cmd.stdout).expect("unable to parse `php-config` stdout"); @@ -109,13 +105,23 @@ fn main() { ); let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()); - bindgen::Builder::default() + let mut bindgen = 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) .no_copy("_zend_value") + .layout_tests(env::var("EXT_PHP_RS_TEST").is_ok()); + + for binding in ALLOWED_BINDINGS.iter() { + bindgen = bindgen + .allowlist_function(binding) + .allowlist_type(binding) + .allowlist_var(binding); + } + + bindgen .generate() .expect("Unable to generate bindings for PHP") .write_to_file(out_path.join("bindings.rs")) @@ -161,3 +167,176 @@ impl Configure { self.0.contains("--enable-debug") } } + +/// Array of functions/types used in `ext-php-rs` - used to allowlist when generating +/// bindings, as we don't want to generate bindings for everything (i.e. stdlib headers). +const ALLOWED_BINDINGS: &[&str] = &[ + "HashTable", + "_Bucket", + "_call_user_function_impl", + "_efree", + "_emalloc", + "_zend_executor_globals", + "_zend_expected_type", + "_zend_expected_type_Z_EXPECTED_ARRAY", + "_zend_expected_type_Z_EXPECTED_BOOL", + "_zend_expected_type_Z_EXPECTED_DOUBLE", + "_zend_expected_type_Z_EXPECTED_LONG", + "_zend_expected_type_Z_EXPECTED_OBJECT", + "_zend_expected_type_Z_EXPECTED_RESOURCE", + "_zend_expected_type_Z_EXPECTED_STRING", + "_zend_new_array", + "_zval_struct__bindgen_ty_1", + "_zval_struct__bindgen_ty_2", + "ext_php_rs_executor_globals", + "ext_php_rs_php_build_id", + "ext_php_rs_zend_object_alloc", + "ext_php_rs_zend_object_release", + "ext_php_rs_zend_string_init", + "ext_php_rs_zend_string_release", + "object_properties_init", + "php_info_print_table_end", + "php_info_print_table_header", + "php_info_print_table_row", + "php_info_print_table_start", + "std_object_handlers", + "zend_array_destroy", + "zend_array_dup", + "zend_ce_argument_count_error", + "zend_ce_arithmetic_error", + "zend_ce_compile_error", + "zend_ce_division_by_zero_error", + "zend_ce_error_exception", + "zend_ce_exception", + "zend_ce_parse_error", + "zend_ce_throwable", + "zend_ce_type_error", + "zend_ce_unhandled_match_error", + "zend_ce_value_error", + "zend_class_entry", + "zend_declare_class_constant", + "zend_declare_property", + "zend_do_implement_interface", + "zend_execute_data", + "zend_function_entry", + "zend_hash_clean", + "zend_hash_index_del", + "zend_hash_index_find", + "zend_hash_index_update", + "zend_hash_next_index_insert", + "zend_hash_str_del", + "zend_hash_str_find", + "zend_hash_str_update", + "zend_internal_arg_info", + "zend_is_callable", + "zend_long", + "zend_lookup_class_ex", + "zend_module_entry", + "zend_object", + "zend_object_handlers", + "zend_object_std_init", + "zend_objects_clone_members", + "zend_register_bool_constant", + "zend_register_double_constant", + "zend_register_internal_class_ex", + "zend_register_long_constant", + "zend_register_string_constant", + "zend_resource", + "zend_string", + "zend_string_init_interned", + "zend_throw_exception_ex", + "zend_type", + "zend_value", + "zend_wrong_parameters_count_error", + "zval", + "CONST_CS", + "CONST_DEPRECATED", + "CONST_NO_FILE_CACHE", + "CONST_PERSISTENT", + "HT_MIN_SIZE", + "IS_ARRAY", + "IS_ARRAY_EX", + "IS_CALLABLE", + "IS_CONSTANT_AST", + "IS_CONSTANT_AST_EX", + "IS_DOUBLE", + "IS_FALSE", + "IS_INTERNED_STRING_EX", + "IS_LONG", + "IS_MIXED", + "IS_NULL", + "IS_OBJECT", + "IS_OBJECT_EX", + "IS_REFERENCE", + "IS_REFERENCE_EX", + "IS_RESOURCE", + "IS_RESOURCE_EX", + "IS_STRING", + "IS_STRING_EX", + "IS_TRUE", + "IS_TYPE_COLLECTABLE", + "IS_TYPE_REFCOUNTED", + "IS_UNDEF", + "IS_VOID", + "MAY_BE_ANY", + "MAY_BE_BOOL", + "USING_ZTS", + "ZEND_ACC_ABSTRACT", + "ZEND_ACC_ANON_CLASS", + "ZEND_ACC_CALL_VIA_TRAMPOLINE", + "ZEND_ACC_CHANGED", + "ZEND_ACC_CLOSURE", + "ZEND_ACC_CONSTANTS_UPDATED", + "ZEND_ACC_CTOR", + "ZEND_ACC_DEPRECATED", + "ZEND_ACC_DONE_PASS_TWO", + "ZEND_ACC_EARLY_BINDING", + "ZEND_ACC_FAKE_CLOSURE", + "ZEND_ACC_FINAL", + "ZEND_ACC_GENERATOR", + "ZEND_ACC_HAS_FINALLY_BLOCK", + "ZEND_ACC_HAS_RETURN_TYPE", + "ZEND_ACC_HAS_TYPE_HINTS", + "ZEND_ACC_HAS_UNLINKED_USES", + "ZEND_ACC_HEAP_RT_CACHE", + "ZEND_ACC_IMMUTABLE", + "ZEND_ACC_IMPLICIT_ABSTRACT_CLASS", + "ZEND_ACC_INTERFACE", + "ZEND_ACC_LINKED", + "ZEND_ACC_NEARLY_LINKED", + "ZEND_ACC_NEVER_CACHE", + "ZEND_ACC_NO_DYNAMIC_PROPERTIES", + "ZEND_ACC_PRELOADED", + "ZEND_ACC_PRIVATE", + "ZEND_ACC_PROMOTED", + "ZEND_ACC_PROPERTY_TYPES_RESOLVED", + "ZEND_ACC_PROTECTED", + "ZEND_ACC_PUBLIC", + "ZEND_ACC_RESOLVED_INTERFACES", + "ZEND_ACC_RESOLVED_PARENT", + "ZEND_ACC_RETURN_REFERENCE", + "ZEND_ACC_REUSE_GET_ITERATOR", + "ZEND_ACC_STATIC", + "ZEND_ACC_STRICT_TYPES", + "ZEND_ACC_TOP_LEVEL", + "ZEND_ACC_TRAIT", + "ZEND_ACC_TRAIT_CLONE", + "ZEND_ACC_UNRESOLVED_VARIANCE", + "ZEND_ACC_USES_THIS", + "ZEND_ACC_USE_GUARDS", + "ZEND_ACC_VARIADIC", + "ZEND_DEBUG", + "ZEND_HAS_STATIC_IN_METHODS", + "ZEND_ISEMPTY", + "ZEND_MM_ALIGNMENT", + "ZEND_MM_ALIGNMENT_MASK", + "ZEND_MODULE_API_NO", + "ZEND_PROPERTY_EXISTS", + "ZEND_PROPERTY_ISSET", + "Z_TYPE_FLAGS_SHIFT", + "_IS_BOOL", + "_ZEND_IS_VARIADIC_BIT", + "_ZEND_SEND_MODE_SHIFT", + "_ZEND_TYPE_NULLABLE_BIT", + "ts_rsrc_id", +];