# -*- Python -*-

import glob
import sys
import distutils.sysconfig
import shutil, stat
import re
import os
import os.path
from helpers import *
import SCons
import commands
import platform

print """Please remember that SCons does NOT automatically use your shell
environment variables. This script uses PKG_CONFIG_PATH explicitly."""

opts = Variables('SCustomize')

default_module_prefix = os.path.join(distutils.sysconfig.get_python_lib(),'jppy')

opts.Add(PathVariable('python_module_prefix','Prefix to install python module to',
                    default_module_prefix,PathVariable.PathAccept))
opts.Add(PathVariable('python_bin_module_prefix','Prefix to install python binary module to',
                    default_module_prefix,PathVariable.PathAccept))
opts.Add(PathVariable('prefix','Prefix to install /bin/<scripts> to',
                    '/usr/local'))
opts.Add(PathVariable('mx_datetime_includes','Path to mxDateTime.h',
                    '/usr/include/python%s/mx' % sys.version[0:3], PathVariable.PathIsDir ))
opts.Add(PathVariable('python_includes','Path to Python.h',
                    '/usr/include/python%s' % sys.version[0:3], PathVariable.PathIsDir ))
opts.Add(PathVariable('pisock_includes','Path to pi-socket.h','/usr/include'))
if '64bit' == platform.architecture()[0]:
     opts.Add(PathVariable('pisock_library','Path to libpisock.so','/usr/lib64'))
else:
     opts.Add(PathVariable('pisock_library','Path to libpisock.so','/usr/lib'))
     
opts.Add(PathVariable('jppyroot','Install jppy to a different root than /',
                    '/',PathVariable.PathIsDirCreate))
opts.Add(PathVariable('jppyguiroot','Install jppy\'s gui to a different root than /',
                    '/',PathVariable.PathIsDirCreate))
if not 'darwin' == sys.platform:
     # Mac doesn't support dlopen(), so jpilot doesn't build there
     opts.Add(PathVariable('jpilotroot','Install jpilot plugins to a different root than /',
                         '/',PathVariable.PathIsDirCreate))
opts.Add(PackageVariable('rpathoverride','Link with an rpath','no'))
opts.Add(BoolVariable('test','Do you want to run the tests?','yes'))
opts.Add(BoolVariable('docs','Do you want to generate documentation?','no'))
opts.Add(BoolVariable('profile','Do you want compile with profiling?','no'))
opts.Add('python_version','Python library version', sys.version[0:3])

env = Environment(options=opts,
                  CCFLAGS=['-g'],
                  CPPPATH=['${mx_datetime_includes}',
                           '${pisock_includes}',
                           '${python_includes}',
                           '#/libversit_src'],
                  LIBPATH=['${pisock_library}'],
                  tools = ["default", "doxygen"],
                  toolpath='.',
                  ENV = {'PATH' : os.environ['PATH'],
                         'HOME' : os.environ['HOME'],
                         'TERM' : os.environ.get('TERM',''),}
                  )

if env['docs']:
     env.Doxygen("Doxyfile")

if env['python_module_prefix'] != default_module_prefix and \
   env['python_bin_module_prefix'] == default_module_prefix:
     print "Making python_bin_module_prefix match your non-default python_module_prefix"
     env['python_bin_module_prefix'] = env['python_module_prefix']

if env['profile']:
     env.Append(CCFLAGS='-pg')
     env.Append(LINKFLAGS='-pg')

SWIGScanner = SCons.Scanner.ClassicCPP(    "SWIGScan",
                                           ".i",
                                           "CPPPATH",
                                           """^[ \t]*[%,#][
                                           \t]*(?:include|import)[
                                           \t]*(<|")([^>"]+)(>|")""")
""" " """ # fix XEmacs' python syntax highlighting.
                                                     
env['SCANNERS'] += [SWIGScanner]


for take_from_env in ["PKG_CONFIG_PATH"]:
     if os.environ.has_key(take_from_env):
          env['ENV'][take_from_env] = os.environ[take_from_env]

if env['rpathoverride']:
     if env['rpathoverride'] in (1,'yes'):
          print "rpathoverride must be a path"
     else:
          env.Append(LINKFLAGS = '-Wl,--rpath=$rpathoverride -L$rpathoverride')

opts.Save('SCustomize',env)

config = env.Configure(custom_tests={'CheckPKGConfig' : CheckPKGConfig, 
                                     'CheckPKG' : CheckPKG })

Help(opts.GenerateHelpText(env))

if not config.CheckPKGConfig('0.15.0'):
     print 'pkg-config >= 0.15.0 not found.' 
     Exit(1) 
 
