1
1
// Copyright 2019 TiKV Project Authors. Licensed under Apache-2.0.
2
2
3
+ use std:: collections:: HashSet ;
3
4
use std:: env:: VarError ;
5
+ use std:: fs:: File ;
4
6
use std:: io:: prelude:: * ;
5
7
use std:: io:: BufReader ;
6
8
use std:: path:: { Path , PathBuf } ;
@@ -10,24 +12,9 @@ use cmake::Config as CmakeConfig;
10
12
use pkg_config:: { Config as PkgConfig , Library } ;
11
13
use walkdir:: WalkDir ;
12
14
13
- const GRPC_VERSION : & str = "1.38 .0" ;
15
+ const GRPC_VERSION : & str = "1.44 .0" ;
14
16
15
- /// Following two arrays are generated by running pkg-config manually. We can
16
- /// also choose to run pkg-config at build time, but it will requires pkg-config
17
- /// in path, which is unfriendly for platforms like Windows.
18
- // grpc_unsecure.pc is not accurate, see also grpc/grpc#24512. Should also include "address_sorting", "upb", "cares", "z".
19
- #[ rustfmt:: skip]
20
- const COMMON_DEPS : & [ & str ] = & [
21
- "absl_bad_optional_access" , "absl_bad_variant_access" , "absl_base" , "absl_city" , "absl_civil_time" ,
22
- "absl_cord" , "absl_debugging_internal" , "absl_demangle_internal" , "absl_exponential_biased" ,
23
- "absl_graphcycles_internal" , "absl_hash" , "absl_hashtablez_sampler" , "absl_int128" , "absl_log_severity" ,
24
- "absl_malloc_internal" , "absl_raw_hash_set" , "absl_raw_logging_internal" , "absl_spinlock_wait" ,
25
- "absl_stacktrace" , "absl_status" , "absl_statusor" , "absl_str_format_internal" , "absl_strings" ,
26
- "absl_strings_internal" , "absl_symbolize" , "absl_synchronization" , "absl_throw_delegate" , "absl_time" ,
27
- "absl_time_zone" , "absl_wyhash" , "address_sorting" , "cares" , "gpr" , "upb" , "z" ,
28
- ] ;
29
- const GRPC_DEPS : & [ & str ] = & [ "grpc" , "re2" ] ;
30
- const GRPC_UNSECURE_DEPS : & [ & str ] = & [ "grpc_unsecure" ] ;
17
+ include ! ( "link-deps.rs" ) ;
31
18
32
19
fn probe_library ( library : & str , cargo_metadata : bool ) -> Library {
33
20
match PkgConfig :: new ( )
@@ -99,6 +86,68 @@ fn clean_up_stale_cache(cxx_compiler: String) {
99
86
}
100
87
}
101
88
89
+ /// List packages needed for linking in working directory.
90
+ fn list_packages ( dst : & Path ) {
91
+ env:: set_var (
92
+ "PKG_CONFIG_PATH" ,
93
+ format ! ( "{}/lib/pkgconfig" , dst. display( ) ) ,
94
+ ) ;
95
+ let mut cfg = PkgConfig :: new ( ) ;
96
+ cfg. print_system_cflags ( false )
97
+ . print_system_libs ( false )
98
+ . env_metadata ( false )
99
+ . cargo_metadata ( false )
100
+ . atleast_version ( GRPC_VERSION ) ;
101
+ let grpc = cfg. probe ( "grpc" ) . unwrap ( ) ;
102
+ let mut grpc_libs: HashSet < _ > = grpc. libs . iter ( ) . cloned ( ) . collect ( ) ;
103
+ let grpc_unsecure = cfg. probe ( "grpc_unsecure" ) . unwrap ( ) ;
104
+ let mut grpc_unsecure_libs: HashSet < _ > = grpc_unsecure. libs . iter ( ) . cloned ( ) . collect ( ) ;
105
+
106
+ // grpc_unsecure.pc is not accurate, see also grpc/grpc#24512. Should also include "address_sorting", "upb", "cares", "z".
107
+ grpc_unsecure_libs. extend (
108
+ [ "address_sorting" , "upb" , "cares" , "z" ]
109
+ . iter ( )
110
+ . map ( |s| s. to_string ( ) ) ,
111
+ ) ;
112
+ // There is no "rt" on Windows and MacOS.
113
+ grpc_libs. remove ( "rt" ) ;
114
+ grpc_unsecure_libs. remove ( "rt" ) ;
115
+
116
+ // ssl, crypto is managed by us according to different features.
117
+ grpc_libs. remove ( "ssl" ) ;
118
+ grpc_libs. remove ( "crypto" ) ;
119
+
120
+ let mut common_libs: Vec < _ > = grpc_libs. intersection ( & grpc_unsecure_libs) . collect ( ) ;
121
+ let mut secure_only: Vec < _ > = grpc_libs. difference ( & grpc_unsecure_libs) . collect ( ) ;
122
+ let mut unsecure_only: Vec < _ > = grpc_unsecure_libs. difference ( & grpc_libs) . collect ( ) ;
123
+
124
+ common_libs. sort ( ) ;
125
+ secure_only. sort ( ) ;
126
+ unsecure_only. sort ( ) ;
127
+
128
+ let outputs = & [
129
+ ( "COMMON_DEPS" , common_libs) ,
130
+ ( "GRPC_DEPS" , secure_only) ,
131
+ ( "GRPC_UNSECURE_DEPS" , unsecure_only) ,
132
+ ] ;
133
+
134
+ let mut f = File :: create ( "link-deps.rs" ) . unwrap ( ) ;
135
+ f. write_all (
136
+ b"/// Following two arrays are generated by running pkg-config manually. We can
137
+ /// also choose to run pkg-config at build time, but it will requires pkg-config
138
+ /// in path, which is unfriendly for platforms like Windows.
139
+ " ,
140
+ )
141
+ . unwrap ( ) ;
142
+ for ( name, libs) in outputs {
143
+ writeln ! ( f, "const {}: &[&str] = &[" , name) . unwrap ( ) ;
144
+ for lib in libs {
145
+ writeln ! ( f, "\" {}\" ," , lib) . unwrap ( ) ;
146
+ }
147
+ writeln ! ( f, "];" ) . unwrap ( ) ;
148
+ }
149
+ }
150
+
102
151
fn build_grpc ( cc : & mut cc:: Build , library : & str ) {
103
152
prepare_grpc ( ) ;
104
153
@@ -165,7 +214,7 @@ fn build_grpc(cc: &mut cc::Build, library: &str) {
165
214
}
166
215
167
216
// We don't need to generate install targets.
168
- config. define ( "gRPC_INSTALL" , "false" ) ;
217
+ config. define ( "gRPC_INSTALL" , cfg ! ( feature = "_list-package" ) . to_string ( ) ) ;
169
218
// We don't need to build csharp target.
170
219
config. define ( "gRPC_BUILD_CSHARP_EXT" , "false" ) ;
171
220
// We don't need to build codegen target.
@@ -175,15 +224,16 @@ fn build_grpc(cc: &mut cc::Build, library: &str) {
175
224
176
225
// `package` should only be set for secure feature, otherwise cmake will always search for
177
226
// ssl library.
178
- if cfg ! ( feature = "secure " ) {
227
+ if cfg ! ( feature = "_secure " ) {
179
228
config. define ( "gRPC_SSL_PROVIDER" , "package" ) ;
180
229
}
181
- #[ cfg( feature = "secure " ) ]
230
+ #[ cfg( feature = "_secure " ) ]
182
231
if cfg ! ( feature = "openssl" ) {
183
232
if cfg ! ( feature = "openssl-vendored" ) {
184
233
config. register_dep ( "openssl" ) ;
185
234
}
186
235
} else {
236
+ #[ cfg( feature = "boringssl" ) ]
187
237
build_boringssl ( & mut config) ;
188
238
}
189
239
if cfg ! ( feature = "no-omit-frame-pointer" ) {
@@ -193,7 +243,10 @@ fn build_grpc(cc: &mut cc::Build, library: &str) {
193
243
}
194
244
// Uses zlib from libz-sys.
195
245
setup_libz ( & mut config) ;
196
- config. build_target ( library) . uses_cxx11 ( ) . build ( )
246
+ if !cfg ! ( feature = "_list-package" ) {
247
+ config. build_target ( library) ;
248
+ }
249
+ config. uses_cxx11 ( ) . build ( )
197
250
} ;
198
251
199
252
let lib_suffix = if target. contains ( "msvc" ) {
@@ -212,6 +265,10 @@ fn build_grpc(cc: &mut cc::Build, library: &str) {
212
265
}
213
266
}
214
267
268
+ if cfg ! ( feature = "_list-package" ) {
269
+ list_packages ( & dst) ;
270
+ }
271
+
215
272
let libs = if library. contains ( "unsecure" ) {
216
273
GRPC_UNSECURE_DEPS
217
274
} else {
@@ -221,7 +278,7 @@ fn build_grpc(cc: &mut cc::Build, library: &str) {
221
278
println ! ( "cargo:rustc-link-lib=static={}" , l) ;
222
279
}
223
280
224
- if cfg ! ( feature = "secure " ) {
281
+ if cfg ! ( feature = "_secure " ) {
225
282
if cfg ! ( feature = "openssl" ) && !cfg ! ( feature = "openssl-vendored" ) {
226
283
figure_ssl_path ( & build_dir) ;
227
284
} else {
@@ -260,7 +317,7 @@ fn figure_ssl_path(build_dir: &str) {
260
317
println ! ( "cargo:rustc-link-lib=crypto" ) ;
261
318
}
262
319
263
- #[ cfg( feature = "secure " ) ]
320
+ #[ cfg( feature = "boringssl " ) ]
264
321
fn build_boringssl ( config : & mut CmakeConfig ) {
265
322
let boringssl_artifact = boringssl_src:: Build :: new ( ) . build ( ) ;
266
323
config. define (
@@ -304,11 +361,17 @@ fn get_env(name: &str) -> Option<String> {
304
361
305
362
// Generate the bindings to grpc C-core.
306
363
// Try to disable the generation of platform-related bindings.
307
- #[ cfg( feature = "use-bindgen" ) ]
364
+ #[ cfg( any(
365
+ feature = "_gen-bindings" ,
366
+ not( all(
367
+ any( target_os = "linux" , target_os = "macos" ) ,
368
+ any( target_arch = "x86_64" , target_arch = "aarch64" )
369
+ ) )
370
+ ) ) ]
308
371
fn bindgen_grpc ( file_path : & Path ) {
309
372
// create a config to generate binding file
310
373
let mut config = bindgen:: Builder :: default ( ) ;
311
- if cfg ! ( feature = "secure " ) {
374
+ if cfg ! ( feature = "_secure " ) {
312
375
config = config. clang_arg ( "-DGRPC_SYS_SECURE" ) ;
313
376
}
314
377
@@ -350,22 +413,23 @@ fn bindgen_grpc(file_path: &Path) {
350
413
. impl_debug ( true )
351
414
. size_t_is_usize ( true )
352
415
. disable_header_comment ( )
353
- . whitelist_function ( r"\bgrpc_.*" )
354
- . whitelist_function ( r"\bgpr_.*" )
355
- . whitelist_function ( r"\bgrpcwrap_.*" )
356
- . whitelist_var ( r"\bGRPC_.*" )
357
- . whitelist_type ( r"\bgrpc_.*" )
358
- . whitelist_type ( r"\bgpr_.*" )
359
- . whitelist_type ( r"\bgrpcwrap_.*" )
360
- . whitelist_type ( r"\bcensus_context.*" )
361
- . whitelist_type ( r"\bverify_peer_options.*" )
362
- . blacklist_type ( r"(__)?pthread.*" )
363
- . blacklist_function ( r"\bgpr_mu_.*" )
364
- . blacklist_function ( r"\bgpr_cv_.*" )
365
- . blacklist_function ( r"\bgpr_once_.*" )
366
- . blacklist_type ( r"gpr_mu" )
367
- . blacklist_type ( r"gpr_cv" )
368
- . blacklist_type ( r"gpr_once" )
416
+ . allowlist_function ( r"\bgrpc_.*" )
417
+ . allowlist_function ( r"\bgpr_.*" )
418
+ . allowlist_function ( r"\bgrpcwrap_.*" )
419
+ . allowlist_var ( r"\bGRPC_.*" )
420
+ . allowlist_type ( r"\bgrpc_.*" )
421
+ . allowlist_type ( r"\bgpr_.*" )
422
+ . allowlist_type ( r"\bgrpcwrap_.*" )
423
+ . allowlist_type ( r"\bcensus_context.*" )
424
+ . allowlist_type ( r"\bverify_peer_options.*" )
425
+ // Block all system headers.
426
+ . blocklist_file ( r"^/.*" )
427
+ . blocklist_function ( r"\bgpr_mu_.*" )
428
+ . blocklist_function ( r"\bgpr_cv_.*" )
429
+ . blocklist_function ( r"\bgpr_once_.*" )
430
+ . blocklist_type ( r"gpr_mu" )
431
+ . blocklist_type ( r"gpr_cv" )
432
+ . blocklist_type ( r"gpr_once" )
369
433
. constified_enum_module ( r"grpc_status_code" )
370
434
. layout_tests ( gen_tests)
371
435
. default_enum_style ( bindgen:: EnumVariation :: Rust {
@@ -379,38 +443,47 @@ fn bindgen_grpc(file_path: &Path) {
379
443
}
380
444
381
445
// Determine if need to update bindings. Supported platforms do not
382
- // need to be updated by default unless the UPDATE_BIND is specified.
446
+ // need to be updated by default unless the _gen-bindings feature is specified.
383
447
// Other platforms use bindgen to generate the bindings every time.
384
448
fn config_binding_path ( ) {
385
449
let target = env:: var ( "TARGET" ) . unwrap ( ) ;
386
450
let file_path: PathBuf = match target. as_str ( ) {
387
- "x86_64-unknown-linux-gnu" | "aarch64-unknown-linux-gnu" => {
451
+ "x86_64-unknown-linux-gnu"
452
+ | "aarch64-unknown-linux-gnu"
453
+ | "x86_64-apple-darwin"
454
+ | "aarch64-apple-darwin" => {
388
455
// Cargo treats nonexistent files changed, so we only emit the rerun-if-changed
389
456
// directive when we expect the target-specific pre-generated binding file to be
390
457
// present.
391
- println ! ( "cargo:rerun-if-changed=bindings/{}- bindings.rs" , & target ) ;
458
+ println ! ( "cargo:rerun-if-changed=bindings/bindings.rs" ) ;
392
459
393
- let file_path = PathBuf :: from ( env:: var ( "CARGO_MANIFEST_DIR" ) . unwrap ( ) )
460
+ PathBuf :: from ( env:: var ( "CARGO_MANIFEST_DIR" ) . unwrap ( ) )
394
461
. join ( "bindings" )
395
- . join ( format ! ( "{}-bindings.rs" , & target) ) ;
396
-
397
- #[ cfg( feature = "use-bindgen" ) ]
398
- if env:: var ( "UPDATE_BIND" ) . is_ok ( ) {
399
- bindgen_grpc ( & file_path) ;
400
- }
401
-
402
- file_path
403
- }
404
- _ => {
405
- let file_path = PathBuf :: from ( env:: var ( "OUT_DIR" ) . unwrap ( ) ) . join ( "grpc-bindings.rs" ) ;
406
-
407
- #[ cfg( feature = "use-bindgen" ) ]
408
- bindgen_grpc ( & file_path) ;
409
-
410
- file_path
462
+ . join ( "bindings.rs" )
411
463
}
464
+ _ => PathBuf :: from ( env:: var ( "OUT_DIR" ) . unwrap ( ) ) . join ( "grpc-bindings.rs" ) ,
412
465
} ;
413
466
467
+ #[ cfg( any(
468
+ feature = "_gen-bindings" ,
469
+ not( all(
470
+ any( target_os = "linux" , target_os = "macos" ) ,
471
+ any( target_arch = "x86_64" , target_arch = "aarch64" )
472
+ ) )
473
+ ) ) ]
474
+ {
475
+ // On some system (like Windows), stack size of main thread may
476
+ // be too small.
477
+ let f = file_path. clone ( ) ;
478
+ std:: thread:: Builder :: new ( )
479
+ . stack_size ( 8 * 1024 * 1024 )
480
+ . name ( "bindgen_grpc" . to_string ( ) )
481
+ . spawn ( move || bindgen_grpc ( & f) )
482
+ . unwrap ( )
483
+ . join ( )
484
+ . unwrap ( ) ;
485
+ }
486
+
414
487
println ! (
415
488
"cargo:rustc-env=BINDING_PATH={}" ,
416
489
file_path. to_str( ) . unwrap( )
@@ -420,12 +493,11 @@ fn config_binding_path() {
420
493
fn main ( ) {
421
494
println ! ( "cargo:rerun-if-changed=grpc_wrap.cc" ) ;
422
495
println ! ( "cargo:rerun-if-changed=grpc" ) ;
423
- println ! ( "cargo:rerun-if-env-changed=UPDATE_BIND" ) ;
424
496
425
497
// create a builder to compile grpc_wrap.cc
426
498
let mut cc = cc:: Build :: new ( ) ;
427
499
428
- let library = if cfg ! ( feature = "secure " ) {
500
+ let library = if cfg ! ( feature = "_secure " ) {
429
501
cc. define ( "GRPC_SYS_SECURE" , None ) ;
430
502
"grpc"
431
503
} else {
0 commit comments