# $Id: Portfile 68295 2010-05-31 10:36:17Z jmr@macports.org $

PortSystem          1.0
PortGroup           muniversal 1.0

categories          math
name                atlas
version             3.8.3
revision            2

# additional versions
set lapackversion   3.2.1
set lapackname      lapack
set atlasdist       ${name}${version}.tar.bz2
set lapackdist      ${lapackname}.tgz

maintainers         jameskyle
platforms           darwin

description         Portable optimal linear algebra software
long_description    The current version provides a complete BLAS and LAPACK API.\
                    For many operations, ATLAS achieves performance on par with\
                    machine-specific tuned libraries.

homepage            http://math-atlas.sourceforge.net/

master_sites        sourceforge:math-atlas/${name}${version}.tar.bz2:atlas \
                    http://www.netlib.org/lapack:lapack

distfiles           ${atlasdist}:atlas \
                    ${lapackdist}:lapack

patchfiles          patch-ATL_AVgcc-fix.diff \
                    patch-archinfo_freebsd.c.diff \
                    patch-SpewMakeInc.c.diff

checksums           atlas${version}.tar.bz2 \
                    md5     6c13be94a87178e7582111c08e9503bc \
                    sha1    c7546210df4796457d9e96a00444adc4c0f2e77f \
                    rmd160  0425e630d9d0c5b7aae81427a41b7eaa18447e90 \
                    lapack.tgz \
                    md5     a3202a4f9e2f15ffd05d15dab4ac7857 \
                    sha1    c75223fdef3258c461370af5d2b889d580d7f38a \
                    rmd160  e8fabba2fdd944afbc02a83599cf45a0d721030d


use_parallel_build  no
build.target        build
build.dir           ${workpath}/${name}-${version}/build

variant gcc43 conflicts gcc42 conflicts universal description {build using macports-gcc-4.3} {}
variant gcc42 conflicts gcc43 conflicts universal description {build using macports-gcc-4.2} {}

if { [variant_isset gcc42] } {
  set gccversion    4.2
} elseif { [variant_isset gcc43] } {
  set gccversion    4.3
} else {
  set gccversion    4.4
}

set gccnumber       [join [split ${gccversion} .] ""]

destroot.dir        ${build.dir}
destroot.destdir    DESTDIR=${destroot}${prefix}
depends_lib         port:gcc${gccnumber} \
                    port:bzip2 \
                    port:gzip

configure.compiler  macports-gcc-${gccversion}

if { ${os.arch}=="i386" } {
    set universal_archs_supported { i386 x86_64 }
} else {
    set universal_archs_supported { ppc  ppc64 }
}

if {${build_arch} == "x86_64" || ${build_arch} == "ppc64" } {
  set my_arch 64
} else {
  set my_arch 32
}

configure.args      -C xc ${configure.cc} \
                    -C gc ${configure.cc} \
                    -C if ${configure.f77} \
                    -C ic ${configure.cc} \
                    -C dm ${configure.cc} \
                    -C sm ${configure.cc} \
                    -C dk ${configure.cc} \
                    -C sk ${configure.cc} \
                    --cc=${configure.cc} \
                    -b ${my_arch} \
                    -Fa alg -fPIC 
                    
if { [variant_isset universal] } {
    configure.universal_args-delete --disable-dependency-tracking
    configure.args-delete -b ${my_arch}
    lappend merger_configure_args(ppc)     -b 32
    lappend merger_configure_args(ppc64)   -b 64
    lappend merger_configure_args(i386)    -b 32
    lappend merger_configure_args(x86_64)  -b 64
} else {
    lappend merger_configure_args(ppc)
    lappend merger_configure_args(ppc64)
    lappend merger_configure_args(i386)
    lappend merger_configure_args(x86_64)
}

build.env-append    "CC=${configure.cc} CXX=${configure.cxx}"
        

# we are configuring from the build directory
configure.dir       ${workpath}/${name}-${version}/build
configure.cmd       ../configure


# change the default compilers to those of gcc and make into shared library
extract {
    # extract atlas and move to a consistent working directory name
    system "cd ${workpath} && bunzip2 -dc ${distpath}/${atlasdist} | \
         gnutar --no-same-owner -xf -"
    system "mv ${workpath}/ATLAS ${workpath}/${name}-${version}"

    # extract lapack
    system "cd ${workpath} && gunzip -dc ${distpath}/${lapackdist} | \
         gnutar --no-same-owner -xf -"
}

