#!/usr/bin/env python

"""
 This script is meant to be imported by aanet's make.py build 
 scripts. It defines the compiler and linker flags.

 When run as stand-alone command, it prints all the settings.
"""

import os, sys
from util import aafabricate
from util.aafabricate import shell, ExecutionError, run, after, subjob, subjobs_report
d1 = dir()

def env( key ) :
    try : return os.environ[key]
    except : return None
    
aadir = env('AADIR')

if not aadir :
    print("Please run 'source setenv.sh' first, to set the AAnet environment.")
    raise SystemExit

build_dir   = aadir+"/build/"
lib_dir     = aadir+"/lib/"
aa3dwww     = os.environ['HOME']+"/www/aa3d/"

root_config = os.environ['ROOTSYS'] + '/bin/root-config'
incroot     = shell(root_config,'--cflags') 
libroot     = shell(root_config,'--libs') +' -lEG '
rootcintopt = "-I"+shell(root_config,'--incdir')
rootversion = shell( root_config , "--version").split("/")

gccversion = shell("gcc","--version").splitlines()[0].split()[-1]
#gccversion = int( ( gccversion.decode("utf-8") ).split(".")[0] )  # major version only
gccversion = int( ( gccversion ).split(".")[0] ) 


cc          = "g++"
gccopt      = "-fPIC -Wall -g -O3 "

# support ancient compiler in lyon

print( gccversion, rootversion[0])

if gccversion < 5 :
    gccopt += "-std=c++11"

    if float(rootversion[0])<6.26 :
        aafabricate.stdcxx = "-std=c++11"


fortran_comp= 'gfortran -fPIC -fno-second-underscore '
libfortran  = " -lgfortran "

dirjpp      = env('JPP_DIR') or aadir+'/jpp'
#libjpp      = "-L"+dirjpp + "/out/Linux/lib/ -Wl,--unresolved-symbols=ignore-all -ltriggerROOT -llang -levtROOT -L/pbs/home/h/heijboer/sps/aanet_df/lib "
libjpp      = "-L"+dirjpp + "/out/Linux/lib/ -lacousticsROOT -lcompassROOT -ltriggerROOT -llang -luuid -levtROOT  -L/pbs/home/h/heijboer/sps/aanet_df/lib "
incjpp      = "-I" + dirjpp + "/software/ -I"+dirjpp+"/externals/antares-daq/include/"

haveantcc   = os.path.exists( dirjpp+"/externals/antares-daq/include/antcc")

incaa       = "-I" + aadir + "/evt -I"+aadir+"/astro -I" + aadir +" -I"+aadir+"/externals -I"+aadir+"/externals/km3net-dataformat/offline " +"-I"+aadir+"/externals/km3net-dataformat/online -I"+aadir+"/externals/flux"

libdatafmt  = "-L"+aadir+"/externals/km3net-dataformat/lib/ -lKM3NeTROOT -luuid"
libflux     = "-L"+aadir+"/externals/flux/ -lKM3NeTflux"

libaa        =  "-L"+aadir+"/lib -laaevt -laastro " + libfortran


    
# ---------------------------------
# Check jpp and antcc
# ---------------------------------

if os.path.exists( dirjpp ) :
    gccopt += " -D HAVEJPP "
    rootcintopt += " -DHAVEJPP "

    if not dirjpp in env("LD_LIBRARY_PATH"):

        print ("note: JPP lib dir not in LD_LIBRARY_PATH -> using full-path linking")
        w = " -Wl,-rpath,"+dirjpp+"/out/Linux/lib "
        libjpp = w + libjpp
        
else :
    print ("NOTE: will build without JPP")
    libjpp = incjpp = dirjpp = ""
    
if haveantcc   : 
    gccopt += " -D HAVEANTCC "
    rootcintopt += "-DHAVEANTCC "
    libjpp += dirjpp + "/externals/antares-daq/out/Linux/lib/libantccROOT.so "


# -------------------------------------------------
#  Some strange hack for apple(?) 
# -------------------------------------------------    
if sys.platform == 'darwin':
    incroot = incroot.replace('-stdlib=libc++', '')
    libroot = libroot.replace('-stdlib=libc++', '')



    
# =================================================
#  default functions to compile, build, etc 
# =================================================

def base( s ):
    return s.rsplit('.',1)[0].rsplit("/")[-1]


def write_dictionary( source_file ) :    
    "call rootcint on a source file. If the source file is a .cc, the dictonary uses the .hh"
    
    dict_cc_file = build_dir+"/"+base(source_file)+'.dict.cc'
    linkdef      = base(source_file)+'.linkdef.h'
    source_file  = source_file.replace(".cc",".hh")

    run('rootcling -f {dict_cc_file} {rootcintopt} {incaa} {incjpp} {source_file} {linkdef}')
    return dict_cc_file


def compile( source_file , extra_args = "" ) :

    obj = build_dir+"/"+base(source_file)+'.o'
    
    # tell gcc we really want to build an obj file, even if it's a .hh
    xopt = "-x c++" if source_file.endswith("h") else ""
    run('{cc} {gccopt} -c -o {obj} {extra_args} -I. {incaa} {incroot} {incjpp} {xopt} {source_file} ')
    return obj


def compile_fortran( source_file ):
    obj = source_file.replace(".f",".o")
    run('{fortran_comp} -c -o {obj} {source_file} ')
    return obj


def make_library( object_files, target , extra_link_args = "" ):
    objs = " ".join( object_files )
    res = run('{cc} {gccopt} -shared {objs} {libroot} {libdatafmt} {libflux} {libjpp} {extra_link_args} -o {target} ')
    return res


def make_executable( source_file,
                     target = 'auto',
                     extra_args = '' ):

    if target == 'auto' : target = source_file.replace(".cc","")
    res = run('{cc} -Wl,--no-as-needed  {gccopt} {incaa} {incroot} {incjpp} {libroot} {libdatafmt} {libflux} {libjpp} {libaa} {extra_args} -o {target} {source_file} ')

    
def default_build_shared_library( sources,
                                  target,
                                  extra_link_args = "",
                                  extra_compile_args = "" ):
     
    with subjob("generating root dictionaries") :
        
        dict_files = [ write_dictionary( s ) for s in sources ]
   
    with subjob("compiling c++ files"):
        
        obj_files = [ compile( s , extra_args = extra_compile_args ) for s in sources + dict_files ]
   
        
    with subjob("linking and copying pcm files"):
        
        make_library( obj_files , target , extra_link_args )
        pcm_files = " ".join( s.replace('.cc' , '_rdict.pcm' ) for s in dict_files )
        run("cp {pcm_files} {lib_dir}")

    subjobs_report()


    
# -------------------------------------------------
#  Parameters that control the build process
# -------------------------------------------------

dependency_dirs = [ '.', aadir ] 
parallel_jobs   = 4
build_debug     = True

    
# -------------------------------------------------
#  Nice output
# -------------------------------------------------

D = locals() 
setup_s = "\n".join( [ "%15s : %s " % (k, D[k]) for k in dir() if k not in d1 and k != 'd1' \
                       and not k.startswith("__") ] )

def print_setup():
    print ("========================================================================")
    print (setup_s)
    print ("========================================================================")    

if __name__ == "__main__" :
    print_setup()