from __future__ import print_function
# vim: set filetype=python :

import os
import sys
import glob

Import('env')
ReadFileList=env['_ReadFileList']

# Source lists
basic = ReadFileList('basic.files')
basic_noint = ReadFileList('basic_noint.files')
basic_omp = ReadFileList('basic_omp.files')
basic_omp_noint = ReadFileList('basic_omp_noint.files')
basic_geqp3 = ReadFileList('basic_geqp3.files')
diag = ReadFileList('diag.files')
tri = ReadFileList('tri.files')
tri_noint = ReadFileList('tri_noint.files')

band = ReadFileList('band.files')
band_noint = ReadFileList('band_noint.files')
sym = ReadFileList('sym.files')
sym_noint = ReadFileList('sym_noint.files')
sym_omp_noint = ReadFileList('sym_omp_noint.files')
sym_stegr = ReadFileList('sym_stegr.files')
symband = ReadFileList('symband.files')
symband_noint = ReadFileList('symband_noint.files')

lib_files= basic + diag + tri
lib_noint_files= basic_noint + tri_noint
lib_omp_files= basic_omp
lib_omp_noint_files= basic_omp_noint
lib_geqp3_files= basic_geqp3
sblib_files= band + sym + symband
sblib_noint_files= band_noint + sym_noint + symband_noint
sblib_omp_noint_files= sym_omp_noint
sblib_stegr_files= sym_stegr


env1 = env.Clone()

if env['MEM_DEBUG']:
    print('Using mmgr.cpp')
    lib_files += ['mmgr.cpp']

if env['NAN_TEST']:
    env1.Append(CPPDEFINES=['TMV_INITIALIZE_NAN'])
if not env['INST_FLOAT']:
    env1.Append(CPPDEFINES=['NO_INST_FLOAT'])
if not env['INST_DOUBLE']:
    env1.Append(CPPDEFINES=['NO_INST_DOUBLE'])
if env['INST_LONGDOUBLE'] or env['TEST_LONGDOUBLE']:
    env1.Append(CPPDEFINES=['INST_LONGDOUBLE'])

env2 = env1.Clone()

if env['INST_INT'] or env['TEST_INT']:
    env1.Append(CPPDEFINES=['INST_INT'])

env3 = env1.Clone()
env4 = env2.Clone()
if env['WITH_OPENMP'] :
    env3.Append(CCFLAGS=env['OMP_FLAGS'])
    env4.Append(CCFLAGS=env['OMP_FLAGS'])

env5 = env2.Clone()
if env['LAP'] :
    if not env['USE_GEQP3']:
        env5.Append(CPPDEFINES=['NOGEQP3'])

env6 = env2.Clone()
if env['LAP'] :
    if not env['USE_STEGR']:
        env6.Append(CPPDEFINES=['NOSTEGR'])

