# vim: filetype=python expandtab sw=4 tabstop=4

import string
import os

Import("commonEnvironment", "commandOptions", "util" )
Import("configure")

commandOptions.Add('buildInterfaces',
    "Build interface library for C++.",
    '0')
commandOptions.Add('buildLuaWrapper',
    "Build interface library for Lua (needs buildInterfaces)",
    '0')
commandOptions.Add('buildPythonWrapper',
    "Build interface library for Python (needs buildInterfaces)",
    '0')
commandOptions.Add('buildJavaWrapper',
    'Set to 1 to build Java wrapper for the interface library (needs buildInterfaces).',
    '0')

commandOptions.Update(commonEnvironment)
util.fixEnvForOLPC(commonEnvironment)


# Ugly but necessary: scons doesn't manage swig that well
# We need to list all files because the scons scanner won't always
# detect all of them and thus fail sometimes
javaSources = Split('''
    CppSound.java                   csCfgVariableBoolean_t.java
    csCfgVariableDouble_t.java      csCfgVariableFloat_t.java
    csCfgVariableHead_t.java        csCfgVariableInt_t.java
    csCfgVariableMYFLT_t.java       csCfgVariableString_t.java
    csCfgVariable_t.java            csndConstants.java
    csnd.java                       csndJNI.java
    CsoundArgVList.java             CsoundCallbackWrapper.java
    CsoundChannelListEntry.java     CsoundChannelList.java
    CsoundFile.java                 CSOUND_FILETYPES.java
    Csound.java                     CsoundMidiInputBuffer.java
    CsoundMidiInputStream.java      CsoundMidiOutputBuffer.java
    CsoundMidiOutputStream.java     CsoundMutex.java
    CsoundMYFLTArray.java           CsoundOpcodeList.java
    CsoundPerformanceThread.java    CsoundRandMT.java
    CsoundRandMTState.java          CSOUND_STATUS.java
    CsoundThreadLock.java           CsoundTimer.java
    CsoundUtilityList.java          csRtAudioParams.java
    IntToStringMap.java             MyfltVector.java
    opcodeListEntry.java            PVSDATEXT.java
    RTCLOCK.java                    Soundfile.java
    SWIGTYPE_p_cslanguage_t.java    SWIGTYPE_p_CSOUND_.java
    SWIGTYPE_p_double.java          SWIGTYPE_p_FILE.java
    SWIGTYPE_p_float.java
    SWIGTYPE_p_f_p_CSOUND__int_p_q_const__char_va_list__void.java
    SWIGTYPE_p_f_p_CSOUND__p_p_void_p_q_const__char__int.java
    SWIGTYPE_p_f_p_CSOUND__p_q_const__char_float__void.java
    SWIGTYPE_p_f_p_CSOUND__p_q_const__char_p_float_int__void.java
    SWIGTYPE_p_f_p_CSOUND__p_q_const__char_p_float__void.java
    SWIGTYPE_p_f_p_CSOUND__p_void__int.java
    SWIGTYPE_p_f_p_CSOUND__p_void_p_unsigned_char_int__int.java
    SWIGTYPE_p_f_p_void_p_void_unsigned_int__int.java
    SWIGTYPE_p_f_p_void__uintptr_t.java
    SWIGTYPE_p_f_p_void__void.java
    SWIGTYPE_p_int32.java
    SWIGTYPE_p_int.java
    SWIGTYPE_p_int_least64_t.java
    SWIGTYPE_p_p_char.java
    SWIGTYPE_p_p_csCfgVariable_u.java
    SWIGTYPE_p_p_CsoundChannelListEntry_.java
    SWIGTYPE_p_p_float.java
    SWIGTYPE_p_p_opcodeListEntry.java
    SWIGTYPE_p_p_p_char.java
    SWIGTYPE_p_p_void.java
    SWIGTYPE_p_std__istream.java
    SWIGTYPE_p_std__ostream.java
    SWIGTYPE_p_std__string.java
    SWIGTYPE_p_std__vectorT_char_p_t.java
    SWIGTYPE_p_std__vectorT_std__string_t.java
    SWIGTYPE_p_uint32.java
    SWIGTYPE_p_uintptr_t.java
    SWIGTYPE_p_unsigned_char.java
    SWIGTYPE_p_unsigned_int.java
    SWIGTYPE_p_void.java
''')

