@@ -60,44 +60,47 @@ impl Build {
60
60
self
61
61
}
62
62
63
- fn cmd_make ( & self ) -> Command {
64
- let host = & self . host . as_ref ( ) . expect ( "HOST dir not set" ) [ ..] ;
65
- if host. contains ( "dragonfly" )
66
- || host. contains ( "freebsd" )
67
- || host. contains ( "openbsd" )
68
- || host. contains ( "solaris" )
69
- || host. contains ( "illumos" )
70
- {
71
- Command :: new ( "gmake" )
72
- } else {
73
- Command :: new ( "make" )
74
- }
63
+ fn cmd_make ( & self ) -> Result < Command , & ' static str > {
64
+ let host = & self . host . as_ref ( ) . ok_or ( "HOST dir not set" ) ?[ ..] ;
65
+ Ok (
66
+ if host. contains ( "dragonfly" )
67
+ || host. contains ( "freebsd" )
68
+ || host. contains ( "openbsd" )
69
+ || host. contains ( "solaris" )
70
+ || host. contains ( "illumos" )
71
+ {
72
+ Command :: new ( "gmake" )
73
+ } else {
74
+ Command :: new ( "make" )
75
+ } ,
76
+ )
75
77
}
76
78
77
79
#[ cfg( windows) ]
78
80
fn check_env_var ( & self , var_name : & str ) -> Option < bool > {
79
- env:: var_os ( var_name) . map ( |s| {
81
+ env:: var_os ( var_name) . and_then ( |s| {
80
82
if s == "1" {
81
83
// a message to stdout, let user know asm is force enabled
82
84
println ! (
83
- "{}: nasm.exe is force enabled by the \
85
+ "cargo:warning= {}: nasm.exe is force enabled by the \
84
86
'OPENSSL_RUST_USE_NASM' env var.",
85
87
env!( "CARGO_PKG_NAME" )
86
88
) ;
87
- true
89
+ Some ( true )
88
90
} else if s == "0" {
89
91
// a message to stdout, let user know asm is force disabled
90
92
println ! (
91
- "{}: nasm.exe is force disabled by the \
93
+ "cargo:warning= {}: nasm.exe is force disabled by the \
92
94
'OPENSSL_RUST_USE_NASM' env var.",
93
95
env!( "CARGO_PKG_NAME" )
94
96
) ;
95
- false
97
+ Some ( false )
96
98
} else {
97
- panic ! (
98
- "The environment variable {} is set to an unacceptable value: {:?}" ,
99
+ println ! (
100
+ "cargo:warning= The environment variable {} is set to an unacceptable value: {:?}" ,
99
101
var_name, s
100
102
) ;
103
+ None
101
104
}
102
105
} )
103
106
}
@@ -107,11 +110,11 @@ impl Build {
107
110
self . check_env_var ( "OPENSSL_RUST_USE_NASM" )
108
111
. unwrap_or_else ( || {
109
112
// On Windows, use cmd `where` command to check if nasm is installed
110
- let wherenasm = Command :: new ( "cmd" )
113
+ Command :: new ( "cmd" )
111
114
. args ( & [ "/C" , "where nasm" ] )
112
115
. output ( )
113
- . expect ( "Failed to execute `cmd`." ) ;
114
- wherenasm . status . success ( )
116
+ . map ( |w| w . status . success ( ) )
117
+ . unwrap_or ( false )
115
118
} )
116
119
}
117
120
@@ -121,23 +124,35 @@ impl Build {
121
124
false
122
125
}
123
126
127
+ /// Exits the process on failure. Use `try_build` to handle the error.
124
128
pub fn build ( & mut self ) -> Artifacts {
125
- let target = & self . target . as_ref ( ) . expect ( "TARGET dir not set" ) [ ..] ;
126
- let host = & self . host . as_ref ( ) . expect ( "HOST dir not set" ) [ ..] ;
127
- let out_dir = self . out_dir . as_ref ( ) . expect ( "OUT_DIR not set" ) ;
129
+ match self . try_build ( ) {
130
+ Ok ( a) => a,
131
+ Err ( e) => {
132
+ println ! ( "cargo:warning=openssl-src: failed to build OpenSSL from source" ) ;
133
+ eprintln ! ( "\n \n \n {e}\n \n \n " ) ;
134
+ std:: process:: exit ( 1 ) ;
135
+ }
136
+ }
137
+ }
138
+
139
+ pub fn try_build ( & mut self ) -> Result < Artifacts , String > {
140
+ let target = & self . target . as_ref ( ) . ok_or ( "TARGET dir not set" ) ?[ ..] ;
141
+ let host = & self . host . as_ref ( ) . ok_or ( "HOST dir not set" ) ?[ ..] ;
142
+ let out_dir = self . out_dir . as_ref ( ) . ok_or ( "OUT_DIR not set" ) ?;
128
143
let build_dir = out_dir. join ( "build" ) ;
129
144
let install_dir = out_dir. join ( "install" ) ;
130
145
131
146
if build_dir. exists ( ) {
132
- fs:: remove_dir_all ( & build_dir) . unwrap ( ) ;
147
+ fs:: remove_dir_all ( & build_dir) . map_err ( |e| format ! ( "build_dir: {e}" ) ) ? ;
133
148
}
134
149
if install_dir. exists ( ) {
135
- fs:: remove_dir_all ( & install_dir) . unwrap ( ) ;
150
+ fs:: remove_dir_all ( & install_dir) . map_err ( |e| format ! ( "install_dir: {e}" ) ) ? ;
136
151
}
137
152
138
153
let inner_dir = build_dir. join ( "src" ) ;
139
- fs:: create_dir_all ( & inner_dir) . unwrap ( ) ;
140
- cp_r ( & source_dir ( ) , & inner_dir) ;
154
+ fs:: create_dir_all ( & inner_dir) . map_err ( |e| format ! ( "{}: {e}" , inner_dir . display ( ) ) ) ? ;
155
+ cp_r ( & source_dir ( ) , & inner_dir) ? ;
141
156
142
157
let perl_program =
143
158
env:: var ( "OPENSSL_SRC_PERL" ) . unwrap_or ( env:: var ( "PERL" ) . unwrap_or ( "perl" . to_string ( ) ) ) ;
@@ -154,7 +169,10 @@ impl Build {
154
169
// native and cross builds.
155
170
configure. arg ( & format ! (
156
171
"--prefix={}" ,
157
- install_dir. to_str( ) . unwrap( ) . replace( "\\ " , "/" )
172
+ install_dir
173
+ . to_str( )
174
+ . ok_or( "bad install_dir" ) ?
175
+ . replace( "\\ " , "/" )
158
176
) ) ;
159
177
} else {
160
178
configure. arg ( & format ! ( "--prefix={}" , install_dir. display( ) ) ) ;
@@ -170,7 +188,7 @@ impl Build {
170
188
let openssl_dir = self
171
189
. openssl_dir
172
190
. as_ref ( )
173
- . expect ( "path to the openssl directory must be set" ) ;
191
+ . ok_or ( "path to the openssl directory must be set" ) ? ;
174
192
let mut dir_arg: OsString = "--openssldir=" . into ( ) ;
175
193
dir_arg. push ( openssl_dir) ;
176
194
configure. arg ( dir_arg) ;
@@ -391,7 +409,12 @@ impl Build {
391
409
"aarch64-unknown-linux-ohos" => "linux-aarch64" ,
392
410
"armv7-unknown-linux-ohos" => "linux-generic32" ,
393
411
"x86_64-unknown-linux-ohos" => "linux-x86_64" ,
394
- _ => panic ! ( "don't know how to configure OpenSSL for {}" , target) ,
412
+ _ => {
413
+ return Err ( format ! (
414
+ "don't know how to configure OpenSSL for {}" ,
415
+ target
416
+ ) )
417
+ }
395
418
} ;
396
419
397
420
let mut ios_isysroot: std:: option:: Option < String > = None ;
@@ -410,7 +433,7 @@ impl Build {
410
433
cc_env = compiler. path ( ) . to_path_buf ( ) . into_os_string ( ) ;
411
434
}
412
435
configure. env ( "CC" , cc_env) ;
413
- let path = compiler. path ( ) . to_str ( ) . unwrap ( ) ;
436
+ let path = compiler. path ( ) . to_str ( ) . ok_or ( "compiler path" ) ? ;
414
437
415
438
// Both `cc::Build` and `./Configure` take into account
416
439
// `CROSS_COMPILE` environment variable. So to avoid double
@@ -464,7 +487,7 @@ impl Build {
464
487
465
488
if is_isysroot {
466
489
is_isysroot = false ;
467
- ios_isysroot = Some ( arg. to_str ( ) . unwrap ( ) . to_string ( ) ) ;
490
+ ios_isysroot = Some ( arg. to_str ( ) . ok_or ( "isysroot arg" ) ? . to_string ( ) ) ;
468
491
continue ;
469
492
}
470
493
}
@@ -574,26 +597,26 @@ impl Build {
574
597
575
598
// And finally, run the perl configure script!
576
599
configure. current_dir ( & inner_dir) ;
577
- self . run_command ( configure, "configuring OpenSSL build" ) ;
600
+ self . run_command ( configure, "configuring OpenSSL build" ) ? ;
578
601
579
602
// On MSVC we use `nmake.exe` with a slightly different invocation, so
580
603
// have that take a different path than the standard `make` below.
581
604
if target. contains ( "msvc" ) {
582
605
let mut build =
583
- cc:: windows_registry:: find ( target, "nmake.exe" ) . expect ( "failed to find nmake" ) ;
606
+ cc:: windows_registry:: find ( target, "nmake.exe" ) . ok_or ( "failed to find nmake" ) ? ;
584
607
build. arg ( "build_libs" ) . current_dir ( & inner_dir) ;
585
- self . run_command ( build, "building OpenSSL" ) ;
608
+ self . run_command ( build, "building OpenSSL" ) ? ;
586
609
587
610
let mut install =
588
- cc:: windows_registry:: find ( target, "nmake.exe" ) . expect ( "failed to find nmake" ) ;
611
+ cc:: windows_registry:: find ( target, "nmake.exe" ) . ok_or ( "failed to find nmake" ) ? ;
589
612
install. arg ( "install_dev" ) . current_dir ( & inner_dir) ;
590
- self . run_command ( install, "installing OpenSSL" ) ;
613
+ self . run_command ( install, "installing OpenSSL" ) ? ;
591
614
} else {
592
- let mut depend = self . cmd_make ( ) ;
615
+ let mut depend = self . cmd_make ( ) ? ;
593
616
depend. arg ( "depend" ) . current_dir ( & inner_dir) ;
594
- self . run_command ( depend, "building OpenSSL dependencies" ) ;
617
+ self . run_command ( depend, "building OpenSSL dependencies" ) ? ;
595
618
596
- let mut build = self . cmd_make ( ) ;
619
+ let mut build = self . cmd_make ( ) ? ;
597
620
build. arg ( "build_libs" ) . current_dir ( & inner_dir) ;
598
621
if !cfg ! ( windows) {
599
622
if let Some ( s) = env:: var_os ( "CARGO_MAKEFLAGS" ) {
@@ -607,11 +630,11 @@ impl Build {
607
630
build. env ( "CROSS_SDK" , components[ 1 ] ) ;
608
631
}
609
632
610
- self . run_command ( build, "building OpenSSL" ) ;
633
+ self . run_command ( build, "building OpenSSL" ) ? ;
611
634
612
- let mut install = self . cmd_make ( ) ;
635
+ let mut install = self . cmd_make ( ) ? ;
613
636
install. arg ( "install_dev" ) . current_dir ( & inner_dir) ;
614
- self . run_command ( install, "installing OpenSSL" ) ;
637
+ self . run_command ( install, "installing OpenSSL" ) ? ;
615
638
}
616
639
617
640
let libs = if target. contains ( "msvc" ) {
@@ -620,46 +643,58 @@ impl Build {
620
643
vec ! [ "ssl" . to_string( ) , "crypto" . to_string( ) ]
621
644
} ;
622
645
623
- fs:: remove_dir_all ( & inner_dir) . unwrap ( ) ;
646
+ fs:: remove_dir_all ( & inner_dir) . map_err ( |e| format ! ( "{}: {e}" , inner_dir . display ( ) ) ) ? ;
624
647
625
- Artifacts {
648
+ Ok ( Artifacts {
626
649
lib_dir : install_dir. join ( "lib" ) ,
627
650
bin_dir : install_dir. join ( "bin" ) ,
628
651
include_dir : install_dir. join ( "include" ) ,
629
652
libs : libs,
630
653
target : target. to_string ( ) ,
631
- }
654
+ } )
632
655
}
633
656
634
- fn run_command ( & self , mut command : Command , desc : & str ) {
657
+ #[ track_caller]
658
+ fn run_command ( & self , mut command : Command , desc : & str ) -> Result < ( ) , String > {
635
659
println ! ( "running {:?}" , command) ;
636
660
let status = command. status ( ) ;
637
661
638
- let ( status_or_failed, error) = match status {
639
- Ok ( status) if status. success ( ) => return ,
640
- Ok ( status) => ( "Exit status" , format ! ( "{}" , status) ) ,
641
- Err ( failed) => ( "Failed to execute" , format ! ( "{}" , failed) ) ,
662
+ let verbose_error = match status {
663
+ Ok ( status) if status. success ( ) => return Ok ( ( ) ) ,
664
+ Ok ( status) => format ! (
665
+ "'{exe}' reported failure with {status}" ,
666
+ exe = command. get_program( ) . to_string_lossy( )
667
+ ) ,
668
+ Err ( failed) => match failed. kind ( ) {
669
+ std:: io:: ErrorKind :: NotFound => format ! (
670
+ "Command '{exe}' not found. Is {exe} installed?" ,
671
+ exe = command. get_program( ) . to_string_lossy( )
672
+ ) ,
673
+ _ => format ! (
674
+ "Could not run '{exe}', because {failed}" ,
675
+ exe = command. get_program( ) . to_string_lossy( )
676
+ ) ,
677
+ } ,
642
678
} ;
643
- panic ! (
644
- "
645
-
646
-
647
- Error {}:
648
- Command: {:?}
649
- {}: {}
650
-
651
-
652
- " ,
653
- desc, command, status_or_failed, error
654
- ) ;
679
+ println ! ( "cargo:warning={desc}: {verbose_error}" ) ;
680
+ Err ( format ! (
681
+ "Error {desc}:
682
+ {verbose_error}
683
+ Command failed: {command:?}"
684
+ ) )
655
685
}
656
686
}
657
687
658
- fn cp_r ( src : & Path , dst : & Path ) {
659
- for f in fs:: read_dir ( src) . unwrap ( ) {
660
- let f = f. unwrap ( ) ;
688
+ fn cp_r ( src : & Path , dst : & Path ) -> Result < ( ) , String > {
689
+ for f in fs:: read_dir ( src) . map_err ( |e| format ! ( "{}: {e}" , src. display( ) ) ) ? {
690
+ let f = match f {
691
+ Ok ( f) => f,
692
+ _ => continue ,
693
+ } ;
661
694
let path = f. path ( ) ;
662
- let name = path. file_name ( ) . unwrap ( ) ;
695
+ let name = path
696
+ . file_name ( )
697
+ . ok_or_else ( || format ! ( "bad dir {}" , src. display( ) ) ) ?;
663
698
664
699
// Skip git metadata as it's been known to cause issues (#26) and
665
700
// otherwise shouldn't be required
@@ -668,27 +703,32 @@ fn cp_r(src: &Path, dst: &Path) {
668
703
}
669
704
670
705
let dst = dst. join ( name) ;
671
- let ty = f. file_type ( ) . unwrap ( ) ;
706
+ let ty = f. file_type ( ) . map_err ( |e| e . to_string ( ) ) ? ;
672
707
if ty. is_dir ( ) {
673
- fs:: create_dir_all ( & dst) . unwrap ( ) ;
674
- cp_r ( & path, & dst) ;
708
+ fs:: create_dir_all ( & dst) . map_err ( |e| e . to_string ( ) ) ? ;
709
+ cp_r ( & path, & dst) ? ;
675
710
} else if ty. is_symlink ( ) && path. iter ( ) . any ( |p| p == "cloudflare-quiche" ) {
676
711
// not needed to build
677
712
continue ;
678
713
} else {
679
714
let _ = fs:: remove_file ( & dst) ;
680
715
if let Err ( e) = fs:: copy ( & path, & dst) {
681
- panic ! ( "failed to copy {path:?} to {dst:?}: {e}" ) ;
716
+ return Err ( format ! (
717
+ "failed to copy '{}' to '{}': {e}" ,
718
+ path. display( ) ,
719
+ dst. display( )
720
+ ) ) ;
682
721
}
683
722
}
684
723
}
724
+ Ok ( ( ) )
685
725
}
686
726
687
727
fn sanitize_sh ( path : & Path ) -> String {
688
728
if !cfg ! ( windows) {
689
- return path. to_str ( ) . unwrap ( ) . to_string ( ) ;
729
+ return path. to_string_lossy ( ) . into_owned ( ) ;
690
730
}
691
- let path = path. to_str ( ) . unwrap ( ) . replace ( "\\ " , "/" ) ;
731
+ let path = path. to_string_lossy ( ) . replace ( "\\ " , "/" ) ;
692
732
return change_drive ( & path) . unwrap_or ( path) ;
693
733
694
734
fn change_drive ( s : & str ) -> Option < String > {
0 commit comments