if env['SHARED']:

    obj_lib = env1.SharedObject(lib_files)
    obj_noint_lib = env2.SharedObject(lib_noint_files)
    obj_omp_lib = env3.SharedObject(lib_omp_files)
    obj_omp_noint_lib = env4.SharedObject(lib_omp_noint_files)
    obj_geqp3_lib = env5.SharedObject(lib_geqp3_files)

    obj_sblib = env1.SharedObject(sblib_files)
    obj_noint_sblib = env2.SharedObject(sblib_noint_files)
    obj_omp_noint_sblib = env4.SharedObject(sblib_omp_noint_files)
    obj_stegr_sblib = env6.SharedObject(sblib_stegr_files)

    env7 = env1.Clone()

    # Some stuff to get it to set the right library name and compatibility version:
    version_text = os.popen(os.path.join('..','bin','tmv-version')).read()
    version = tuple(version_text.strip().split('.'))
    print('TMV Version ',version_text)
    # Currently, I manually set the compatibility version when less than
    # the current version.  Any way to automate this?  Probably not.
    #compat_version = version 
    compat_version = 0,70

    lib_final_dir = os.path.join(env['FINAL_PREFIX'],'lib')

    if sys.platform == 'darwin':
        lib_final_name = os.path.join(lib_final_dir,'libtmv.%s.dylib'%compat_version[0])
        lib_full_name = os.path.join(GetBuildPath('#lib'),'libtmv.%s.%s.dylib'%version)
        lib_short_name = os.path.join(GetBuildPath('#lib'),'libtmv.%s.dylib'%version[0])
        link_name = os.path.join(GetBuildPath('#lib'),'libtmv.dylib')
        #print 'lib_final_name = ',lib_final_name
        #print 'lib_short_name = ',lib_short_name
        #print 'link_name = ',link_name
        env1.AppendUnique( SHLINKFLAGS=[
            '-dynamic',
            '-Wl,-install_name,%s'%lib_final_name,
            '-Wl,-compatibility_version,%s.%s'%compat_version,
            '-Wl,-current_version,%s.%s'%version ] )
        env1.Replace(SHLIBSUFFIX = '.%s.dylib'%compat_version[0])

        sblib_final_name = os.path.join(lib_final_dir,'libtmv_symband.%s.dylib'%compat_version[0])
        sblib_full_name = os.path.join(GetBuildPath('#lib'),'libtmv_symband.%s.%s.dylib'%version)
        sblib_short_name = os.path.join(GetBuildPath('#lib'),'libtmv_symband.%s.dylib'%version[0])
        sblink_name = os.path.join(GetBuildPath('#lib'),'libtmv_symband.dylib')
        env7.AppendUnique( SHLINKFLAGS=[
            '-dynamic',
            '-Wl,-install_name,%s'%sblib_final_name,
            '-Wl,-compatibility_version,%s.%s'%compat_version,
            '-Wl,-current_version,%s.%s'%version ] )
        env7.Replace(SHLIBSUFFIX = '.%s.dylib'%compat_version[0])

    elif sys.platform.startswith('linux'):  # Should work for both linux2 and linux3
        # If the BLAS/LAPACK libs are static, this fails on linux (at least where I tried it),
        # On the other hand, the link step doesn't seem to require the other libraries
        # as it does on OSX.  So I think it's safe to just clear out LIBS here.
        env1.Replace(LIBS=[])
        lib_final_name = 'libtmv.so.%s'%compat_version[0]
        lib_full_name = os.path.join(GetBuildPath('#lib'),'libtmv.so.%s.%s'%version)
        lib_short_name = os.path.join(GetBuildPath('#lib'),'libtmv.so.%s'%version[0])
        link_name = os.path.join(GetBuildPath('#lib'),'libtmv.so')
        env1.AppendUnique(SHLINKFLAGS=['-Wl,-soname,%s'%lib_final_name ])
        env1.Replace(SHLIBSUFFIX = '.so.%s'%compat_version[0])

        sblib_final_name = 'libtmv_symband.so.%s'%compat_version[0]
        sblib_full_name = os.path.join(GetBuildPath('#lib'),'libtmv_symband.so.%s.%s'%version)
        sblib_short_name = os.path.join(GetBuildPath('#lib'),'libtmv_symband.so.%s'%version[0])
        sblink_name = os.path.join(GetBuildPath('#lib'),'libtmv_symband.so')
        env7.AppendUnique( SHLINKFLAGS=['-Wl,-soname,%s'%sblib_final_name ]) 
        env7.Replace(SHLIBSUFFIX = '.so.%s'%compat_version[0])

    elif sys.platform == 'win32':
        raise ValueError(
            "Sorry, making shared libraries on Windows is unsupported.  Use SHARED=false")

    lib = env1.SharedLibrary(
            os.path.join('#lib','tmv'),
            obj_lib + obj_noint_lib + obj_omp_lib + obj_omp_noint_lib + obj_geqp3_lib)

    if sys.platform == 'darwin':
        env7.Prepend(LIBS=lib)

    sblib = env7.SharedLibrary(
            os.path.join('#lib','tmv_symband'),
            obj_sblib + obj_noint_sblib + obj_omp_noint_sblib + obj_stegr_sblib)

    def SymLink(target, source, env):
        #print 'SymLink: source = ',str(source[0])
        #print 'target = ',str(target[0])
        #print 'LibName = ',env['LibName']
        t = os.path.abspath(str(target[0]))
        if os.path.exists(t): os.remove(t) 
        os.symlink(env['LibName'], t)

    # This just makes a link in the #lib directory.  Need to redo this in the install directory.
    link = env1.Command( link_name , lib , SymLink, LibName=lib_short_name)
    #link2 = env1.Command( lib_full_name , lib , SymLink, LibName=lib_short_name)
    sblink = env7.Command( sblink_name , sblib , SymLink, LibName=sblib_short_name)
    #sblink2 = env7.Command( sblib_full_name , sblib , SymLink, LibName=sblib_short_name)
    Default(link,sblink)

    lib_targets = [lib,sblib]


else:
    obj_lib = env1.StaticObject(lib_files)
    obj_noint_lib = env2.StaticObject(lib_noint_files)
    obj_omp_lib = env3.StaticObject(lib_omp_files)
    obj_omp_noint_lib = env4.StaticObject(lib_omp_noint_files)
    obj_geqp3_lib = env5.StaticObject(lib_geqp3_files)

    obj_sblib = env1.StaticObject(sblib_files)
    obj_noint_sblib = env2.StaticObject(sblib_noint_files)
    obj_omp_noint_sblib = env4.StaticObject(sblib_omp_noint_files)
    obj_stegr_sblib = env6.StaticObject(sblib_stegr_files)

    lib = env1.StaticLibrary(
            os.path.join('#lib','tmv'),
            obj_lib + obj_noint_lib + obj_omp_lib + obj_omp_noint_lib + obj_geqp3_lib)
    sblib = env1.StaticLibrary(
            os.path.join('#lib','tmv_symband'),
            obj_sblib + obj_noint_sblib + obj_omp_noint_sblib + obj_stegr_sblib)
    lib_targets = [lib,sblib]

