22
33use crate :: { check:: * , error:: * } ;
44use std:: { env, fs, path:: * , process:: Command , str:: FromStr } ;
5- use walkdir:: WalkDir ;
65
76/// Interface for 32-bit interger (LP64) and 64-bit integer (ILP64)
87#[ derive( Debug , Clone , Copy , PartialEq , Eq , Hash ) ]
@@ -345,12 +344,6 @@ impl Default for Configure {
345344 }
346345}
347346
348- /// Deliverables of `make` command
349- pub struct Deliverables {
350- /// Inspection what `make` command really show.
351- pub make_conf : MakeConf ,
352- }
353-
354347impl Configure {
355348 fn make_args ( & self ) -> Vec < String > {
356349 let mut args = Vec :: new ( ) ;
@@ -396,37 +389,6 @@ impl Configure {
396389 args
397390 }
398391
399- /// Inspect existing build deliverables, and validate them.
400- ///
401- /// Error
402- /// ------
403- /// - No build deliverables exist
404- /// - Build deliverables are not valid
405- /// - e.g. `self.no_lapack == false`, but the existing library does not contains LAPACK symbols.
406- ///
407- pub fn inspect ( & self , out_dir : impl AsRef < Path > ) -> Result < Deliverables , Error > {
408- let out_dir = out_dir. as_ref ( ) ;
409- let make_conf = MakeConf :: new ( out_dir. join ( "Makefile.conf" ) ) ?;
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- }
415- }
416- if !self . no_shared {
417- let lib_path = if cfg ! ( target_os = "macos" ) {
418- out_dir. join ( "libopenblas.dylib" )
419- } else {
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 } )
428- }
429-
430392 /// Build OpenBLAS
431393 ///
432394 /// Libraries are created directly under `out_dir` e.g. `out_dir/libopenblas.a`
@@ -437,42 +399,11 @@ impl Configure {
437399 /// This means that the system environment is not appropriate to execute `make`,
438400 /// e.g. LAPACK is required but there is no Fortran compiler.
439401 ///
440- pub fn build (
441- self ,
442- openblas_root : impl AsRef < Path > ,
443- out_dir : impl AsRef < Path > ,
444- ) -> Result < Deliverables , Error > {
445- let out_dir = out_dir. as_ref ( ) ;
446- if !out_dir. exists ( ) {
447- fs:: create_dir_all ( out_dir) ?;
448- }
449-
450- // Do not build if libraries and Makefile.conf already exist and are valid
451- if let Ok ( deliv) = self . inspect ( out_dir) {
452- return Ok ( deliv) ;
453- }
454-
455- // Copy OpenBLAS sources from this crate to `out_dir`
402+ pub fn build < P : AsRef < Path > > ( self , openblas_root : P ) -> Result < MakeConf , Error > {
456403 let root = openblas_root. as_ref ( ) ;
457- for entry in WalkDir :: new ( root) {
458- let entry = entry. expect ( "Unknown IO error while walkdir" ) ;
459- let dest = out_dir. join (
460- entry
461- . path ( )
462- . strip_prefix ( root)
463- . expect ( "Directory entry is not under root" ) ,
464- ) ;
465- if dest. exists ( ) {
466- // Do not overwrite
467- // Cache of previous build should be cleaned by `cargo clean`
468- continue ;
469- }
470- if entry. file_type ( ) . is_dir ( ) {
471- fs:: create_dir ( & dest) ?;
472- }
473- if entry. file_type ( ) . is_file ( ) {
474- fs:: copy ( entry. path ( ) , & dest) ?;
475- }
404+ // Do not build if libraries and Makefile.conf already exist and are valid
405+ if let Ok ( make_conf) = MakeConf :: new ( root. join ( "Makefile.conf" ) ) {
406+ return Ok ( make_conf) ;
476407 }
477408
478409 // check if cross compile is needed
@@ -491,10 +422,10 @@ impl Configure {
491422 // - cargo sets `TARGET` environment variable as target triple (e.g. x86_64-unknown-linux-gnu)
492423 // while binding build.rs, but `make` read it as CPU target specification.
493424 //
494- let out = fs:: File :: create ( out_dir . join ( "out.log" ) ) . expect ( "Cannot create log file" ) ;
495- let err = fs:: File :: create ( out_dir . join ( "err.log" ) ) . expect ( "Cannot create log file" ) ;
425+ let out = fs:: File :: create ( root . join ( "out.log" ) ) . expect ( "Cannot create log file" ) ;
426+ let err = fs:: File :: create ( root . join ( "err.log" ) ) . expect ( "Cannot create log file" ) ;
496427 match Command :: new ( "make" )
497- . current_dir ( out_dir )
428+ . current_dir ( root )
498429 . stdout ( out)
499430 . stderr ( err)
500431 . args ( self . make_args ( ) )
@@ -506,15 +437,16 @@ impl Configure {
506437 Err ( err @ Error :: NonZeroExitStatus { .. } ) => {
507438 eprintln ! (
508439 "{}" ,
509- fs:: read_to_string( out_dir . join( "err.log" ) ) . expect( "Cannot read log file" )
440+ fs:: read_to_string( root . join( "err.log" ) ) . expect( "Cannot read log file" )
510441 ) ;
511442 return Err ( err) ;
512443 }
513444 Err ( e) => {
514445 return Err ( e) ;
515446 }
516447 }
517- self . inspect ( out_dir)
448+
449+ MakeConf :: new ( root. join ( "Makefile.conf" ) )
518450 }
519451}
520452
@@ -531,62 +463,96 @@ mod tests {
531463 ) ) ;
532464 }
533465
534- fn get_openblas_source ( ) -> PathBuf {
535- let openblas_src_root = PathBuf :: from ( env ! ( "CARGO_MANIFEST_DIR" ) ) . join ( "../openblas-src" ) ;
536- crate :: download ( & openblas_src_root) . unwrap ( )
466+ fn get_openblas_source < P : AsRef < Path > > ( out_dir : P ) -> PathBuf {
467+ let openblas_src_root = PathBuf :: from ( env ! ( "CARGO_MANIFEST_DIR" ) ) . join ( "../openblas-src/" ) ;
468+ let source = crate :: download ( & openblas_src_root) . unwrap ( ) ;
469+ // copy files to the target directory
470+ let out_dir = out_dir. as_ref ( ) ;
471+ fs:: create_dir_all ( out_dir) . unwrap ( ) ;
472+ for entry in walkdir:: WalkDir :: new ( & source) {
473+ let entry = entry. unwrap ( ) ;
474+ let src = entry. path ( ) ;
475+ let dest = out_dir. join ( src. strip_prefix ( & source) . unwrap ( ) ) ;
476+ if entry. file_type ( ) . is_dir ( ) {
477+ fs:: create_dir_all ( & dest) . unwrap ( ) ;
478+ } else {
479+ fs:: copy ( src, dest) . unwrap ( ) ;
480+ }
481+ }
482+ out_dir. to_path_buf ( )
537483 }
538484
539485 #[ ignore]
540486 #[ test]
541487 fn build_default ( ) {
542488 let root = PathBuf :: from ( env ! ( "CARGO_MANIFEST_DIR" ) ) ;
489+ let out_dir = root. join ( "test_build/build_default" ) ;
543490 let opt = Configure :: default ( ) ;
544- let _detail = opt
545- . build ( get_openblas_source ( ) , root. join ( "test_build/build_default" ) )
546- . unwrap ( ) ;
491+ let _ = opt. build ( get_openblas_source ( & out_dir) ) . unwrap ( ) ;
547492 }
548493
549494 #[ ignore]
550495 #[ test]
551496 fn build_no_shared ( ) {
552497 let root = PathBuf :: from ( env ! ( "CARGO_MANIFEST_DIR" ) ) ;
498+ let out_dir = root. join ( "test_build/build_no_shared" ) ;
553499 let mut opt = Configure :: default ( ) ;
554500 opt. no_shared = true ;
555- let detail = opt
556- . build (
557- get_openblas_source ( ) ,
558- root. join ( "test_build/build_no_shared" ) ,
559- )
560- . unwrap ( ) ;
561- assert ! ( detail. shared_lib. is_none( ) ) ;
501+ opt. build ( get_openblas_source ( & out_dir) ) . unwrap ( ) ;
502+ let _ = LibInspect :: new ( out_dir. join ( "libopenblas.a" ) ) . unwrap ( ) ;
562503 }
563504
564505 #[ ignore]
565506 #[ test]
566507 fn build_no_lapacke ( ) {
567508 let root = PathBuf :: from ( env ! ( "CARGO_MANIFEST_DIR" ) ) ;
509+ let out_dir = root. join ( "test_build/build_no_lapacke" ) ;
568510 let mut opt = Configure :: default ( ) ;
569511 opt. no_lapacke = true ;
570- let detail = opt
571- . build (
572- get_openblas_source ( ) ,
573- root. join ( "test_build/build_no_lapacke" ) ,
574- )
575- . unwrap ( ) ;
576- let shared_lib = detail. shared_lib . unwrap ( ) ;
577- assert ! ( shared_lib. has_lapack( ) ) ;
578- assert ! ( !shared_lib. has_lapacke( ) ) ;
512+ let _ = opt. build ( get_openblas_source ( & out_dir) ) . unwrap ( ) ;
513+ let lib_name = if cfg ! ( target_os = "macos" ) {
514+ "libopenblas.dylib"
515+ } else {
516+ "libopenblas.so"
517+ } ;
518+ let lib_inspect = LibInspect :: new ( out_dir. join ( lib_name) ) . unwrap ( ) ;
519+
520+ assert ! ( lib_inspect. has_lapack( ) ) ;
521+ assert ! ( !lib_inspect. has_lapacke( ) ) ;
522+ }
523+
524+ #[ ignore]
525+ #[ test]
526+ fn build_no_cblas ( ) {
527+ let root = PathBuf :: from ( env ! ( "CARGO_MANIFEST_DIR" ) ) ;
528+ let out_dir = root. join ( "test_build/build_no_cblas" ) ;
529+ let mut opt = Configure :: default ( ) ;
530+ opt. no_lapacke = true ;
531+ let _ = opt. build ( get_openblas_source ( & out_dir) ) . unwrap ( ) ;
532+ let lib_name = if cfg ! ( target_os = "macos" ) {
533+ "libopenblas.dylib"
534+ } else {
535+ "libopenblas.so"
536+ } ;
537+ let lib_inspect = LibInspect :: new ( out_dir. join ( lib_name) ) . unwrap ( ) ;
538+
539+ assert ! ( !lib_inspect. has_cblas( ) ) ;
579540 }
580541
581542 #[ ignore]
582543 #[ test]
583544 fn build_openmp ( ) {
584545 let root = PathBuf :: from ( env ! ( "CARGO_MANIFEST_DIR" ) ) ;
546+ let out_dir = root. join ( "test_build/build_openmp" ) ;
585547 let mut opt = Configure :: default ( ) ;
586548 opt. use_openmp = true ;
587- let detail = opt
588- . build ( get_openblas_source ( ) , root. join ( "test_build/build_openmp" ) )
589- . unwrap ( ) ;
590- assert ! ( detail. shared_lib. unwrap( ) . has_lib( "gomp" ) ) ;
549+ let _ = opt. build ( get_openblas_source ( & out_dir) ) . unwrap ( ) ;
550+ let lib_name = if cfg ! ( target_os = "macos" ) {
551+ "libopenblas.dylib"
552+ } else {
553+ "libopenblas.so"
554+ } ;
555+ let lib_inspect = LibInspect :: new ( out_dir. join ( lib_name) ) . unwrap ( ) ;
556+ assert ! ( lib_inspect. has_lib( "gomp" ) ) ;
591557 }
592558}
0 commit comments