# vim: filetype=python expandtab sw=4 tabstop=4
# Synched to SConstruct revision 1.710, except for the Sun changes in 1.769
print '''
C S O U N D 5

SCons build file for Csound 5:
API library, plugin opcodes, utilities, and front ends.

By Michael Gogins <gogins at pipeline dot com>

For custom options, run 'scons -h'.
For default options, run 'scons -H'.
If headers or libraries are not found, edit 'custom.py'.
For Linux, run in the standard shell
    with standard Python and just run 'scons'.
For MinGW, run in the MSys shell
    and use www.python.org WIN32 Python to run scons.
For Microsoft Visual C++, run in the Platform SDK
    command shell, and use www.python.org WIN32 Python to run scons.
'''

import time
import glob
import os
import os.path
import sys
import string
import shutil
import copy

#############################################################################
#
#   UTILITY FUNCTIONS
#############################################################################

# This class contains all utility functions that are needed.
class Utility:

    def __init__(self):
        if sys.platform[:5] == 'linux'      : self.platform = 'linux'
        elif sys.platform[:3] == 'win'      : self.platform = 'win32'
        elif sys.platform[:6] == 'darwin'   : self.platform = 'darwin'
        else                                : self.platform = 'unsupported'
        # library version is CS_VERSION.CS_APIVERSION
        self.csoundLibraryVersion = '5.2'
        self.csoundLibraryName = 'csound'

    def compilerIntel(self):
        if self.platform == 'win32' and initialEnvironment['withICL'] == '1':
            return True
        else:
            return False

    def compilerMicrosoft(self):
        if self.platform == 'win32' and initialEnvironment['withMSVC'] == '1':
            return True
        else:
            return False

    def compilerGNU(self):
        if not self.compilerIntel() and not self.compilerMicrosoft():
            return True
        else:
            return False

    def MacOSX_InstallHeader(self, headerName):
        if not buildOSXFramework:
            return
        baseName = headerName[(headerName.rfind('/') + 1):]
        targetName = '%s/Headers/%s' % (OSXFrameworkCurrentVersion, baseName)
        cmd = 'cp -f %s %s' % (headerName, targetName)
        csoundFrameworkEnvironment.Command(targetName, headerName, cmd)

    def MacOSX_InstallPlugin(self, fileName):
        if buildOSXFramework:
            pluginDir = '%s/Resources/Opcodes' % OSXFrameworkCurrentVersion
            if initialEnvironment['useDouble'] != '0':
                pluginDir += '64'
            cmd = 'cp -f %s %s/' % (fileName, pluginDir)
            csoundFrameworkEnvironment.Command('%s/%s' % (pluginDir, fileName),
                    fileName, cmd)

    def makePlugin(self, env, pluginName, srcs):
        pluginLib = env.SharedLibrary(pluginName, srcs)
        self.MacOSX_InstallPlugin('lib' + pluginName + '.dylib')
        plugindir = "csound/plugins"
        if env['useDouble'] == '1':
            plugindir += '64'
        plugindir += '-%s' % self.csoundLibraryVersion
        self.installLib(pluginLib, plugindir)
        return pluginLib

    def fixCFlagsForSwig(self, env):
        if '-pedantic' in env['CCFLAGS']:
            env['CCFLAGS'].remove('-pedantic')
        if '-pedantic' in env['CXXFLAGS']:
            env['CXXFLAGS'].remove('-pedantic')
        if self.compilerGNU():
            # work around non-ANSI type punning in SWIG generated wrapper files
            env['CCFLAGS'].append('-fno-strict-aliasing')
            env['CXXFLAGS'].append('-fno-strict-aliasing')

    def makePythonModule(self, env, targetName, srcs):
        if self.platform == 'darwin':
            env.Prepend(LINKFLAGS = ['-bundle'])
            pyModule_ = env.Program('_%s.so' % targetName, srcs)
        else:
            if self.platform == 'linux':
                pyModule_ = env.SharedLibrary('%s' % targetName, srcs,
                        SHLIBPREFIX="_", SHLIBSUFFIX = '.so')
            else:
                pyModule_ = env.SharedLibrary('_%s' % targetName,
                        srcs, SHLIBSUFFIX = '.pyd')
            if self.platform == 'win32' and \
             initialEnvironment['pythonVersion'] < '2.4':
                    Depends(pyModule_, pythonImportLibrary)
            print "PYTHON MODULE %s..." % targetName
        modulesdir = 'lib/python%s/site-packages' % env['pythonVersion']
        self.installFiles(pyModule_, modulesdir)
        self.installFiles('%s.py' % targetName, modulesdir)
        return pyModule_

    def addOSXResourceFork(self, env, baseName, dirName):
        if self.platform == 'darwin':
            if dirName != ''    : fileName = dirName + '/' + baseName
            else                : fileName = baseName
            env.Command(('%s/resources' % fileName).replace('/', '_'), fileName,
                        "/Developer/Tools/Rez -i APPL -o $SOURCE cs5.r")

    def fluidTarget(self, env, dirName, baseName, objFiles, dir = None):
        flFile = dirName + '/' + baseName + '.fl'
        cppFile = dirName + '/' + baseName + '.cpp'
        hppFile = dirName + '/' + baseName + '.hpp'
        if dir != None:
            env.Command([cppFile, hppFile], flFile,
                        'fluid -c -o %s/%s -h %s/%s %s/%s' % 
                        (dir, cppFile, dir, hppFile, dir, flFile))
        else:
            env.Command([cppFile, hppFile], flFile,
                    'fluid -c -o %s -h %s %s' % (cppFile, hppFile, flFile))
        for i in objFiles:
            Depends(i, cppFile)
        return cppFile

    def gettextTarget(self, env, baseName, target):
        gtFile = 'po/' + baseName + '.po'
        ttFile = 'po/' + target + '/LC_MESSAGES/csound5.mo'
        env.Command(ttFile, gtFile, 'msgfmt -o %s %s' % (ttFile, gtFile))
        self.installFiles(target, 'share/locale')
        return ttFile
    # Output stuff
    def confDecision(self, msg):
        print "CONFIGURATION DECISION: " + msg
    def fatal(self, msg):
        print >> sys.stderr, "FATAL: " + msg
        Exit(1)

    def fixEnvForOLPC(self, env):
        if env['buildOLPC'] == '1':
            env['pythonVersion']    = '2.5'
            env.Prepend(CPPFLAGS    = ['-DOLPC'])
            env.Prepend(CPPFLAGS    = ['-DENABLE_OPCODEDIR_WARNINGS=0'])

            if util.getPlatform() != 'linux': print "Build platform is not linux"
            # Set other options??
            env['useGettext']           = '1'
            env['useDouble']            = '0'
            env['usePortAudio']         = '0'
            env['useJack']              = '1'
            env['usePulseAudio']        = '1'
            env['buildCsoundAC']        = '0'
            env['buildCsound5GUI']      = '0'
            env['useDouble']            = '0'
            env['usePortMIDI']          = '0'
            env['useALSA']              = '1'
            env['useFLTK']              = '0'
            env['buildCsoundVST']       = '0'
            env['buildCsoundAC']        = '0'
            #'buildCsound5GUI'
            env['buildLoris']           = '0'
            env['buildStkOpcodes']      = '0'
            env['useOSC']               = '1'
            env['buildFluidOpcodes']    = '0'
            env['prefix']               = '/usr'
            env['buildUtilities']       = '0'
            env['gcc3opt']              = 'k6'
            env['useLrint']             = '1'
            env['Word64']               = '0'
            env['Lib64']                = '0'
            env['buildPDClass']         = '0'
            env['buildDSSI']            = '0'
            env['buildVirtual']         = '1'
            env['buildInterfaces']      = '1'
            env['buildJavaWrapper']     = '0'
            env['buildNewParser']       = '0'
            env['buildvst4cs']          = '0'
            env['buildImageOpcodes']    = '1'
            env['dynamicCsoundLibrary'] = '1'

    def fixEnvForPython(self, env, conf):
        if util.platform == 'linux':
            path1 = '/usr/include/python%s' % env['pythonVersion']
            path2 = '/usr/local/include/python%s' % env['pythonVersion']
            pythonIncludePath   = [path1, path2]
            pythonLinkFlags     = []
            if env['Lib64'] == '1':
                tmp = '/usr/lib64/python%s/config' % env['pythonVersion']
                pythonLibraryPath   = ['/usr/local/lib64', '/usr/lib64', tmp]
            else:
                tmp = '/usr/lib/python%s/config' % env['pythonVersion']
                pythonLibraryPath   = ['/usr/local/lib', '/usr/lib', tmp]
            pythonLibs              = ['python%s' % env['pythonVersion']]
        elif util.platform == 'darwin':
            # find Mac OS X major version
            fout = os.popen("uname -r")
            kernelstr = fout.readline()
            fout.close()
            OSXvers = int(kernelstr[:kernelstr.find('.')]) - 4
            print "Mac OS X version 10.%d" % OSXvers
            # dictionary mapping OS X version to Apple Python version
            # ex. 4:3 maps OS X 10.4 to Python 2.3
            # Note that OS X 10.2 did not ship with a Python framework
            # and 10.0 and 10.1 shipped with no Python at all
            OSXSystemPythonVersions = { 0:0, 1:0, 2:2, 3:3, 4:3, 5:5 }
            sysPyVers = OSXSystemPythonVersions[OSXvers]
            if OSXvers >= 2:
                print "Apple Python version is 2.%d" % sysPyVers
            # vers = (int(sys.hexversion) >> 24, (int(sys.hexversion) >> 16) & 255)
            vers = sys.version_info
            pvers = "%s.%s" % (vers[0], vers[1])
            # This logic is not quite right on OS X 10.2 and earlier
            # or if the MacPython version equals the expected Apple Python version
            if vers[1] == sysPyVers:
                print "Current Python version is %s, using Apple Python Framework" % pvers
                pyBasePath = '/System/Library/Frameworks/Python.framework'
            else:
                print "Current Python version is %s, using MacPython Framework" % pvers
                pyBasePath = '/Library/Frameworks/Python.framework'
            if commonEnvironment['pythonVersion'] != pvers:
                commonEnvironment['pythonVersion'] = pvers
                print "WARNING python version used is " + pvers
            pythonIncludePath = ['%s/Headers' % pyBasePath]
            pythonLinkFlags = [ '-F' + pyBasePath, '-framework', 'python']
            path1 = '%s/Versions/Current/lib' % pyBasePath
            path2 = '%s/python%s/config' % (path1, commonEnvironment['pythonVersion'])
            pythonLibraryPath = [path1, path2]
            pythonLibs = []
        elif util.platform == 'win32':
            pythonIncludePath   = []
            pythonLinkFlags     = []
            pythonLibraryPath   = []
            pythonLibs          = ['python%s' % env['pythonVersion'].replace('.', '')]

        pythonFound = conf.CheckHeader("Python.h", language = "C" )
        for path in pythonIncludePath:
            pythonFound = pythonFound or conf.CheckHeader(
                "%s/Python.h" % path, language = "C")

        if not pythonFound:
            return False
        env.Append( CPPPATH = pythonIncludePath )
        env.Append( LINKFLAGS = pythonLinkFlags )
        env.Append( LIBPATH = pythonLibraryPath )
        env.Append( LIBS = pythonLibs )
        return True

    def installFiles(self, files, subdir):
        # initialEnvironment is the first one to exist
        if initialEnvironment['install'] == '1':
            destdir = initialEnvironment['instdir']
            destdir += "/%s/%s" % (initialEnvironment['prefix'], subdir)
            destdir = destdir.replace("//", "/")
            # most likely
            if destdir[0] != '/':
                destdir = '#' + destdir
            Default(initialEnvironment.Install(destdir, files))

    def installProgram(self, program):
        self.installFiles(program, "bin")

    def installLib(self, lib, subdir = None):
        libdir = "lib"
        if initialEnvironment['Lib64'] == '1':
            libdir += "64"
        if subdir:
            libdir += "/" + subdir
        self.installFiles(lib, libdir)

    def installHeaders(self, headers):
        self.installFiles(headers, "include/csound")