all_obj_files = \
    obj_lib + obj_noint_lib + obj_omp_lib + \
    obj_omp_noint_lib + obj_geqp3_lib + \
    obj_sblib + obj_noint_sblib + \
    obj_omp_noint_sblib + obj_stegr_sblib

# Note: this next bit depends on the object files being in the src directory.
# If this ever changes, I'll need to do something different to get the name
# of the corresponding inst file.
for objfile in all_obj_files:
    if str(objfile).startswith('TMV'):
        inst = os.path.splitext(str(objfile))[0] + '.inst'
        Depends(objfile,inst)

env.Alias(target='lib', source=lib)
env.Alias(target='sblib', source=sblib)

#
# install/uninstall
#

Default(lib_targets)

# Add the prefix to the installation directories
lib_install_dir = os.path.join(env['INSTALL_PREFIX'],'lib')
header_install_dir = os.path.join(env['INSTALL_PREFIX'],'include')
header_install_dir_sub = os.path.join(env['INSTALL_PREFIX'],'include','tmv')

lib_file = '#' + lib[0].path
sblib_file = '#' + sblib[0].path

# Save this info for share/SConscript
env['LIB_FILE_NAMES'] = [lib_file,sblib_file]

if 'install' in COMMAND_LINE_TARGETS: 

    if env['SHARED']:
        installed_lib = env1.Install(dir=lib_install_dir, source=lib)
        if sys.platform == 'darwin':
            env.Depends(sblib,installed_lib)
        installed_sblib = env7.Install(dir=lib_install_dir, source=sblib)

        installed_link_name = os.path.join(lib_install_dir, os.path.basename(link_name))
        #installed_lib_short_name = os.path.join(lib_install_dir, os.path.basename(lib_short_name))
        installed_sblink_name = os.path.join(lib_install_dir, os.path.basename(sblink_name))
        #installed_sblib_short_name = os.path.join(lib_install_dir, os.path.basename(sblib_short_name))

        installed_link = env1.Command( installed_link_name , installed_lib , SymLink,
            LibName=lib_final_name)
        #installed_link2 = env1.Command( installed_lib_short_name , installed_lib , SymLink,
            #LibName=lib_final_name)
        installed_sblink = env7.Command( installed_sblink_name , installed_sblib , SymLink, 
            LibName=sblib_final_name)
        #installed_sblink2 = env7.Command( installed_sblib_short_name , installed_sblib , SymLink, 
            #LibName=sblib_final_name)

        env.Alias(target='install', 
            source=[installed_lib,installed_sblib,
                    installed_link,installed_sblink ])

    else :
        env.Alias(target='install', 
            source=env1.Install(dir=lib_install_dir, source=lib_targets))

    hfiles1 = []
    hfiles = glob.glob(os.path.join(GetBuildPath('#include'),'tmv','TMV*.h'))
    for f in hfiles:
        hfiles1 += [os.path.join('#include','tmv',f)]
    installed_h = env1.Install(dir=header_install_dir_sub, source=hfiles1)
    env.Alias(target='install', source=installed_h)

    hfiles2 = []
    hfiles = glob.glob(os.path.join(GetBuildPath('#include'),'TMV*.h'))
    for f in hfiles:
        hfiles2 += [os.path.join('#include',f)]
    installed_h = env1.Install(dir=header_install_dir, source=hfiles2)
    env.Alias(target='install', source=installed_h)

if 'uninstall' in COMMAND_LINE_TARGETS:
    # There is no env.Uninstall method, we must build our own
    deltarget = Delete("$TARGET")

    # delete lib/*tmv.a files
    libfiles = [os.path.join(lib_install_dir, os.path.basename(str(f[0]))) for f in lib_targets]

    for f in libfiles:
        env.Alias('uninstall', env1.Command(f, None, deltarget))

    # Delete files from include/tmv
    hfiles1 = glob.glob(os.path.join(GetBuildPath('#include'),'tmv','TMV*.h'))
    for f in hfiles1:
        cmd = env1.Command(os.path.join(header_install_dir_sub,f), None, deltarget)
        env.Alias('uninstall',cmd)

    # Delete include/tmv subdirectory
    env.Alias('uninstall', env1.Command(header_install_dir_sub, None, deltarget))

    # Delete include/*.h files
    hfiles2 = os.listdir(GetBuildPath('#include'))
    hfiles2 = glob.glob(os.path.join(GetBuildPath('#include'),'TMV*.h'))
    for f in hfiles2:
        if f[0:3] == 'TMV':
            cmd = env1.Command(os.path.join(header_install_dir,f), None, deltarget)
            env.Alias('uninstall',cmd)


