#!/usr/bin/python
###########################################################################
# setup - description                                                     #
# ------------------------------                                          #
# begin     : Thu Apr 21 2005                                             #
# copyright : (C) 2005 by Simon Edwards                                   #
# email     : simon@simonzone.com                                         #
#                                                                         #
###########################################################################
#                                                                         #
#   This program is free software; you can redistribute it and/or modify  #
#   it under the terms of the GNU Library General Public License as       #
#   published by the Free Software Foundation; either version 2 of the    #
#   License, or (at your option) any later version.                       #
#                                                                         #
###########################################################################
from distutils.cmd import Command
from distutils import sysconfig
from distutils.spawn import find_executable,spawn
from distutils import dir_util
import sys
import os
import glob

sys.path.insert(0,"src") # We need this for the import statement below.
import tdedistutils

def main():
    tdedistutils.setup(name="pytdeextensions",
        version="0.4.0",
        author="Simon Edwards",
        author_email="simon@simonzone.com",
        url="http://www.simonzone.com/software/pykdeextensions/",
        min_kde_version = "3.0.0",
        min_tqt_version = "3.0.0",
        license = "LGPL",
        package_dir = {'': 'src'},
        py_modules = ["tdedistutils","tqtuicompiler","tqtdesigner","tdedesigner"],
        application_data = ["app_templates","AUTHORS","ChangeLog","COPYING","INSTALL","NEWS"],
        docbooks = [ ('doc/en','en') ],
        cmdclass = {
            'install' : InstallPyKDEExtensions,
            'build_libpythonize' : BuildLibpythonize,
            'install_libpythonize' : InstallLibpythonize
        }
        )

###########################################################################
class InstallPyKDEExtensions(tdedistutils.InstallKDE):
    sub_commands = tdedistutils.InstallKDE.sub_commands[:]
    sub_commands.append( ('install_libpythonize',None) )
    
    user_options = tdedistutils.InstallKDE.user_options
    user_options.append( ('install-clib=', None, "installation directory for shared libraries") )
    user_options.append( ('install-cheaders=', None, "installation directory for C header files") )
            
    def initialize_options(self):
        self.install_clib = None
        self.tde_libdir = None
        self.install_cheaders = None
        tdedistutils.InstallKDE.initialize_options(self)

    def finalize_options(self):
        if self.tde_libdir is None:
            self.announce("Detecting KDE library directory...")
            self.tde_libdir = tdedistutils.ask_kde_config('--install lib --expandvars').strip()
            self.announce("  ...KDE library directory is %s" % self.tde_libdir)
        if self.install_clib is None:
            if self.prefix is not None:
                self.install_clib = os.path.join(self.prefix,'lib')
            else:
                self.install_clib = self.tde_libdir
        if self.install_cheaders is None:
            if self.prefix is not None:
                self.install_cheaders = os.path.join(self.prefix,'include')
            else:
                self.announce("Detecting KDE headers directory...")
                self.install_cheaders = os.path.normpath(os.path.join(tdedistutils.ask_kde_config('--install lib --expandvars').strip(),"../include"))
                self.announce("  ...KDE library headers is %s" % self.install_cheaders)

        tdedistutils.InstallKDE.finalize_options(self)

        if self.root is not None:
            self.change_roots('clib','cheaders')
    