util = Utility()

headers = Split('''
    H/cfgvar.h H/cscore.h H/csdl.h H/csound.h H/csound.hpp H/csoundCore.h
    H/cwindow.h H/msg_attr.h H/OpcodeBase.hpp H/pstream.h H/pvfileio.h
    H/soundio.h H/sysdep.h H/text.h H/version.h
    interfaces/CsoundFile.hpp interfaces/CppSound.hpp interfaces/filebuilding.h
    interfaces/csPerfThread.hpp
''')

#############################################################################
#
#   DEFINE CONFIGURATION
#
#############################################################################

print "System platform is '" + util.platform + "'."

# Create options that can be set from the command line.

commandOptions = Options()
commandOptions.Add('CC')
commandOptions.Add('CXX')
commandOptions.Add('LINK')
commandOptions.Add('LINKFLAGS')
commandOptions.Add('custom',
    'Specify name of custom options file (default is "custom.py")',
    'custom.py')
commandOptions.Add('useDouble',
    'Set to 1 to use double-precision floating point for audio samples.',
    '0')
commandOptions.Add('usePortAudio',
    'Set to 1 to use PortAudio for real-time audio input and output.',
    '1')
commandOptions.Add('usePortMIDI',
    'Build PortMidi plugin for real time MIDI input and output.',
    '1')
commandOptions.Add('useALSA',
    'Set to 1 to use ALSA for real-time audio and MIDI input and output.',
    '1')
commandOptions.Add('usePulseAudio',
    'Set to 1 to use PulseAudio for real-time audio and MIDI input and output.',
    '0')
commandOptions.Add('useJack',
    'Set to 1 if you compiled PortAudio to use Jack; also builds Jack plugin.',
    '1')
commandOptions.Add('pythonVersion',
    'Set to the Python version to be used.',
    '%d.%d' % (int(sys.hexversion) >> 24, (int(sys.hexversion) >> 16) & 255))
commandOptions.Add('generateTags',
    'Set to 1 to generate TAGS',
    '0')
commandOptions.Add('generatePdf',
    'Set to 1 to generate PDF documentation',
    '0')
commandOptions.Add('buildPythonOpcodes',
    'Set to 1 to build Python opcodes',
    '0')
commandOptions.Add('prefix',
    'Base directory for installs. Defaults to /usr/local.',
    '/usr/local')
commandOptions.Add('instdir',
    'For the install target: puts instdir before the prefix',
    '')
commandOptions.Add('buildRelease',
    'Set to 1 to build for release (implies noDebug).',
    '0')
commandOptions.Add('noDebug',
    'Build without debugging information.',
    '0')
commandOptions.Add('gcc3opt',
    'Enable gcc 3.3.x or later optimizations for a specific CPU architecture (e.g. pentium3); implies noDebug.',
    '0')
commandOptions.Add('gcc4opt',
    'Enable gcc 4.0 or later optimizations for a specific CPU architecture (e.g. pentium3); implies noDebug.',
    '0')
commandOptions.Add('useLrint',
    'Use lrint() and lrintf() for converting floating point values to integers.',
    '0')
commandOptions.Add('useGprof',
    'Build with profiling information (-pg).',
    '0')
commandOptions.Add('Word64',
    'Build for 64bit computer',
    '0')
commandOptions.Add('Lib64',
    'Build for lib64 rather than lib',
    '0')