post-patch {
    reinplace "s|__MACPORTS_GCC__|${configure.cc}|g" ${workpath}/${name}-${version}/CONFIG/src/SpewMakeInc.c
}

pre-configure {
    if { [variant_isset universal] } {
        foreach arch ${universal_archs_to_use} {
            copy ${workpath}/${name}-${version} ${workpath}/${name}-${version}-${arch}
            copy ${workpath}/${lapackname}-${lapackversion} ${workpath}/${lapackname}-${lapackversion}-${arch}
        }
    }

    reinplace "s|cc=gcc|cc=${configure.cc}|g" ${worksrcpath}/configure
    reinplace "s|-no-cpp-precomp||g" ${workpath}/${name}-${version}/CONFIG/src/atlcomp.txt
    
    # Get some system specific variables for maximum optimization
    set cpufreq [expr {[exec sysctl -n hw.cpufrequency]/1000000}]
    ui_debug "Setting CPU Frequency for: ${cpufreq}"
    
    if {[string equal "${os.arch}" "powerpc"]} {
      configure.args-append -D c -DWALL
    } else {
      configure.args-append -D c -DPentiumCPS=${cpufreq}
    }

    if { [variant_isset universal] } {
        set archs ${universal_archs_to_use}
    } else {
        set archs ${build_arch}
    }

    foreach arch ${archs} {
 
    # first do a 'fake configure' of atlas so we get optimized lapack libraries
    ui_debug "performing fake configure of atlas for optimized lapack"
    # atlas docs: 3.1.2
    if { ! [variant_isset universal] } {
        set atlas_path  ${workpath}/${name}-${version}
        set lapack_path ${workpath}/${lapackname}-${lapackversion}
    } else {
        set atlas_path ${workpath}/${name}-${version}-${arch}
        set lapack_path ${workpath}/${lapackname}-${lapackversion}-${arch}
    }
    ui_debug "Clean out old temp directory if exists"
    file delete -force ${atlas_path}/temp
    file mkdir ${atlas_path}/temp
    ui_debug "Assembled Command: '${configure.cmd} ${configure.args} $merger_configure_args(${arch})"
    system "cd ${atlas_path}/temp && \
            ${configure.cmd} ${configure.args} $merger_configure_args(${arch})"

    # Get the F77FLAGS
    set atlas_f77    [join [lrange [split [exec grep "F77 = " $atlas_path/temp/Make.inc     ] =] 1 end] =]
    ui_debug "Found atlas F77: ${atlas_f77}"

    set atlas_fflags [join [lrange [split [exec grep "F77FLAGS = " $atlas_path/temp/Make.inc] =] 1 end] =]
    ui_debug "Found atlas F77FLAGS: ${atlas_fflags}"

    ui_debug "Remove the old test configure directory"
    file delete -force ${atlas_path}/temp

    # compile lapack
    system "cd ${lapack_path} && \
            cp INSTALL/make.inc.gfortran make.inc"
    reinplace "s|gfortran|${atlas_f77}|" \
           ${lapack_path}/make.inc
    reinplace "s|OPTS     = -O2|OPTS = ${atlas_fflags}|" \
           ${lapack_path}/make.inc
      
    if { ! [variant_isset universal] } {
        reinplace "s|NOOPT    = -O0|NOOPT = -O2 -m${my_arch}|" \
               ${lapack_path}/make.inc
    } else {
        if { ${arch}=="i386" || ${arch}=="ppc" } {
            reinplace "s|NOOPT    = -O0|NOOPT = -O2 -m32|" \
                   ${lapack_path}/make.inc
        } else {
            reinplace "s|NOOPT    = -O0|NOOPT = -O2 -m64|" \
                   ${lapack_path}/make.inc
        }
    }

    reinplace "s|PLAT = _LINUX|PLAT = _darwin|" \
           ${lapack_path}/make.inc

    reinplace "s|LOADOPTS =|LOADOPTS = ${atlas_fflags}|" \
           ${lapack_path}/make.inc

    system "cd ${lapack_path} && make lib"

    # create a build directory for atlas
    file mkdir ${atlas_path}/build

    if { ! [variant_isset universal] } {
        configure.args-append --with-netlib-lapack=${lapack_path}/lapack_darwin.a
    } else {
        lappend merger_configure_args(${arch}) --with-netlib-lapack=${lapack_path}/lapack_darwin.a
    }
}
}

