summaryrefslogtreecommitdiffstats
path: root/src/kdedistutils.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/kdedistutils.py')
-rw-r--r--src/kdedistutils.py2209
1 files changed, 2209 insertions, 0 deletions
diff --git a/src/kdedistutils.py b/src/kdedistutils.py
new file mode 100644
index 0000000..b6e2458
--- /dev/null
+++ b/src/kdedistutils.py
@@ -0,0 +1,2209 @@
+#!/usr/bin/python
+###########################################################################
+# kdedistutils - description #
+# ------------------------------ #
+# begin : Thu Apr 21 2005 #
+# copyright : (C) 2005 by Simon Edwards #
+# email : [email protected] #
+# #
+###########################################################################
+# #
+# 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. #
+# #
+###########################################################################
+
+import distutils.core
+from distutils.core import Extension
+from distutils.cmd import Command
+from distutils.dist import Distribution
+from distutils.command.build import build
+from distutils.command.install import install
+from distutils.command.install_scripts import install_scripts
+from distutils.command.install_data import install_data
+from distutils.command.install_lib import install_lib
+from distutils.util import change_root, convert_path
+from distutils.spawn import find_executable,spawn
+from distutils import sysconfig
+from distutils import log
+from distutils import file_util
+from distutils import dir_util
+from distutils.util import byte_compile
+import qtuicompiler
+import stat
+import os,os.path,imp,glob
+import sys
+from types import StringType
+
+INSTALL_LIST = 'install_log.txt'
+
+###########################################################################
+def setup(**arg_dict):
+
+ if 'cmdclass' not in arg_dict:
+ arg_dict['cmdclass'] = {}
+
+ cmdclass = arg_dict['cmdclass']
+
+ arg_dict.setdefault('data_files',[])
+
+ kdecmdclass = {'install' : InstallKDE,
+ 'install_executable_links' : InstallExecutableLinks,
+ 'install_application_data' : InstallApplicationDataAndLinks,
+ 'build_messages' : BuildI18NMessages,
+ 'install_messages' : InstallI18NMessages,
+ 'update_messages' : UpdateI18NMessages,
+ 'checkpyqt' : CheckPyQt,
+ 'checkpykde' : CheckPyKDE,
+ 'uninstall' : Uninstall,
+ 'build' : BuildKDE,
+ 'build_kcm' : BuildKControlModule,
+ 'install_kcm' : InstallKControlModule,
+ 'build_html' : BuildDocbookHTML,
+ 'install_html' : InstallDocbookHTML,
+ 'install_lib' : InstallLibWithRoot,
+ 'build_kioslave' : BuildKioslave,
+ 'install_kioslave' : InstallKioslave}
+
+ for key in kdecmdclass.iterkeys():
+ cmdclass.setdefault(key,kdecmdclass[key])
+
+ arg_dict.setdefault('distclass',KDEDistribution)
+
+ apply(distutils.core.setup,[],arg_dict)
+
+###########################################################################
+class KDEDistribution(Distribution):
+ def __init__(self,attrs=None):
+ self.min_kde_version = None
+ self.min_qt_version = None
+ self.kcontrol_modules = None
+ self.kioslaves = None
+ self.executable_links = None
+ self.docbooks = None
+ self.application_data = None
+ self.i18n = None
+ Distribution.__init__(self,attrs)
+
+###########################################################################
+def has_kcms(self):
+ if self.distribution.kcontrol_modules is None:
+ return 0
+ return len(self.distribution.kcontrol_modules)!=0
+
+def has_docbook_html(self):
+ if self.distribution.docbooks is None:
+ return 0
+ return len(self.distribution.docbooks)!=0
+
+def has_messages(self):
+ if self.distribution.i18n is None:
+ return 0
+ return len(self.distribution.i18n)!=0
+
+def has_application_data(self):
+ if self.distribution.application_data is None:
+ return 0
+ return len(self.distribution.application_data)!=0
+
+def has_kioslaves(self):
+ if self.distribution.kioslaves is None:
+ return 0
+ return len(self.distribution.kioslaves)!=0
+
+###########################################################################
+# Our slightly extended build command. This also does kcontrol modules.
+class BuildKDE(build):
+
+ user_options = build.user_options[:]
+ user_options.append( ('msgfmt-exe=',None,'Path to the msgfmt executable') )
+ user_options.append( ('meinproc-exe=',None,'Path to the meinproc executable') )
+
+ sub_commands = build.sub_commands[:]
+ sub_commands.append( ('build_kcm',has_kcms) )
+ sub_commands.append( ('build_kioslave',has_kioslaves) )
+ sub_commands.append( ('build_html',has_docbook_html) )
+ sub_commands.append( ('build_messages',has_messages) )
+
+ def __init__(self,dist):
+ build.__init__(self,dist)
+ self.has_kcms = has_kcms
+ self.has_kioslaves = has_kioslaves
+ self.has_docbook_html = has_docbook_html
+ self.has_messages = has_messages
+
+ def initialize_options(self):
+ self.msgfmt_exe = None
+ self.meinproc_exe = None
+ build.initialize_options(self)
+
+ def finalize_options(self):
+ build.finalize_options(self)
+
+ if self.msgfmt_exe is None:
+ # Find msgfmt
+ canidatepaths = []
+ canidatepaths.append( ask_kde_config('--install exe --expandvars').strip() )
+ self.msgfmt_exe = FindExeOnPath('msgfmt',canidatepaths)
+ if self.msgfmt_exe is None:
+ raise SystemExit, "Unable to find 'msgfmt', needed to build i18n messages."
+
+ if self.meinproc_exe is None:
+ # Find meinproc
+ canidatepaths = []
+ canidatepaths.append( ask_kde_config('--install exe --expandvars').strip() )
+ self.meinproc_exe = FindExeOnPath('meinproc',canidatepaths)
+ if self.meinproc_exe is None:
+ raise SystemExit, "Unable to find 'meinproc', needed to generate Docbook HTML documentation."
+
+###########################################################################
+def has_executable_links(self):
+ if self.distribution.executable_links is None:
+ return 0
+ return len(self.distribution.executable_links)!=0
+
+###########################################################################
+class InstallKDE(install):
+ user_options = install.user_options[:]
+ user_options.append( ('kde-prefix=',None,"KDE installation prefix") )
+ user_options.append( ('install-messages=',None,"installation directory for i18n message files") )
+ user_options.append( ('install-html=',None,"installation directory for Docbook HTML files") )
+ user_options.append( ('install-cmd=',None,"Command to use to install the files") )
+ user_options.append( ('install-xdg-apps=',None,"directory for XDG app files") )
+ user_options.append( ('install-kcm=',None,"directory for kcm library files") )
+ user_options.append( ('install-kioslave',None,"directory for kioslave library files") )
+ user_options.append( ('install-protocol',None,"directory for kioslave protocol files") )
+
+ sub_commands = install.sub_commands[:]
+ sub_commands.insert(0, ('checkpykde',None) )
+ sub_commands.insert(0, ('checkpyqt',None) )
+ sub_commands.append( ('install_executable_links',has_executable_links) )
+ sub_commands.append( ('install_messages',has_messages) )
+ sub_commands.append( ('install_html',has_docbook_html) )
+ sub_commands.append( ('install_kcm',has_kcms) )
+ sub_commands.append( ('install_kioslave',has_kioslaves) )
+ sub_commands.append( ('install_application_data',has_application_data) )
+
+ def initialize_options(self):
+ self.kde_prefix = None
+ self.install_messages = None
+ self.install_html = None
+ self.install_cmd = None
+ self.install_xdg_apps = None
+ self.install_kcm = None
+ self.install_kioslave = None
+ self.install_protocol = None
+ self.install_application_data = None
+ install.initialize_options(self)
+
+ def finalize_options(self):
+ # If no install prefix was provided, then we try to detect the KDE install prefix.
+ self.user_supplied_kde_prefix = True
+
+ if self.install_scripts is None:
+ if self.kde_prefix is not None:
+ self.install_scripts = os.path.join(self.kde_prefix,'bin')
+ else:
+ self.announce("Detecting KDE 'bin' directory...")
+ self.install_scripts = ask_kde_config('--install exe --expandvars').strip()
+ self.announce(" ...KDE 'bin' directory is %s" % self.install_scripts)
+
+ if self.install_application_data is None:
+ if self.kde_prefix is not None:
+ self.install_application_data = os.path.join(self.kde_prefix,'share/apps',self.distribution.metadata.name)
+ else:
+ self.announce("Detecting KDE application directory...")
+ kdeappdir = ask_kde_config('--install data --expandvars').strip()
+ self.announce(" ...KDE application directory is %s" % self.install_application_data)
+ self.install_application_data = os.path.join(kdeappdir,self.distribution.metadata.name)
+
+ if self.install_messages is None:
+ if self.kde_prefix is not None:
+ self.install_messages = os.path.join(self.kde_prefix,'share/locale')
+ else:
+ self.announce("Detecting KDE messages directory...")
+ self.install_messages = ask_kde_config('--install locale --expandvars').strip()
+ self.announce(" ...KDE messages directory is %s" % self.install_messages)
+
+ if self.install_html is None:
+ if self.kde_prefix is not None:
+ self.install_html = os.path.join(self.kde_prefix,'share/doc/HTML')
+ else:
+ self.announce("Detecting KDE HTML directory...")
+ self.install_html = ask_kde_config('--install html --expandvars').strip()
+ self.announce(" ...KDE HTML directory is %s" % self.install_html)
+
+ if self.kde_prefix is None:
+ self.announce("Detecting KDE install prefix...")
+ self.kde_prefix = ask_kde_config('--prefix').strip()
+ self.announce(" ...KDE install prefix is %s" % self.kde_prefix)
+ self.user_supplied_kde_prefix = False
+
+ if self.install_cmd is None:
+ self.announce("Detecting 'install' command...")
+ # Ok, time to find the install command.
+ self.install_cmd = find_executable('install')
+ if self.install_cmd is None:
+ raise SystemExit, "Unable to find the 'install' command, needed to install libraries."
+ self.announce(" ...'install' command is %s" % self.install_cmd)
+
+ if self.install_xdg_apps is None:
+ self.announce("Detecting XDG apps directory...")
+ self.install_xdg_apps = ask_kde_config('--install xdgdata-apps --expandvars').strip()
+ self.announce(" ...XDG apps directory is %s" % self.install_xdg_apps)
+
+ if self.install_kcm is None:
+ self.announce("Detecting kcm library directory...")
+ self.install_kcm = os.path.join(ask_kde_config('--install lib --expandvars').strip(),'kde3')
+ self.announce(" ...kcm library directory is %s" % self.install_kcm)
+
+ if self.install_kioslave is None:
+ self.announce("Detecting kioslave library directory...")
+ self.install_kioslave = os.path.join(ask_kde_config('--install lib --expandvars').strip(),'kde3')
+ self.announce(" ...kioslave library directory is %s" % self.install_kioslave)
+
+ if self.install_protocol is None:
+ self.announce("Detecting kioslave protocol directory...")
+ self.install_protocol = ask_kde_config('--install services --expandvars').strip()
+ self.announce(" ...kioslave protocol directory is %s" % self.install_protocol)
+
+ install.finalize_options(self)
+
+ if self.root is not None:
+ self.change_roots('application_data','html','messages','xdg_apps','kcm')
+
+ def get_command_name(self):
+ return 'install'
+
+ def run(self):
+ global INSTALL_LIST
+ install.run(self)
+
+ # Write out the uninstall list.
+ fhandle = open(INSTALL_LIST,'w')
+ for item in self.get_outputs():
+ fhandle.write(item)
+ fhandle.write('\n')
+ fhandle.close()
+
+###########################################################################
+class InstallApplicationDataAndLinks(install_data):
+ def get_command_name(self):
+ return 'install_application_data'
+
+ def initialize_options(self):
+ install_data.initialize_options(self)
+
+ self.data_files = self.distribution.application_data
+
+ def finalize_options(self):
+ self.set_undefined_options('install',
+ ('install_application_data', 'install_dir'),
+ ('root', 'root'),
+ ('force', 'force'),
+ )
+
+ def run(self):
+ self.outfiles.extend(self.mkpath(self.install_dir))
+ for f in self.data_files:
+ if type(f) is StringType:
+ # it's a simple file, so copy it
+ f = convert_path(f)
+ if self.warn_dir:
+ self.warn("setup script did not provide a directory for "
+ "'%s' -- installing right in '%s'" %
+ (f, self.install_dir))
+ if os.path.isfile(f):
+ (out, _) = self.copy_file(f, self.install_dir)
+ self.outfiles.append(out)
+ elif os.path.isdir(f):
+ out = self.copy_tree(f,os.path.join(self.install_dir,f))
+ self.outfiles.extend(out)
+ else:
+ self.warn("Setup script can't find file or directory %s needed for installation." % f)
+ else:
+ # it's a tuple with path to install to and a list of files
+ dir = convert_path(f[0])
+ if not os.path.isabs(dir):
+ dir = change_root(self.install_dir, dir)
+ elif self.root:
+ dir = change_root(self.root, dir)
+ self.outfiles.extend(self.mkpath(dir))
+
+ if f[1] == []:
+ # If there are no files listed, the user must be
+ # trying to create an empty directory, so add the
+ # directory to the list of output files.
+ self.outfiles.append(dir)
+ else:
+ # Copy files, adding them to the list of output files.
+ for data in f[1]:
+ data = convert_path(data)
+ if os.path.islink(data):
+ # Transplant the link to the new location without changing
+ # where it points to. (ie it is _not_ relocated).
+ dest = os.path.join(dir, os.path.basename(data))
+ if os.path.exists(dest):
+ os.remove(dest)
+ os.symlink(os.readlink(data),dest)
+ log.info("moving link %s -> %s" % (data,dest) )
+ #os.chmod(dest, os.stat(data)[stat.ST_MODE])
+ elif os.path.isdir(data):
+ out = self.copy_tree(data,dir)
+ self.outfiles.extend(out)
+ else:
+ (out, _) = self.copy_file(data, dir)
+ self.outfiles.append(out)
+
+ # Compile the .ui files
+ install_cmd = self.get_finalized_command('install')
+ prefix = self.install_dir
+ if prefix[-1] != os.sep:
+ prefix = prefix + os.sep
+ self.outfiles.extend(compile_qtdesigner(self.outfiles, force=1, prefix=prefix, base_dir=install_cmd.prefix, dry_run=self.dry_run))
+
+ # Byte compile the .py files
+ from distutils.util import byte_compile
+ byte_compile(self.outfiles, optimize=0, force=1, prefix=prefix, base_dir=install_cmd.prefix, dry_run=self.dry_run)
+
+ # Add the .pyc files to the list of outfiles.
+ self.outfiles.extend( [item+'c' for item in self.outfiles if item.endswith('.py')] )
+
+ def mkpath(self, name, mode=0777):
+ return dir_util.mkpath(name, mode, dry_run=self.dry_run)
+
+###########################################################################
+class InstallExecutableLinks(Command):
+ description = "Install symlinks"
+
+ user_options = []
+
+ def initialize_options(self):
+ self.outfiles = []
+
+ def finalize_options(self):
+ pass
+
+ def get_command_name(self):
+ return 'install_executable_links'
+
+ def run(self):
+ # FIXME add cmd options?
+ install_script_cmd = self.get_finalized_command('install_scripts')
+ install_data_cmd = self.get_finalized_command('install_application_data')
+
+ destination_dir = install_data_cmd.install_dir
+
+ if not os.path.exists(install_script_cmd.install_dir):
+ self.outfiles.extend(self.mkpath(install_script_cmd.install_dir))
+
+ if self.distribution.executable_links is not None:
+ for link in self.distribution.executable_links:
+ symname = os.path.join(install_script_cmd.install_dir,link[0])
+ target = os.path.join(destination_dir,link[1])
+ log.info("symlinking %s -> %s", symname, target)
+ if not self.dry_run:
+ if os.path.islink(symname):
+ os.remove(symname)
+ os.symlink(target,symname)
+ self.outfiles.append(symname)
+
+ def get_outputs(self):
+ return self.outfiles or []
+
+ def mkpath(self, name, mode=0777):
+ return dir_util.mkpath(name, mode, dry_run=self.dry_run)
+
+###########################################################################
+# Fix the --root option for the install_lib command.
+class InstallLibWithRoot(install_lib):
+ user_options = install_lib.user_options[:]
+ user_options.append( ('root=',None,"install everything relative to this alternate root directory") )
+
+ def initialize_options(self):
+ install_lib.initialize_options(self)
+ self.root = None
+
+ def finalize_options(self):
+ own_install_dir = self.install_dir is not None
+
+ install_lib.finalize_options(self)
+ self.set_undefined_options('install', ('root', 'root'))
+
+ if self.root is not None and own_install_dir:
+ self.install_dir = change_root(self.root, self.install_dir)
+
+###########################################################################
+class Uninstall(Command):
+ description = "Remove all installed files"
+
+ user_options = []
+
+ def initialize_options(self):
+ pass
+
+ def finalize_options(self):
+ pass
+
+ def get_command_name(self):
+ return 'uninstall'
+
+ def run(self):
+ global INSTALL_LIST
+
+ if not os.path.isfile(INSTALL_LIST):
+ self.announce("Unable to uninstall, can't find the file list %s." % INSTALL_LIST)
+ return
+
+ # Suck in the file list.
+ fhandle = open(INSTALL_LIST,'r')
+ file_list = fhandle.readlines()
+ fhandle.close()
+
+ # Remove the files first.
+ for item in file_list:
+ item = item.strip()
+ if os.path.isfile(item) or os.path.islink(item):
+ self.announce("removing '%s'" % item)
+ if not self.dry_run:
+ try:
+ os.remove(item)
+ except OSError, details:
+ self.warn("Could not remove file: %s" % details)
+ elif not os.path.isdir(item):
+ self.announce("skipping removal of '%s' (does not exist)" % item)
+
+ # Remove the directories.
+ file_list.sort()
+ file_list.reverse()
+ # Starting with the longest paths first.
+ for item in file_list:
+ item = item.strip()
+ if os.path.isdir(item):
+ self.announce("removing '%s'" % item)
+ if not self.dry_run:
+ try:
+ os.rmdir(item)
+ except OSError, details:
+ self.warn("Could not remove directory: %s" % details)
+
+###########################################################################
+class BuildKControlModule(Command):
+ description = "Build KControl extensions"
+
+ user_options = [('no-kcontrol',None,"Don't build kcontrol extensions"),
+ ('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'),
+ ('kde-inc-dir=',None,'Directory containing C++ header files for KDE'),
+ ('kde-lib-dir=',None,'Directory containing library files for KDE'),
+ ('kde-kcm-lib-dir=',None,'Directory for KDE kcm library files'),
+ ('qt-inc-dir=',None,'Directory containing C++ header files for Qt'),
+ ('qt-lib-dir=',None,'Directory containing library files for Qt'),
+ ('sip-dir=','/usr/lib/pyshared/python2.6','Directory containing the sip library files'),
+ ('clib=',None,'gcc library and path'),
+ ('pyqt-dir=','/usr/lib/pyshared/python2.6','PyQt module directory'),
+ ('pykde-dir=',None,'PyKDE module directory'),
+ ('data-dir=',None,'installation directory for data (script) files')]
+
+ def initialize_options(self):
+ self.no_kcontrol = 0
+ self.build_dir = None
+ self.python_inc_dir = None
+ self.python_dir = None
+ self.kde_inc_dir = None
+ self.kde_lib_dir = None
+ self.kde_kcm_lib_dir = None
+ self.qt_inc_dir = None
+ self.qt_lib_dir = None
+ self.sip_dir = "/usr/lib/pyshared/python2.6"
+ self.clib = None
+ self.pyqt_dir = "/usr/lib/pyshared/python2.6"
+ self.pykde_dir = None
+ self.data_dir = None
+
+ def finalize_options(self):
+ if self.no_kcontrol==0:
+ self.set_undefined_options('install', ('build_base', 'build_dir'),('install_application_data','data_dir'))
+
+ install = self.get_finalized_command('install')
+ self.install_prefix = "/opt/kde3/"
+
+ # KDE inc dir: find it!
+ if self.kde_inc_dir is None:
+ canidatepaths = []
+ kdedir = os.getenv("KDEDIR")
+ if kdedir!=None:
+ canidatepaths.append(os.path.join(kdedir,"include"))
+ canidatepaths.append(os.path.join(install.prefix,"include"))
+ canidatepaths.append('/opt/kde3/include')
+ canidatepaths.append('/opt/kde/include')
+ self.kde_inc_dir = FindFileInPaths('kapplication.h',canidatepaths)
+ if self.kde_inc_dir is None:
+ raise SystemExit, "Failed to find the KDE header file directory."
+ if FindFileInPaths('kapplication.h',[self.kde_inc_dir]) is None:
+ raise SystemExit, "Failed to find KDE header files in: %s" % self.kde_inc_dir
+ self.announce("Using %s for KDE header files" % self.kde_inc_dir)
+
+ # KDE lib dir
+ #if self.kde_lib_dir is None:
+ # self.kde_lib_dir = os.path.join(install.prefix,"lib")
+ self.kde_lib_dir = "/opt/kde3/lib/"
+ self.announce("Using %s for KDE library files" % self.kde_lib_dir)
+
+ # KDE KCM lib dir
+ #if self.kde_kcm_lib_dir is None:
+ # self.kde_kcm_lib_dir = os.path.join(self.kde_lib_dir,"kde3")
+ self.kde_kcm_lib_dir = "/opt/kde3/lib/kde3/"
+ if FindFileInPaths('*kcm*.so',[self.kde_kcm_lib_dir]) is None:
+ raise SystemExit, "Failed to find KDE KCM files in: %s" % self.kde_kcm_lib_dir
+ self.announce("Using %s for KDE KCM library files" % self.kde_kcm_lib_dir)
+
+ # Qt inc dir
+ if self.qt_inc_dir is None:
+ canidatepaths = []
+ qtdir = os.getenv("QTDIR")
+ if qtdir != None:
+ canidatepaths.append(os.path.join(qtdir,"include"))
+ canidatepaths.append(os.path.join(install.prefix,"lib/qt3/include"))
+ canidatepaths.append(os.path.join(install.prefix,"lib/qt3/include"))
+ canidatepaths.append(os.path.join(install.prefix,"include"))
+ canidatepaths.append("/opt/qt3/include")
+ canidatepaths.append("/opt/qt/include")
+ canidatepaths.append("/opt/qt/lib/include")
+ canidatepaths.append("/opt/qt3/lib/include")
+ canidatepaths.append("/usr/include/qt3")
+ self.qt_inc_dir = FindFileInPaths('qstring.h',canidatepaths)
+ if self.qt_inc_dir is None:
+ raise SystemExit,"Failed to find the Qt header file directory"
+ if FindFileInPaths('qstring.h',[self.qt_inc_dir]) is None:
+ raise SystemExit, "Failed to find Qt header files in: %s" % self.qt_inc_dir
+ self.announce("Using %s for Qt header files" % self.qt_inc_dir)
+
+ # Qt lib dir
+ if self.qt_lib_dir is None:
+ canidatepaths = []
+ qtdir = os.getenv("QTDIR")
+ if qtdir != None:
+ canidatepaths.append(os.path.join(qtdir,get_libdir_name()))
+ canidatepaths.append(os.path.join(install.prefix,"lib/qt3/"+get_libdir_name()))
+ canidatepaths.append(os.path.join(install.prefix,"lib/qt3/"+get_libdir_name()))
+ canidatepaths.append(os.path.join(install.prefix,get_libdir_name()))
+ canidatepaths.append("/opt/qt3/"+get_libdir_name())
+ canidatepaths.append("/opt/qt/"+get_libdir_name())
+ canidatepaths.append("/opt/qt/lib/"+get_libdir_name())
+ canidatepaths.append("/opt/qt3/lib/"+get_libdir_name())
+ self.qt_lib_dir = FindFileInPaths('libqt*',canidatepaths)
+ if self.qt_lib_dir is None:
+ raise SystemExit, "Failed to find Qt library files"
+ self.announce("Using %s for Qt library files" % self.qt_lib_dir)
+
+ # Python dir
+ if self.python_dir is None:
+ self.python_dir = os.path.split(sysconfig.get_config_var("LIBP"))[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)
+
+ # PyQt dir
+ if self.pyqt_dir is None:
+ self.pyqt_dir = sysconfig.get_python_lib()
+ if (FindFileInPaths("libqtcmodule*",[self.pyqt_dir]) is None) and (FindFileInPaths("qt*",[self.pyqt_dir]) is None):
+ raise SystemExit, "Failed to find the PyQt directory: %s" % self.pyqt_dir
+ self.announce("Using %s for PyQt modules" % self.pyqt_dir)
+
+ # PyKDE dir
+ if self.pykde_dir is None:
+ self.pykde_dir = sysconfig.get_python_lib()
+ if (FindFileInPaths("libkdecorecmodule*",[self.pykde_dir]) is None) and (FindFileInPaths("kdecore*",[self.pykde_dir]) is None):
+ raise SystemExit, "Failed to find the PyKDE directory: %s" % self.pykde_dir
+ self.announce("Using %s for PyKDE modules" % self.pykde_dir)
+
+ # Sip dir
+ if self.sip_dir is None:
+ self.sip_dir = sysconfig.get_python_lib()
+ if (FindFileInPaths("libsip*", [self.sip_dir]) is None) and (FindFileInPaths("sip*", [self.sip_dir]) is None):
+ raise SystemExit, "Failed to find libsip files in directory: %s" % self.sip_dir
+ self.announce("Using %s for libsip files" % self.sip_dir)
+
+ # Find the C library (libgcc, libgcc_s or some other variation).
+ if self.clib is None:
+ canidatepaths = ["/usr/"+get_libdir_name(), "/usr/local/"+get_libdir_name() ]
+ self.clib = FindFileInPaths("libgcc*.so",canidatepaths)
+ if self.clib!=None:
+ self.clib = glob.glob(os.path.join(self.clib,'libgcc*.so'))[0]
+ else:
+ self.clib = 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, "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("LIBP")
+ 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_kcm'
+
+ def run(self):
+ if self.no_kcontrol:
+ self.announce("Skipping KControl modules")
+ return
+
+ if not os.path.isdir(self.build_dir):
+ os.mkdir(self.build_dir)
+
+ for moduletuple in self.distribution.kcontrol_modules:
+ self.announce("Building KControl module from desktop file %s." % moduletuple[0])
+
+ # Read the desktop file
+ factoryfunction = None
+ libraryname = None
+ cmodulecategory = None
+ try:
+ fhandle = open(moduletuple[0],'r')
+ for line in fhandle.readlines():
+ parts = line.strip().split('=')
+ try:
+ if parts[0]=="X-KDE-Library":
+ libraryname = parts[1]
+ elif parts[0]=="Exec":
+ shellcmd = parts[1].split()
+ modulepath = shellcmd[-1]
+ if '/' in modulepath:
+ cmodulecategory = os.path.dirname(modulepath)
+ else:
+ cmodulecategory = ""
+ elif parts[0]=="X-KDE-FactoryName":
+ factoryfunction = 'create_'+parts[1]
+ except IndexError:
+ pass
+ fhandle.close()
+ except IOError:
+ raise SystemExit, "Failed to find kcontrol desktop file: %s" % moduletuple[0]
+
+ # Sanity check.
+ if factoryfunction is None:
+ raise SystemExit, "Failed to find factory name (Was there a X-KDE-FactoryName entry in the desktop file?)"
+ if libraryname is None:
+ raise SystemExit, "Failed to find library name (Was there a X-KDE-Library entry in the desktop file?)"
+ if cmodulecategory is None:
+ raise SystemExit, "Failed to find the kcontrol category name (Was there a Exec entry in the desktop file?)"
+
+ modulename = os.path.basename(moduletuple[1])
+ if modulename.endswith('.py'):
+ modulename = modulename[:-3]
+ desktopfilename = moduletuple[0]
+
+ stub_cpp_name = 'kcm_'+libraryname+'.cpp'
+ stub_so_name = 'kcm_'+libraryname+'.so'
+ stub_la_name = 'kcm_'+libraryname+'.la'
+ python_version = '%i.%i' % (sys.version_info[0],sys.version_info[1])
+
+ # Build the 'stub' code.
+ cppcode = self.cpptemplate % {"moduledir": self.data_dir,
+ "modulename": modulename,
+ "factoryfunction": factoryfunction,
+ "python_version": python_version}
+
+ # Put it on disk.
+ cppfile = os.path.join(os.path.dirname(moduletuple[0]),stub_cpp_name)
+ try:
+ fhandle = open(cppfile,'w')
+ fhandle.write(cppcode)
+ fhandle.close()
+ except IOError:
+ raise SystemExit, "Could not write the C++ stub: %s" % cppfile
+
+ # Compile the stub library.
+ cmdlist = ['libtool']
+
+ # Couldn't get it to pass without this ...
+ cmdlist.append("--mode=compile")
+ cmdlist.append("--tag=CXX")
+
+ # Find the compiler flags and options
+ # CXX is empty on some Systems, let's do it 'the hard way'.
+ # FIXME :: get CXX from make.conf for Gentoo.
+ if len(sysconfig.get_config_var("CXX").split()) >= 2:
+ cmdlist.extend(sysconfig.get_config_var("CXX").split())
+ else:
+ cmdlist.extend(['g++', '-pthread'])
+
+ #cmdlist.extend(sysconfig.get_config_var("CXX").split())
+
+ # cc_flags
+ cmdlist.append("-c")
+ cmdlist.append("-g")
+
+ # The 4 is randomly chosen!
+ # FIXME :: get CFLAGS from make.conf for Gentoo.
+ if len(sysconfig.get_config_var("CFLAGS").split()) >=4:
+ cmdlist.extend(sysconfig.get_config_var("CFLAGS").split())
+ else:
+ # On Gentoo systems, CFLAGS are not in the environment.
+ raw = os.popen('emerge info 2> /dev/null|grep CFLAGS')
+ lines = raw.readlines()
+ if len(lines):
+ cflags = lines[0].split('"')[1].split()
+ print "Got CFLAGS from emerge info."
+ cmdlist.extend(cflags)
+ else:
+ # Still no CFLAGS found, use these ...
+ cmdlist.extend(['-fno-strict-aliasing', '-DNDEBUG', '-g', '-O3', '-Wall', '-Wstrict-prototypes'])
+
+ #sysconfig.get_config_var("CFLAGS").split()
+ # includes
+ cmdlist.append("-I" + sysconfig.get_config_var("INCLUDEDIR"))
+ 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("-I" + self.kde_inc_dir)
+ cmdlist.append("-I" + self.qt_inc_dir)
+ cmdlist.append("-I.")
+ # input
+ cmdlist.append(cppfile)
+ # output
+ outputfile = os.path.join(self.build_dir,libraryname+'.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")
+
+ # 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.kde_kcm_lib_dir)
+ cmdlist.append("-o"); cmdlist.append(os.path.join(self.build_dir,stub_la_name))
+ # Link libs
+ linklist = []
+ linklist.append("-lpython%s" % python_version)
+ linklist.extend(sysconfig.get_config_var("LIBS").split())
+
+ # FIXME I doubt half of these libraries need to be here.
+ linklist.append(self.sip_dir+"/sip.so")
+ # PyQt libs
+ linklist.append(self.pyqt_dir+"/qt.so")
+ # PyKDE libs
+ linklist.append(self.pykde_dir+"/kdecore.so")
+ linklist.append(self.pykde_dir+"/kdeui.so")
+
+# linklist.append("-L"+self.sip_dir); linklist.append("-lsip")
+# # PyQt libs
+# linklist.append("-L"+self.pyqt_dir); linklist.append("-lqtcmodule")
+# # PyKDE libs
+# linklist.append("-L"+self.pykde_dir); linklist.append("-lkdecorecmodule"); linklist.append("-lkdeuicmodule")
+
+ linklist.append("-L"+self.kde_lib_dir); linklist.append("-L/opt/kde3/lib"); linklist.append("-lkdecore"); linklist.append("-lpythonize")
+ linklist.append("-L"+self.qt_lib_dir); linklist.append("-lqt-mt")
+ linklist.append("-lm")
+ linklist.append("-lstdc++")
+ linklist.append("-lc")
+ linklist.append(self.clib)
+
+ linklist.append("-R"); linklist.append(self.python_dir)
+ linklist.append("-R"); linklist.append(self.qt_lib_dir)
+ linklist.append("-R"); linklist.append(self.sip_dir)
+ linklist.append("-R"); linklist.append(self.pyqt_dir)
+ linklist.append("-R"); linklist.append(self.pykde_dir)
+ linklist.append("-R"); linklist.append(self.kde_lib_dir)
+
+ cmdlist.extend(linklist)
+ spawn(cmdlist) # Execute!!
+ print
+
+ cpptemplate = r"""
+/*
+ * pykcm_launcher.cpp
+ *
+ * Launch Control Centre modules written in Python using an embedded Python
+ * interpreter.
+ * Based on David Boddie's PyKDE-components.
+ */
+
+// pythonize.h must be included first.
+#include <pythonize.h>
+#include <kcmodule.h>
+#include <kglobal.h>
+#include <klocale.h>
+#include <klibloader.h>
+#include <kstandarddirs.h>
+#include <ksimpleconfig.h>
+#include <qstring.h>
+#include <sip.h>
+
+#define MODULE_DIR "%(moduledir)s"
+#define EXTRA_MODULE_DIR "/opt/kde3/share/python-support/kde-guidance-kde3"
+#define EXTRA_MODULE_DIR_TWO "/opt/kde3/share/python-support/guidance-backends-kde3"
+#define EXTRA_MODULE_DIR_THREE "/opt/kde3/share/python-support/kde-guidance-powermanager-kde3"
+#define MODULE_NAME "%(modulename)s"
+#define FACTORY "%(factoryfunction)s"
+#define CPP_FACTORY %(factoryfunction)s
+#define LIB_PYTHON "libpython%(python_version)s.so"
+#define debug 1
+
+static KCModule *report_error(char *msg) {
+ if (debug) printf ("error: %%s\n", msg);
+ return NULL;
+}
+
+static KCModule* return_instance( QWidget *parent, const char *name ) {
+ KCModule* kcmodule;
+ PyObject *pyKCModuleTuple;
+ PyObject *pyKCModule;
+ Pythonize *pyize; // Pythonize object to manage the Python interpreter.
+ int isErr;
+
+ // Try to determine what py script we're loading. Note that "name"
+ // typically appears to be NULL.
+ QString script(MODULE_NAME);
+
+ // Reload libpython, but this time tell the runtime linker to make the
+ // symbols global and available for later loaded libraries/module.
+ KLibLoader::self()->globalLibrary(LIB_PYTHON);
+
+ // Start the interpreter.
+ pyize = initialize();
+ if (!pyize) {
+ return report_error ("***Failed to start interpreter\n");
+ }
+
+ // Add the path to the python script to the interpreter search path.
+ QString path = QString(MODULE_DIR);
+ if(path == QString::null) {
+ return report_error ("***Failed to locate script path");
+ }
+ if(!pyize->appendToSysPath (path.latin1 ())) {
+ return report_error ("***Failed to set sys.path\n");
+ }
+ QString extrapath = QString(EXTRA_MODULE_DIR);
+ if(!pyize->appendToSysPath (extrapath.latin1 ())) {
+ return report_error ("***Failed to set extra sys.path\n");
+ }
+ QString extrapath_two = QString(EXTRA_MODULE_DIR_TWO);
+ if(!pyize->appendToSysPath (extrapath_two.latin1 ())) {
+ return report_error ("***Failed to set extra 2 sys.path\n");
+ }
+ QString extrapath_three = QString(EXTRA_MODULE_DIR_THREE);
+ if(!pyize->appendToSysPath (extrapath_three.latin1 ())) {
+ return report_error ("***Failed to set extra 3 sys.path\n");
+ }
+
+ // Load the Python script.
+ PyObject *pyModule = pyize->importModule ((char *)script.latin1 ());
+ if(!pyModule) {
+ PyErr_Print();
+ return report_error ("***failed to import module\n");
+ }
+
+ // Inject a helper function
+ QString bridge = QString("import sip\n"
+ "import qt\n"
+ "def kcontrol_bridge_" FACTORY "(parent,name):\n"
+ " if parent!=0:\n"
+#if SIP_VERSION >= 0x040200
+ " wparent = sip.wrapinstance(parent,qt.QWidget)\n"
+#else
+ " wparent = sip.wrapinstance(parent,'QWidget')\n"
+#endif
+ " else:\n"
+ " wparent = None\n"
+ " inst = " FACTORY "(wparent, name)\n"
+ " return (inst,sip.unwrapinstance(inst))\n");
+ PyRun_String(bridge.latin1(),Py_file_input,PyModule_GetDict(pyModule),PyModule_GetDict(pyModule));
+
+ // Get the Python module's factory function.
+ PyObject *kcmFactory = pyize->getNewObjectRef(pyModule, "kcontrol_bridge_" FACTORY);
+ if(!kcmFactory) {
+ return report_error ("***failed to find module factory\n");
+ }
+
+ // Call the factory function. Set up the args.
+ PyObject *pyParent = PyLong_FromVoidPtr(parent);
+ PyObject *pyName = PyString_FromString(MODULE_NAME);
+ // Using NN here is effect gives our references to the arguement away.
+ PyObject *args = Py_BuildValue ("NN", pyParent, pyName);
+ if(pyName && pyParent && args) {
+ // run the factory function
+ pyKCModuleTuple = pyize->runFunction(kcmFactory, args);
+ if(!pyKCModuleTuple) {
+ PyErr_Print();
+ return report_error ("*** runFunction failure\n;");
+ }
+ } else {
+ return report_error ("***failed to create args\n");
+ }
+ // cleanup a bit
+ pyize->decref(args);
+ pyize->decref(kcmFactory);
+
+ // Stop this from getting garbage collected.
+ Py_INCREF(PyTuple_GET_ITEM(pyKCModuleTuple,0));
+
+ // convert the KCModule PyObject to a real C++ KCModule *.
+ isErr = 0;
+ pyKCModule = PyTuple_GET_ITEM(pyKCModuleTuple,1);
+ kcmodule = (KCModule *)PyLong_AsVoidPtr(pyKCModule);
+ if(!kcmodule) {
+ return report_error ("***failed sip conversion to C++ pointer\n");
+ }
+ pyize->decref(pyKCModuleTuple);
+
+ // PyKDE can't run the module without this - Pythonize
+ // grabs the lock at initialization and we have to give
+ // it back before exiting. At this point, we no longer need
+ // it.
+ //pyize->releaseLock ();
+
+ // take care of any translation info
+ KGlobal::locale()->insertCatalogue(script);
+
+ // Return the pointer to our new KCModule
+ return kcmodule;
+}
+
+extern "C" {
+ // Factory function that kcontrol will call.
+ KCModule* CPP_FACTORY(QWidget *parent, const char *name) {
+ return return_instance(parent, name);
+ }
+}
+"""
+
+###########################################################################
+class InstallKControlModule(Command):
+ description = "Install Kcontrol module files"
+
+ user_options = [
+ ('install-dir=', 'd', "base directory for installing kcontrol module files"),
+ ('install-cmd=', None, "Command to use to install the files"),
+ ('xdg-apps-dir=',None,"directory for XDG app files"),
+ ('build-dir=','b', "build directory (where to install from)"),
+ ('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.build_dir = None
+ self.install_dir = None
+ self.install_cmd = None
+ self.xdg_apps_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_xdg_apps_dir = self.xdg_apps_dir is not None
+
+ self.set_undefined_options('install',
+ ('build_base', 'build_dir'),
+ ('install_kcm', 'install_dir'),
+ ('install_xdg_apps','xdg_apps_dir'),
+ ('root', 'root'),
+ ('force', 'force'),
+ ('skip_build', 'skip_build'),
+ ('install_cmd', 'install_cmd')
+ )
+
+ if own_install_dir and self.root is not None:
+ self.install_dir = change_root(self.root,self.installdir)
+ if own_xdg_apps_dir and self.root is not None:
+ self.xdg_apps_dir = change_root(self.root,self.xdg_apps_dir)
+
+ def get_command_name(self):
+ return 'install_kcm'
+
+ def run(self):
+ if not self.skip_build:
+ self.run_command('build_kcm')
+
+ self.announce("Installing Kcontrol module files...")
+
+ for moduletuple in self.distribution.kcontrol_modules:
+ self.announce("Building KControl module from desktop file %s." % moduletuple[0])
+
+ # Read the desktop file
+ libraryname = None
+ cmodulecategory = None
+ try:
+ fhandle = open(moduletuple[0],'r')
+ for line in fhandle.readlines():
+ parts = line.strip().split('=')
+ try:
+ if parts[0]=="X-KDE-Library":
+ libraryname = parts[1]
+ elif parts[0]=="Exec":
+ shellcmd = parts[1].split()
+ modulepath = shellcmd[-1]
+ if '/' in modulepath:
+ cmodulecategory = os.path.dirname(modulepath)
+ else:
+ cmodulecategory = ""
+ except IndexError:
+ pass
+ fhandle.close()
+ except IOError:
+ raise SystemExit, "Failed to find kcontrol desktop file: %s" % moduletuple[0]
+
+ if libraryname is None:
+ raise SystemExit, "Failed to find library name (Was there a X-KDE-Library entry in the desktop file?)"
+ if cmodulecategory is None:
+ raise SystemExit, "Failed to find the kcontrol category name (Was there a Exec entry in the desktop file?)"
+
+ desktopfilename = moduletuple[0]
+ self.outfiles.extend(self.mkpath(self.xdg_apps_dir))
+ desktopfile_dest = os.path.join(self.xdg_apps_dir,os.path.basename(desktopfilename))
+ self.copy_file(desktopfilename, desktopfile_dest)
+
+ stub_la_name = 'kcm_'+libraryname+'.la'
+
+ 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,stub_la_name))
+ cmdlist.append(os.path.join(self.install_dir,stub_la_name))
+ spawn(cmdlist) # Execute!!
+ print
+
+ self.outfiles = [os.path.join(self.install_dir,os.path.basename(file)) for file in glob.glob(os.path.join(self.build_dir,'.libs','kcm_'+libraryname+'*'))]
+ self.outfiles.append(desktopfile_dest)
+
+ self.announce("Done installing Kcontrol module files.")
+
+ def get_outputs(self):
+ return self.outfiles or []
+
+ def mkpath(self, name, mode=0777):
+ return dir_util.mkpath(name, mode, dry_run=self.dry_run)
+
+###########################################################################
+class BuildDocbookHTML(Command):
+ description = "Build Docbook HTML documentation"
+
+ user_options = [('meinproc-exe=',None,"Path to the meinproc executable")]
+
+ def initialize_options(self):
+ self.html_prefix = None
+ self.meinproc_exe = None
+
+ def finalize_options(self):
+ self.set_undefined_options('build', ('meinproc_exe', 'meinproc_exe') )
+
+ def get_command_name(self):
+ return 'build_docbook'
+
+ def run(self):
+ for docbook_tuple in self.distribution.docbooks:
+ input_dir = docbook_tuple[0]
+ language_code = docbook_tuple[1]
+
+ self.announce("Building Docbook documentation from directory %s." % input_dir)
+
+ indexdoc_file_name = os.path.join(input_dir,'index.docbook')
+ if not os.path.exists(indexdoc_file_name):
+ raise SystemExit, "File %s is missing." % indexdoc_file_name
+
+ cwd = os.getcwd()
+ os.chdir(input_dir)
+ try:
+ spawn([self.meinproc_exe,"--check","--cache",'index.cache.bz2', 'index.docbook'])
+ spawn([self.meinproc_exe, 'index.docbook'])
+ finally:
+ os.chdir(cwd)
+
+###########################################################################
+class InstallDocbookHTML(Command):
+ description = "Install Docbook HTML files"
+
+ user_options = [
+ ('install-dir=', 'd',"base directory for installing docbook HTML 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.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
+
+ self.set_undefined_options('install',
+ ('install_html', 'install_dir'),
+ ('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.installdir)
+
+ def get_command_name(self):
+ return 'install_html'
+
+ def run(self):
+ if not self.skip_build:
+ self.run_command('build_html')
+
+ self.announce("Installing HTML files...")
+ counter = 0
+ for docbook_tuple in self.distribution.docbooks:
+ input_dir = docbook_tuple[0]
+ language_code = docbook_tuple[1]
+
+ self.announce("Install Docbook documentation from directory %s." % input_dir)
+ source_file = os.path.join(input_dir,'index.cache.bz2')
+ if not os.path.exists(source_file):
+ raise SystemExit, "File %s is missing." % source_file
+
+ dest_path = os.path.join(self.install_dir, language_code, self.distribution.metadata.name)
+ self.outfiles.extend(self.mkpath(dest_path))
+ dest_file = os.path.join(dest_path,'index.cache.bz2')
+
+ self.copy_file(source_file, dest_file)
+ self.outfiles.append(dest_file)
+ counter += 1
+
+ # Also install any lose HTML files.
+ for source_file in glob.glob(os.path.join(input_dir,'*.html')):
+ htmlfile = os.path.basename(source_file)
+ dest_file = os.path.join(dest_path,htmlfile)
+ self.copy_file(source_file, dest_file)
+ self.outfiles.append(dest_file)
+ counter += 1
+
+ if len(docbook_tuple)==3:
+ extra_files = docbook_tuple[2]
+ for file in extra_files:
+ source_file = os.path.join(input_dir,file)
+ dest_file = os.path.join(self.install_dir, language_code, self.distribution.metadata.name,file)
+ self.copy_file(source_file, dest_file)
+ self.outfiles.append(dest_file)
+ counter += 1
+
+ self.announce("Done installing %i HTML files." % counter)
+
+ def get_outputs(self):
+ return self.outfiles or []
+
+ def mkpath(self, name, mode=0777):
+ return dir_util.mkpath(name, mode, dry_run=self.dry_run)
+
+###########################################################################
+class UpdateI18NMessages(Command):
+ description = "Extract and update messages for translation"
+
+ user_options = [('xgettext-exe=',None,'Full path to the xgetext executable'),\
+ ('kde-pot=',None,'Location of the the KDE pot file'),\
+ ('msgmerge-exe=',None,'Full path to the msgmerge executable')]
+
+ def initialize_options(self):
+ self.xgettext_exe = None
+ self.msgmerge_exe = None
+ self.kde_pot = None
+
+ def finalize_options(self):
+ if self.xgettext_exe is None:
+ install = self.get_finalized_command('install')
+
+ canidate_paths = []
+ if install.user_supplied_kde_prefix:
+ canidate_paths.append(os.path.join(install.kde_prefix,'bin'))
+
+ self.announce("Detecting xgettext...")
+ canidate_paths.append(ask_kde_config('--install exe --expandvars').strip())
+ self.xgettext_exe = FindExeOnPath('xgettext',canidate_paths)
+ if self.xgettext_exe is None:
+ raise SystemExit, "Unable to find 'xgettext'."
+ self.announce(" ...xgettext found at %s" % self.xgettext_exe)
+
+ if self.msgmerge_exe is None:
+ install = self.get_finalized_command('install')
+
+ canidate_paths = []
+ if install.user_supplied_kde_prefix:
+ canidate_paths.append(os.path.join(install.kde_prefix,'bin'))
+
+ self.announce("Detecting msgmerge...")
+ canidate_paths.append(ask_kde_config('--install exe --expandvars').strip())
+ self.msgmerge_exe = FindExeOnPath('msgmerge',canidate_paths)
+ if self.msgmerge_exe is None:
+ raise SystemExit, "Unable to find 'xgettext'."
+ self.announce(" ...msgmerge found at %s" % self.msgmerge_exe)
+
+ if self.kde_pot is None:
+ self.announce("Detecting kde.pot...")
+ canidatepaths = []
+ kdedir = os.getenv("KDEDIR")
+ if kdedir!=None:
+ canidatepaths.append(os.path.join(kdedir,"include"))
+ install = self.get_finalized_command('install')
+ canidatepaths.append(os.path.join(install.kde_prefix,"include"))
+ canidatepaths.append('/opt/kde3/include')
+ canidatepaths.append('/opt/kde/include')
+ kde_pot_dir = FindFileInPaths('kde.pot',canidatepaths)
+
+ if kde_pot_dir is None:
+ raise SystemExit, "Failed to find the kde.pot file."
+
+ self.kde_pot = os.path.join(kde_pot_dir,'kde.pot')
+ self.announce(" ...kde.pot found at %s" % self.kde_pot)
+
+ def get_command_name(self):
+ return 'update_messages'
+
+ def run(self):
+ if self.distribution.i18n is None: return
+
+ self.announce("Extracting and merging i18n messages...")
+ po_dir = self.distribution.i18n[0]
+
+ # FIXME : .rc and .ui files
+ input_files = []
+
+ # Compile any UI files
+ for dir in self.distribution.i18n[1]:
+ for file in glob.glob(os.path.join(dir,'*.ui')):
+ qtuicompiler.UpdateUI(file,kde=True)
+
+ # Fetch all of the python files.
+ for dir in self.distribution.i18n[1]:
+ input_files.extend(glob.glob(os.path.join(dir,'*.py')))
+
+ target_pot = os.path.join(po_dir,self.distribution.metadata.name+".pot")
+
+ cmd = [self.xgettext_exe, '-o', target_pot, '-ki18n', '-ktr2i18n', \
+ '-kI18N_NOOP', '-ktranslate', '-kaliasLocale','-x',self.kde_pot]
+ cmd.extend(input_files)
+ spawn(cmd)
+
+ for po_file in glob.glob(os.path.join(po_dir,'*.po')):
+ temp_po = po_file + '.temp'
+ cmd = [self.msgmerge_exe,'-q','-o',temp_po,po_file,target_pot]
+ spawn(cmd)
+ os.rename(temp_po,po_file)
+
+ self.announce("Finished with i18n messages.")
+
+###########################################################################
+class BuildI18NMessages(Command):
+ description = "Build i18n messages"
+
+ user_options = [('msgfmt-exe=',None,'Path to the msgfmt executable')]
+
+ def initialize_options(self):
+ self.msgfmt_exe = None
+
+ def finalize_options(self):
+ self.set_undefined_options('build', ('msgfmt_exe', 'msgfmt_exe'))
+
+ def get_command_name(self):
+ return 'build_messages'
+
+ def run(self):
+ if self.distribution.i18n is None: return
+
+ self.announce("Building i18n messages...")
+ po_dir = self.distribution.i18n[0]
+
+ i = 0
+ for po_file in [file for file in os.listdir(po_dir) if file.endswith('.po')]:
+ source = os.path.join(po_dir,po_file)
+ target = source[:-3]+'.gmo'
+ cmd = [self.msgfmt_exe,'-o',target, source]
+ spawn(cmd)
+ i += 1
+ self.announce("Done building %i i18n messages." % i)
+
+###########################################################################
+class InstallI18NMessages(Command):
+ description = "Install messages"
+
+ user_options = [
+ ('install-dir=', 'd',"base directory for installing message files (default: installation base dir)"),
+ ('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.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
+
+ self.set_undefined_options('install',
+ ('install_messages', 'install_dir'),
+ ('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.installdir)
+
+ def get_command_name(self):
+ return 'install_messages'
+
+ def run(self):
+ if not self.skip_build:
+ self.run_command('build_messages')
+
+ self.announce("Installing i18n messages...")
+ po_dir = self.distribution.i18n[0]
+
+ counter = 0
+ for po_file in os.listdir(po_dir):
+ if po_file.endswith('.po'):
+ source_file = os.path.join(po_dir,po_file[:-3]) + '.gmo'
+
+ # Setup installation of the translation file.
+ dest_path = os.path.join(self.install_dir, po_file[:-3],'LC_MESSAGES')
+ self.outfiles.extend(self.mkpath(dest_path))
+ dest_file = os.path.join(dest_path, self.distribution.metadata.name+'.mo')
+
+ self.copy_file(source_file, dest_file)
+ self.outfiles.append(dest_file)
+ counter += 1
+ self.announce("Done installing %i i18n messages." % counter)
+
+ def get_outputs(self):
+ return self.outfiles
+
+ def mkpath(self, name, mode=0777):
+ return dir_util.mkpath(name, mode, dry_run=self.dry_run)
+
+
+###########################################################################
+class BuildKioslave(Command):
+ description = "Build Kioslaves"
+
+ user_options = [('no-kioslave',None,"Don't build kioslaves"),
+ ('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'),
+ ('kde-inc-dir=',None,'Directory containing C++ header files for KDE'),
+ ('kde-lib-dir=',None,'Directory containing library files for KDE'),
+ ('kde-kioslave-lib-dir=',None,'Directory for KDE kioslave library files'),
+ ('kde-protocol-dir=',None,'Directory for KDE kioslave protocol files'),
+ ('qt-inc-dir=',None,'Directory containing C++ header files for Qt'),
+ ('qt-lib-dir=',None,'Directory containing library files for Qt'),
+ ('sip-dir=','/usr/lib/pyshared/python2.6','Directory containing the sip library files'),
+ ('clib=',None,'gcc library and path'),
+ ('pyqt-dir=','/usr/lib/pyshared/python2.6','PyQt module directory'),
+ ('pykde-dir=',None,'PyKDE module directory'),
+ ('data-dir=',None,'installation directory for data (script) files')]
+
+ def initialize_options(self):
+ self.no_kioslave = 0
+ self.build_dir = None
+ self.python_inc_dir = None
+ self.python_dir = None
+ self.kde_inc_dir = None
+ self.kde_lib_dir = None
+ self.kde_kioslave_lib_dir = None
+ self.kde_protocol_dir = None
+ self.qt_inc_dir = None
+ self.qt_lib_dir = None
+ self.sip_dir = "/usr/lib/pyshared/python2.6"
+ self.clib = None
+ self.pyqt_dir = "/usr/lib/pyshared/python2.6"
+ self.pykde_dir = None
+ self.data_dir = None
+
+ def finalize_options(self):
+ if self.no_kioslave==0:
+ self.set_undefined_options('install', ('build_base', 'build_dir'),('install_application_data','data_dir'))
+
+ install = self.get_finalized_command('install')
+ self.install_prefix = "/opt/kde3/"
+
+ # KDE inc dir: find it!
+ if self.kde_inc_dir is None:
+ canidatepaths = []
+ kdedir = os.getenv("KDEDIR")
+ if kdedir!=None:
+ canidatepaths.append(os.path.join(kdedir,"include"))
+ canidatepaths.append(os.path.join(install.prefix,"include"))
+ canidatepaths.append('/opt/kde3/include')
+ canidatepaths.append('/opt/kde/include')
+ self.kde_inc_dir = FindFileInPaths('kapplication.h',canidatepaths)
+ if self.kde_inc_dir is None:
+ raise SystemExit, "Failed to find the KDE header file directory."
+ if FindFileInPaths('kapplication.h',[self.kde_inc_dir]) is None:
+ raise SystemExit, "Failed to find KDE header files in: %s" % self.kde_inc_dir
+ self.announce("Using %s for KDE header files" % self.kde_inc_dir)
+
+ # KDE lib dir
+ #if self.kde_lib_dir is None:
+ # self.kde_lib_dir = os.path.join(install.prefix,"lib")
+ self.kde_lib_dir = "/opt/kde3/lib/"
+ self.announce("Using %s for KDE library files" % self.kde_lib_dir)
+
+ # KDE kioslave lib dir
+ #if self.kde_kioslave_lib_dir is None:
+ # self.kde_kioslave_lib_dir = os.path.join(self.kde_lib_dir,"kde3")
+ self.kde_kioslave_lib_dir = "/opt/kde3/lib/kde3/"
+ if FindFileInPaths('kio_*.so',[self.kde_kioslave_lib_dir]) is None:
+ raise SystemExit, "Failed to find KDE Kioslave library files in: %s" % self.kde_kioslave_lib_dir
+ self.announce("Using %s for KDE Kioslave library files" % self.kde_kioslave_lib_dir)
+
+ # Qt inc dir
+ if self.qt_inc_dir is None:
+ canidatepaths = []
+ qtdir = os.getenv("QTDIR")
+ if qtdir != None:
+ canidatepaths.append(os.path.join(qtdir,"include"))
+ canidatepaths.append(os.path.join(install.prefix,"lib/qt3/include"))
+ canidatepaths.append(os.path.join(install.prefix,"lib/qt3/include"))
+ canidatepaths.append(os.path.join(install.prefix,"include"))
+ canidatepaths.append("/opt/qt3/include")
+ canidatepaths.append("/opt/qt/include")
+ canidatepaths.append("/opt/qt/lib/include")
+ canidatepaths.append("/opt/qt3/lib/include")
+ self.qt_inc_dir = FindFileInPaths('qstring.h',canidatepaths)
+ if self.qt_inc_dir is None:
+ raise SystemExit,"Failed to find the Qt header file directory"
+ if FindFileInPaths('qstring.h',[self.qt_inc_dir]) is None:
+ raise SystemExit, "Failed to find Qt header files in: %s" % self.qt_inc_dir
+ self.announce("Using %s for Qt header files" % self.qt_inc_dir)
+
+ # Qt lib dir
+ if self.qt_lib_dir is None:
+ canidatepaths = []
+ qtdir = os.getenv("QTDIR")
+ if qtdir != None:
+ canidatepaths.append(os.path.join(qtdir,get_libdir_name()))
+ canidatepaths.append(os.path.join(install.prefix,"lib/qt3/"+get_libdir_name()))
+ canidatepaths.append(os.path.join(install.prefix,"lib/qt3/"+get_libdir_name()))
+ canidatepaths.append(os.path.join(install.prefix,get_libdir_name()))
+ canidatepaths.append("/opt/qt3/"+get_libdir_name())
+ canidatepaths.append("/opt/qt/"+get_libdir_name())
+ canidatepaths.append("/opt/qt/lib/"+get_libdir_name())
+ canidatepaths.append("/opt/qt3/lib/"+get_libdir_name())
+ self.qt_lib_dir = FindFileInPaths('libqt*',canidatepaths)
+ if self.qt_lib_dir is None:
+ raise SystemExit, "Failed to find Qt library files"
+ self.announce("Using %s for Qt library files" % self.qt_lib_dir)
+
+ # Python dir
+ if self.python_dir is None:
+ self.python_dir = os.path.split(sysconfig.get_config_var("LIBP"))[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)
+
+ # PyQt dir
+ if self.pyqt_dir is None:
+ self.pyqt_dir = sysconfig.get_python_lib()
+ if (FindFileInPaths("libqtcmodule*",[self.pyqt_dir]) is None) and (FindFileInPaths("qt*",[self.pyqt_dir]) is None):
+ raise SystemExit, "Failed to find the PyQt directory: %s" % self.pyqt_dir
+ self.announce("Using %s for PyQt modules" % self.pyqt_dir)
+
+ # PyKDE dir
+ if self.pykde_dir is None:
+ self.pykde_dir = sysconfig.get_python_lib()
+ if (FindFileInPaths("libkdecorecmodule*",[self.pykde_dir]) is None) and (FindFileInPaths("kdecore*",[self.pykde_dir]) is None):
+ raise SystemExit, "Failed to find the PyKDE directory: %s" % self.pykde_dir
+ self.announce("Using %s for PyKDE modules" % self.pykde_dir)
+
+ # Sip dir
+ if self.sip_dir is None:
+ self.sip_dir = sysconfig.get_python_lib()
+ if (FindFileInPaths("libsip*", [self.sip_dir]) is None) and (FindFileInPaths("sip*", [self.sip_dir]) is None):
+ raise SystemExit, "Failed to find libsip files in directory: %s" % self.sip_dir
+ self.announce("Using %s for libsip files" % self.sip_dir)
+
+ # Find the C library (libgcc, libgcc_s or some other variation).
+ if self.clib is None:
+ canidatepaths = ["/usr/"+get_libdir_name(), "/usr/local/"+get_libdir_name() ]
+ self.clib = FindFileInPaths("libgcc*.so",canidatepaths)
+ if self.clib!=None:
+ self.clib = glob.glob(os.path.join(self.clib,'libgcc*.so'))[0]
+ else:
+ self.clib = 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, "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("LIBP")
+ 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_kioslave'
+
+ def run(self):
+ if self.no_kioslave:
+ self.announce("Skipping KIO Slaves")
+ return
+
+ if not os.path.isdir(self.build_dir):
+ os.mkdir(self.build_dir)
+
+ for moduletuple in self.distribution.kioslaves:
+ self.announce("Building KIO Slave from protocol file %s." % moduletuple[0])
+
+ protocolfilename = moduletuple[0]
+
+ # Read the protocol file
+ libraryname = None
+ try:
+ fhandle = open(protocolfilename,'r')
+ for line in fhandle.readlines():
+ parts = line.strip().split('=')
+ try:
+ if parts[0]=="exec":
+ libraryname = parts[1]
+ except IndexError:
+ pass
+ fhandle.close()
+ except IOError:
+ raise SystemExit, "Failed to find kioslave protocol file: %s" % moduletuple[0]
+
+ # Sanity check.
+ if libraryname is None:
+ raise SystemExit, "Failed to find library name (Was there a exec entry in the protocol file?)"
+
+ modulename = os.path.basename(moduletuple[1])
+ if modulename.endswith('.py'):
+ modulename = modulename[:-3]
+
+ stub_cpp_name = libraryname+'.cpp'
+ stub_so_name = libraryname+'.so'
+ stub_la_name = libraryname+'.la'
+ python_version = '%i.%i' % (sys.version_info[0],sys.version_info[1])
+
+ # Build the 'stub' code.
+ cppcode = self.cpptemplate % {"moduledir": self.data_dir,
+ "modulename": modulename,
+ "python_version": python_version}
+
+ # Put it on disk.
+ cppfile = os.path.join(os.path.dirname(moduletuple[0]),stub_cpp_name)
+ try:
+ fhandle = open(cppfile,'w')
+ fhandle.write(cppcode)
+ fhandle.close()
+ except IOError:
+ raise SystemExit, "Could not write the C++ stub: %s" % cppfile
+
+ # Compile the stub library.
+ cmdlist = ['libtool']
+
+ # Couldn't get it to pass without this ...
+ cmdlist.append("--mode=compile")
+ cmdlist.append("--tag=CXX")
+
+ # Find the compiler flags and options
+ # CXX is empty on some Systems, let's do it 'the hard way'.
+ # FIXME :: get CXX from make.conf for Gentoo.
+ if len(sysconfig.get_config_var("CXX").split()) >= 2:
+ cmdlist.extend(sysconfig.get_config_var("CXX").split())
+ else:
+ cmdlist.extend(['g++', '-pthread'])
+
+ #cmdlist.extend(sysconfig.get_config_var("CXX").split())
+
+ # cc_flags
+ cmdlist.append("-c")
+ cmdlist.append("-g")
+
+ # The 4 is randomly chosen!
+ # FIXME :: get CFLAGS from make.conf for Gentoo.
+ if len(sysconfig.get_config_var("CFLAGS").split()) >=4:
+ cmdlist.extend(sysconfig.get_config_var("CFLAGS").split())
+ else:
+ # On Gentoo systems, CFLAGS are not in the environment.
+ raw = os.popen('emerge info 2> /dev/null|grep CFLAGS')
+ lines = raw.readlines()
+ if len(lines):
+ cflags = lines[0].split('"')[1].split()
+ print "Got CFLAGS from emerge info."
+ cmdlist.extend(cflags)
+ else:
+ # Still no CFLAGS found, use these ...
+ cmdlist.extend(['-fno-strict-aliasing', '-DNDEBUG', '-g', '-O3', '-Wall', '-Wstrict-prototypes'])
+
+ #sysconfig.get_config_var("CFLAGS").split()
+ # includes
+ cmdlist.append("-I" + sysconfig.get_config_var("INCLUDEDIR"))
+ 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("-I" + self.kde_inc_dir)
+ cmdlist.append("-I" + self.qt_inc_dir)
+ cmdlist.append("-I.")
+ # input
+ cmdlist.append(cppfile)
+ # output
+ outputfile = os.path.join(self.build_dir,libraryname+'.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")
+
+ # 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.kde_kioslave_lib_dir)
+ cmdlist.append("-o"); cmdlist.append(os.path.join(self.build_dir,stub_la_name))
+ # Link libs
+ linklist = []
+ linklist.append("-lpython%s" % python_version)
+ linklist.extend(sysconfig.get_config_var("LIBS").split())
+
+ # FIXME I doubt half of these libraries need to be here.
+ linklist.append(self.sip_dir+"/sip.so")
+ # PyQt libs
+ linklist.append(self.pyqt_dir+"/qt.so")
+ # PyKDE libs
+ linklist.append(self.pykde_dir+"/kdecore.so")
+
+# linklist.append("-L"+self.sip_dir); linklist.append("-lsip")
+# # PyQt libs
+# linklist.append("-L"+self.pyqt_dir); linklist.append("-lqtcmodule")
+# # PyKDE libs
+# linklist.append("-L"+self.pykde_dir); linklist.append("-lkdecorecmodule"); linklist.append("-lkdeuicmodule")
+
+ linklist.append("-L"+self.kde_lib_dir); linklist.append("-L/opt/kde3/lib"); linklist.append("-lkdecore"); linklist.append("-lpythonize")
+ linklist.append("-L"+self.qt_lib_dir); linklist.append("-lqt-mt")
+ linklist.append("-lm")
+ linklist.append("-lstdc++")
+ linklist.append("-lc")
+ linklist.append(self.clib)
+
+ linklist.append("-R"); linklist.append(self.python_dir)
+ linklist.append("-R"); linklist.append(self.qt_lib_dir)
+ linklist.append("-R"); linklist.append(self.sip_dir)
+ linklist.append("-R"); linklist.append(self.pyqt_dir)
+ linklist.append("-R"); linklist.append(self.pykde_dir)
+ linklist.append("-R"); linklist.append(self.kde_lib_dir)
+
+ cmdlist.extend(linklist)
+ spawn(cmdlist) # Execute!!
+ print
+
+ cpptemplate = r"""
+/*
+ * Launch Control Centre modules written in Python using an embedded Python
+ * interpreter.
+ * Based on David Boddie's PyKDE-components.
+ */
+
+#include <stdio.h>
+#include <Python.h>
+#include <kinstance.h>
+#define MODULE_DIR "%(moduledir)s"
+#define MODULE_NAME "%(modulename)s"
+#define FACTORY "SlaveFactory"
+
+const char modname[] = MODULE_NAME;
+#define MAIN_METHOD "dispatchLoop"
+
+FILE *d = NULL;
+
+PyObject* call_function(PyObject *callable, PyObject *args) {
+ PyObject *result, *pArgs;
+
+ if (callable == NULL) {
+ printf(MODULE_NAME " kioslave error: callable == NULL in call_function\n");
+ return NULL;
+ }
+
+ if (PyCallable_Check(callable)) {
+ if(args == NULL) {
+ pArgs = PyTuple_New(0);
+ } else {
+ pArgs = args;
+ }
+ result = PyObject_CallObject(callable, pArgs);
+
+ /* If the arguments were created is this function then decrease
+ their reference count. */
+ if(args == NULL) {
+ Py_XDECREF(pArgs);
+ /* pDict and pFunc are borrowed and must not be Py_DECREF-ed */
+ }
+
+ if(result == NULL) {
+ PyErr_Print();
+ PyErr_Clear();
+ }
+ }
+
+ return result;
+}
+
+extern "C" {
+ int kdemain( int argc, char **argv) {
+ PyObject *pModule, *pName, *pDict;
+ KInstance slave(MODULE_NAME);
+
+ Py_SetProgramName(argv[0]);
+ Py_Initialize();
+ //PyEval_InitThreads();
+ PySys_SetArgv(1, argv);
+
+ PyRun_SimpleString("import sys\n");
+ PyRun_SimpleString("sys.path.append('"MODULE_DIR"')\n");
+
+ pName = PyString_FromString(modname);
+ pModule = PyImport_Import(pName);
+
+ Py_XDECREF(pName);
+
+ if(pModule == NULL) {
+ printf(MODULE_NAME " kioslave error: pModule == NULL\n");
+ return 1;
+ } else {
+ PyObject *pClass, *pMethod, *pArgs, *pArg1, *pArg2, *pInstance;
+ int i;
+
+ pDict = PyModule_GetDict(pModule);
+ /* pDict is a borrowed reference */
+
+ pClass = PyDict_GetItemString(pDict, FACTORY);
+
+ if(pClass == NULL) {
+ printf(MODULE_NAME " kioslave error: pClass == NULL\n");
+ return 1;
+ } else {
+ pArgs = PyTuple_New(2);
+
+ pArg1 = PyString_FromString(argv[2]);
+ pArg2 = PyString_FromString(argv[3]);
+
+ PyTuple_SetItem(pArgs, 0, pArg1);
+ PyTuple_SetItem(pArgs, 1, pArg2);
+
+ call_function(pClass, pArgs);
+
+ /* Some time later... */
+ Py_XDECREF(pClass);
+ Py_XDECREF(pArgs);
+ }
+
+ Py_XDECREF(pModule);
+ }
+
+ Py_Finalize();
+ return 0;
+ }
+}
+"""
+###########################################################################
+class InstallKioslave(Command):
+ description = "Install Kioslave files"
+
+ user_options = [
+ ('install-dir=', 'd', "base directory for installing kioslave module files"),
+ ('install-cmd=', None, "Command to use to install the files"),
+ ('install-protocol-dir=',None,"directory for kioslave protocol files"),
+ ('build-dir=','b', "build directory (where to install from)"),
+ ('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.build_dir = None
+ self.install_dir = None
+ self.install_cmd = None
+ self.install_protocol_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_install_protocol_dir = self.install_protocol_dir is not None
+
+ self.set_undefined_options('install',
+ ('build_base', 'build_dir'),
+ ('install_kioslave', 'install_dir'),
+ ('root', 'root'),
+ ('force', 'force'),
+ ('skip_build', 'skip_build'),
+ ('install_cmd', 'install_cmd'),
+ ('install_protocol','install_protocol_dir')
+ )
+
+ if own_install_dir and self.root is not None:
+ self.install_dir = change_root(self.root,self.installdir)
+
+ if own_install_protocol_dir and self.root is not None:
+ self.install_protocol_dir = change_root(self.root,self.install_protocol_dir)
+
+ def get_command_name(self):
+ return 'install_kioslave'
+
+ def run(self):
+ if not self.skip_build:
+ self.run_command('build_kioslave')
+
+ self.announce("Installing Kioslave files...")
+
+ for moduletuple in self.distribution.kioslaves:
+ self.announce("Building Kioslave module from protocol file %s." % moduletuple[0])
+
+ protocolfilename = moduletuple[0]
+
+ # Read the protocol file
+ libraryname = None
+ try:
+ fhandle = open(protocolfilename,'r')
+ for line in fhandle.readlines():
+ parts = line.strip().split('=')
+ try:
+ if parts[0]=="exec":
+ libraryname = parts[1]
+ except IndexError:
+ pass
+ fhandle.close()
+ except IOError:
+ raise SystemExit, "Failed to find kioslave protocol file: %s" % moduletuple[0]
+
+ if libraryname is None:
+ raise SystemExit, "Failed to find library name (Was there a exec entry in the protocol file?)"
+
+ self.outfiles.extend(self.mkpath(self.install_protocol_dir))
+ protocolfile_dest = os.path.join(self.install_protocol_dir,os.path.basename(protocolfilename))
+ self.copy_file(protocolfilename, protocolfile_dest)
+
+ stub_la_name = libraryname+'.la'
+
+ 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,stub_la_name))
+ cmdlist.append(os.path.join(self.install_dir,stub_la_name))
+ spawn(cmdlist) # Execute!!
+ print
+
+ self.outfiles = [os.path.join(self.install_dir,os.path.basename(file)) for file in glob.glob(os.path.join(self.build_dir,'.libs',libraryname+'*'))]
+ self.outfiles.append(protocolfile_dest)
+
+ self.announce("Done installing Kioslave files.")
+
+ def get_outputs(self):
+ return self.outfiles or []
+
+ def mkpath(self, name, mode=0777):
+ return dir_util.mkpath(name, mode, dry_run=self.dry_run)
+
+###########################################################################
+class CheckPyQt(Command):
+ description = "Checks for the presence of a working PyQt installation"
+
+ user_options = []
+
+ def initialize_options(self):
+ pass
+
+ def finalize_options(self):
+ self.min_qt_version = self.distribution.min_qt_version
+
+ def run(self):
+ if self.min_qt_version!=None:
+ qtver,kdever = get_qt_kde_versions()
+ if compare_versions(self.min_qt_version,qtver)==1:
+ raise SystemExit, "Your Qt version is too old. Version %s or higher is required, found %s." % (self.min_qt_version,qtver)
+ self.announce("Found Qt version %s." % qtver)
+ try:
+ self.announce("Checking for a working PyQt...")
+ import qt
+ self.announce(" ...PyQt is working")
+ except:
+ raise SystemExit, "Couldn't import Qt! Please make sure that PyQt is installed and working."
+
+ def get_outputs(self): return []
+
+###########################################################################
+class CheckPyKDE(Command):
+ description = "Checks for the presence of a working PyKDE installation"
+
+ user_options = []
+
+ def initialize_options(self):
+ pass
+
+ def finalize_options(self):
+ self.min_kde_version = self.distribution.min_kde_version
+
+ def run(self):
+ if self.min_kde_version!=None:
+ qtver,kdever = get_qt_kde_versions()
+ if compare_versions(self.min_kde_version,kdever)==1:
+ raise SystemExit, "Your KDE version is too old. Version %s or higher is required, found %s." % (self.min_kde_version,kdever)
+ self.announce("Found KDE version %s." % kdever)
+ self.announce("Checking for a working PyKDE...")
+
+ # Try to import modules one by one.
+ for k_module in ('dcop', 'kdecore', 'kdeui', 'kio', 'kfile', 'kparts', 'khtml', 'kspell'):
+ self.announce(k_module)
+ try:
+ exec('import ' + k_module)
+ except:
+ raise SystemExit, "Error: Couldn't find module '" + k_module + "'. \n" + \
+ "Couldn't import KDE! Please make sure that PyKDE is installed and working.\n" + \
+ "PyKDE is available here: http://www.riverbankcomputing.co.uk/pykde/index.php"
+ self.announce(" ...PyKDE is working")
+
+ def get_outputs(self): return []
+
+###########################################################################
+def FindFileInPaths2(globpattern,canidatepaths):
+ if canidatepaths is None or len(canidatepaths)==0:
+ return (None,None)
+
+ # Look for the globpattern on the path.
+ for path in canidatepaths:
+ if path!=None:
+ files = glob.glob(os.path.join(path, globpattern))
+ if len(files)!=0:
+ return (path,os.path.basename(files[0]))
+
+ # Continue searching with a breadth first search.
+ dirs = []
+ for path in canidatepaths:
+ # Examine any directories on this path.
+ dirlist = glob.glob(os.path.join(path, "*"))
+ for item in dirlist:
+ if os.path.isdir(item):
+ # Examine each subdirectory.
+ dirs.append(item)
+ # Examine all subdirectories.
+ return FindFileInPaths2(globpattern, dirs)
+
+###########################################################################
+def FindFileInPaths(globpattern,canidatepaths):
+ x,y = FindFileInPaths2(globpattern,canidatepaths)
+ return x
+
+###########################################################################
+# FIXME replace this with spawn.find_executable().
+def FindExeOnPath(exe_name,high_prio_dirs=None,low_prio_dirs=None):
+ candiate_paths = []
+
+ if high_prio_dirs is not None:
+ candiate_paths.extend(high_prio_dirs)
+
+ path_var = os.getenv("PATH")
+ candiate_paths.extend(path_var.split(':'))
+
+ if low_prio_dirs is not None:
+ candiate_paths.extend(low_prio_dirs)
+
+ for dir in candiate_paths:
+ if dir is not None:
+ candiate = os.path.join(dir,exe_name)
+ if os.path.isfile(candiate):
+ if os.access(candiate,os.X_OK):
+ return candiate
+ return None
+
+###########################################################################
+
+def ask_kde_config(question):
+ # Look for the kde-config program
+ kdeconfig = find_executable("kde-config", os.environ['PATH'] + os.pathsep + \
+ os.pathsep.join(['/bin','/usr/bin','/opt/kde3/bin','/opt/kde/bin','/usr/local/bin']))
+ if kdeconfig!=None:
+ # Ask the kde-config program for the
+ fhandle = os.popen(kdeconfig+' ' + question,'r')
+ result = fhandle.read()
+ fhandle.close()
+ return result
+ else:
+ return None
+
+###########################################################################
+# Convert for example, "3.1.1a" => [3,1,1,'a']
+#
+def split_version_name(name):
+ result = []
+ accu = ''
+ type = 0
+ for c in name:
+ if type==0:
+ if c.isdigit():
+ type = 1
+ else:
+ type = 2
+ accu += c
+ elif c=='.':
+ if type==1:
+ result.append(int(accu))
+ else:
+ result.append(accu)
+ accu = ''
+ type = 0
+ elif type==1:
+ # Digits
+ if c.isdigit():
+ accu += c
+ else:
+ result.append(int(accu))
+ type = 2
+ accu = c
+ else:
+ if c.isdigit():
+ result.append(accu)
+ type = 1
+ accu = c
+ else:
+ accu += c
+ if accu!='':
+ result.append(accu)
+ return result
+
+###########################################################################
+#
+# Returns:
+# -1 if a < b
+# 0 if a and b are equal
+# 1 if a > b
+def compare_versions(a,b):
+ aparts = split_version_name(a)
+ bparts = split_version_name(b)
+ if len(aparts)>len(bparts):
+ compmax = len(aparts)
+ else:
+ compmax = len(bparts)
+ i = 0
+ for i in range(compmax):
+ abit = 0
+ if i<len(aparts):
+ abit = aparts[i]
+ bit = 0
+ if i<len(bparts):
+ bbit = bparts[i]
+ if isinstance(abit,str) and not isinstance(bbit,str):
+ return 1
+ elif not isinstance(abit,str) and isinstance(bbit,str):
+ return -1
+ else:
+ if abit>bbit:
+ return 1
+ elif abit<bbit:
+ return -1
+ return 0
+
+###########################################################################
+def get_qt_kde_versions():
+ versioninfo = ask_kde_config('--version')
+ qtver = None
+ kdever = None
+ if versioninfo!=None:
+ for line in versioninfo.splitlines():
+ if line.startswith("Qt: "):
+ qtver = line[4:]
+ elif line.startswith("KDE: "):
+ kdever = line[5:]
+ return qtver,kdever
+
+###########################################################################
+def compile_qtdesigner(ui_files,
+ force=0,
+ prefix=None, base_dir=None,
+ verbose=1, dry_run=0):
+ """Compile a collection of QT Designer UI files to .py
+
+ If 'dry_run' is true, doesn't actually do anything that would
+ affect the filesystem.
+ """
+ generated_files = []
+ for file in ui_files:
+ if not file.endswith(".ui"):
+ continue
+
+ # Terminology from the py_compile module:
+ # cfile - byte-compiled file
+ # dfile - purported source filename (same as 'file' by default)
+ if base_dir:
+ file = os.path.join(base_dir ,file)
+
+ pyfile = file[:-3] + '.py'
+ uifile = file
+
+ pyfile_base = os.path.basename(pyfile)
+ if force or newer(uifile, pyfile):
+ log.info("compiling Qt-Designer UI %s to %s", file, pyfile_base)
+ if not dry_run:
+ qtuicompiler.CompileUI(uifile, pyfile)
+ generated_files.append(pyfile)
+ else:
+ log.debug("skipping Qt-Designer compilation of %s to %s",
+ file, pyfile_base)
+ return generated_files
+
+###########################################################################
+def get_libdir_name():
+ #if os.uname()[4] in ['x86_64','mips64','ppc64','sparc64','s390x']:
+ # return 'lib64'
+ #else:
+ return 'lib'