11use {
22 bindgen:: Builder ,
33 std:: {
4- path:: PathBuf ,
4+ path:: {
5+ Path ,
6+ PathBuf ,
7+ } ,
58 process:: Command ,
69 } ,
710} ;
811
912fn main ( ) {
1013 let target_arch = std:: env:: var ( "CARGO_CFG_TARGET_ARCH" ) . unwrap ( ) ;
1114
15+ let has_feat_pythnet = std:: env:: var ( "CARGO_FEATURE_PYTHNET" ) . is_ok ( ) ;
16+ let has_feat_check = std:: env:: var ( "CARGO_FEATURE_CHECK" ) . is_ok ( ) ;
17+
1218 // OUT_DIR is the path cargo provides to a build directory under `target/` specifically for
1319 // isolated build artifacts. We use this to build the C program and then link against the
1420 // resulting static library. This allows building the program when used as a dependency of
1521 // another crate.
1622 let out_dir = std:: env:: var ( "OUT_DIR" ) . unwrap ( ) ;
23+
24+ // Useful for C binary debugging, not printed without -vv cargo flag
25+ eprintln ! ( "OUT_DIR is {}" , out_dir) ;
1726 let out_dir = PathBuf :: from ( out_dir) ;
1827
28+ let mut make_extra_flags = vec ! [ ] ;
29+ let mut clang_extra_flags = vec ! [ ] ;
30+
31+ if has_feat_pythnet {
32+ // Define PC_PYTHNET for the C binary build
33+ make_extra_flags. push ( "PC_PYTHNET=1" ) ;
34+
35+ // Define PC_PYTHNET for the bindings build
36+ clang_extra_flags. push ( "-DPC_PYTHNET=1" ) ;
37+ }
38+
1939 let mut make_targets = vec ! [ ] ;
2040 if target_arch == "bpf" {
2141 make_targets. push ( "cpyth-bpf" ) ;
2242 } else {
2343 make_targets. push ( "cpyth-native" ) ;
2444 }
25- make_targets. push ( "test" ) ;
2645
27- // We must forward OUT_DIR as an env variable to the make script otherwise it will output
28- // its artifacts to the wrong place.
29- std:: process:: Command :: new ( "make" )
30- . env ( "VERBOSE" , "1" )
31- . env ( "OUT_DIR" , out_dir. display ( ) . to_string ( ) )
32- . current_dir ( "../c" )
33- . args ( make_targets)
34- . status ( )
35- . expect ( "Failed to build C program" ) ;
46+ make_targets. push ( "test" ) ;
3647
37- // Link against the right library for the architecture
38- if target_arch == "bpf" {
39- println ! ( "cargo:rustc-link-lib=static=cpyth-bpf" ) ;
48+ // When the `check` feature is active, we skip the make
49+ // build. This is used in pre-commit checks to avoid requiring
50+ // Solana in its GitHub Action.
51+ if has_feat_check {
52+ eprintln ! ( "WARNING: `check` feature active, make build is skipped" ) ;
4053 } else {
41- println ! ( "cargo:rustc-link-lib=static=cpyth-native" ) ;
54+ do_make_build ( make_extra_flags, make_targets, & out_dir) ;
55+
56+ // Link against the right library for the architecture
57+ if target_arch == "bpf" {
58+ println ! ( "cargo:rustc-link-lib=static=cpyth-bpf" ) ;
59+ } else {
60+ println ! ( "cargo:rustc-link-lib=static=cpyth-native" ) ;
61+ }
62+
63+ println ! ( "cargo:rustc-link-lib=static=cpyth-test" ) ;
64+ println ! ( "cargo:rustc-link-search={}" , out_dir. display( ) ) ;
4265 }
43- println ! ( "cargo:rustc-link-lib=static=cpyth-test" ) ;
44- println ! ( "cargo:rustc-link-search={}" , out_dir. display( ) ) ;
4566
4667 std:: fs:: create_dir ( "./codegen" ) . unwrap_or_else ( |e| {
4768 eprintln ! (
@@ -53,16 +74,41 @@ fn main() {
5374 // Generate and write bindings
5475 let bindings = Builder :: default ( )
5576 . clang_arg ( format ! ( "-I{:}" , get_solana_inc_path( ) . display( ) ) )
77+ . clang_args ( clang_extra_flags)
5678 . header ( "./src/bindings.h" )
5779 . rustfmt_bindings ( true )
5880 . generate ( )
5981 . expect ( "Unable to generate bindings" ) ;
82+
6083 bindings
6184 . write_to_file ( "./codegen/bindings.rs" )
6285 . expect ( "Couldn't write bindings!" ) ;
6386
6487 // Rerun the build script if either the rust or C code changes
65- println ! ( "cargo:rerun-if-changed=../" )
88+ println ! ( "cargo:rerun-if-changed=../" ) ;
89+ }
90+
91+ fn do_make_build ( extra_flags : Vec < & str > , targets : Vec < & str > , out_dir : & Path ) {
92+ // We must forward OUT_DIR as an env variable to the make script otherwise it will output
93+ // its artifacts to the wrong place.
94+ let make_output = std:: process:: Command :: new ( "make" )
95+ . env ( "VERBOSE" , "1" )
96+ . env ( "OUT_DIR" , out_dir. display ( ) . to_string ( ) )
97+ . current_dir ( "../c" )
98+ . args ( extra_flags)
99+ . args ( targets)
100+ . output ( )
101+ . expect ( "Failed to run make for C oracle program" ) ;
102+
103+ if !make_output. status . success ( ) {
104+ panic ! (
105+ "C oracle make build did not exit with 0 (code
106+ ({:?}).\n \n stdout:\n {}\n \n stderr:\n {}" ,
107+ make_output. status. code( ) ,
108+ String :: from_utf8( make_output. stdout) . unwrap_or( "<non-utf8>" . to_owned( ) ) ,
109+ String :: from_utf8( make_output. stderr) . unwrap_or( "<non-utf8>" . to_owned( ) )
110+ ) ;
111+ }
66112}
67113
68114/// Find the Solana C header bindgen
0 commit comments