1
1
use {
2
2
bindgen:: Builder ,
3
3
std:: {
4
- path:: PathBuf ,
4
+ path:: {
5
+ Path ,
6
+ PathBuf ,
7
+ } ,
5
8
process:: Command ,
6
9
} ,
7
10
} ;
8
11
9
12
fn main ( ) {
10
13
let target_arch = std:: env:: var ( "CARGO_CFG_TARGET_ARCH" ) . unwrap ( ) ;
11
14
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
+
12
18
// OUT_DIR is the path cargo provides to a build directory under `target/` specifically for
13
19
// isolated build artifacts. We use this to build the C program and then link against the
14
20
// resulting static library. This allows building the program when used as a dependency of
15
21
// another crate.
16
22
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) ;
17
26
let out_dir = PathBuf :: from ( out_dir) ;
18
27
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
+
19
39
let mut make_targets = vec ! [ ] ;
20
40
if target_arch == "bpf" {
21
41
make_targets. push ( "cpyth-bpf" ) ;
22
42
} else {
23
43
make_targets. push ( "cpyth-native" ) ;
24
44
}
25
- make_targets. push ( "test" ) ;
26
45
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" ) ;
36
47
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" ) ;
40
53
} 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( ) ) ;
42
65
}
43
- println ! ( "cargo:rustc-link-lib=static=cpyth-test" ) ;
44
- println ! ( "cargo:rustc-link-search={}" , out_dir. display( ) ) ;
45
66
46
67
std:: fs:: create_dir ( "./codegen" ) . unwrap_or_else ( |e| {
47
68
eprintln ! (
@@ -53,16 +74,41 @@ fn main() {
53
74
// Generate and write bindings
54
75
let bindings = Builder :: default ( )
55
76
. clang_arg ( format ! ( "-I{:}" , get_solana_inc_path( ) . display( ) ) )
77
+ . clang_args ( clang_extra_flags)
56
78
. header ( "./src/bindings.h" )
57
79
. rustfmt_bindings ( true )
58
80
. generate ( )
59
81
. expect ( "Unable to generate bindings" ) ;
82
+
60
83
bindings
61
84
. write_to_file ( "./codegen/bindings.rs" )
62
85
. expect ( "Couldn't write bindings!" ) ;
63
86
64
87
// 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
+ }
66
112
}
67
113
68
114
/// Find the Solana C header bindgen
0 commit comments