import sys

Import("env")

cuba = "Cuba-4.2.2p1"
zlib = "zlib-1.3.1"
form = "form-4.3.1"
gmp = "gmp-6.3.0"
gsl = "gsl-2.8"
nauty = "nauty2_8_9"
normaliz = "normaliz-3.10.4"
cln = "cln-1.3.7"
ginac = "ginac-1.8.9"

contrib_extra_source = File(Split(f"""
    SConscript
    {gmp}.list
    {gsl}.list
    {cln}.list
    {ginac}.list
"""))

contrib = []

contrib += \
    File(["__init__.py", "__main__.py"])

contrib += \
    Install("include", "qmc.hpp")

contrib += \
    Install("include", "exparse.hpp")

contrib += \
    Install("include/secdecutil", Glob("util/secdecutil/*hpp")) + \
    Install("include/secdecutil/integrators", Glob("util/secdecutil/integrators/*hpp"))

def ConfigureAndInstall(env, target, packagename, extension=".tar.gz", extra_sources=[], pre_commands="", post_commands="", extra_configure_args="", build_target="", install_target="install", bindir=True):
    return env.Command(target, [f"{packagename}{extension}"] + extra_sources, f"""
        cd pySecDecContrib && \
        tar -xf {packagename}{extension} && \
        cd {packagename} && \
        {pre_commands} \
        ./configure \
            --prefix="$$PWD/../install" \
            --libdir="$$PWD/../lib" \
            --includedir="$$PWD/../include" \
            {'--bindir="$$PWD/../bin"' if bindir else ''} \
            {extra_configure_args} && \
        {post_commands} \
        make {build_target} && \
        make {install_target} && \
        cd .. && \
        rm -rf */*.la {packagename}
    """)

cuba_files = ["lib/libcuba.a", "include/cuba.h"]
contrib += \
    ConfigureAndInstall(env, cuba_files, cuba,
        pre_commands="""\
            sed -i.bak -e 's/mcc/NOmcc/g' -e 's/qmake/NOqmake/g' configure && \
            sed -i.bak \
                -e 's/puts(s)/fputs(s,stderr); putc(10,stderr)/' \
                -e 's/stdout/stderr/g' src/common/stddecl.h && \
        """,
        extra_configure_args="CFLAGS='-O3 -fno-omit-frame-pointer -ffast-math -fno-finite-math-only -fexceptions -fcommon -fPIC'",
        build_target="lib")

zlib_files = ["lib/libz.a", "include/zlib.h", "include/zconf.h"]
contrib += \
    ConfigureAndInstall(env, zlib_files, zlib, extra_configure_args="--static", bindir=False)

form_files = ["bin/form", "bin/tform"]
contrib += \
    ConfigureAndInstall(env, form_files, form,
        extra_sources = zlib_files,
        extra_configure_args="--without-gmp --with-zlib --enable-native=no")

gmp_files = open(f"{gmp}.list").read().splitlines()
contrib += \
    ConfigureAndInstall(env, gmp_files, gmp, extension=".tar.bz2",
        pre_commands="mv config.guess config.guess.orig && ln -sf configfsf.guess config.guess && ",
        extra_configure_args="--enable-cxx --enable-fat --disable-shared --enable-static --with-pic --exec-prefix=\"$$PWD/..\"")

gsl_files = open(f"{gsl}.list").read().splitlines()
contrib += \
    ConfigureAndInstall(env, gsl_files, gsl,
        extra_configure_args="--disable-shared --enable-static --with-pic")

nauty_files = ["bin/dreadnaut"]
contrib += \
    env.Command(nauty_files, [f"{nauty}.tar.gz"], f"""
        cd pySecDecContrib && \
        tar -xf {nauty}.tar.gz && \
        cd {nauty} && \
        ./configure --enable-generic --disable-popcnt --disable-clz && \
        make dreadnaut && \
        strip dreadnaut && \
        cp -a dreadnaut ../bin/dreadnaut && \
        cd .. && \
        rm -rf {nauty}
    """)

normaliz_files = ["bin/normaliz"]
contrib += \
    ConfigureAndInstall(env, normaliz_files, normaliz,
        extra_sources=gmp_files,
        pre_commands="env GMPXX_CPPFLAGS=\"-I$$PWD/../include\" GMPXX_LDFLAGS=\"-L$$PWD/../lib\" ",
        extra_configure_args="--enable-static --disable-shared --disable-openmp --with-gmp=\"$$PWD/..\" --with-cocoalib=no --with-flint=no --with-hashlibrary=no --with-nauty=no --with-e-antic=no",
        install_target="install-strip")

cln_files = open(f"{cln}.list").read().splitlines()
contrib += \
    ConfigureAndInstall(env, cln_files, cln, extension=".tar.bz2",
        extra_configure_args="--disable-shared --enable-static --with-pic --without-gmp")

ginac_files = open(f"{ginac}.list").read().splitlines()
contrib += \
    ConfigureAndInstall(env, ginac_files, ginac, extension=".tar.bz2",
        extra_sources = cln_files,
        extra_configure_args=f"--disable-shared --enable-static --with-pic --enable-excompiler=no "
            f"CLN_CFLAGS=-I$$PWD/../include CLN_LIBS=\"-L$$PWD/../lib -lcln\" "
            f"PYTHON='{sys.executable}'",
        pre_commands="sed -i.bak 's/readline/NOreadline/g' configure && ",
        install_target="install-strip")

conf = Configure(env)
librt = [] if conf.CheckFunc("clock_gettime") or not conf.CheckLib("rt") else ["rt"]
env = conf.Finish()

contrib += env.Program("bin/pysecdec_cpuworker", [f"disteval/cpuworker.cpp"],
    CXXFLAGS="-std=c++14 -O3 -Wall",
    LIBS=["ginac", "cln", "dl", *librt],
    LIBPATH=["lib"], CPPPATH=["include"], LINKFLAGS="-s")
contrib += env.Program("bin/pysecdec_cudaworker", [f"disteval/cudaworker.cpp"],
    CXXFLAGS="-std=c++14 -O3 -Wall",
    LIBS=["ginac", "cln", "dl", *librt, "pthread"],
    LIBPATH=["lib"], CPPPATH=["include"], LINKFLAGS="-s")
contrib += env.Program("bin/pysecdec_listcuda", [f"disteval/listcuda.cpp"],
    CXXFLAGS="-std=c++14 -O3 -Wall",
    LIBS=["dl"],
    LINKFLAGS="-s")
File("disteval/minicuda.h")

contrib += [File("bin/export_sector")]
contrib += [File("bin/formwrapper")]
contrib += [File("lib/write_contour_deformation.frm")]
contrib += [File("lib/write_integrand.frm")]

Return("contrib")
