@@ -14,6 +14,8 @@ pub enum Interface {
1414#[ derive( Debug , Clone , Copy , PartialEq , Eq , Hash ) ]
1515#[ allow( non_camel_case_types) ] // to use original identifiers
1616pub enum Target {
17+ // for DYNNAMIC_ARCH=1
18+ GENERIC ,
1719 // X86/X86_64 Intel
1820 P2 ,
1921 KATMAI ,
@@ -156,6 +158,7 @@ impl FromStr for Target {
156158
157159 fn from_str ( s : & str ) -> Result < Self , Self :: Err > {
158160 let target = match s. to_ascii_lowercase ( ) . as_str ( ) {
161+ "generic" => Self :: GENERIC ,
159162 // X86/X86_64 Intel
160163 "p2" => Self :: P2 ,
161164 "katamai" => Self :: KATMAI ,
@@ -302,6 +305,28 @@ impl FromStr for Target {
302305 }
303306}
304307
308+ impl Target {
309+ fn get_generic_target ( ) -> Option < Self > {
310+ let target = env:: var ( "TARGET" ) . unwrap ( ) ;
311+ let target_arch = target. split ( '-' ) . nth ( 0 ) . unwrap ( ) ;
312+ match target_arch {
313+ "aarch64" => Some ( Target :: ARMV8 ) ,
314+ "arm" => Some ( Target :: ARMV6 ) ,
315+ "armv5te" => Some ( Target :: ARMV5 ) ,
316+ "armv6" => Some ( Target :: ARMV6 ) ,
317+ "armv7" => Some ( Target :: ARMV7 ) ,
318+ "loongarch64" => Some ( Target :: LOONGSONGENERIC ) ,
319+ "mips64" => Some ( Target :: MIPS64_GENERIC ) ,
320+ "mips64el" => Some ( Target :: MIPS64_GENERIC ) ,
321+ "riscv64" => Some ( Target :: RISCV64_GENERIC ) ,
322+ "csky" => Some ( Target :: CK860FV ) ,
323+ "sparc" => Some ( Target :: SPARCV7 ) ,
324+ //TODO: add more generic targets
325+ _ => None ,
326+ }
327+ }
328+ }
329+
305330#[ derive( Default , Debug , Clone , PartialEq , Eq , Hash ) ]
306331pub struct Compilers {
307332 pub cc : Option < String > ,
@@ -345,48 +370,101 @@ impl Default for Configure {
345370}
346371
347372impl Configure {
348- fn make_args ( & self ) -> Vec < String > {
373+ fn make_args ( & self ) -> Result < Vec < String > , Error > {
374+ // check if it is cross-compilation
375+ let build_target = env:: var ( "TARGET" ) . unwrap_or_default ( ) ;
376+ let build_host = env:: var ( "HOST" ) . unwrap_or_default ( ) ;
377+ let is_cross_compile = build_target != build_host;
378+
349379 let mut args = Vec :: new ( ) ;
350380 if self . no_static {
351- args. push ( "NO_STATIC=1" . into ( ) )
381+ args. push ( "NO_STATIC=1" . into ( ) ) ;
352382 }
353383 if self . no_shared {
354- args. push ( "NO_SHARED=1" . into ( ) )
384+ args. push ( "NO_SHARED=1" . into ( ) ) ;
355385 }
356386 if self . no_cblas {
357- args. push ( "NO_CBLAS=1" . into ( ) )
387+ args. push ( "NO_CBLAS=1" . into ( ) ) ;
358388 }
359389 if self . no_lapack {
360- args. push ( "NO_LAPACK=1" . into ( ) )
390+ args. push ( "NO_LAPACK=1" . into ( ) ) ;
361391 }
362392 if self . no_lapacke {
363- args. push ( "NO_LAPACKE=1" . into ( ) )
393+ args. push ( "NO_LAPACKE=1" . into ( ) ) ;
364394 }
365395 if self . use_thread {
366- args. push ( "USE_THREAD=1" . into ( ) )
396+ args. push ( "USE_THREAD=1" . into ( ) ) ;
367397 }
368398 if self . use_openmp {
369- args. push ( "USE_OPENMP=1" . into ( ) )
399+ args. push ( "USE_OPENMP=1" . into ( ) ) ;
370400 }
371401 if matches ! ( self . interface, Interface :: ILP64 ) {
372- args. push ( "INTERFACE64=1" . into ( ) )
402+ args. push ( "INTERFACE64=1" . into ( ) ) ;
373403 }
374404 if let Some ( target) = self . target . as_ref ( ) {
375- args. push ( format ! ( "TARGET={:?}" , target) )
405+ args. push ( format ! ( "TARGET={:?}" , target) ) ;
406+ } else if is_cross_compile {
407+ if let Some ( target) = Target :: get_generic_target ( ) {
408+ args. push ( format ! ( "TARGET={:?}" , target) ) ;
409+ } else {
410+ return Err ( Error :: MissingCrossCompileInfo {
411+ info : "TARGET" . to_string ( ) ,
412+ } ) ;
413+ }
376414 }
377- if let Some ( compiler_cc) = self . compilers . cc . as_ref ( ) {
378- args. push ( format ! ( "CC={}" , compiler_cc) )
415+
416+ let mut cc_compiler = self . compilers . cc . clone ( ) ;
417+ if let Some ( cc) = self . compilers . cc . as_ref ( ) {
418+ args. push ( format ! ( "CC={}" , cc) ) ;
419+ } else if is_cross_compile {
420+ let compiler = cc:: Build :: new ( ) . get_compiler ( ) ;
421+ let compiler_path = compiler. path ( ) . to_str ( ) ;
422+ if let Some ( cc) = compiler_path {
423+ args. push ( format ! ( "CC={}" , cc) ) ;
424+ cc_compiler = Some ( cc. to_string ( ) ) ;
425+ } else {
426+ return Err ( Error :: MissingCrossCompileInfo {
427+ info : "CC" . to_string ( ) ,
428+ } ) ;
429+ }
379430 }
380- if let Some ( compiler_fc) = self . compilers . fc . as_ref ( ) {
381- args. push ( format ! ( "FC={}" , compiler_fc) )
431+ if let Some ( fc) = self . compilers . fc . as_ref ( ) {
432+ args. push ( format ! ( "FC={}" , fc) )
433+ } else if is_cross_compile {
434+ let mut fortran = false ;
435+ if let Some ( cc) = cc_compiler {
436+ let fc = cc
437+ . replace ( "gcc" , "gfortran" )
438+ . replace ( "clang" , "flang" )
439+ . replace ( "icc" , "ifort" ) ;
440+
441+ if Command :: new ( & fc) . arg ( "--version" ) . check_call ( ) . is_ok ( ) {
442+ args. push ( format ! ( "FC={}" , fc) ) ;
443+ fortran = true ;
444+ }
445+ }
446+ if !fortran {
447+ println ! ( "cargo:warning=OpenBLAS: Detecting fortran compiler failed. Can only compile BLAS and f2c-converted LAPACK." ) ;
448+ args. push ( "NOFORTRAN=1" . into ( ) ) ;
449+ }
382450 }
383- if let Some ( compiler_hostcc) = self . compilers . hostcc . as_ref ( ) {
384- args. push ( format ! ( "HOSTCC={}" , compiler_hostcc) )
451+ if let Some ( hostcc) = self . compilers . hostcc . as_ref ( ) {
452+ args. push ( format ! ( "HOSTCC={}" , hostcc) )
453+ } else if is_cross_compile {
454+ let compiler = cc:: Build :: new ( ) . target ( build_host. as_str ( ) ) . get_compiler ( ) ;
455+ let compiler_path = compiler. path ( ) . to_str ( ) ;
456+ if let Some ( hostcc) = compiler_path {
457+ args. push ( format ! ( "HOSTCC={}" , hostcc) ) ;
458+ } else {
459+ return Err ( Error :: MissingCrossCompileInfo {
460+ info : "HOSTCC" . to_string ( ) ,
461+ } ) ;
462+ }
385463 }
386- if let Some ( compiler_ranlib ) = self . compilers . ranlib . as_ref ( ) {
387- args. push ( format ! ( "RANLIB={}" , compiler_ranlib ) )
464+ if let Some ( ranlib ) = self . compilers . ranlib . as_ref ( ) {
465+ args. push ( format ! ( "RANLIB={}" , ranlib ) )
388466 }
389- args
467+ Ok ( args)
390468 }
391469
392470 /// Build OpenBLAS
@@ -407,12 +485,12 @@ impl Configure {
407485 }
408486
409487 // check if cross compile is needed
410- let build_target = env:: var ( "TARGET" ) . unwrap_or_default ( ) ;
411- let build_host = env:: var ( "HOST" ) . unwrap_or_default ( ) ;
412- let is_cross_compile = build_target != build_host;
413- if is_cross_compile && ( self . compilers . cc . is_none ( ) || self . compilers . hostcc . is_none ( ) ) {
414- return Err ( Error :: MissingCrossCompileInfo ) ;
415- }
488+ // let build_target = env::var("TARGET").unwrap_or_default();
489+ // let build_host = env::var("HOST").unwrap_or_default();
490+ // let is_cross_compile = build_target != build_host;
491+ // if is_cross_compile && (self.compilers.cc.is_none() || self.compilers.hostcc.is_none()) {
492+ // return Err(Error::MissingCrossCompileInfo);
493+ // }
416494
417495 // Run `make` as an subprocess
418496 //
@@ -428,7 +506,7 @@ impl Configure {
428506 . current_dir ( root)
429507 . stdout ( out)
430508 . stderr ( err)
431- . args ( self . make_args ( ) )
509+ . args ( self . make_args ( ) ? )
432510 . args ( [ "all" ] )
433511 . env_remove ( "TARGET" )
434512 . check_call ( )
@@ -446,7 +524,11 @@ impl Configure {
446524 }
447525 }
448526
449- MakeConf :: new ( root. join ( "Makefile.conf" ) )
527+ let make_conf = MakeConf :: new ( root. join ( "Makefile.conf" ) ) ?;
528+ if make_conf. no_fortran {
529+ println ! ( "cargo:warning=OpenBLAS: Detecting fortran compiler failed. Only BLAS and f2c-converted LAPACK are compiled." ) ;
530+ }
531+ Ok ( make_conf)
450532 }
451533}
452534
0 commit comments