###########################################################################
class BuildLibpythonize(Command):
    description = "Build libpythonize"

    user_options = [
                    ('tde-rpath=', 'd',"Rpath that will be added to C libraries."),
                    ('no-libpythonize',None,"Don't build libpythonize"),
                    ('build-dir=','b', "build directory (where to install from)"),
                    ('python-dir=',None,'Directory containing the Python installation'),
                    ('python-inc-dir=',None,'Directory containing C Header files for Python'),
                    ('clib=',None,'gcc library and path'),
                    ]
    
    def initialize_options(self):
        self.build_dir = None
        self.tde_rpath = None
        self.no_libpythonize = 0
        self.python_inc_dir = None
        self.python_dir = None
        self.clib = None
        
    def finalize_options(self):
        if self.no_libpythonize==0:

            self.set_undefined_options('install',\
                                ('build_base', 'build_dir'),
                                ('tde_libdir', 'tde_rpath') )

            # Python dir
            if self.python_dir is None:
                self.python_dir = os.path.split(sysconfig.get_config_var("LIBPL"))[0]
            self.announce("Using %s for the python directory" % self.python_dir)
            
            # Python include dir.
            if self.python_inc_dir is None:
                # Find the Python include directory.
                self.python_inc_dir = sysconfig.get_config_var("INCLUDEPY")
            self.announce("Using %s for Python header files" % self.python_inc_dir)
                
            # Find the C library (libgcc, libgcc_s or some other variation).
            if self.clib is None:
                canidatepaths = ["/usr/"+tdedistutils.get_libdir_name(), "/usr/local/"+tdedistutils.get_libdir_name(), "/usr/lib" ]
                self.clib = tdedistutils.FindFileInPaths("libgcc*.so",canidatepaths)
                if self.clib!=None:
                    self.clib = glob.glob(os.path.join(self.clib,'libgcc*.so'))[0]
                else:
                    self.clib = tdedistutils.FindFileInPaths("libgcc*.a",canidatepaths)
                    if self.clib!=None:
                        self.clib = glob.glob(os.path.join(self.clib,'libgcc*.a'))[0]
            if self.clib is None:
                raise SystemExit("setup.py: Failed to find a suitable libgcc library")
            self.announce("Using %s for clib" % self.clib)
    
            # Make a list of places to look for python .so modules
            self.python_sub_dirs = sysconfig.get_config_var("LIBSUBDIRS").split()
            base = sysconfig.get_config_var("LIBPL")
            self.python_sub_dirs = [ os.path.join(base,item) for item in self.python_sub_dirs ]
            self.python_sub_dirs.append(base)

    def get_command_name(self):
        return 'build_libpythonize'

    def run(self):
        if self.no_libpythonize:
            self.announce("Skipping libpythonize")
            return
    
        self.announce("Building libpythonize.")
        
        cppfile = "src/pythonize.cpp"
        # Compile the library.
        cmdlist = ['libtool']

        # Couldn't get it to pass without this ...
        cmdlist.append("--mode=compile")
        cmdlist.append("--tag=CXX")
        
        # Find the compiler and flags
        cxx = sysconfig.get_config_var("CXX").split() or os.environ.get("CXX").split() or ["c++"]
        cxxflags = []
        # Use python's CFLAGS
        cflags = (sysconfig.get_config_var("CFLAGS"))
        if cflags:
            cxxflags.extend(cflags.split())
        # Append our own flags
        cxxflags.append ('-fno-strict-aliasing')
        # Get user-provided flags
        if os.environ.get("CXXFLAGS"):
            cxxflags.extend(os.environ["CXXFLAGS"].split())

        cmdlist.extend(cxx)
        # cc_flags
        cmdlist.append("-c")

        cmdlist.extend(cxxflags)
        
        # includes
        cmdlist.append("-I" + sysconfig.get_config_var("INCLUDEDIR"))
        cmdlist.append("-I" + sysconfig.get_config_var("INCLUDEPY"))
        cmdlist.append("-I" + self.python_inc_dir)
        cmdlist.append("-Isrc")
        # input
        cmdlist.append(cppfile)
        # output
        outputfile = os.path.join(self.build_dir,'libpythonize.lo')
        cmdlist.append("-o")
        cmdlist.append(outputfile)
        spawn(cmdlist) # Execute!!!
        print()
        
        # Link the resulting object file to create a shared library.
        cmdlist = ['libtool']
        cmdlist.append("--mode=link")
        cmdlist.append("--tag=CXX")
        
        # Grab the linker command name
        cmdlist.append(sysconfig.get_config_var("LDSHARED").split()[0])
        # link_flags
        cmdlist.append("-module")
        cmdlist.append("-export-dynamic")
        # object
        cmdlist.append(outputfile)
        cmdlist.append("-rpath"); cmdlist.append(self.tde_rpath)
        cmdlist.append("-o"); cmdlist.append(os.path.join(self.build_dir,'libpythonize.la'))
        # Link libs
        linklist = []
        linklist.append("-lpython%i.%i%s" % (sys.version_info[0], sys.version_info[1], sys.abiflags) )
        linklist.extend(sysconfig.get_config_var("LIBS").split())
        
        linklist.append("-lm")
        linklist.append("-lc")
        linklist.append(self.clib)

        linklist.append("-R"); linklist.append(self.python_dir)

        cmdlist.extend(linklist)
        spawn(cmdlist) # Execute!!
        print()