commandOptions.Add('bufferoverflowu',
    'Set to 1 to use the Windows buffer overflow library, required if you use MinGW to link with MSVC-built libraries',
    '0')
if util.platform == 'win32':
    commandOptions.Add('dynamicCsoundLibrary',
        'Set to 0 to build static Csound library instead of csound.dll',
        '1')
else:
    commandOptions.Add('dynamicCsoundLibrary',
        'Build dynamic Csound library instead of libcsound.a',
        '0')
commandOptions.Add('buildStkOpcodes',
    "Build opcodes encapsulating Perry Cook's Synthesis Toolkit in C++ instruments and effects",
    '0')
commandOptions.Add('install',
    'Enables the Install targets',
    '0')
commandOptions.Add('useCoreAudio',
    "Set to 1 to use CoreAudio for real-time audio input and output.",
    '1')
commandOptions.Add('useAltivec',
    "On OSX use the gcc AltiVec optmisation flags",
    '0')
commandOptions.Add('buildUtilities',
    "Build stand-alone executables for utilities that can also be used with -U",
    '1')
commandOptions.Add('withICL',
    'On Windows, set to 1 to build with the Intel C++ Compiler (also requires Microsoft Visual C++), or set to 0 to build with MinGW',
    '0')
commandOptions.Add('withMSVC',
    'On Windows, set to 1 to build with Microsoft Visual C++, or set to 0 to build with MinGW',
    '0')
commandOptions.Add('buildNewParser',
    'Enable building new parser (requires Flex/Bison)',
    '0')
commandOptions.Add('buildvst4cs',
    'Set to 1 to build vst4cs plugins (requires Steinberg VST headers)',
    '0')
commandOptions.Add('useGettext',
    'Set to 1 to use the GNU internationalisation/localisation scheme',
    '0')
##### JPff for OLPC #####
commandOptions.Add('buildOLPC',
    'Set to 1 to build OLPC version',
    '0')

# Define the common part of the build environment.
# This section also sets up customized options for third-party libraries, which
# should take priority over default options.

if util.compilerIntel():
    print 'Importing complete environment for the Intel C++ Compiler (ICL)...'
    initialEnvironment = Environment(ENV = os.environ)
    Tool('icl')(initialEnvironment)
    optionsFilename = 'custom-msvc.py'
elif util.compilerMicrosoft():
    # To enable the Microsoft tools, 
    # the WHOLE environment must be imported,
    # not just the PATH; so we replace the 
    # enviroment with a more complete one.
    print 'Importing complete environment for Microsoft Visual C++ (MSVC)...'
    initialEnvironment = Environment(ENV = os.environ)
    optionsFilename = 'custom-msvc.py'
elif util.platform == 'win32':
    # Similarly, on Windows, to exclude MSVC tools,
    # we have to force MinGW tools and then re-create
    # the environment from scratch.
    initialEnvironment = Environment(ENV = os.environ, tools = ['mingw', 'swig', 'javac', 'jar'])
    #Tool('mingw')(initialEnvironment)
    optionsFilename = 'custom-mingw.py'
else:
    initialEnvironment = Environment(ENV = os.environ)
    optionsFilename = 'custom.py'

commandOptions.Update(initialEnvironment)

Help(commandOptions.GenerateHelpText(initialEnvironment))

if initialEnvironment['custom']:
    optionsFilename = initialEnvironment['custom']

util.installHeaders(headers)

print "Using options from '%s.'" % optionsFilename

fileOptions = Options(optionsFilename)
fileOptions.Add('customCPPPATH', 'List of custom CPPPATH variables')
fileOptions.Add('customCCFLAGS')
fileOptions.Add('customCXXFLAGS')
fileOptions.Add('customLIBS')
fileOptions.Add('customLIBPATH')
fileOptions.Add('customSHLINKFLAGS')
fileOptions.Add('customSWIGFLAGS')
fileOptions.Update(initialEnvironment)

customCPPPATH       = initialEnvironment['customCPPPATH']
initialEnvironment.Prepend(CPPPATH = customCPPPATH)
customCCFLAGS       = initialEnvironment['customCCFLAGS']
initialEnvironment.Prepend(CCFLAGS = customCCFLAGS)
customCXXFLAGS      = initialEnvironment['customCXXFLAGS']
initialEnvironment.Prepend(CXXFLAGS = customCXXFLAGS)
customLIBS          = initialEnvironment['customLIBS']
initialEnvironment.Prepend(LIBS = customLIBS)
customLIBPATH       = initialEnvironment['customLIBPATH']
initialEnvironment.Prepend(LIBPATH = customLIBPATH)
customSHLINKFLAGS   = initialEnvironment['customSHLINKFLAGS']
initialEnvironment.Prepend(SHLINKFLAGS = customSHLINKFLAGS)
customSWIGFLAGS     = initialEnvironment['customSWIGFLAGS']
initialEnvironment.Prepend(SWIGFLAGS = customSWIGFLAGS)

buildOLPC           = ( initialEnvironment['buildOLPC'] == '1')
util.fixEnvForOLPC( initialEnvironment )

if initialEnvironment['useDouble'] != '0'   : util.csoundLibraryName += '64'
elif util.platform == 'win32'               : util.csoundLibraryName += '32'

# Define options for different platforms.
if util.platform != 'win32':
    print "Build platform is '" + util.platform + "'."
else:
    if util.compilerMicrosoft():
        print "Build platform is Microsoft Visual C++ (MSVC)."
    elif util.compilerIntel():
        print "Build platform is the Intel C++ Compiler (ICL)."
    elif util.compilerGNU():
        print "Build platform is MinGW/MSYS"

print "SCons tools on this platform: ", initialEnvironment['TOOLS']

if util.compilerGNU():
    # Avoid warnings about things we won't fix anyway
    initialEnvironment.Append(CCFLAGS  = '-Wno-write-strings')
    initialEnvironment.Append(CXXFLAGS = '-Wno-write-strings')

initialEnvironment.Prepend(CPPPATH = ['#/.', '#/H'])
#initialEnvironment.Prepend(CPPPATH = ['.', './H']) # The swig builder sucks

if initialEnvironment['useLrint'] != '0':
    initialEnvironment.Prepend(CCFLAGS = ['-DUSE_LRINT'])
if initialEnvironment['useGettext'] != '0':
    print "Using GNU gettext scheme"
    initialEnvironment.Prepend(CCFLAGS = ['-DGNU_GETTEXT'])
    if util.platform == "win32":
        initialEnvironment.Append(LIBS=['intl'])
else:
    print "Using Istvan localisation"
    initialEnvironment.Prepend(CCFLAGS = ['-DNOGETTEXT'])

if initialEnvironment['gcc3opt'] != '0' or initialEnvironment['gcc4opt'] != '0':
    initialEnvironment.Prepend(CCFLAGS = ['-ffast-math'])
    if not buildOLPC:
        initialEnvironment.Append(CCFLAGS = ['-freorder-blocks'])
        if initialEnvironment['useGprof'] != '1':
            initialEnvironment.Prepend(CCFLAGS = ['-fomit-frame-pointer'])
    if initialEnvironment['gcc4opt'] != '0':
        initialEnvironment.Prepend(CCFLAGS = ['-ftree-vectorize'])
        cpuType = initialEnvironment['gcc4opt']
    else:
        cpuType = initialEnvironment['gcc3opt']
    if util.platform == 'darwin':
        initialEnvironment.Prepend(CCFLAGS = Split(
            '-O3 -mcpu=%s -mtune=%s' % (cpuType, cpuType)))
    else:
        initialEnvironment.Prepend(CCFLAGS = Split('-O3 -mtune=%s' % (cpuType)))

if initialEnvironment['buildRelease'] != '0':
    if util.compilerMicrosoft():
        initialEnvironment.Append(CCFLAGS = Split('/O2'))
    elif util.compilerIntel():
        initialEnvironment.Append(CCFLAGS = Split('/O3'))

