# -*- mode: python -*-

#Targets are "core, gnucash, gnucash-unstable, gnucash-svn, gnucash-private, gnucash-unstable-private, or gnucash-svn-private
_target = None
_build = None
_debug = "release"
_local_old_build = os.environ.get("JHBUILD")
_in_source = True
# Need to call index on this, and Py2.5 in Leopard doesn't have tuple.index
_osx_versions = ['Cheetah', 'Puma', 'Jaguar', 'Panther', 'Tiger', 'Leopard',
                 'SnowLeopard', 'Lion', 'MountainLion', 'Mavericks']
_special_builds = set(('universal', 'PPC', 'native'))
_targets = ('gnucash', 'gramps', 'gtk', 'bootstrap', 'core')

makeargs="-j4"
nice_build = False
partial_build = False

repos['git.gnome.org'] = "ssh://jralls@git.gnome.org/git/"
repos["gramps"] = "ssh://jralls@git.code.sf.net/p/gramps/"

_gtk_osx_dir = os.environ["GTK_OSX_DIR"]
_default_build_drive = os.environ["GTK_OSX_BUILD_DIR"]
if os.environ.has_key("DRIVE") and os.environ["DRIVE"]:
    _build_drive = os.environ["DRIVE"]
else:
    _build_drive = _default_build_drive

_gtk_build_base = os.path.join(_build_drive, "gtk-build")
_gnucash_build_base = os.path.join(_build_drive, "Gnucash-Build")
_gramps_build_base = os.path.join(_build_drive, "Gramps-Build")

if os.environ.has_key('OUT_OF_SOURCE'):
    checkoutroot = os.path.join(_default_build_drive, "gtk-sources")
    os.environ['SRCROOT'] = checkoutroot
    _in_source = False

#cvs_program = "git-cvsimport"
#svn_program = "git-svn"

if os.environ.has_key("TARGET") and os.environ["TARGET"]:
    _target = os.environ["TARGET"]
    del os.environ["TARGET"]

#Builds are PPC, Leopard, universal, git-stable or unstable; if
#running on Tiger, it's ignored; if not one of the defined ones, it
#will build a 10.4 i386 binary unless the target is gnucash-unstable
#or gnucash-svn, in which case it will build for Leopard.

if os.environ.has_key("BUILD") and os.environ["BUILD"]:
    _build = os.environ["BUILD"]

#Debug can be debug or release
if os.environ.has_key("DEBUG") and os.environ['DEBUG'] > 0:
    _debug = "debug"

if os.environ.has_key("POLICY") and os.environ["POLICY"]:
    build_policy=os.environ["POLICY"]
else:
    build_policy = "updated-deps"
    pass

if os.environ.has_key("BUILD_PYTHON"):
    _gtk_osx_use_jhbuild_python=os.environ["BUILD_PYTHON"]

if os.environ.has_key("GITHUB") and os.environ["GITHUB"] == "yes":
    _moduleset_base_1 = "https://raw.github.com/jralls"
    _moduleset_base_2 = "master"
else:
    _moduleset_base_1 = _gtk_osx_dir + "/"
    _moduleset_base_2 = ""

#Set the Apple Signing Certificate:
#if not "APPLICATION_CERT" in os.environ:
#    os.environ["APPLICATION_CERT"] = "John D Ralls"

def make_moduleset( project, stable, moduleset ):
    def stable_set( stability ):
        if not stability:
            return "modulesets"
        else:
            return "modulesets-" + stability

    if _moduleset_base_1.startswith("http"):
        return "/".join([ _moduleset_base_1, project, _moduleset_base_2,
                          stable_set( stable ), moduleset ])
    else:
        return os.path.normpath( os.path.join( _moduleset_base_1, project,
                                               _moduleset_base_2,
                                               stable_set( stable ),
                                               moduleset ))

def make_moduleset_gtk( stable ):
    return make_moduleset( "gtk-osx-build", stable, "gtk-osx.modules")

def make_moduleset_gnucash( ):
    return make_moduleset( "gnucash-on-osx", None, "gnucash.modules" )

def make_builddir( base, builddir ):
    global buildroot, prefix, checkoutroot
    if _in_source:
        checkoutroot = os.path.join (base, builddir, 'src')
    else:
        buildroot = os.path.join( base, builddir, "build" )

    prefix = os.path.join( base, builddir, "inst" )

make_builddir( _gtk_build_base, "gtk-stable" )

