#$Id: Portfile 144924 2016-01-21 13:29:36Z vince@macports.org $ set ports_ignore_different "yes" PortSystem 1.0 PortGroup muniversal 1.0 categories math license BSD name atlas version 3.10.2 revision 2 use_bzip2 yes # additional versions set lapackversion 3.6.0 set lapackname lapack set atlasdist ${name}${version}${extract.suffix} set lapackdist ${lapackname}-${lapackversion}.tgz maintainers vince platforms darwin description Portable optimal linear algebra software long_description Provides a complete BLAS and LAPACK API.\nATLAS\ achieves performance on par\ with machine-specific tuned libraries. # No precompiled binaries #archive_sites homepage http://math-atlas.sourceforge.net/ master_sites sourceforge:project/math-atlas/Stable/${version}:atlas \ http://www.netlib.org/lapack:lapack distfiles ${atlasdist}:atlas \ ${lapackdist}:lapack extract.only ${atlasdist} patchfiles patch-archinfo_x86_c.diff \ patch-emit_mm_c.diff \ patch-makes-Make.lib.diff checksums atlas${version}.tar.bz2 \ rmd160 af4099e8bb65f5d771618ca1580f5bc8210f83fe \ sha256 3aab139b118bf3fcdb4956fbd71676158d713ab0d3bccb2ae1dc3769db22102f \ lapack-${lapackversion}.tgz \ rmd160 a92d0d869e42cf5835039b043e613e323b069f04 \ sha256 a9a0082c918fe14e377bbd570057616768dca76cbdc713457d8199aaa233ffc3 worksrcdir ATLAS variant gcc5 conflicts gcc49 mpclang37 perf\ description {build using macports-gcc-5} { configure.compiler macports-gcc-5 } if {[variant_isset gcc5]} { set gcc_version 5 set use_clang "" } variant gcc49 conflicts gcc5 mpclang37 perf\ description {build using macports-gcc-4.9} { configure.compiler macports-gcc-4.9 } if {[variant_isset gcc49]} { set gcc_version 49 set use_clang "" } variant mpclang37 conflicts gcc49 gcc5 perf\ description {use mp-clang-3.7 and gfortran} { configure.compiler macports-clang-3.7 } if {[variant_isset mpclang37]} { set use_clang "37" set gcc_version 0 } # Disabled until further notice #variant perf conflicts gcc47 gcc48 gcc49 gcc5 mpclang34 clang \ # description {Uses clang-mp-3.4 for C and dragonegg-3.4 for Fortran} { # # if {[vercmp ${xcodeversion} 5.0] < 0} { # configure.compiler macports-clang-3.4 # } else { # set use_clang "XCode" # set gcc_version 0 # } # # depends_build-append port:dragonegg-3.4-gcc-4.8 # configure.f77 ${prefix}/bin/dragonegg-3.4-gfortran-mp-4.8 # # set clang_flags "-O3 -fPIC -fomit-frame-pointer" # set gcc_flags "${clang_flags} \ # -specs=${prefix}/libexec/dragonegg/llvm34gcc48-integrated-as.specs" #} # #if {[variant_isset perf]} { # # set use_clang "34" # set gcc_version 48 #} variant nofortran description {Forgo use of fortran compiler} { } # AVX or higher? if {(${os.major} > 11 && \ (![catch {sysctl hw.optional.fma} result1] && $result1 == 1)) || (![catch {sysctl hw.cpufamily} result2] && $result2 == 280134364)} { set has_fma "yes" } else { set has_fma "no" } if {(${os.major} > 11 && \ (![catch {sysctl hw.optional.avx2_0} result1] && $result1 == 1)) || (![catch {sysctl hw.cpufamily} result2] && $result2 == 280134364)} { set has_avx2 "yes" } else { set has_avx2 "no" } if {(${os.major} > 10 && \ (![catch {sysctl hw.optional.avx1_0} result1] && $result1 == 1)) || (![catch {sysctl hw.cpufamily} result2] && $result2 == 1418770316)} { set has_avx "yes" } else { set has_avx "no" } # If none of the above variants is chosen, make gcc47 the default for # up to SSE4.2 (Core i1) capable processors, and XCode-clang for newer if {![variant_isset gcc49] && ![variant_isset gcc5] && ![variant_isset mpclang37]} { if {${has_avx} == "no"} { # Defaults to gcc47 default_variants +gcc5 set gcc_version 5 set use_clang "" } else { # Use an appropriate version of Clang set gcc_version 0 if {[vercmp ${xcodeversion} 6.0] >= 0} { # With XCode 5.0+, defaults to Xcode-clang set use_clang "XCode" } else { # Otherwise use Macports clang 3.7 default_variants +mpclang37 set use_clang "37" } } } set universal [variant_isset universal] # Finds the type of CPU we are running on set native_arch ${build_arch} if {${os.arch} eq "i386"} { set universal_archs_supported {i386 x86_64} if {![catch {exec sysctl -n hw.machine} result]} { set native_arch ${result} } } elseif {${os.arch} eq "powerpc"} { set universal_archs_supported {ppc ppc64} if {![catch {exec sysctl -n hw.cpusubtype} result] && $result == 100} { set native_arch "ppc64" } else { set native_arch "ppc" } } configure.args \ --with-netlib-lapack-tarfile=${distpath}/${lapackdist} \ -O 12 \ -v 5 \ --dylibs # Chose the right flags for GCC and Clang compilers if {${build_arch} eq "i386" || ${build_arch} eq "x86_64"} { # General flags # GCC set gcc_flags "-fomit-frame-pointer -mfpmath=sse -O3\ -fno-schedule-insns2 -fPIC" # Clang set clang_flags "-O3 -fomit-frame-pointer -fPIC" # Vectorizing unit flags if {${has_fma} == "yes"} { # Only Clang handles AVX+ correctly set gvct_flag "-msse4.2" # downgrade FMA to AVX for the time being set cvct_flag "-mfma" if {${use_clang} != ""} { configure.args-append -A 28 -V 456 } else { # No AVX when using GCC 4.x configure.args-append -A 26 -V 448 } } elseif {${has_avx2} == "yes"} { set gvct_flag "-msse4.2" set cvct_flag "-mavx" } elseif {${has_avx} == "yes"} { set gvct_flag "-msse4.2" set cvct_flag "-mavx" } elseif {${os.major} > 9 && \ ![catch {sysctl hw.optional.sse4_2} result1] && $result1 == 1} { set gvct_flag "-msse4.2" set cvct_flag "-msse4.2" } elseif {${os.major} > 9 && \ ![catch {sysctl hw.optional.sse4_1} result1] && $result1 == 1} { set gvct_flag "-msse4.1" set cvct_flag "-msse4.1" } elseif {${os.major} > 8 && \ ![catch {sysctl hw.optional.supplementalsse3} result1] && $result1 == 1} { set gvct_flag "-mssse3" set cvct_flag "-mssse3" } else { # Default vectorization flag is sse3 (CoreSolo / CoreDuo) set gvct_flag "-msse3" set cvct_flag "-msse3" } } elseif {${build_arch} eq "ppc"} { # PPC set gcc_flags "-O3 -mcpu=7400 -mtune=7400\ -fno-schedule-insns -fschedule-insns2 -fPIC \ -force_cpusubtype_ALL" set clang_flags "-O3 -arch ppc -fPIC" set gvct_flag "-maltivec -mabi=altivec" set cvct_flag "-maltivec" configure.args-append -A 4 # On Leopard, we may warn the user that ppc # is not as efficient as ppc64 pre-fetch { if {${native_arch} eq "ppc64"} { ui_msg "Compiling for ppc on a G5 machine.\ This could lead to reduced performance." } } } else { # PPC64 set gcc_flags "-mcpu=970 -mtune=970 -mvrsave -mpowerpc64\ -fno-schedule-insns -fschedule-insns2 -fPIC \ -force_cpusubtype_ALL" # Clang has no PPC64 target so compile for PPC set clang_flags "-O3 -arch ppc -fPIC" set gvct_flag "-maltivec -mabi=altivec" set cvct_flag "-maltivec" } # Basic universal config # Advanced config (flags) is done during pre-configure phase if {${universal} == 1} { configure.universal_args-delete --disable-dependency-tracking lappend merger_configure_args(ppc) --cflags=-m32 \ -b 32 \ -A 4 \ -V 4 \ -s gas_ppc \ -Fa alg -force_cpusubtype_ALL lappend merger_configure_args(ppc64) --cflags=-m64 \ -b 64 \ -A 5 \ -V 4 \ -s gas_ppc \ -Fa alg -force_cpusubtype_ALL lappend merger_configure_args(i386) --cflags=-m32 \ -b 32 \ -A 22 \ -V 448 \ -t 2 \ -s gas_x86_32 lappend merger_configure_args(x86_64) --cflags=-m64 \ -b 64 \ -s gas_x86_64 } # Threading # If we run on a mono-processor machine (PPC), then disable threading if {![catch {sysctl hw.logicalcpu} result] && $result == 1} { configure.args-append -t 0 set no_threads 1 } else { set no_threads 0 # Threading relies on OpenMP if gcc compilers are selected # Does not seem to work reliably. Disabled. #if {${gcc_version} != 0} { configure.args-append -Si omp 0 #} } # Phases # Work around some bugs in the 3.10.1 tarball: # https://code.google.com/p/libarchive/issues/detail?id=299 # https://sourceforge.net/p/math-atlas/support-requests/884 extract.post_args-replace -xf -xkf extract.post_args-append {|| true} post-patch { if {${build_arch} eq "ppc" || ${build_arch} eq "ppc64"} { reinplace \ "s|cMVFLAGS=\\\\\"%s\\\\\"|cMVFLAGS=\\\\\"-force_cpusubtype_ALL\ %s\\\\\"|" \ ${worksrcpath}/include/atlas_mvtesttime.h } if {${no_threads} == 1} { exec sed -i bak -E "/.*threads.*/d" ${worksrcpath}/Make.top } } # Change the default compilers pre-configure { # Inform user of selected C compiler ui_msg "Selected C compiler: ${configure.cc}" # Fortran stuff set fortran [expr ! [variant_isset nofortran]] # If we use clang, we must grasp a gfortran compiler to build # Fortran sources (do not impact overall Atlas performance) if {${use_clang} != "" && ${fortran} == 1} { # if {![variant_isset perf]} { set gflist [glob -noc ${prefix}/bin/gfortran-mp-*] if {[llength ${gflist}] == 0} { # No fortran compiler found, bail out return -code error "Atlas could not detect any fortran compiler.\ If you really don’t need the fortran interface\ to be built, please use the +nofortran option,\ else install a fortran compiler (e.g. gcc4X)\ before building Atlas." } else { # Select most recent gfortran global gcc_version configure.f77 [lindex [lsort -dec ${gflist}] 0] set gcc_version \ [string replace ${configure.f77} 0 [string length ${prefix}]+[string length bin/gfortran-mp-]] set gcc_version [string map {. ""} $gcc_version] } # } else { # set libgccpath ${prefix}/lib/gcc48 # } } if {${fortran} == 1} { # Output the F77 selected compiler if {[variant_isset perf]} { ui_msg "Using dragonegg-3.4-gfortran-mp-4.8 as Fortran compiler." } else { ui_msg "Selected F77 compiler: gfortran${gcc_version}" } } else { # No Fortran configure.args-append --nof77 } # Now set the flags according to the compiler family chosen # Also set “width” of the processor (32 or 64-bit) if {${gcc_version} != 0} { set libgccpath ${prefix}/lib/gcc${gcc_version} } # Some tweaks on the original source before universal build # duplicates it # Overrides goodgcc reinplace -E "s|GOODGCC =.*|GOODGCC = ${configure.cc}\");|" \ ${worksrcpath}/CONFIG/src/SpewMakeInc.c # Some further tweaks reinplace "s|cc=gcc|cc=${configure.cc}|g" \ ${worksrcpath}/configure reinplace "s|-no-cpp-precomp||g" \ ${worksrcpath}/CONFIG/src/atlcomp.txt # Non-universal builds if {${universal} == 0} { configure.args-append -C acg ${configure.cc} # If we build for the CPU of the machine, use # machine arch tuning (except on ppc) # -march=natives supersedes -msse4.2 so disable it on AVX # capable machines if {${has_avx} == "no" && ${build_arch} ne "ppc"} { append gcc_flags " -march=native" } append clang_flags " -march=native" # AVX stuff. GCC compilers cannot use AVX instruction set because the # system as(1) is outdated # Clang 3.7 is fine if {${has_avx} == "yes" && ${use_clang} == ""} { # Force Core i1 arch for ASM kernels ui_warn "GCC compilers on MacOS do not support AVX:\ downgrading." configure.args-append -A 25 } if {${build_arch} eq "ppc"} { # ppc uses altivec vectorizing unit configure.args-append -V 4 } if {${use_clang} == ""} { # GCC configure.args-append -F acg "'${gcc_flags} ${gvct_flag}'" if {${fortran} == 1} { configure.args-append -C if ${configure.f77} configure.args-append -F if "'${gcc_flags} ${gvct_flag}'" configure.args-append -Ss f77lib \ ${libgccpath}/libgfortran.dylib } if {${build_arch} eq "x86_64" || ${build_arch} eq "ppc64"} { configure.args-append -b 64 } else { configure.args-append -b 32 } } else { # clang if {[variant_isset perf]} { append cvct_flag " -march=native" set gvct_flag ${cvct_flag} } configure.args-append -F acg "'${clang_flags} ${cvct_flag}'" if {${fortran} == 1} { configure.args-append -C if ${configure.f77} configure.args-append -F if "'${gcc_flags} ${gvct_flag}'" configure.args-append -Ss f77lib \ ${libgccpath}/libgfortran.dylib } if {${build_arch} eq "x86_64"} { configure.args-append -b 64 } else { # Clang has no ppc64 target so ppc64 ➸ regular ppc (32 bit) configure.args-append -b 32 } } # Create build directory file mkdir ${worksrcpath}/build } else { # Universal builds foreach arch ${universal_archs_to_use} { # Init ‘universal’ flags set gcc_univ_flags ${gcc_flags} set gvct_univ_flag ${gvct_flag} set clang_univ_flags ${clang_flags} set cvct_univ_flag ${cvct_flag} set gcc_supp_flags "" set clang_supp_flags "" # We build for the native architecture if {${arch} eq ${native_arch} && ${build_arch} ne "ppc"} { # Don’t add -march=native to a GCC build on an AVX # machine because this flag overrides -msse4.2 if {${has_avx} == "no"} { append gcc_supp_flags "-march=native " } append clang_supp_flags "-march=native " } # Non-native targets. Apply a priori flags. # Clamp i386 optimization to -sse3 in universal builds and # forces clang/gcc to use -m32 flag if {${arch} eq "i386" && ${native_arch} ne "i386"} { set gvct_univ_flag "-msse3" set cvct_univ_flag "-msse3" append gcc_supp_flags "-m32" append clang_supp_flags "-m32" } # For x86_64 builds, be conservative and use only -ssse3 # Core2 CPU and SSE3 ASM kernels if {${arch} eq "x86_64" && ${native_arch} ne "x86_64"} { set gvct_univ_flag "-mssse3" set cvct_univ_flag "-mssse3" append gcc_supp_flags "-m64" append clang_supp_flags "-m64" lappend merger_configure_args("x86_64") -A 25 -V 448 } # ppc (on Intel or ppc64 machines) if {${arch} eq "ppc" && ${native_arch} ne "ppc"} { set gcc_univ_flags "-O3 -mcpu=7400 -mtune=7400\ -fno-schedule-insns -fschedule-insns2\ -fPIC" set clang_univ_flags "-O3 -arch ppc -fPIC" set gvct_univ_flag "-maltivec -mabi=altivec" set cvct_univ_flag "-maltivec" append gcc_supp_flags "-m32" append clang_supp_flags "-m32" } # ppc64 (only for gcc, for clang this is taken to be the # same target as ppc) if {${arch} eq "ppc64" && ${native_arch} ne "ppc64"} { set gcc_univ_flags "-mcpu=970 -mtune=970 -mvrsave \ -mpowerpc64 -fno-schedule-insns\ -fschedule-insns2 -fPIC" set clang_univ_flags "-O3 -arch ppc -fPIC" set gvct_univ_flag "-maltivec -mabi=altivec" set cvct_univ_flag "-maltivec" append gcc_supp_flags "-m64" append clang_supp_flags "-m64" } # Now add the flags to merger_configure_args(${arch}) # Same code as the non-universal case lappend merger_configure_args(${arch}) -C acg ${configure.cc} if {${use_clang} == ""} { # GCC lappend merger_configure_args(${arch}) \ -F acg "'${gcc_univ_flags} ${gcc_supp_flags}\ ${gvct_univ_flag}'" if {${fortran} == 1} { lappend merger_configure_args(${arch}) \ -C if ${configure.f77} \ -F if "'${gcc_univ_flags} ${gcc_supp_flags}\ ${gvct_univ_flag}'" set libgccarchpath ${libgccpath}/${arch} if {[file exists ${libgccarchpath}/libgfortran.dylib]} { lappend merger_configure_args(${arch}) \ -Ss f77lib ${libgccarchpath}/libgfortran.dylib } else { lappend merger_configure_args(${arch}) \ -Ss f77lib ${libgccpath}/libgfortran.dylib } } } else { # clang lappend merger_configure_args(${arch}) \ -F acg "'${clang_univ_flags} ${clang_supp_flags}\ ${cvct_univ_flag}'" if {${fortran} == 1} { lappend merger_configure_args(${arch}) \ -C if ${configure.f77} \ -F if "'${gcc_univ_flags} ${gcc_supp_flags}\ ${gvct_univ_flag}'" set libgccarchpath ${libgccpath}/${arch} if {[file exists ${libgccarchpath}/libgfortran.dylib]} { lappend merger_configure_args(${arch}) \ -Ss f77lib ${libgccarchpath}/libgfortran.dylib } else { lappend merger_configure_args(${arch}) \ -Ss f77lib ${libgccpath}/libgfortran.dylib } } } # Remove spurious { } from arguments list set merger_configure_args(${arch}) \ [join [split $merger_configure_args(${arch}) "{}"]] # Create ${arch} build tree copy ${worksrcpath} ${worksrcpath}-${arch} file mkdir ${worksrcpath}-${arch}/build } } # On PPC64 we need extra flags for configuring if {${native_arch} eq "ppc64"} { configure.args-append --cc="\"${configure.cc} -m32 \ -force_cpusubtype_ALL\"" } # Get some system specific variables for maximum optimization set cpufreq [expr {[sysctl hw.cpufrequency] / 1000000}] if {${os.arch} eq "powerpc"} { configure.args-append -D c -DWALL } else { configure.args-append -D c -DPentiumCPS=${cpufreq} } } # We configure from the build directory configure.dir ${worksrcpath}/build configure.cmd ../configure post-configure { # Store in ${atlas_paths} the ${worksrcpath}s corresponding to the # archs Atlas is being built for. set atlas_paths {} if {${universal} == 1} { foreach arch ${universal_archs_to_use} { lappend atlas_paths ${worksrcpath}-${arch} } } else { lappend atlas_paths ${worksrcpath} } foreach path ${atlas_paths} { # Recursively remove directories ui_debug "Patch to recursively remove directories on clean." reinplace "s|rm -f|rm -rf|g" ${path}/build/Makefile # Threading — ensure libgomp is correctly pulled in during link #if {${gcc_version} != 0 && ${no_threads} == 0} { # set gmpfx ${prefix}/lib/gcc${gcc_version} # set arch [lindex [split [lindex [split $path "/"] end] "-"] 2] # if {${arch} ne "" && \ # [file exists ${gmpfx}/${arch}/libgomp.dylib]} { # reinplace -E \ # "s|(LIBS =.*)|\\1 ${gmpfx}/${arch}/libgomp.dylib|" \ # ${path}/build/Make.inc # } else { # reinplace -E \ # "s|(LIBS =.*)|\\1 ${gmpfx}/libgomp.dylib|" \ # ${path}/build/Make.inc # } #} } } build.env-append "CC=${configure.cc} CXX=${configure.cxx}" use_parallel_build no build.target build build.dir ${worksrcpath}/build post-build { if {${universal} == 0} { set libdir ${build.dir}/lib reinplace "s|^LIBTOOL=.*$|LIBTOOL=\$\(GCC\) \$\(GCCFLAGS\)|" \ ${libdir}/Makefile # On mono-processors machines, build libsatlas.dylib only if {${no_threads} == 1} { system -W ${libdir} "${build.cmd} dylib" } else { system -W ${libdir} "${build.cmd} shared_all" } } else { foreach arch ${universal_archs_to_use} { set libdir ${worksrcpath}-${arch}/build/lib reinplace "s|^LIBTOOL=.*$|LIBTOOL=\$\(GCC\) \$\(GCCFLAGS\)|" \ ${libdir}/Makefile # Same as above if {${no_threads} == 1} { system -W ${libdir} "${build.cmd} dylib" } else { system -W ${libdir} "${build.cmd} shared_all" } } } } destroot.dir ${build.dir} destroot.destdir DESTDIR=${destroot}${prefix} post-destroot { # On monoprocessor machines, make tatlas and satlas synonymous if {${no_threads} == 1} { set libdir ${destroot}${prefix}/lib system -W ${libdir} "ln -s libsatlas.dylib libtatlas.dylib" } } livecheck.name math-atlas livecheck.distname Stable