if initialEnvironment['noDebug'] == '0':
    if util.compilerGNU()           : initialEnvironment.Append(CCFLAGS = ['-g'])

if initialEnvironment['useGprof'] == '1':
    initialEnvironment.Append(CCFLAGS = ['-pg'])
    initialEnvironment.Append(CXXFLAGS = ['-pg'])
    initialEnvironment.Append(LINKFLAGS = ['-pg'])
    initialEnvironment.Append(SHLINKFLAGS = ['-pg'])

if util.compilerGNU():
    initialEnvironment.Prepend(CXXFLAGS = ['-fexceptions'])

initialEnvironment.Prepend(LIBPATH = ['.', '#.'])

if initialEnvironment['buildRelease'] == '0':
    initialEnvironment.Prepend(CPPFLAGS = ['-DBETA'])

if initialEnvironment['Lib64'] == '1':
    initialEnvironment.Prepend(LIBPATH = ['.', '#.', '/usr/local/lib64'])
else:
    initialEnvironment.Prepend(LIBPATH = ['.', '#.', '/usr/local/lib'])

if initialEnvironment['Word64'] == '1':
    initialEnvironment.Append(CCFLAGS = ['-fPIC'])

if initialEnvironment['useDouble'] == '0':
    print 'CONFIGURATION DECISION: Using single-precision floating point for audio samples.'
else:
    print 'CONFIGURATION DECISION: Using double-precision floating point for audio samples.'
    initialEnvironment.Append(CPPFLAGS = ['-DUSE_DOUBLE'])

# Define different build environments for different types of targets.

if util.platform == 'linux':
    initialEnvironment.Append(CCFLAGS   = "-DLINUX")
    initialEnvironment.Append(CPPFLAGS  = '-DHAVE_SOCKETS')
    initialEnvironment.Append(CPPPATH   = '/usr/local/include')
    initialEnvironment.Append(CPPPATH   = '/usr/include')
    initialEnvironment.Append(CPPPATH   = '/usr/include')
    initialEnvironment.Append(CPPPATH   = '/usr/X11R6/include')
    initialEnvironment.Append(CCFLAGS   = "-DPIPES")
    initialEnvironment.Append(LINKFLAGS = ['-Wl,-Bdynamic'])
elif util.platform == 'darwin':
    initialEnvironment.Append(CCFLAGS   = "-DMACOSX")
    initialEnvironment.Append(CPPPATH   = '/usr/local/include')
    initialEnvironment.Append(CCFLAGS   = "-DPIPES")
    if initialEnvironment['useAltivec'] == '1':
        print 'CONFIGURATION DECISION using Altivec optmisation'
        initialEnvironment.Append(CCFLAGS = "-faltivec")
elif util.platform == 'win32':
    initialEnvironment.Append(CCFLAGS   =  '-D_WIN32')
    initialEnvironment.Append(CCFLAGS   =  '-DWIN32')
    initialEnvironment.Append(CCFLAGS   =  '-DPIPES')
    initialEnvironment.Append(CCFLAGS   =  '-DOS_IS_WIN32')
    initialEnvironment.Append(CXXFLAGS  = '-D_WIN32')
    initialEnvironment.Append(CXXFLAGS  = '-DWIN32')
    initialEnvironment.Append(CXXFLAGS  = '-DPIPES')
    initialEnvironment.Append(CXXFLAGS  = '-DOS_IS_WIN32')
    initialEnvironment.Append(CXXFLAGS = '-DFL_DLL')
    if util.compilerGNU():
        initialEnvironment.Prepend(CCFLAGS  = "-Wall")
        initialEnvironment.Append(CPPPATH   = '/usr/local/include')
        initialEnvironment.Append(CPPPATH   = '/usr/include')
        initialEnvironment.Append(CCFLAGS   = '-mthreads')
	initialEnvironment.Append(SHLINKFLAGS = 
            Split('''-mwindows -mno-cygwin -Wl,--enable-auto-import
                  -Wl,--enable-runtime-pseudo-reloc'''))
    else:
        initialEnvironment.Append(CCFLAGS   =  '/DMSVC')
        initialEnvironment.Append(CXXFLAGS  = '/EHsc')
        initialEnvironment.Append(CCFLAGS   =  '/D_CRT_SECURE_NO_DEPRECATE')
        initialEnvironment.Append(CCFLAGS   =  '/MD')
        initialEnvironment.Append(CCFLAGS   =  '/W2')
        initialEnvironment.Append(CCFLAGS   =  '/wd4251')
        initialEnvironment.Append(CCFLAGS   =  '/wd4996')
        initialEnvironment.Append(CCFLAGS   =  '/MP')
        initialEnvironment.Append(CCFLAGS   =  '/GR')
        initialEnvironment.Append(CCFLAGS   =  '/G7')
        initialEnvironment.Append(CCFLAGS =  '/D_SCL_SECURE_NO_DEPRECATE')
        initialEnvironment.Prepend(CCFLAGS  = Split('/Zi /D_NDEBUG /DNDEBUG'))
        initialEnvironment.Prepend(LINKFLAGS = Split('''/INCREMENTAL:NO /OPT:REF /OPT:ICF /DEBUG'''))
        initialEnvironment.Prepend(SHLINKFLAGS = Split(
            '/INCREMENTAL:NO /OPT:REF /OPT:ICF /DEBUG'))
        # With Visual C++ it is now necessary to embed the manifest into the target.
        initialEnvironment['LINKCOM'] = [initialEnvironment['LINKCOM'],
        'mt.exe -nologo -manifest ${TARGET}.manifest -outputresource:$TARGET;1']
        initialEnvironment['SHLINKCOM'] = [initialEnvironment['SHLINKCOM'],
        'mt.exe -nologo -manifest ${TARGET}.manifest -outputresource:$TARGET;2']
    if util.compilerMicrosoft():
        initialEnvironment.Append(CCFLAGS =  '/arch:sse')
    if util.compilerIntel():
        print 'Generating code optimized for Intel Core 2 Duo and Pentium 4'
        print 'that will run on other processors also.'
        initialEnvironment.Append(CCFLAGS = Split('/O3 /QaxTP'))

if util.platform == 'linux':
    path1 = '/usr/include/python%s' % initialEnvironment['pythonVersion']
    path2 = '/usr/local/include/python%s' % initialEnvironment['pythonVersion']
    pythonIncludePath   = [path1, path2]
    pythonLinkFlags     = []
    if initialEnvironment['Lib64'] == '1':
        tmp = '/usr/lib64/python%s/config' % initialEnvironment['pythonVersion']
        pythonLibraryPath   = ['/usr/local/lib64', '/usr/lib64', tmp]
    else:
        tmp = '/usr/lib/python%s/config' % initialEnvironment['pythonVersion']
        pythonLibraryPath   = ['/usr/local/lib', '/usr/lib', tmp]
    pythonLibs              = ['python%s' % initialEnvironment['pythonVersion']]
elif util.platform == 'darwin':
    vers = (int(sys.hexversion) >> 24, (int(sys.hexversion) >> 16) & 255)
    if vers[1] == 3:
        print "Python version is 2.%s, using Apple Python Framework" % vers[1]
        pyBasePath = '/System/Library/Frameworks/Python.framework'
    else:
        print "Python version is 2.%s, using MacPython Framework"    % vers[1]
        pyBasePath = '/Library/Frameworks/Python.Framework'
    pvers = "2.%s" % vers[1]
    if initialEnvironment['pythonVersion'] != pvers:
        initialEnvironment['pythonVersion'] = pvers
        print "WARNING python version used is " + pvers
    pythonIncludePath   = ['%s/Headers' % pyBasePath]
    pythonLinkFlags     = [ '-F' + pyBasePath, '-framework', 'python']
    path1               = '%s/Versions/Current/lib' % pyBasePath
    path2 = '%s/python%s/config' % (path1, initialEnvironment['pythonVersion'])
    pythonLibraryPath   = [path1, path2]
    pythonLibs          = []
    tclIncludePath      = []