if commonEnvironment['buildInterfaces'] == '1':
    if not 'swig' in commonEnvironment['TOOLS']:
        util.fatal('You specified buildInterfaces but swig was not found')
    util.confDecision('Building Csound interfaces library.')

    csoundInterfacesEnvironment = commonEnvironment.Clone()
    csoundInterfacesEnvironment.Append(CPPPATH = ['#./interfaces'])
    csoundInterfacesSources = []
    for i in Split('''CppSound CsoundFile Soundfile csPerfThread
      cs_glue filebuilding pyMsgCb'''):
        csoundInterfacesSources.append('%s.cpp' % i)
    if util.platform == 'win32' and util.compilerGNU():
        csoundInterfacesEnvironment.Append(
            SHLINKFLAGS = '-Wl,--add-stdcall-alias')
    csoundInterfacesEnvironment.Append(SWIGFLAGS = 
        Split('''-c++ -includeall -verbose'''))
    csoundWrapperEnvironment = csoundInterfacesEnvironment.Clone()

    if util.platform == 'darwin':
        if commonEnvironment['dynamicCsoundLibrary'] == '1':
            ilibName = "lib_csnd.dylib"
            ilibVersion = util.csoundLibraryVersion
            csoundInterfacesEnvironment.Append(SHLINKFLAGS = Split(
                '''-Xlinker -compatibility_version
                -Xlinker %s''' % ilibVersion))
            csoundInterfacesEnvironment.Append(SHLINKFLAGS = Split(
                '''-Xlinker -current_version -Xlinker %s''' % ilibVersion))
            tmp = '''-install_name
                /Library/Frameworks/CsoundLib.framework/Versions/%s/%s'''
            csoundInterfacesEnvironment.Append(SHLINKFLAGS = Split(
                 tmp % ('5.1', ilibName)))
            csoundInterfaces = csoundInterfacesEnvironment.SharedLibrary(
                '_csnd', csoundInterfacesSources)
        else:
            csoundInterfaces = csoundInterfacesEnvironment.Library(
                '_csnd', csoundInterfacesSources)
    elif util.platform == 'linux':
        csoundInterfacesEnvironment.Append(LINKFLAGS = ['-Wl,-rpath-link,.'])
        name    = 'libcsnd.so'
        soname  = name + '.' + util.csoundLibraryVersion
        # This works because scons chdirs while reading SConscripts
        # When building stuff scons doesn't chdir by default!
        try     : os.symlink(soname, '%s' % name)
        except  : pass
        Clean(soname, name) #Delete symlink on clean
        linkflags = csoundInterfacesEnvironment['SHLINKFLAGS']
        soflag = [ '-Wl,-soname=%s' % soname ]
        extraflag = ['-L.']
        csoundInterfaces = csoundInterfacesEnvironment.SharedLibrary(
            soname, csoundInterfacesSources, 
            SHLINKFLAGS = linkflags+soflag+extraflag,
            SHLIBPREFIX = '', SHLIBSUFFIX = '')
    else:
        csoundInterfaces = csoundInterfacesEnvironment.SharedLibrary(
            'csnd', csoundInterfacesSources)

    util.fixCFlagsForSwig(csoundWrapperEnvironment)
    csoundWrapperEnvironment.Append(CPPFLAGS = '-D__BUILDING_CSOUND_INTERFACES')
    csoundWrapperEnvironment.Append(LIBS = csoundInterfaces[0])
    for option in csoundWrapperEnvironment['CCFLAGS']:
        if string.find(option, '-D') == 0:
            csoundWrapperEnvironment.Append(SWIGFLAGS = [option])
    for option in csoundWrapperEnvironment['CPPFLAGS']:
        if string.find(option, '-D') == 0:
            csoundWrapperEnvironment.Append(SWIGFLAGS = [option])
    for option in csoundWrapperEnvironment['CPPPATH']:
        csoundWrapperEnvironment.Append(SWIGPATH = [option])
    swigflags = csoundWrapperEnvironment['SWIGFLAGS']

    if commonEnvironment['buildPythonWrapper'] != '0':
        csndPythonEnvironment = csoundWrapperEnvironment.Clone()
        if not util.fixEnvForPython( csndPythonEnvironment, configure):
            util.fatal("You specified buildPythonWrapper but Python was not found")

        util.confDecision("Building Csound Python interface library")
        csndPythonEnvironment.Append(LINKFLAGS = pythonLinkFlags)
        csndPythonEnvironment.Prepend(LIBPATH = pythonLibraryPath)
        csndPythonEnvironment.Prepend(LIBS = pythonLibs)
        csndPythonEnvironment.Append(CPPPATH = pythonIncludePath)
        util.fixCFlagsForSwig(csndPythonEnvironment)
        csndPythonEnvironment.Append(LIBS = csoundInterfaces)
        csndPythonEnvironment.Append(SWIGFLAGS = ['-python', '-outdir',
            'interfaces'])
        csndModule = util.makePythonModule(
            csndPythonEnvironment, 'csnd', 'python_interface.i')
        csndPythonEnvironment.Clean(csndModule, 'python_interface_wrap.h')

    if commonEnvironment['buildLuaWrapper'] != '0':
        if not configure.CheckHeader('lua5.1/lua.h', language = 'C'):
            util.fatal("You specified buildLuaWrapper but Lua was not found")
        util.confDecision('Building Csound Lua interface library.')
        csoundLuaEnvironment = csoundWrapperEnvironment.Clone()
        csoundLuaEnvironment.Append(CPPPATH=['/usr/include/lua5.1'])
        csoundLuaEnvironment.Append(SWIGFLAGS = ['-lua', '-outdir',
            'interfaces'])
        csoundLuaEnvironment.Append(LIBS = csoundInterfaces)
        csoundLuaInterface = csoundLuaEnvironment.SharedLibrary('lua-csnd',
            'lua_interface.i')
        if util.platform == 'win32':
            csoundInterfacesEnvironment.Prepend(LIBS = ['lua51'])
        else:
            csoundInterfacesEnvironment.Prepend(LIBS = ['lua'])


    if commonEnvironment['buildJavaWrapper'] != '0':
        if util.platform == 'darwin':
            javaFound   = configure.CheckHeader(
                "/System/Library/Frameworks/JavaVM.Framework/Headers/jni.h",
                language = "C++")
        else:
            javaFound   = configure.CheckHeader("jni.h", language = "C++")
        if not javaFound:
            util.fatal("You specified buildJavaWrapper but java was not found")
        util.confDecision('Building Java wrappers for Csound interfaces library.')
        csoundJavaWrapperEnvironment = csoundWrapperEnvironment.Clone()
        csoundJavaWrapperEnvironment.Append(
            SWIGFLAGS = [ '-java', '-package', 'csnd'] )
        csoundJavaWrapperEnvironment.Append(LIBS = csoundInterfaces)
        if util.platform == 'darwin':
            csoundWrapperEnvironment.Append(CPPPATH =
                ['/System/Library/Frameworks/JavaVM.Framework/Headers'])

        csoundJavaWrapperSources = [ 'java_interface.i', 'pyMsgCb_stub.cpp' ]

        if util.platform == 'darwin':
            csoundJavaWrapperEnvironment.Prepend(LINKFLAGS  = ['-bundle'])
            csoundJavaWrapperEnvironment.Append(
                LINKFLAGS   = ['-framework', 'JavaVM', '-Wl'])
            csoundJavaWrapper = csoundJavaWrapperEnvironment.Program(
                'lib_jcsound.jnilib', csoundJavaWrapperSources)
        else:
            csoundJavaWrapper = csoundJavaWrapperEnvironment.SharedLibrary(
                '_jcsound', csoundJavaWrapperSources)

        # Make sure the java builder sees all java files
        Execute( Touch(javaSources) )
        jcsnd = csoundJavaWrapperEnvironment.Java(
            target      = './', source = './',
            JAVACFLAGS  = ['-source', '1.4', '-target', '1.4'] )

        Depends(jcsnd, csoundJavaWrapper)
        Clean( '.', 'java_interface_wrap.h')
        Clean( csoundJavaWrapper, javaSources )
        Clean( jcsnd, 'csnd' )

        Execute( Mkdir('csnd') )
        jcsndJar = csoundJavaWrapperEnvironment.Jar(
            'csnd.jar', ['csnd'], JARCHDIR = 'interfaces')
        Depends(jcsndJar, jcsnd)
    else:
        util.confDecision('Not building Java wrappers for Csound interfaces library.')