@@ -2,21 +2,55 @@ use std::env;
22use std:: path:: { Path , PathBuf } ;
33
44fn main ( ) {
5- let curdir = std:: env:: current_dir ( ) . unwrap ( ) ;
6- let srcdir = curdir. parent ( ) . and_then ( Path :: parent) . unwrap ( ) ;
5+ let manifest_dir = PathBuf :: from ( env:: var ( "CARGO_MANIFEST_DIR" ) . unwrap ( ) ) ;
6+ let srcdir = manifest_dir
7+ . parent ( )
8+ . and_then ( Path :: parent)
9+ . expect ( "expected Modules/cpython-sys to live under the source tree" ) ;
710 let out_path = PathBuf :: from ( env:: var ( "OUT_DIR" ) . unwrap ( ) ) ;
8- generate_c_api_bindings ( srcdir, & out_path. as_path ( ) ) ;
11+ let builddir = env:: var ( "PYTHON_BUILD_DIR" ) . ok ( ) ;
12+ if gil_disabled ( & srcdir, builddir. as_deref ( ) ) {
13+ println ! ( "cargo:rustc-cfg=py_gil_disabled" ) ;
14+ }
15+ generate_c_api_bindings ( srcdir, builddir. as_deref ( ) , & out_path. as_path ( ) ) ;
916 // TODO(emmatyping): generate bindings to the internal parser API
1017 // The parser includes things slightly differently, so we should generate
1118 // it's bindings independently
1219 //generate_parser_bindings(srcdir, &out_path.as_path());
1320}
1421
15- fn generate_c_api_bindings ( srcdir : & Path , out_path : & Path ) {
16- let bindings = bindgen:: Builder :: default ( )
17- . header ( "wrapper.h" )
18- . clang_arg ( format ! ( "-I{}" , srcdir. as_os_str( ) . to_str( ) . unwrap( ) ) )
19- . clang_arg ( format ! ( "-I{}/Include" , srcdir. as_os_str( ) . to_str( ) . unwrap( ) ) )
22+ fn gil_disabled ( srcdir : & Path , builddir : Option < & str > ) -> bool {
23+ let mut candidates = Vec :: new ( ) ;
24+ if let Some ( build) = builddir {
25+ candidates. push ( PathBuf :: from ( build) ) ;
26+ }
27+ candidates. push ( srcdir. to_path_buf ( ) ) ;
28+ for base in candidates {
29+ let path = base. join ( "pyconfig.h" ) ;
30+ if let Ok ( contents) = std:: fs:: read_to_string ( & path) {
31+ if contents. contains ( "Py_GIL_DISABLED 1" ) {
32+ return true ;
33+ }
34+ }
35+ }
36+ false
37+ }
38+
39+ fn generate_c_api_bindings ( srcdir : & Path , builddir : Option < & str > , out_path : & Path ) {
40+ let mut builder = bindgen:: Builder :: default ( ) . header ( "wrapper.h" ) ;
41+
42+ // Always search the source dir and the public headers.
43+ let mut include_dirs = vec ! [ srcdir. to_path_buf( ) , srcdir. join( "Include" ) ] ;
44+ // Include the build directory if provided; out-of-tree builds place
45+ // the generated pyconfig.h there.
46+ if let Some ( build) = builddir {
47+ include_dirs. push ( PathBuf :: from ( build) ) ;
48+ }
49+ for dir in include_dirs {
50+ builder = builder. clang_arg ( format ! ( "-I{}" , dir. display( ) ) ) ;
51+ }
52+
53+ let bindings = builder
2054 . allowlist_function ( "_?Py.*" )
2155 . allowlist_type ( "_?Py.*" )
2256 . allowlist_var ( "_?Py.*" )
0 commit comments