elif util.platform == 'win32':
    pythonIncludePath   = []
    pythonLinkFlags     = []
    pythonLibraryPath   = []
    tclIncludePath      = []
    pythonLibs          = ['python%s' %
        initialEnvironment['pythonVersion'].replace('.', '')]
else:
    pythonIncludePath   = []
    pythonLinkFlags     = []
    pythonLibraryPath   = []
    tclIncludePath      = []
    pythonLibs          = []

# Check for prerequisites.
# We check only for headers; checking for libs may fail
# even if they are present, due to secondary dependencies.

libsndfileTests = [
    'int foobar(void)\n{\nreturn (int) SF_FORMAT_SD2;\n}',
    'int foobar(SF_INSTRUMENT *p)\n{\nreturn (int) p->loop_count;\n}',
    'int foobar(void)\n{\nreturn (int) SFC_GET_SIGNAL_MAX;\n}'
]

def CheckSndFile1011(context):
    context.Message('Checking for libsndfile version 1.0.11 or later... ')
    testProgram = '\n#include <sndfile.h>\n\n' + libsndfileTests[0] + '\n\n'
    result      = context.TryCompile(testProgram, '.c')
    context.Result(result)
    return result

def CheckSndFile1013(context):
    context.Message('Checking for libsndfile version 1.0.13 or later... ')
    testProgram = '\n#include <sndfile.h>\n\n' + libsndfileTests[1] + '\n\n'
    result      = context.TryCompile(testProgram, '.c')
    context.Result(result)
    return result

def CheckSndFile1016(context):
    context.Message('Checking for libsndfile version 1.0.16 or later... ')
    testProgram = '\n#include <sndfile.h>\n\n' + libsndfileTests[2] + '\n\n'
    result      = context.TryCompile(testProgram, '.c')
    context.Result(result)
    return result

def CheckGcc4(context):
    # We need gcc4 if we want -fvisibility=hidden
    context.Message('Checking for gcc version 4 or later... ')
    testProgram = '''int main() {
        #if __GNUC__ >= 4
        /* OK */
           return 0;
        #else /* GCC < 4.0 */
        #error __GNUC__ < 4
        #endif
        }
    '''
    result = context.TryCompile(testProgram, '.c' )
    context.Result(result)
    return result

configure = initialEnvironment.Configure(custom_tests = {
    'CheckSndFile1011' : CheckSndFile1011,
    'CheckSndFile1013' : CheckSndFile1013,
    'CheckSndFile1016' : CheckSndFile1016,
    'CheckGcc4'        : CheckGcc4
})

if not configure.CheckHeader("stdio.h", language = "C"):
    print " *** Failed to compile a simple test program. The compiler is"
    print " *** possibly not set up correctly, or is used with invalid flags."
    print " *** Check config.log to find out more about the error."
    Exit(-1)
if not configure.CheckLibWithHeader("sndfile", "sndfile.h", language = "C"):
    print "The sndfile library is required to build Csound 5."
    Exit(-1)
if not configure.CheckLibWithHeader("pthread", "pthread.h", language = "C"):
    print "The pthread library is required to build Csound 5."
    Exit(-1)
if configure.CheckLibWithHeader('pthread', 'pthread.h', 'C', 'pthread_barrier_init(0, 0, 0);'):
    initialEnvironment.Append(CPPFLAGS = ['-DHAVE_PTHREAD_BARRIER_INIT'])
if not util.compilerMicrosoft():
    if configure.CheckLibWithHeader('m', 
     'stdint.h', 'C', '__sync_lock_test_and_set((int32_t *)0, 0);',
      autoadd = False):
        initialEnvironment.Append(CPPFLAGS = ['-DHAVE_SYNC_LOCK_TEST_AND_SET'])

if util.platform == 'win32':
    initialEnvironment['ENV']['PATH']   = os.environ['PATH']
    initialEnvironment['SYSTEMROOT']    = os.environ['SYSTEMROOT']

# Define macros that configure and config.h used to define.
headerMacroCheck = [
    ['io.h',        '-DHAVE_IO_H'       ],
    ['fcntl.h',     '-DHAVE_FCNTL_H'    ],
    ['unistd.h',    '-DHAVE_UNISTD_H'   ],
    ['stdint.h',    '-DHAVE_STDINT_H'   ],
    ['sys/time.h',  '-DHAVE_SYS_TIME_H' ],
    ['sys/types.h', '-DHAVE_SYS_TYPES_H'],
    ['termios.h',   '-DHAVE_TERMIOS_H'  ]]

for h in headerMacroCheck:
    if configure.CheckHeader(h[0], language = "C"):
        initialEnvironment.Append(CPPFLAGS = [h[1]])

if util.platform == 'win32':
    if configure.CheckHeader("winsock.h", language = "C"):
        initialEnvironment.Append(CPPFLAGS = '-DHAVE_SOCKETS')
elif configure.CheckHeader("sys/socket.h", language = "C"):
    initialEnvironment.Append(CPPFLAGS = '-DHAVE_SOCKETS')

if util.platform == 'darwin':
    initialEnvironment.Append(CPPFLAGS = '-DHAVE_DIRENT_H')
elif configure.CheckHeader("dirent.h", language = "C"):
    initialEnvironment.Append(CPPFLAGS = '-DHAVE_DIRENT_H')

if configure.CheckSndFile1016():
    initialEnvironment.Prepend(CPPFLAGS = ['-DHAVE_LIBSNDFILE=1016'])
elif configure.CheckSndFile1013():
    initialEnvironment.Prepend(CPPFLAGS = ['-DHAVE_LIBSNDFILE=1013'])
elif configure.CheckSndFile1011():
    initialEnvironment.Prepend(CPPFLAGS = ['-DHAVE_LIBSNDFILE=1011'])
else:
    initialEnvironment.Prepend(CPPFLAGS = ['-DHAVE_LIBSNDFILE=1000'])

# Package contents.

# flags for linking with the Csound library
libCsoundLinkFlags = []
libCsoundLibs = ['sndfile']

buildOSXFramework = 0
if util.platform == 'darwin':
    if initialEnvironment['dynamicCsoundLibrary'] != '0':
        buildOSXFramework = 1
        CsoundLib_OSX = 'CsoundLib'
        # comment the next two lines out to disable building a separate
        # framework (CsoundLib64) for double precision
        if initialEnvironment['useDouble'] != '0':
            CsoundLib_OSX += '64'
        OSXFrameworkBaseDir = '%s.Framework' % CsoundLib_OSX
        tmp = OSXFrameworkBaseDir + '/Versions/%s'
        OSXFrameworkCurrentVersion = tmp % csoundLibraryVersion

csoundLibraryEnvironment = initialEnvironment.Clone()

if initialEnvironment['buildNewParser'] != '0':
    if util.platform == "win32":
        Tool('lex')(csoundLibraryEnvironment)
        Tool('yacc')(csoundLibraryEnvironment)
    print 'CONFIGURATION DECISION: Building with new parser enabled'
    csoundLibraryEnvironment.Append(
        YACCFLAGS = ['-d', '--report=itemset', '-p','csound_orc'])
    csoundLibraryEnvironment.Append(LEXFLAGS = ['-d', '-Pcsound_orc'])
    csoundLibraryEnvironment.Append(CPPFLAGS = ['-DENABLE_NEW_PARSER'])
    yaccBuild = csoundLibraryEnvironment.CFile(
        target = 'Engine/csound_orcparse.c',
        source = 'Engine/csound_orc.y')
    lexBuild = csoundLibraryEnvironment.CFile(
        target = 'Engine/csound_orclex.c',
        source = 'Engine/csound_orc.l')