###########################################################################
class InstallLibpythonize(Command):
    description = "Install libpythonize"

    user_options = [
        ('install-dir=', 'd',"Directory for the libpythonize shared library."),
        ('build-dir=','b', "build directory (where to install from)"),
        ('cheader-dir=', 'h',"Directory for the pythonize.h C header file."),
        ('install-cmd=', None, "Command to use to install the files"),
        ('root=', None, "install everything relative to this alternate root directory"),
        ('force', 'f', "force installation (overwrite existing files)"),
        ('skip-build', None, "skip the build steps"),
        ]
        
    boolean_options = ['force', 'skip-build']
    
    def initialize_options(self):
        self.install_dir = None
        self.build_dir = None
        self.install_cmd = None
        self.cheader_dir = None
        self.outfiles = []
        self.root = None
        self.force = 0
        self.warn_dir = 1
        self.skip_build = None

    def finalize_options(self):
        own_install_dir = self.install_dir is not None
        own_cheader_dir = self.cheader_dir is not None
        
        self.set_undefined_options('install',
                                ('build_base','build_dir'),
                                ('install_clib', 'install_dir'),
                                ('install_cheaders', 'cheader_dir'),
                                ('install_cmd', 'install_cmd'),
                                ('root', 'root'),
                                ('force', 'force'),
                                ('skip_build', 'skip_build')
                                )

        if own_install_dir and self.root is not None:
            self.install_dir = change_root(self.root,self.install_dir)
        if own_cheader_dir and self.root is not None:
            self.cheader_dir = change_root(self.root,self.cheader_dir)

    def get_command_name(self):
        return 'install_libpythonize'
        
    def run(self):
        if not self.skip_build:
            self.run_command('build_libpythonize')
    
        self.announce("Installing libpythonize...")
        
        self.outfiles.extend(self.mkpath(self.install_dir))
        
        # Install the library.
        cmdlist = ['libtool']
        cmdlist.append("--mode=install")
        cmdlist.append(self.install_cmd)
        cmdlist.append("-c")
        cmdlist.append(os.path.join(self.build_dir,"libpythonize.la"))
        cmdlist.append(os.path.join(self.install_dir,"libpythonize.la"))
        spawn(cmdlist) # Execute!!
        print()

        # Work the names of the files that were installed.
        self.outfiles = []
        for file in glob.glob(os.path.join(self.build_dir,'.libs/libpythonize*')):
            self.outfiles.append(os.path.join(self.install_dir,os.path.basename(file)))

        # Create a directory for the C header file.
        self.outfiles.extend(self.mkpath(self.cheader_dir))
        
        # Install the header file.
        (out, _) = self.copy_file("src/pythonize.h", os.path.join(self.cheader_dir,'pythonize.h'))
        self.outfiles.append(out)

        self.announce("Done installing libpythonize.")

    def get_outputs(self):
        return self.outfiles

    def mkpath(self, name, mode=0o777):
        dir_util.mkpath(name, mode, dry_run=self.dry_run)
        return name
        
main()