def check_prefix():
    global prefix
    saved = prefix+".Save"
    if os.path.exists( saved ):
        if os.path.islink( prefix ):
            os.unlink( prefix )
        elif os.path.exists( prefix ):
            os.rename( prefix, prefix + ".Relocate" )
        os.rename( saved, prefix )

def set_xcode3():
    if 'XCODE3' in os.environ and os.path.exists(os.environ['XCODE3']):
        xcode3_dir = os.environ['XCODE3']
    else:
        xcode3_dir = os.path.join("/Volumes", "Data", "XCode3")

    if not os.path.exists(xcode3_dir):
        return False

    os.environ["DEVELOPER_DIR"] = xcode3_dir
    skip.append("perl-xml-parser")
    path = os.environ["PATH"].split(':')
    xcode_path = os.path.join(xcode3_dir, "usr", "bin")
    path.insert(1, xcode_path)
    os.environ["PATH"]= ':'.join(path)
    return True

def target_version(target=None):
  if target == None or not isinstance(target, list):
      return None
  try:
      version = list(set(_osx_versions).intersection(target))[0]
  except IndexError:
      version = None
  if not version:
      return None
  vnum = _osx_versions.index(version)
  osv = int((_osx_version - 10) * 10)
  if vnum < osv:
      raise RuntimeError('Can\'t build for %s when running older version %s' %
                         (version, _osx_versions[osv]))
  return vnum

def set_environment(build=None):
    global module_makeargs, buildroot, prefix, modules, moduleset, skip
#Don't mess with anything if there's an external config file (usually
#for a framework)
    xcode3 = False
    sysarch = _popen('uname -p')
    if _osx_version < 5.0:
        os.environ["MACOSX_DEPLOYMENT_TARGET"] = "10.4"
        module_makeargs["gtk+"]="LDFLAGS='-framework AppKit -framework Carbon -framework CoreFoundation -framework ApplicationServices -lobjc'"
        module_makeargs["gtk-mac-integration"]="LDFLAGS='-framework AppKit -lobjc'"
        module_makeargs["aqbanking"]="LDFLAGS='-liconv'"
        build = "Tiger"
        return

    sdk = None
    if build == None:
        build = 'native'
    if isinstance(build, str):
        build_parms = build.split('-')
    elif isinstance(build, list):
        build_parms = build
    else:
        raise RuntimeError("Can't handle build of type %s" % type(build))

    if "PPC" in build_parms and sysarch != 'powerpc': #PPC
        make_builddir(_gtk_build_base, "gtk-ppc")
        setup_ppc_build()
        return

    if "universal" in build_parms:			#universal
        make_builddir( _gtk_build_base, "gtk-univ" )
        modules = ["meta-gtk-osx-bootstrap", "meta-gtk-universal"]
        moduleset = make_moduleset_gtk("unstable")
        skip.append("glib")
        skip.append("gtk+")
        setup_universal_build(architectures=['i386', 'x86_64'])
        return

    if '64' in build_parms:
        if sysarch == 'powerpc':
            arch_type = 'ppc_64'
        else:
            arch_type = 'x86_64'
    else:
        if sysarch == 'powerpc':
            arch_type = 'ppc'
        else:
            arch_type = 'i386'

    min_supp = target_version(build_parms) or _osx_version

    if (_osx_version >= 8.0 and min_supp < 7 or
        _osx_version >= 7.0 and min_supp < 6):

       if not set_xcode3():
           min_supp = 8 #This now also depends upon Xcode version
       else:
           xcode3 = True

    if min_supp == 4:
        min_supp = '10.4'
        sdk = '10.4u'
    else:
        min_supp = '10.%d' % min_supp
    if not min_supp:
        min_supp = int(_osx_version)
        sdk = 'native'
    if not sdk:
        sdk = min_supp