else:
    print 'CONFIGURATION DECISION: Not building with new parser.'

csoundLibraryEnvironment.Append(CPPFLAGS = ['-D__BUILDING_LIBCSOUND'])
if initialEnvironment['buildRelease'] != '0':
    csoundLibraryEnvironment.Append(CPPFLAGS = ['-D_CSOUND_RELEASE_'])
    if util.platform == 'linux':
        if initialEnvironment['Lib64'] == '0':
            tmp = '%s/lib/csound/plugins' % initialEnvironment['prefix']
        else:
            tmp = '%s/lib64/csound/plugins' % initialEnvironment['prefix']
        if initialEnvironment['useDouble'] != '0':
            tmp += '64'
        s = '-DCS_DEFAULT_PLUGINDIR=\\"%s\\"' % tmp
        csoundLibraryEnvironment.Append(CPPFLAGS = [s])
    elif buildOSXFramework != 0:
        tmp = '/Library/Frameworks/%s' % OSXFrameworkCurrentVersion
        tmp += '/Resources/Opcodes'
        if initialEnvironment['useDouble'] != '0':
            tmp += '64'
        s = '-DCS_DEFAULT_PLUGINDIR=\\"%s\\"' % tmp
        csoundLibraryEnvironment.Append(CPPFLAGS = [s])
csoundDynamicLibraryEnvironment = csoundLibraryEnvironment.Clone()
csoundDynamicLibraryEnvironment.Append(LIBS = ['sndfile'])
if util.platform == 'win32':
    # These are the Windows system call libraries.
    if util.compilerGNU():
        csoundWindowsLibraries = Split('''
            advapi32    comctl32    comdlg32    glu32       kernel32
            msvcrt      odbc32      odbccp32    ole32       oleaut32
            shell32     user32      uuid        winmm       winspool
            ws2_32      wsock32     advapi32    comctl32    comdlg32
            glu32       kernel32    odbc32      odbccp32    ole32
            oleaut32    shell32     user32      uuid        winmm
            winspool    ws2_32      wsock32     pthread
        ''')
    else:
        csoundWindowsLibraries = Split('''
            kernel32        gdi32           wsock32         ole32
            uuid            winmm           user32.lib      ws2_32.lib
            comctl32.lib    gdi32.lib       comdlg32.lib    advapi32.lib
            shell32.lib     ole32.lib       oleaut32.lib    uuid.lib
            odbc32.lib      odbccp32.lib    kernel32.lib
            user32.lib      gdi32.lib       winspool.lib    comdlg32.lib
            advapi32.lib    shell32.lib     ole32.lib       oleaut32.lib
            uuid.lib        odbc32.lib      odbccp32.lib    pthread.lib
        ''')
    if commonEnvironment['bufferoverflowu'] != '0':
        csoundWindowsLibraries.append('bufferoverflowu')
    csoundDynamicLibraryEnvironment.Append(LIBS = csoundWindowsLibraries)
    if util.compilerGNU():
        csoundDynamicLibraryEnvironment.Append(SHLINKFLAGS = ['-module'])
elif util.platform == 'linux':
    csoundDynamicLibraryEnvironment.Append(LIBS = ['dl', 'm', 'pthread'])

if buildOSXFramework:
    csoundFrameworkEnvironment = csoundDynamicLibraryEnvironment.Clone()
    # create directory structure for the framework
    tmp = [OSXFrameworkBaseDir]
    tmp += ['%s/Versions' % OSXFrameworkBaseDir]
    tmp += [OSXFrameworkCurrentVersion]
    tmp += ['%s/Headers' % OSXFrameworkCurrentVersion]
    tmp += ['%s/Resources' % OSXFrameworkCurrentVersion]
    if initialEnvironment['useDouble'] == '0':
        tmp += ['%s/Resources/Opcodes' % OSXFrameworkCurrentVersion]
    else:
        tmp += ['%s/Resources/Opcodes64' % OSXFrameworkCurrentVersion]
    for i in tmp:
        try:
            os.mkdir(i, 0755)
        except:
            pass
    # set up symbolic links
    tmp = [['/Versions/Current', csoundLibraryVersion]]
    tmp += [['/' + CsoundLib_OSX, 'Versions/Current/' + CsoundLib_OSX]]
    tmp += [['/Headers', 'Versions/Current/Headers']]
    tmp += [['/Resources', 'Versions/Current/Resources']]
    for i in tmp:
        try:
            os.remove('%s/%s' % (OSXFrameworkBaseDir, i[0]))
        except:
            pass
        os.symlink(i[1], '%s/%s' % (OSXFrameworkBaseDir, i[0]))

libEngine = '''
Engine/auxfd.c      Engine/cfgvar.c     Engine/entry1.c     Engine/envvar.c
Engine/express.c    Engine/extract.c    Engine/fgens.c      Engine/insert.c
Engine/linevent.c   Engine/memalloc.c   Engine/memfiles.c   Engine/musmon.c
Engine/namedins.c   Engine/otran.c      Engine/rdorch.c     Engine/rdscor.c
Engine/scsort.c     Engine/scxtract.c   Engine/sort.c       Engine/sread.c
Engine/swrite.c     Engine/twarp.c
'''
libSndMid = '''
InOut/libsnd.c      InOut/libsnd_u.c    InOut/midifile.c    InOut/midirecv.c
InOut/midisend.c    InOut/winascii.c    InOut/windin.c      InOut/window.c
'''
libOO = '''
OOps/aops.c         OOps/bus.c          OOps/cmath.c        OOps/diskin.c
OOps/diskin2.c      OOps/disprep.c      OOps/dumpf.c        OOps/fftlib.c
OOps/goto_ops.c     OOps/midiinterop.c  OOps/midiops.c      OOps/midiout.c
OOps/mxfft.c        OOps/oscils.c       OOps/pstream.c      OOps/pvfileio.c
OOps/pvsanal.c      OOps/random.c       OOps/remote.c       OOps/schedule.c
OOps/sndinfUG.c     OOps/str_ops.c      OOps/ugens1.c       OOps/ugens2.c
OOps/ugens3.c       OOps/ugens4.c       OOps/ugens5.c       OOps/ugens6.c
OOps/ugrw1.c        OOps/ugrw2.c        OOps/vdelay.c
'''

if buildOLPC:
    libCsoundSources = Split( libEngine + libSndMid + libOO + '''
Top/argdecode.c     Top/csmodule.c      Top/csound.c        Top/getstring.c
Top/main.c          Top/new_opts.c      Top/one_file.c      Top/opcode.c
Top/threads.c       Top/utility.c
''')
else:
    libCsoundSources = Split(libEngine + libSndMid + libOO + '''
Top/argdecode.c Top/cscore_internal.c   Top/cscorfns.c  Top/csmodule.c
Top/csound.c    Top/getstring.c         Top/main.c      Top/new_opts.c
Top/one_file.c  Top/opcode.c            Top/threads.c   Top/utility.c
InOut/winEPS.c
''')

newParserSources = Split('''
Engine/csound_orclex.c          Engine/csound_orcparse.c
Engine/csound_orc_semantics.c   Engine/csound_orc_expressions.c
Engine/csound_orc_optimize.c    Engine/csound_orc_compile.c
Engine/new_orc_parser.c         Engine/symbtab.c
''')

if initialEnvironment['buildNewParser'] != '0':
    libCsoundSources += newParserSources