post-configure {
    if { [variant_isset universal] } {
        set archs ${universal_archs_to_use}
    } else {
        set archs ${build_arch}
    }
 
    foreach arch ${archs} {
        if { ! [variant_isset universal] } {
            set atlas_path  ${workpath}/${name}-${version}
        } else {
            set atlas_path ${workpath}/${name}-${version}-${arch}
        }

    # recursively remove directories
    ui_debug "reinplace for make to recursively remove directories on clean"
    reinplace "s|rm -f|rm -rf|g" ${atlas_path}/build/Makefile
    }
}

proc make_dylib { lib lib_dir arch libs } {
    global destroot prefix gccnumber
    system "cd ${lib_dir} && \
            ( test ! -e ${lib}.a ||
              /usr/bin/ld -arch ${arch} -dynamic -dylib -single_module -dead_strip \
              -x -all_load -L. -L${prefix}/lib/gcc${gccnumber}/${arch} -L${prefix}/lib/gcc${gccnumber} -ldylib1.o \
              -dylib_install_name ${prefix}/lib/${lib}.dylib \
              ${lib}.a -o ${lib}.dylib ${libs} )"
}

post-build {
  # We have to manually create the dylib shared libs as the default build does not do this

  set ncpu [exec sysctl -n hw.ncpu]

    if { [variant_isset universal] } {
        set archs ${universal_archs_to_use}
    } else {
        set archs ${build_arch}
    }
 
    foreach arch ${archs} {
        if { ! [variant_isset universal] } {
            set atlas_path  ${workpath}/${name}-${version}
        } else {
            set atlas_path ${workpath}/${name}-${version}-${arch}
        }
        set lib_dir ${atlas_path}/build/lib

  make_dylib libatlas ${lib_dir} ${arch} { -lSystem }

  if {${ncpu} == "1" } {
    # there are no threaded libraries (libpt*) on single-core machines
    make_dylib libcblas   ${lib_dir} ${arch} { -latlas -lSystem }
    make_dylib libf77blas ${lib_dir} ${arch} { -lgfortran -latlas -lSystem }
  } else {
    make_dylib libptcblas   ${lib_dir} ${arch} { -latlas -lSystem }
    make_dylib libptf77blas ${lib_dir} ${arch} { -lgfortran -latlas -lSystem }
  }

  make_dylib liblapack ${lib_dir} ${arch} { -lf77blas -lcblas -latlas -lgfortran -lgcc_s.1 -lSystem }
}
}

pre-destroot {
   if { [variant_isset universal] } {
        set archs ${universal_archs_to_use}
    } else {
        set archs ${build_arch}
    }
 
    foreach arch ${archs} {
        if { ! [variant_isset universal] } {
            set atlas_path  ${workpath}/${name}-${version}
            set dest_path   ${destroot}${prefix}/lib/
        } else {
            set atlas_path ${workpath}/${name}-${version}-${arch}
            set dest_path  ${destroot}-${arch}${prefix}/lib/
        }
        set lib_dir ${atlas_path}/build/lib

        file mkdir ${dest_path}
        eval xinstall -m 755 [glob ${lib_dir}/*.dylib] ${dest_path}
    }
}

post-destroot {
    if { ![file exists ${destroot}${prefix}/lib/libcblas.dylib] && [file exists ${destroot}${prefix}/lib/libptcblas.dylib]} {
        ln -s libptcblas.dylib ${destroot}${prefix}/lib/libcblas.dylib
    }
    if { ![file exists ${destroot}${prefix}/lib/libf77blas.dylib] && [file exists ${destroot}${prefix}/lib/libptf77blas.dylib]} {
        ln -s libptf77blas.dylib ${destroot}${prefix}/lib/libf77blas.dylib
    }
}

livecheck.name      math-atlas
livecheck.distname  Stable
