@@ -60,44 +60,47 @@ impl Build {
6060 self
6161 }
6262
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+ )
7577 }
7678
7779 #[ cfg( windows) ]
7880 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| {
8082 if s == "1" {
8183 // a message to stdout, let user know asm is force enabled
8284 println ! (
83- "{}: nasm.exe is force enabled by the \
85+ "cargo:warning= {}: nasm.exe is force enabled by the \
8486 'OPENSSL_RUST_USE_NASM' env var.",
8587 env!( "CARGO_PKG_NAME" )
8688 ) ;
87- true
89+ Some ( true )
8890 } else if s == "0" {
8991 // a message to stdout, let user know asm is force disabled
9092 println ! (
91- "{}: nasm.exe is force disabled by the \
93+ "cargo:warning= {}: nasm.exe is force disabled by the \
9294 'OPENSSL_RUST_USE_NASM' env var.",
9395 env!( "CARGO_PKG_NAME" )
9496 ) ;
95- false
97+ Some ( false )
9698 } 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: {:?}" ,
99101 var_name, s
100102 ) ;
103+ None
101104 }
102105 } )
103106 }
@@ -107,11 +110,11 @@ impl Build {
107110 self . check_env_var ( "OPENSSL_RUST_USE_NASM" )
108111 . unwrap_or_else ( || {
109112 // On Windows, use cmd `where` command to check if nasm is installed
110- let wherenasm = Command :: new ( "cmd" )
113+ Command :: new ( "cmd" )
111114 . args ( & [ "/C" , "where nasm" ] )
112115 . output ( )
113- . expect ( "Failed to execute `cmd`." ) ;
114- wherenasm . status . success ( )
116+ . map ( |w| w . status . success ( ) )
117+ . unwrap_or ( false )
115118 } )
116119 }
117120
@@ -121,23 +124,35 @@ impl Build {
121124 false
122125 }
123126
127+ /// Exits the process on failure. Use `try_build` to handle the error.
124128 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" ) ?;
128143 let build_dir = out_dir. join ( "build" ) ;
129144 let install_dir = out_dir. join ( "install" ) ;
130145
131146 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}" ) ) ? ;
133148 }
134149 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}" ) ) ? ;
136151 }
137152
138153 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) ? ;
141156
142157 let perl_program =
143158 env:: var ( "OPENSSL_SRC_PERL" ) . unwrap_or ( env:: var ( "PERL" ) . unwrap_or ( "perl" . to_string ( ) ) ) ;
@@ -154,7 +169,10 @@ impl Build {
154169 // native and cross builds.
155170 configure. arg ( & format ! (
156171 "--prefix={}" ,
157- install_dir. to_str( ) . unwrap( ) . replace( "\\ " , "/" )
172+ install_dir
173+ . to_str( )
174+ . ok_or( "bad install_dir" ) ?
175+ . replace( "\\ " , "/" )
158176 ) ) ;
159177 } else {
160178 configure. arg ( & format ! ( "--prefix={}" , install_dir. display( ) ) ) ;
@@ -170,7 +188,7 @@ impl Build {
170188 let openssl_dir = self
171189 . openssl_dir
172190 . as_ref ( )
173- . expect ( "path to the openssl directory must be set" ) ;
191+ . ok_or ( "path to the openssl directory must be set" ) ? ;
174192 let mut dir_arg: OsString = "--openssldir=" . into ( ) ;
175193 dir_arg. push ( openssl_dir) ;
176194 configure. arg ( dir_arg) ;
@@ -391,7 +409,12 @@ impl Build {
391409 "aarch64-unknown-linux-ohos" => "linux-aarch64" ,
392410 "armv7-unknown-linux-ohos" => "linux-generic32" ,
393411 "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+ }
395418 } ;
396419
397420 let mut ios_isysroot: std:: option:: Option < String > = None ;
@@ -410,7 +433,7 @@ impl Build {
410433 cc_env = compiler. path ( ) . to_path_buf ( ) . into_os_string ( ) ;
411434 }
412435 configure. env ( "CC" , cc_env) ;
413- let path = compiler. path ( ) . to_str ( ) . unwrap ( ) ;
436+ let path = compiler. path ( ) . to_str ( ) . ok_or ( "compiler path" ) ? ;
414437
415438 // Both `cc::Build` and `./Configure` take into account
416439 // `CROSS_COMPILE` environment variable. So to avoid double
@@ -464,7 +487,7 @@ impl Build {
464487
465488 if is_isysroot {
466489 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 ( ) ) ;
468491 continue ;
469492 }
470493 }
@@ -574,26 +597,26 @@ impl Build {
574597
575598 // And finally, run the perl configure script!
576599 configure. current_dir ( & inner_dir) ;
577- self . run_command ( configure, "configuring OpenSSL build" ) ;
600+ self . run_command ( configure, "configuring OpenSSL build" ) ? ;
578601
579602 // On MSVC we use `nmake.exe` with a slightly different invocation, so
580603 // have that take a different path than the standard `make` below.
581604 if target. contains ( "msvc" ) {
582605 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" ) ? ;
584607 build. arg ( "build_libs" ) . current_dir ( & inner_dir) ;
585- self . run_command ( build, "building OpenSSL" ) ;
608+ self . run_command ( build, "building OpenSSL" ) ? ;
586609
587610 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" ) ? ;
589612 install. arg ( "install_dev" ) . current_dir ( & inner_dir) ;
590- self . run_command ( install, "installing OpenSSL" ) ;
613+ self . run_command ( install, "installing OpenSSL" ) ? ;
591614 } else {
592- let mut depend = self . cmd_make ( ) ;
615+ let mut depend = self . cmd_make ( ) ? ;
593616 depend. arg ( "depend" ) . current_dir ( & inner_dir) ;
594- self . run_command ( depend, "building OpenSSL dependencies" ) ;
617+ self . run_command ( depend, "building OpenSSL dependencies" ) ? ;
595618
596- let mut build = self . cmd_make ( ) ;
619+ let mut build = self . cmd_make ( ) ? ;
597620 build. arg ( "build_libs" ) . current_dir ( & inner_dir) ;
598621 if !cfg ! ( windows) {
599622 if let Some ( s) = env:: var_os ( "CARGO_MAKEFLAGS" ) {
@@ -607,11 +630,11 @@ impl Build {
607630 build. env ( "CROSS_SDK" , components[ 1 ] ) ;
608631 }
609632
610- self . run_command ( build, "building OpenSSL" ) ;
633+ self . run_command ( build, "building OpenSSL" ) ? ;
611634
612- let mut install = self . cmd_make ( ) ;
635+ let mut install = self . cmd_make ( ) ? ;
613636 install. arg ( "install_dev" ) . current_dir ( & inner_dir) ;
614- self . run_command ( install, "installing OpenSSL" ) ;
637+ self . run_command ( install, "installing OpenSSL" ) ? ;
615638 }
616639
617640 let libs = if target. contains ( "msvc" ) {
@@ -620,46 +643,58 @@ impl Build {
620643 vec ! [ "ssl" . to_string( ) , "crypto" . to_string( ) ]
621644 } ;
622645
623- fs:: remove_dir_all ( & inner_dir) . unwrap ( ) ;
646+ fs:: remove_dir_all ( & inner_dir) . map_err ( |e| format ! ( "{}: {e}" , inner_dir . display ( ) ) ) ? ;
624647
625- Artifacts {
648+ Ok ( Artifacts {
626649 lib_dir : install_dir. join ( "lib" ) ,
627650 bin_dir : install_dir. join ( "bin" ) ,
628651 include_dir : install_dir. join ( "include" ) ,
629652 libs : libs,
630653 target : target. to_string ( ) ,
631- }
654+ } )
632655 }
633656
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 > {
635659 println ! ( "running {:?}" , command) ;
636660 let status = command. status ( ) ;
637661
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+ } ,
642678 } ;
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+ ) )
655685 }
656686}
657687
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+ } ;
661694 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( ) ) ) ?;
663698
664699 // Skip git metadata as it's been known to cause issues (#26) and
665700 // otherwise shouldn't be required
@@ -668,27 +703,32 @@ fn cp_r(src: &Path, dst: &Path) {
668703 }
669704
670705 let dst = dst. join ( name) ;
671- let ty = f. file_type ( ) . unwrap ( ) ;
706+ let ty = f. file_type ( ) . map_err ( |e| e . to_string ( ) ) ? ;
672707 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) ? ;
675710 } else if ty. is_symlink ( ) && path. iter ( ) . any ( |p| p == "cloudflare-quiche" ) {
676711 // not needed to build
677712 continue ;
678713 } else {
679714 let _ = fs:: remove_file ( & dst) ;
680715 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+ ) ) ;
682721 }
683722 }
684723 }
724+ Ok ( ( ) )
685725}
686726
687727fn sanitize_sh ( path : & Path ) -> String {
688728 if !cfg ! ( windows) {
689- return path. to_str ( ) . unwrap ( ) . to_string ( ) ;
729+ return path. to_string_lossy ( ) . into_owned ( ) ;
690730 }
691- let path = path. to_str ( ) . unwrap ( ) . replace ( "\\ " , "/" ) ;
731+ let path = path. to_string_lossy ( ) . replace ( "\\ " , "/" ) ;
692732 return change_drive ( & path) . unwrap_or ( path) ;
693733
694734 fn change_drive ( s : & str ) -> Option < String > {
0 commit comments