csoundLibraryEnvironment.Append(CCFLAGS='-fPIC')
if initialEnvironment['dynamicCsoundLibrary'] == '1':
    print 'CONFIGURATION DECISION: Building dynamic Csound library'
    if util.platform == 'linux':
        # The linker will pull in dependencies
        libCsoundLibs   = []
        libName         = 'lib' + util.csoundLibraryName + '.so'
        libName2        = libName + '.' + util.csoundLibraryVersion
        try     : os.symlink(libName2, libName)
        except  : pass
        Clean(libName2, libName) # Delete the symlink on clean
        tmp = csoundDynamicLibraryEnvironment['SHLINKFLAGS']
        tmp += ['-Wl,-soname=%s' % libName2]
        cflags = csoundDynamicLibraryEnvironment['CCFLAGS']
        if configure.CheckGcc4():
            cflags   += ['-fvisibility=hidden']
        csoundLibrary = csoundDynamicLibraryEnvironment.SharedLibrary(
            libName2, libCsoundSources,
            SHLINKFLAGS = tmp, SHLIBPREFIX = '', SHLIBSUFFIX = '',
            CCFLAGS = cflags)
    elif util.platform == 'darwin':
        libName = CsoundLib_OSX
        libVersion = util.csoundLibraryVersion
        csoundFrameworkEnvironment.Append(SHLINKFLAGS = Split('''
            -Xlinker -compatibility_version -Xlinker %s
        ''' % libVersion))
        csoundFrameworkEnvironment.Append(SHLINKFLAGS = Split('''
            -Xlinker -current_version -Xlinker %s
        ''' % libVersion))
        csoundFrameworkEnvironment.Append(SHLINKFLAGS = Split('''
            -install_name /Library/Frameworks/%s/%s
        ''' % (OSXFrameworkCurrentVersion, libName)))
        csoundLibraryFile = csoundFrameworkEnvironment.SharedLibrary(
            libName, libCsoundSources, SHLIBPREFIX = '', SHLIBSUFFIX = '')
        csoundFrameworkEnvironment.Command(
            '%s/%s' % (OSXFrameworkCurrentVersion, libName), libName,
            'cp -f %s %s/' % (libName, OSXFrameworkCurrentVersion))
        for i in headers:
            util.MacOSX_InstallHeader(i)
        tmp = (OSXFrameworkBaseDir, OSXFrameworkBaseDir)
        csoundLibrary = csoundFrameworkEnvironment.Command(
            'CsoundLib_install', libName,
            'rm -r /Library/Frameworks/%s; cp -R %s /Library/Frameworks/' % tmp)
        libCsoundLinkFlags = ['-F.', '-framework', libName, '-lsndfile']
        libCsoundLibs = []
    elif util.platform == 'win32':
        csoundLibrary = csoundDynamicLibraryEnvironment.SharedLibrary(
            util.csoundLibraryName, libCsoundSources,
            SHLIBSUFFIX = '.dll.%s' % util.csoundLibraryVersion)
        if util.compilerGNU():
            libCsoundLinkFlags.append('--subsystem:windows')
            libCsoundLibs += [ 'stdc++', 'supc++']
        else:
            libCsoundLinkFlags.append('/IMPLIB:dummy.lib')
        libCsoundLibs += csoundWindowsLibraries
    else: # Is this useful?
        csoundLibrary = csoundDynamicLibraryEnvironment.SharedLibrary(
            util.csoundLibraryName, libCsoundSources)
else:
    print 'CONFIGURATION DECISION: Building static Csound library'
    if util.platform == 'linux':
        libCsoundLibs.append('dl')
    if util.platform != 'win32':
        libCsoundLibs += ['pthread', 'm']
    if util.platform == 'win32':
        libCsoundLibs += csoundWindowsLibraries
    if util.platform == 'darwin':
        libCsoundLinkFlags += Split(
            '-framework Carbon -framework CoreAudio -framework CoreMidi')
    csoundLibrary = csoundLibraryEnvironment.Library(
        util.csoundLibraryName, libCsoundSources)

libCsoundLibs.append(util.csoundLibraryName)

util.installLib(csoundLibrary)

# Make everything link (correctly) against libcsound, even if not needed.
# FIXME: when linking statically this may lead to larger than normal binaries.
# Stripping should help (?). It appears that at least gcc doesn't link
# statically if no symbols are referenced.
commonEnvironment = initialEnvironment.Clone()
commonEnvironment.Append( LIBS      = libCsoundLibs )
commonEnvironment.Append( LINKFLAGS = libCsoundLinkFlags )

#############################################################################
#
#   DEFINE TARGETS AND SOURCES
#
#############################################################################




if commonEnvironment['generatePdf'] == '0':
    print 'CONFIGURATION DECISION: Not generating Csound API PDF documentation.'
else:
    print 'CONFIGURATION DECISION: Generating Csound API PDF documentation.'
    refmanTex = commonEnvironment.Command(
        'doc/latex/refman.tex', 'Doxyfile', ['doxygen $SOURCE'])
    Depends(refmanTex, csoundLibrary)
    csoundPdf = commonEnvironment.Command(
        'refman.pdf', 'doc/latex/refman.tex',
        ['pdflatex --include-directory=doc/latex --interaction=nonstopmode --job-name=CsoundAPI $SOURCE'])
    Depends(csoundPdf, refmanTex)

#############################################################################
#
# Plugins with External Dependencies
#############################################################################

# FLTK widgets

csoundProgramEnvironment    = commonEnvironment.Clone()


if util.platform == 'win32':
    if not util.compilerGNU():
        csoundProgramEnvironment.Append(LINKFLAGS = ["/IMPLIB:dummy.lib"])
else:
    if util.platform == 'linux':
        csoundProgramEnvironment.Append(LIBS = ['dl'])
    csoundProgramEnvironment.Append(    LIBS = ['pthread', 'm'])
    if util.platform == 'darwin':
        csoundProgramEnvironment.Append(LINKFLAGS = Split('''
            -framework Carbon -framework CoreAudio -framework CoreMidi
        '''))
pluginEnvironment = commonEnvironment.Clone()

# REAL TIME AUDIO AND MIDI

if commonEnvironment['useCoreAudio'] == '1' and util.platform == 'darwin':
    util.confDecision("Building CoreAudio plugin.")
    coreaudioEnvironment = pluginEnvironment.Clone()
    coreaudioEnvironment.Append(
        CCFLAGS = '-I/system/library/Frameworks/CoreAudio.framework/Headers')
    util.makePlugin(coreaudioEnvironment, 'rtcoreaudio', ['InOut/rtcoreaudio.c'])
else:
    util.confDecision("Not building CoreAudio plugin.")

if commonEnvironment['useALSA'] == '1':
    if not configure.CheckLibWithHeader("asound", "alsa/asoundlib.h",
      language = "C", autoadd = False):
        util.fatal("You specified useALSA but asound was not found")
    util.confDecision("Building ALSA plugin.")
    alsaEnvironment = pluginEnvironment.Clone()
    alsaEnvironment.Append(LIBS = ['asound', 'pthread'])
    util.makePlugin(alsaEnvironment, 'rtalsa', ['InOut/rtalsa.c'])
else:
    util.confDecision("Building ALSA plugin")

if commonEnvironment['usePulseAudio'] == '1':
    if not configure.CheckHeader("pulse/simple.h", language = "C"):
        util.fatal("You specified usePulseAudio but PulseAudio was not found")
    util.confDecision("Building PulseAudio plugin")
    pulseaudioEnv = pluginEnvironment.Clone()
    pulseaudioEnv.Append(LIBS = ['pulse-simple'])
    makePlugin(pulseaudioEnv, 'rtpulse', ['InOut/rtpulse.c'])

if util.platform == 'win32':
    winmmEnvironment = pluginEnvironment.Clone()
    winmmEnvironment.Append(LIBS = ['winmm', 'gdi32', 'kernel32'])
    util.makePlugin(winmmEnvironment, 'rtwinmm', ['InOut/rtwinmm.c'])

