11//! Execute make of OpenBLAS, and its options
22
33use crate :: { check:: * , error:: * } ;
4- use std:: { fs, path:: * , process:: Command , str:: FromStr } ;
4+ use std:: { env , fs, path:: * , process:: Command , str:: FromStr } ;
55use walkdir:: WalkDir ;
66
77/// Interface for 32-bit interger (LP64) and 64-bit integer (ILP64)
@@ -303,6 +303,14 @@ impl FromStr for Target {
303303 }
304304}
305305
306+ #[ derive( Default , Debug , Clone , PartialEq , Eq , Hash ) ]
307+ pub struct Compilers {
308+ pub cc : Option < String > ,
309+ pub fc : Option < String > ,
310+ pub hostcc : Option < String > ,
311+ pub ranlib : Option < String > ,
312+ }
313+
306314/// make option generator
307315#[ derive( Debug , Clone , PartialEq , Eq , Hash ) ]
308316pub struct Configure {
@@ -316,6 +324,7 @@ pub struct Configure {
316324 pub dynamic_arch : bool ,
317325 pub interface : Interface ,
318326 pub target : Option < Target > ,
327+ pub compilers : Compilers ,
319328}
320329
321330impl Default for Configure {
@@ -331,45 +340,18 @@ impl Default for Configure {
331340 dynamic_arch : false ,
332341 interface : Interface :: LP64 ,
333342 target : None ,
343+ compilers : Compilers :: default ( ) ,
334344 }
335345 }
336346}
337347
338348/// Deliverables of `make` command
339349pub struct Deliverables {
340- /// None if `no_static`
341- pub static_lib : Option < LibInspect > ,
342- /// None if `no_shared`
343- pub shared_lib : Option < LibInspect > ,
344350 /// Inspection what `make` command really show.
345351 pub make_conf : MakeConf ,
346352}
347353
348354impl Configure {
349- fn cross_compile_args ( & self ) -> Result < Vec < String > , Error > {
350- let mut args = Vec :: new ( ) ;
351- for name in [ "CC" , "FC" , "HOSTCC" ] {
352- if let Ok ( value) = std:: env:: var ( format ! ( "OPENBLAS_{}" , name) ) {
353- args. push ( format ! ( "{}={}" , name, value) ) ;
354- eprintln ! ( "{}={}" , name, value) ;
355- } else {
356- eprintln ! ( "not found {}" , name) ;
357- }
358- }
359- // for successful compile all 3 env-vars must be set
360- if !args. is_empty ( ) && args. len ( ) != 3 {
361- return Err ( Error :: MissingCrossCompileInfo ) ;
362- }
363- // optional flags
364- for name in [ "RANLIB" ] {
365- if let Ok ( value) = std:: env:: var ( format ! ( "OPENBLAS_{}" , name) ) {
366- args. push ( format ! ( "{}={}" , name, value) ) ;
367- eprintln ! ( "{}={}" , name, value) ;
368- }
369- }
370- Ok ( args)
371- }
372-
373355 fn make_args ( & self ) -> Vec < String > {
374356 let mut args = Vec :: new ( ) ;
375357 if self . no_static {
@@ -399,13 +381,18 @@ impl Configure {
399381 if let Some ( target) = self . target . as_ref ( ) {
400382 args. push ( format ! ( "TARGET={:?}" , target) )
401383 }
402-
403- for name in [ "CC" , "FC" , "HOSTCC" ] {
404- if let Ok ( value) = std:: env:: var ( format ! ( "OPENBLAS_{}" , name) ) {
405- args. push ( format ! ( "{}={}" , name, value) ) ;
406- }
384+ if let Some ( compiler_cc) = self . compilers . cc . as_ref ( ) {
385+ args. push ( format ! ( "CC={}" , compiler_cc) )
386+ }
387+ if let Some ( compiler_fc) = self . compilers . fc . as_ref ( ) {
388+ args. push ( format ! ( "FC={}" , compiler_fc) )
389+ }
390+ if let Some ( compiler_hostcc) = self . compilers . hostcc . as_ref ( ) {
391+ args. push ( format ! ( "HOSTCC={}" , compiler_hostcc) )
392+ }
393+ if let Some ( compiler_ranlib) = self . compilers . ranlib . as_ref ( ) {
394+ args. push ( format ! ( "RANLIB={}" , compiler_ranlib) )
407395 }
408-
409396 args
410397 }
411398
@@ -420,28 +407,24 @@ impl Configure {
420407 pub fn inspect ( & self , out_dir : impl AsRef < Path > ) -> Result < Deliverables , Error > {
421408 let out_dir = out_dir. as_ref ( ) ;
422409 let make_conf = MakeConf :: new ( out_dir. join ( "Makefile.conf" ) ) ?;
423-
424- if !self . no_lapack && make_conf. no_fortran {
425- return Err ( Error :: FortranCompilerNotFound ) ;
410+ if !self . no_static {
411+ let lib_path = out_dir. join ( "libopenblas.a" ) ;
412+ if !lib_path. exists ( ) {
413+ return Err ( Error :: LibraryNotExist { path : lib_path } ) ;
414+ }
426415 }
427-
428- Ok ( Deliverables {
429- static_lib : if !self . no_static {
430- Some ( LibInspect :: new ( out_dir. join ( "libopenblas.a" ) ) ?)
431- } else {
432- None
433- } ,
434- shared_lib : if !self . no_shared {
435- Some ( LibInspect :: new ( if cfg ! ( target_os = "macos" ) {
436- out_dir. join ( "libopenblas.dylib" )
437- } else {
438- out_dir. join ( "libopenblas.so" )
439- } ) ?)
416+ if !self . no_shared {
417+ let lib_path = if cfg ! ( target_os = "macos" ) {
418+ out_dir. join ( "libopenblas.dylib" )
440419 } else {
441- None
442- } ,
443- make_conf,
444- } )
420+ out_dir. join ( "libopenblas.so" )
421+ } ;
422+ if !lib_path. exists ( ) {
423+ return Err ( Error :: LibraryNotExist { path : lib_path } ) ;
424+ }
425+ }
426+
427+ Ok ( Deliverables { make_conf } )
445428 }
446429
447430 /// Build OpenBLAS
@@ -492,6 +475,14 @@ impl Configure {
492475 }
493476 }
494477
478+ // check if cross compile is needed
479+ let build_target = env:: var ( "TARGET" ) . unwrap_or_default ( ) ;
480+ let build_host = env:: var ( "HOST" ) . unwrap_or_default ( ) ;
481+ let is_cross_compile = build_target != build_host;
482+ if is_cross_compile && ( self . compilers . cc . is_none ( ) || self . compilers . hostcc . is_none ( ) ) {
483+ return Err ( Error :: MissingCrossCompileInfo ) ;
484+ }
485+
495486 // Run `make` as an subprocess
496487 //
497488 // - This will automatically run in parallel without `-j` flag
@@ -507,7 +498,6 @@ impl Configure {
507498 . stdout ( out)
508499 . stderr ( err)
509500 . args ( self . make_args ( ) )
510- . args ( self . cross_compile_args ( ) ?)
511501 . args ( [ "all" ] )
512502 . env_remove ( "TARGET" )
513503 . check_call ( )
@@ -524,7 +514,6 @@ impl Configure {
524514 return Err ( e) ;
525515 }
526516 }
527-
528517 self . inspect ( out_dir)
529518 }
530519}
0 commit comments