if not config.CheckPKG('gtk+-2.0 >= 2.4.0'): 
     print 'gtk+-2.0 >= 2.4.0 not found.' 
     Exit(1)

if not config.CheckPKG('glib-2.0 >= 2.4.0'): 
     print 'glib-2.0 >= 2.4.0 not found.' 
     Exit(1)

if not config.CheckPKG('pygtk-2.0 >= 2.4.0'): 
     print 'pygtk-2.0 >= 2.4.0 not found.' 
     Exit(1)

try:
     import pytz
except ImportError:
     print 'module pytz is required for jppy'
     Exit(1)

try:
     import MySQLdb
except ImportError:
     print 'module MySQLdb is required for jppy'
     Exit(1)

try:
     import pisock
except ImportError:
     print 'module pisock is required for jppy'
     Exit(1)

try:
     import pyparsing
except ImportError:
     print 'module pyparsing is required for jppy'
     Exit(1)

env.ParseConfig('pkg-config --cflags --libs glib-2.0')
env.ParseConfig('pkg-config --cflags --libs gtk+-2.0')
     
#standard stuff
for hdr in [['Python.h','mxDateTime.h']]:
     if not config.CheckHeader(hdr):
          print "You need '%s' to compile this program" % hdr
          Exit(1)
          
vars = distutils.sysconfig.get_config_vars('CC', 'CXX', 'OPT', 'BASECFLAGS',
                                           'CCSHARED', 'LDSHARED', 'SO') 
for i in range(len(vars)): 
    if vars[i] is None: 
        vars[i] = "" 
 
(pycc, pycxx, pyopt, pybasecflags, pyccshared, pyldshared, pyso_ext) = vars 


current_version = open("current-version", "r").read().strip()
top_version, major_version, minor_version = current_version.split(".")
if "~"  in minor_version:
     minor_version, extra_version = minor_version.split("~")
else:
     extra_version = ""

DEFINES_ALL=["JPPY_VERSION=%s" % current_version,
             "JPPY_MAJOR_VERSION=%s" % major_version,
             "JPPY_MINOR_VERSION=%s" % minor_version,
             "JPPY_EXTRA_VERSION=\\\"%s\\\"" % extra_version,             
             "ENABLE_GTK2"]
env.AppendUnique(CPPDEFINES=DEFINES_ALL)

env = config.Finish()

env['python_module_path'] = os.path.join(env['jppyroot'],
                                         env['python_module_prefix'][1:])
env['python_bin_module_path'] = os.path.join(env['jppyroot'],
                                         env['python_bin_module_prefix'][1:])
env['python_gui_module_path'] = os.path.join(env['jppyguiroot'],
                                             env['python_module_prefix'][1:])

if not 'darwin' == sys.platform:
     # Mac doesn't support dlopen(), so jpilot doesn't build there
     env['jpilot_plugin_prefix'] = os.path.join(env['prefix'],
                                                "lib/jpilot/plugins")
     env['jpilot_plugin_path'] = os.path.join(env['jpilotroot'],
                                              env['jpilot_plugin_prefix'][1:])

######### Jpilot
jpilotEnv = env.Clone()
if not 'darwin' == sys.platform:
     jpilotEnv.AppendUnique(CPPDEFINES=["ENABLE_PLUGINS"])

jpilotConfig = jpilotEnv.Configure()
if not jpilotConfig.CheckLibWithHeader('libpisock',
                                       'pi-socket.h','C','pi_socket_connected(0);'):
     print "You need libpisock to compile this program"
     Exit(1)
jpilotConfig.Finish()
jpilot_sources = ['log', 'libplugin', 'utils', 'prefs',
                  'plugins', 'sync', 'japanese', 'cp1250',
                  'russian', 'password', 'category', 'otherconv',
                  'jp-contact']
# a bit of a hack. Scons doesn't support shared objects in static libraries.
libjpilot = jpilotEnv.StaticLibrary(target='jpilot_src/jppy_jpilot',
                                    source = ["jpilot_src/%s.c" % x for x in jpilot_sources],
                                    CCFLAGS="$CCFLAGS -fPIC")
libjpilot[0].attributes.shared = True

######### Jppy
jppyEnv = jpilotEnv.Clone()
jppyEnv.ParseConfig('pkg-config --cflags --libs pygtk-2.0')
if 'darwin' == sys.platform:
     # Something is different on Mac that causes the shared symbols to not be found at compile time unless I link with libpython. This needs more investigation...
     jppyEnv.Append(LIBS = ['python'])
     