#        print ("Setup_sdk params: Target=%s, SDK=%s, Arch=%s" % (min_supp, sdk, arch_type))

    setup_sdk(target=min_supp, sdk_version=sdk, architectures=[arch_type])

    if 'stable' in build_parms:
        stability = 'stable'
        builddir = 'gtk-stable-%s-%s' % (min_supp, arch_type)
    elif 'unstable' in build_parms:
        stability = 'unstable'
        builddir = 'gtk-unstable-%s-%s' % (min_supp, arch_type)
    else:
        stability = None
        builddir = 'gtk-%s-%s' % (min_supp, arch_type)

    if 'clang' in build_parms:
        _toolpath = os.path.join('/usr', 'bin')
        os.environ["CC"] = os.path.join(_toolpath, "clang")
        os.environ["OBJC"] = os.path.join(_toolpath, "clang")
        os.environ["CXX"] = os.path.join(_toolpath, "clang")

    _build = "%s-%s-%s" % (prefix, min_supp, arch_type)
    make_builddir(_gtk_build_base,
                  os.path.join(_gtk_build_base, builddir))
    moduleset = make_moduleset_gtk(stability)
    if (xcode3 and _osx_version > 8.0):
        sdkdir = get_sdkdir (make_sdk_name(sdk),
                             os.environ['DEVELOPER_DIR'], 3.0)
        prependpath('C_INCLUDE_PATH', os.path.join(sdkdir, "usr", "include"))
        prependpath('CPLUS_INCLUDE_PATH',
                    os.path.join(sdkdir, "usr", "include"))
        prependpath('LIBRARY_PATH', os.path.join(sdkdir, "usr", "lib"))

def get_source(target):
    if 'git' in target:
        source = target.pop(target.index('git'))
    elif 'tarball' in target:
        source = target.pop(target.index('tarball'))
    else:
        source = 'tarball'
    return source

def setup_gnucash(target):
    global prefix, buildroot, moduleset, modules
    if target and not isinstance(target, list):
        raise RuntimeError("setup_gnucash requires a list argument")

    gnucash_versions = ('stable', 'master', 'unstable', 'oldstable',
                        '2.4', '2.2', '2.0', '2.6', '2.7', '2.8')
    stable = "2.6"
    unstable = "2.7"

    if not target:
        version = 'stable'
    elif target[0] in gnucash_versions:
        version = target.pop(0)
    elif 'git' in target:
        version = 'master'
        target.pop(target.index('git'))
    else:
        version = 'stable'

    if version == 'master':
        source = 'git'
    else:
        source = get_source(target)

    if version not in ('master', 'stable', '2.6'):
        raise RuntimeError("Gnucash does not currently have a %s version" %
                           version)

    if version in ('stable', '2.6'):
        if not (set(_osx_versions).intersection(set(target))):
            target.append('Leopard')
        vstr = "-" + stable
        module = "gnucash"
        bundle = "gnucash.bundle"
        doc_module = "gnucash-docs"

    elif version in ("unstable"):
        if not (set(_osx_versions).intersection(set(target))):
            target.append('Leopard')
        vstr = "-" + unstable
        module = "gnucash-unstable"
        bundle = "gnucash-unstable.bundle"
        doc_module = "gnucash-docs-git"
    else:
        if not source == 'git':
            raise RuntimeError("Don't know how to build arbitrary tarballs")

        vstr = '-' + version + "-git"
        module = "gnucash-git"
        bundle = "gnucash-unstable.bundle"
        branches["gnucash-git"] = (None, version)
        doc_module = "gnucash-docs-git"
        branches["gnucash-docs-git"] = (None, version)

    gnucash = "Gnucash" + vstr
    if target:
        gnucash += '-%s' % '-'.join(target)
    set_environment(target)

    make_builddir(_gnucash_build_base, gnucash)
    os.environ['SRCROOT'] = checkoutroot
    moduleset = make_moduleset_gnucash()
#    print moduleset

    if not os.path.exists(prefix):
        os.makedirs(os.path.join(prefix))
    modules = ["python", "meta-gtk-osx-bootstrap", "meta-gtk-osx-core",
               module, doc_module]
    if source == 'git':
        modules.insert (2, "gtkmm")
#        modules.insert (2, "guile2")
#    else:
    skip.remove("guile")


    os.environ["BUNDLE"] = os.path.join(_gtk_osx_dir, 'gnucash-on-osx',
                                        'gnucash-bundler', bundle)
    skip.remove("gmp")

