@@ -14,6 +14,8 @@ pub enum Interface {
14
14
#[ derive( Debug , Clone , Copy , PartialEq , Eq , Hash ) ]
15
15
#[ allow( non_camel_case_types) ] // to use original identifiers
16
16
pub enum Target {
17
+ // for DYNNAMIC_ARCH=1
18
+ GENERIC ,
17
19
// X86/X86_64 Intel
18
20
P2 ,
19
21
KATMAI ,
@@ -156,6 +158,7 @@ impl FromStr for Target {
156
158
157
159
fn from_str ( s : & str ) -> Result < Self , Self :: Err > {
158
160
let target = match s. to_ascii_lowercase ( ) . as_str ( ) {
161
+ "generic" => Self :: GENERIC ,
159
162
// X86/X86_64 Intel
160
163
"p2" => Self :: P2 ,
161
164
"katamai" => Self :: KATMAI ,
@@ -302,6 +305,28 @@ impl FromStr for Target {
302
305
}
303
306
}
304
307
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
+
305
330
#[ derive( Default , Debug , Clone , PartialEq , Eq , Hash ) ]
306
331
pub struct Compilers {
307
332
pub cc : Option < String > ,
@@ -345,48 +370,101 @@ impl Default for Configure {
345
370
}
346
371
347
372
impl 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
+
349
379
let mut args = Vec :: new ( ) ;
350
380
if self . no_static {
351
- args. push ( "NO_STATIC=1" . into ( ) )
381
+ args. push ( "NO_STATIC=1" . into ( ) ) ;
352
382
}
353
383
if self . no_shared {
354
- args. push ( "NO_SHARED=1" . into ( ) )
384
+ args. push ( "NO_SHARED=1" . into ( ) ) ;
355
385
}
356
386
if self . no_cblas {
357
- args. push ( "NO_CBLAS=1" . into ( ) )
387
+ args. push ( "NO_CBLAS=1" . into ( ) ) ;
358
388
}
359
389
if self . no_lapack {
360
- args. push ( "NO_LAPACK=1" . into ( ) )
390
+ args. push ( "NO_LAPACK=1" . into ( ) ) ;
361
391
}
362
392
if self . no_lapacke {
363
- args. push ( "NO_LAPACKE=1" . into ( ) )
393
+ args. push ( "NO_LAPACKE=1" . into ( ) ) ;
364
394
}
365
395
if self . use_thread {
366
- args. push ( "USE_THREAD=1" . into ( ) )
396
+ args. push ( "USE_THREAD=1" . into ( ) ) ;
367
397
}
368
398
if self . use_openmp {
369
- args. push ( "USE_OPENMP=1" . into ( ) )
399
+ args. push ( "USE_OPENMP=1" . into ( ) ) ;
370
400
}
371
401
if matches ! ( self . interface, Interface :: ILP64 ) {
372
- args. push ( "INTERFACE64=1" . into ( ) )
402
+ args. push ( "INTERFACE64=1" . into ( ) ) ;
373
403
}
374
404
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
+ }
376
414
}
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
+ }
379
430
}
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
+ }
382
450
}
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
+ }
385
463
}
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 ) )
388
466
}
389
- args
467
+ Ok ( args)
390
468
}
391
469
392
470
/// Build OpenBLAS
@@ -407,12 +485,12 @@ impl Configure {
407
485
}
408
486
409
487
// 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
+ // }
416
494
417
495
// Run `make` as an subprocess
418
496
//
@@ -428,7 +506,7 @@ impl Configure {
428
506
. current_dir ( root)
429
507
. stdout ( out)
430
508
. stderr ( err)
431
- . args ( self . make_args ( ) )
509
+ . args ( self . make_args ( ) ? )
432
510
. args ( [ "all" ] )
433
511
. env_remove ( "TARGET" )
434
512
. check_call ( )
@@ -446,7 +524,11 @@ impl Configure {
446
524
}
447
525
}
448
526
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)
450
532
}
451
533
}
452
534
0 commit comments