jppymodule = jppyEnv.SharedLibrary(target = 'jppy/__jpilotmodule',
                                   source = ['python_module_src/jpilot.i',
                                             'python_module_src/move_into_libpisock.c',
                                             'python_module_src/jpilot_helpers.c',
                                             libjpilot] +
                                   glob.glob("python_module_src/pytype*.c") +
                                   ["libversit_src/%s" % x for x in ["vcc.y",
                                                                     "vobject.c",
                                                                     "vcaltmp.c"]],
                                   SHLIBPREFIX="",
                                   SHLIBSUFFIX=pyso_ext,
                                   SWIGFLAGS="-python -outdir ./jppy/",
                                   )

######### Jpilot Plugins

if not 'darwin' == sys.platform:
     # Mac doesn't support dlopen(), so jpilot doesn't build there
     
     pluginEnv = env.Clone(SHLIBSUFFIX=pyso_ext,
                           SHLIBPREFIX="lib")
     pluginEnv.Append(CPPPATH=['#/jpilot_src'])

     pluginEnv.Append(CPPDEFINES=['JPILOT_PLUGIN_PREFIX=\\"$jpilot_plugin_prefix\\"'])

     jppyPluginEnv = pluginEnv.Clone()
     linkflags=distutils.sysconfig.get_config_var('LINKFORSHARED')
     jppyPluginEnv.Append(LINKFLAGS=[linkflags])
     jppyPluginConfig = jppyPluginEnv.Configure()
     if not jppyPluginConfig.CheckLibWithHeader("libpython%s" % env['python_version'], 
                                                'Python.h','C','PyErr_Clear();'): 
          print "You need libpython%s.so to compile this program" % env['python_version']
          Exit(1) 
     jppyPluginConfig.Finish()
     python_library_filename = commands.getoutput("./find-python-library-name.sh libpython%s.so" % env['python_version'])
     jppyPluginEnv.Append(CPPDEFINES=['PYTHON_SHARED_LIB=\\"%s\\"' % python_library_filename])

     jpilot_plugins = []

     jpilot_plugins.append(jppyPluginEnv.SharedLibrary(target = "jpilot_plugins/jppy",
                                                       source = "jpilot_plugins/jppy.c"))

     jpilot_plugins.append(pluginEnv.SharedLibrary(target = "jpilot_plugins/sync-Calendar",
                                                   source = "jpilot_plugins/sync-Calendar.c"))

######### Run Tests
if env['test']:
     SConscript(dirs=['tests'],exports=['env','jppymodule'])

first_line_re = re.compile('^#!.*python[0-9.]*([ \t].*)?$')
tokens_re = re.compile('@@([^@]*)@@')

def copyFunc(dest, source, env):
    f = open(source, "r")
    first_line = f.readline()
    rest = f.read()

    first_line_match = first_line_re.match(first_line)
    tokens_match     = tokens_re.search(rest)
    if first_line_match or tokens_match:
         for token in tokens_re.finditer(rest):
              if env.has_key(token.group(1)):
                   print "Replacing %s with %s" % (token.group(0), env[token.group(1)])
                   rest = rest.replace(token.group(0), env[token.group(1)])
         outf = open(dest, "w")
         if first_line_match:
              post_interp = first_line_match.group(1) or ''
              if not distutils.sysconfig.python_build:
                   outf.write("#!%s%s\n" % 
                              (os.path.normpath(sys.executable),
                               post_interp))
              else:
                   outf.write("#!%s%s\n" %
                              (os.path.join(
                        distutils.sysconfig.get_config_var("BINDIR"),
                        "python" + sysconfig.get_config_var("EXE")),
                               post_interp))
         else:
              outf.writelines([first_line])
         outf.write(rest)
         outf.close()
         f.close()
    else:
         f.close()
         shutil.copy(source, dest)
    if env.has_key("INSTALL_PERMS"):
         os.chmod(dest, env['INSTALL_PERMS'])
    else:
         os.chmod(dest, 0644)         
    return 0

######### Install
env['INSTALL'] = copyFunc

env.Alias('install', Dir(env['python_module_path']))
env.Install(env['python_module_path'], glob.glob("jppy/*py"))
env.Install(os.path.join(env['python_module_path'],"conduits"), glob.glob("jppy/conduits/*py"))
env.Install(os.path.join(env['python_module_path'],"jpilot"), glob.glob("jppy/jpilot/*py"))
env.Install(env['python_bin_module_path'], jppymodule)

env.Install(os.path.join(env['python_gui_module_path'],"gui"),
            [glob.glob("jppy/gui/*.py")])


if not 'darwin' == sys.platform:
     # Mac doesn't support dlopen(), so jpilot doesn't build there
     env.Alias('install', Dir(env['jpilot_plugin_path']))
     env.Install(env['jpilot_plugin_path'], jpilot_plugins)

SConscript(dirs=['scripts'],exports=['env'])

SConscript(dirs=['glade'],exports=['env'])