def setup_gramps(target):
    '''
    Set up gramps for building.

    The gramps git repo in _gtk_osx_dir must be clean so that the
    script can check out the correct branch and access that version's
    module and bundle files.
    '''
    from subprocess import call
    global prefix, buildroot, modules, moduleset
    if target and not isinstance(target, list):
        raise RuntimeError("setup_gnucash requires a list argument")
    gramps_versions = ('stable', 'oldstable', 'master', '40', '34', '32', '30')
    stable = 'gramps40'
    oldstable = 'gramps34'

    if not target:
        version = 'stable'
    elif target[0] in gramps_versions:
        version = target.pop(0)
    else:
        version = 'stable'

    source = get_source(target)

    if _in_source:
        bsddb = 'berkeleydb'
    else:
        bsddb = 'berkeleydb-nonsrctree'

    if (version in ('stable', 'oldstable') and
        not (set(_osx_versions).intersection(set(target)))):
        target.append('Leopard')

    set_environment(target)
    gtk3_modules = [bsddb, "python", "meta-gtk-osx-bootstrap",
                    "meta-gtk-osx-freetype", "meta-gtk-osx-gtk3",
                    "meta-gtk-osx-python-gtk3"]
    gtk2_modules = [bsddb, "python", "meta-gtk-osx-bootstrap",
                    "meta-gtk-osx-freetype", "meta-gtk-osx-core",
                    "meta-gtk-osx-python", "boost", "pyexiv2"]

    if version == 'master':
        branch = 'master'
        source = 'git'
    elif version == 'stable':
        branch = stable
    elif version == 'oldstable':
        branch = oldstable
    else:
        branch = 'gramps%s' % version
    grampsdir = os.path.join(_gtk_osx_dir, 'gramps')
#    print ("Check out %s in %s" % (branch, grampsdir))
    call('cd %s; git checkout -q %s' % (grampsdir, branch), shell=True)

    if source == 'git':
        gramps = "gramps-git"
    else:
        gramps = 'gramps'
    if version.startswith('3') or version == 'oldstable':
        modules = gtk2_modules + [gramps]
    else:
        modules = gtk3_modules + [gramps]

    gramps_ver = '-'.join(('gramps', version, source))
    if target:
        gramps_ver += '-%s' %  ('-').join(target)
    make_builddir(_gramps_build_base, gramps_ver)

    moduleset = os.path.join(_gtk_osx_dir, 'gramps', 'mac', "gramps.modules")
    os.environ["BUNDLE"] = os.path.join(_gtk_osx_dir, 'gramps', 'mac',
                                        'gramps.bundle')

    skip.remove("gmp")

def setup_gtk(target):
    """
    Build a Gtk generic target. If you want to do something weird you
    can override the target stuff with build, but ordinarily you can
    just mix target verbs in with "gtk" and the gtk version. e.g.:
    gtk-unstable-3-Leopard-64 will build a 64 bit gtk3 for 10.5 and
    later from git masters.
    """
    global prefix, buildroot, moduleset, modules
    if target and not isinstance(target, list):
        raise RuntimeError("setup_gtk requires a list argument")

    gtk_versions = ('2', '3')
    if not target:
        version = '3'
    elif target[0] in gtk_versions:
        version = target.pop(0)
    else:
        version = '3'

    set_environment(target)
    modules = ['meta-gtk-osx-bootstrap']

    if version == '3':
        modules.append('meta-gtk-osx-gtk3')
        if ('bindings' in target):
            modules.extend(('meta-gtk-osx-python-gtk3', 'meta-gtk-osx-gtkmm3'))
    else:
        modules.append('meta-gtk-osx-core')
        if ('bindings' in target):
            modules.extend(('meta-gtk-osx-python', 'meta-gtk-osx-gtkmm'))

    if (('Leopard' in target or 'Tiger' in target) and
        _osx_version >= 7.0):
        modules.append('python')

def setup_bootstrap():
    global prefix, buildroot, modulesets_dir
    version = '10.%s' % str(_osx_version).split('.')[0]
    if _popen("uname -p") == "powerpc":
        setup_sdk(version, "native", ['ppc'])
    else:
        setup_sdk(version, 'native', ['i386'])
    prefix = os.path.join(os.environ['HOME'], '.local')
    buildroot = os.path.join(os.environ['HOME'], 'Source')

def set_target(targetstr, build=None):
    global prefix, modules, moduleset
#Don't mess with anything if there's an external config file (usually
#for a framework)
    if os.environ.has_key("JHB") and os.environ["JHB"]:
        return

    _setbuild = False
    targetlist = targetstr.split('-')
    if targetlist[0] in _targets:
        target = targetlist.pop(0)
    elif (not build and
        (_special_builds.intersection(set(targetlist)) or
         set(_osx_versions).intersection(set(targetlist)))):
        set_environment(targetstr)
        return
    else:
        set_environment(build)
        return

    if target == "core":
        modules = ["meta-gtk-osx-bootstrap", "meta-gtk-osx-core"]
        set_environment(targetlist)
    elif target == "gnucash":
        setup_gnucash(targetlist)
    elif target == "gramps":
        setup_gramps(targetlist)
    elif target == "gtk":
        setup_gtk(targetlist)
    elif target == "bootstrap":
        setup_bootstrap()
    else:
        set_environment(build)