if commonEnvironment['usePortAudio'] == '1':
    if not configure.CheckLibWithHeader("portaudio","portaudio.h", language = "C",
      autoadd = False):
        util.fatal("You specified usePortAudio but PortAudio was not found")
    portaudioEnvironment = pluginEnvironment.Clone()
    portaudioEnvironment.Append(LIBS = ['portaudio'])
    if util.platform == 'win32':
        portaudioEnvironment.Append(LIBS = ['winmm', 'dsound'])
    util.makePlugin(portaudioEnvironment, 'rtpa', ['InOut/rtpa.c'])


if commonEnvironment['useJack'] == '1':
    if not configure.CheckHeader("jack/jack.h", language = "C"):
        util.fatal("You specified useJack but JACK was not found")
    util.confDecision("Building JACK plugin.")
    jackEnvironment = pluginEnvironment.Clone()
    if util.platform == 'win32':
        jackEnvironment.Append(LIBS = ['jackdmp', 'pthread'])
    else:
        jackEnvironment.Append(LIBS = ['jack', 'pthread'])
    util.makePlugin(jackEnvironment, 'rtjack', ['InOut/rtjack.c'])
else:
    util.confDecision("Not building JACK plugin.")

if commonEnvironment['usePortMIDI'] == '1':
    if not configure.CheckLibWithHeader("portmidi", "portmidi.h",
     language = "C", autoadd = False):
        util.fatal("You specified usePortMIDI but PortMIDI was not found")
    util.confDecision('Building with PortMIDI.')
    portMidiEnvironment = pluginEnvironment.Clone()
    portMidiEnvironment.Append(LIBS = ['portmidi'])
    if util.platform != 'darwin':
        portMidiEnvironment.Append(LIBS = ['porttime'])
    util.makePlugin(portMidiEnvironment, 'pmidi', ['InOut/pmidi.c'])
else:
    util.confDecision('Not building with PortMIDI.')


#############################################################################
#
# Utility programs.
if buildOLPC:
  stdutilSources = Split('''
                        util/cvanal.c       util/dnoise.c
    util/envext.c       util/lpanal.c       util/mixer.c
    util/pvanal.c       util/pvlook.c       util/scale.c
    util/sndinfo.c      util/srconv.c
    util/std_util.c
  ''')
else :
  stdutilSources = Split('''
    util/atsa.c         util/cvanal.c       util/dnoise.c
    util/envext.c       util/xtrct.c        util/het_export.c
    util/het_import.c   util/hetro.c        util/lpanal.c
    util/lpc_export.c   util/lpc_import.c   util/mixer.c
    util/pvanal.c       util/pvlook.c       util/scale.c
    util/sndinfo.c      util/srconv.c       util/pv_export.c
    util/pv_import.c
    util/std_util.c
  ''')

stdutilSources += pluginEnvironment.SharedObject('util/sdif', 'SDIF/sdif.c')
util.makePlugin(pluginEnvironment, 'stdutil', stdutilSources)

if not buildOLPC:
  if (commonEnvironment['buildUtilities'] != '0'):
    utils = [
        ['atsa',        'util/atsa_main.c'    ],
        ['cvanal',      'util/cvl_main.c'     ],
        ['dnoise',      'util/dnoise_main.c'  ],
        ['envext',      'util/env_main.c'     ],
        ['extractor',   'util/xtrc_main.c'    ],
        ['het_export',  'util/hetx_main.c'    ],
        ['het_import',  'util/heti_main.c'    ],
        ['hetro',       'util/het_main.c'     ],
        ['lpanal',      'util/lpc_main.c'     ],
        ['lpc_export',  'util/lpcx_main.c'    ],
        ['lpc_import',  'util/lpci_main.c'    ],
        ['mixer',       'util/mixer_main.c'   ],
        ['pvanal',      'util/pvc_main.c'     ],
        ['pvlook',      'util/pvl_main.c'     ],
        ['pv_export',   'util/pvx_main.c'     ],
        ['pv_import',   'util/pvi_main.c'     ],
        ['scale',       'util/scale_main.c'   ],
        ['sndinfo',     'util/sndinfo_main.c' ],
        ['srconv',      'util/srconv_main.c'  ]]
    for i in utils:
        util.installProgram(csoundProgramEnvironment.Program(i[0], i[1]))

if not buildOLPC:
    util.installProgram(csoundProgramEnvironment.Program(
        'scsort',['util1/sortex/smain.c']))
    util.installProgram(csoundProgramEnvironment.Program(
        'extract', ['util1/sortex/xmain.c']))
    if util.compilerGNU():
        util.installProgram(commonEnvironment.Program(
            'cs', ['util1/csd_util/cs.c']))
        util.installProgram(commonEnvironment.Program(
            'csb64enc',
                ['util1/csd_util/base64.c', 'util1/csd_util/csb64enc.c']))
        util.installProgram(commonEnvironment.Program(
            'makecsd',
                ['util1/csd_util/base64.c', 'util1/csd_util/makecsd.c']))
        util.installProgram(commonEnvironment.Program(
            'scot', ['util1/scot/scot_main.c', 'util1/scot/scot.c']))
#executables.append(csoundProgramEnvironment.Program('cscore',
#    ['util1/cscore/cscore_main.c']))
    util.installProgram(commonEnvironment.Program(
        'sdif2ad', ['SDIF/sdif2adsyn.c', 'SDIF/sdif.c', 'SDIF/sdif-mem.c']))

if (commonEnvironment['generateTags']=='0') or (util.platform != 'darwin' and util.platform != 'linux'):
    print "CONFIGURATION DECISION: Not calling TAGS"
else:
    print "CONFIGURATION DECISION: Calling TAGS"
    allSources = string.join(glob.glob('*/*.h*'))
    allSources = allSources + ' ' + string.join(glob.glob('*/*.c*'))
    allSources = allSources + ' ' + string.join(glob.glob('*/*.hpp'))
    allSources = allSources + ' ' + string.join(glob.glob('*/*/*.c*'))
    allSources = allSources + ' ' + string.join(glob.glob('*/*/*.h'))
    allSources = allSources + ' ' + string.join(glob.glob('*/*/*.hpp'))
    tags = commonEnvironment.Command('TAGS', Split(allSources), 'etags $SOURCES')
    Depends(tags, csoundLibrary)

if commonEnvironment['useGettext'] == '1':
    csound5GettextEnvironment = csoundProgramEnvironment.Clone()
    util.gettextTarget(csound5GettextEnvironment, 'french', 'fr')
    util.gettextTarget(csound5GettextEnvironment, 'american', 'en_US')
    util.gettextTarget(csound5GettextEnvironment, 'csound', 'en_GB')
    util.gettextTarget(csound5GettextEnvironment, 'es_CO', 'es_CO')
    ##  The following are incomplete
    util.gettextTarget(csound5GettextEnvironment, 'german', 'de')
    util.gettextTarget(csound5GettextEnvironment, 'italian', 'it')
    util.gettextTarget(csound5GettextEnvironment, 'romanian', 'ro')
    util.gettextTarget(csound5GettextEnvironment, 'russian', 'ru')

###Code to create pkconfig files
#env = Environment(tools=['default', 'scanreplace'], toolpath=['tools'])
#env['prefix'] = '/usr/local'
#env.ScanReplace('csound5.pc.in')

Export( "commonEnvironment", "commandOptions", "util" )
Export( "configure" )
# Interfaces must be before frontends
SConscript('interfaces/SConscript')
SConscript('frontends/SConscript')
SConscript('Opcodes/SConscript')
SConscript('InOut/SConscript')


if util.platform == 'darwin' and commonEnvironment['useFLTK'] == '1':
    util.confDecision("Adding resource fork for csound")
    util.addOSXResourceFork(commonEnvironment, 'csound', '')