if _local_old_build != None:
    if _build != _local_old_build:
        print "ERROR! jhbuild is already running with a different build."
        raise SystemExit
    else:
        print("WARNING! jhbuild is already running.")
else:
    os.environ["JHBUILD"] = _build or _target or 'gtk-native-x86_32'

if _target != None:
    set_target(_target, _build)
else:
    set_environment(_build)

if _debug == "debug":
    setup_debug()
else:
    setup_release()

#check_prefix()

tarballdir = os.path.join(_default_build_drive , "gtk-downloads")
if os.environ.has_key("BOOTSTRAP") and os.environ['BOOTSTRAP'] == "common":
    _exec_prefix =  os.path.join(_default_build_drive, "Gtk-OSX-Common", "inst")
    addpath("PATH", os.path.join(_exec_prefix, "bin"))

#Some packages want to use tmp, but choke on the goofy pathnames mkstmp provides
_tmpdir = os.path.join(prefix, "tmp")
os.environ["TMPDIR"] = _tmpdir
if not os.path.exists(_tmpdir):
    os.makedirs(_tmpdir)

_aux_root = os.path.join(os.environ['HOME'], '.local')
_catalog_path = os.path.join ('etc', 'xml', 'catalog')
if 'XML_CATALOG_FILES' in os.environ:
#    _cats = os.environ['XML_CATALOG_FILES']
    os.environ['XML_CATALOG_FILES'] = (os.path.join(_aux_root, _catalog_path))
#                                       + ':' + _cats)
else:
     os.environ['XML_CATALOG_FILES'] = os.path.join(_aux_root, _catalog_path)

#Override the default LIBTOOLIZE=$PREFIX/bin/libtoolize to use our
#single tool directory.
if os.path.exists(os.path.join(_aux_root, 'bin', 'libtoolize')):
    os.environ['LIBTOOLIZE'] = os.path.join(_aux_root, 'bin', 'libtoolize')
#skip.append('hicolor-icon-theme')

#For XCode4 we need to disable ppc when building perl:
#os.environ["ARCHFLAGS"]="-arch i386 -arch x86_64"

append_autogenargs("libofx", "--with-opensp-includes=" + prefix + "/include/OpenSP --with-opensp-libs=" + prefix + "/lib")
append_autogenargs("libgnomeui", "--enable-shared --disable-scrollkeeper --disable-xlib --without-x")
append_autogenargs("scrollkeeper", "--with-xml-catalog=" + os.path.join(prefix, "etc/xml/catalog"))

append_autogenargs("OpenSP", "--enable-shared") #To override the global --disable-shared
append_autogenargs("libdbi-drivers","--with-dbi-incdir=" + prefix + "/include --with-dbi-libdir=" + prefix + "/lib")

append_autogenargs("libiconv", "--with-libintl-prefix=" + prefix)
#append_autogenargs("pango", "--enable-introspection=no")
append_autogenargs("gir-repository", '--with-skipped-gir-modules="Soup, Gtk, Poppler, "')
append_autogenargs("gimp", "--host=i686-darwin10.8.0 --target=i686-darwin10.8.0")
remove_autogenargs("zlib", "--disable-static")
append_autogenargs("glib", "--disable-dtrace")

module_makecheck["gmp"] = True
module_extra_env["gnucash-git"] = {'CFLAGS':os.environ['CFLAGS'] + ' -std=gnu99'}

#skip.append("gobject-introspection")
#skip.append("gir-repository")

skip.append("libiconv")
module_makeargs["aqbanking"]="-j1"
#os.environ['CC'] = '/opt/gcc-4.8.1/bin/gcc'
#os.environ['CXX'] = '/opt/gcc-4.8.1/bin/g++'
#os.environ['CPP'] = '/opt/gcc-4.8.1/bin/cpp'

os.environ['CC_FOR_BUILD'] = os.environ['CC']
os.environ['CPP_FOR_BUILD'] = os.environ['CC']
os.environ['CFLAGS_FOR_BUILD'] = os.environ['CFLAGS']
if (xcode_ver() >= 5.0):
    append_autogenargs('libgcrypt', 'CFLAGS="$CFLAGS -fheinous-gnu-extensions"')
    module_extra_env["webkit"] = {'CXXFLAGS':os.environ['CXXFLAGS'] +
                                  ' -stdlib=listdc++'}
