[PyKDE] !@#$% ... distutils setup script for PyQt/PyKDE, again

Thomas Malik Thomas_Malik%LGBANK at lbbw.de
Wed Jun 27 16:47:55 BST 2001



----------  Forwarded Message  ----------
Subject: distutils setup script for
Date: Wed, 27 Jun 2001 14:21:18 +0200
From: Thomas Malik <Thomas_Malik%LGBANK at lbbw.de>

Dumb mail server administrators to hell.
Ok, here are verbatim copies of the scripts. Watch out for wrong line
breaks.
Next time i'll use uuencode to send files (oh, those old days ...)

I've splitted the setup scripts in two parts, mainly because most of the
stuff is the same for PyQt and PyKDE. The configurable options are in the
first file, sip_setup.py, which also contains two class defs, extensions to
the distutils build_ext Extension classes.
Just drop these files into the PyQt/PyKDE source directories, modify the
paths in sip_setup.py and run

python setup.py build
python setup.py install

(or python setup.py --help or python setup.py --help-commands, for that
matter)

Later, i'll modify these so you can set the directories in setup.cfg (not
needing to edit a python source file).

Sorry that i have to send these as an
attached info-zip file, but our email policy doesn't allow me anything else
-
hopefully these will make it through.

BTW, Phil, I've found it useful to have the PyQt version number stored in
the
PyQt module. For this reason, i've appended

char *version;

%C++Code
char *version="2.4";
%End

to qglobal.sip. Would you agree to this ?


### PyQt/sip_setup.py start

# common include for PyQt and PyKDE setup scripts
# this file is meant to be 'execfile'd (the cheesy way)

from distutils.core import setup, Extension
from distutils.cmd import Command
from distutils.command.build_ext import build_ext
from distutils.command.install import install
from distutils.ccompiler import new_compiler
from distutils.sysconfig import customize_compiler
from distutils.util import get_platform

from glob import glob
import sys, os, commands, string, re, types


plat_specifier = ".%s-%s" % (get_platform(), sys.version[0:3])

# configurable stuff starts here
x11_incdir='/apps/prod/X11R6.4/include'

# could have been taken from $KDEDIR (if there were only one of it ...)
# kdedir=os.environ['KDEDIR']
kdedir='/apps/prod/X11R6.4/kde/1.1.2'
kde_incdir=os.path.join(kdedir, 'include')
kde_libdir=os.path.join(kdedir, 'lib')

# could have been taken from $QTDIR (if there were only one of it ...)
# qtdir=os.environ['QTDIR']
qtdir='/apps/prod/X11R6.4/qt-1.44'
qt_incdir=os.path.join(qtdir, 'include')
qt_libdir=os.path.join(qtdir, 'lib')
#qt_libdir='/apps/prod/X11R6.4/lib'

sip_incdir='/opt/tools/include/sip'
sip_libdir='/opt/tools/lib'
# link statically (because of multiple versions in different directories)
extra_objects=[os.path.join(sip_libdir, 'libsip.a')]

# where libstdc++.so lives (without this, gcc link will bomb out)
stdcpp_libdir='/apps/prod/lib'

# build dir for PyQt (only needed for linking the PyKDE shared module with
the PyQt shared module)
# !!! please check !!!
pyqt_builddir = os.path.join(pyqt_srcdir, 'build', 'lib' + plat_specifier)

# used as argument to sip processor
sip_include_dirs=['sip', os.path.join(pyqt_srcdir, 'sip')]


def find_program_in_path(program):
    if os.name == 'posix':
        for dir in string.split(os.environ['PATH'], os.pathsep):
            if os.access(os.path.join(dir, program), os.X_OK):
                return os.path.join(dir, program)
    elif os.name == 'nt':
        (base, ext) = os.path.splitext(string.lower(program))
        if ext != '.exe': program = program + '.exe'
        for dir in string.split(os.environ['PATH'], os.pathsep):
            # no idea if existence is sufficient on NT, but should be in
most cases.
            if os.path.exists(os.path.join(dir, program)):
                return os.path.join(dir, program)


class sip_build_ext(build_ext):
    description = "build C/C++ extensions with sources created from sip
files (compile/link to build directory)"
    user_options = build_ext.user_options + \
                   [('install-platlib=', None, "installation directory for
non-pure module distributions"
                                               " (needed to link against
other shared python modules)"),
                    ('sip-only', None, "only rebuild sources from sip
specifications"),
## currently not used. All other configuration options should be included
as well, so you can put them into setup.cfg.
##                    ('sip-program=', None, "full path of sip program
(default: 'sip' as found in $PATH)"),
##                    ('sip-incdir', None, "where the sip include files
have been installed (default: dirname(sip)/../include/sip"),
##                    ('sip-libdir', None, "where the sip library has been
installed (default: dirname(sip)/../lib"),
                    ('compile', 'c', "compile .py to .pyc"),
                    ('no-compile', None, "don't compile .py files
[default]"),
                    ('optimize=', 'O',
                     "also compile with optimization: -O1 for \"python
-O\", "
                     "-O2 for \"python -OO\", and -O0 to disable [default:
-O0]"),
                    ('force', 'f', "forcibly build everything (ignore file
timestamps)"),
        ]

    boolean_options=build_ext.boolean_options + ['sip-only', 'compile',
'force']
    negative_opt = {'no-compile' : 'compile'}

    command_name = 'build_ext'

    def initialize_options(self):
        self.install_platlib=None
        self.sip_only=0
##        self.sip_program=None
##        self.sip_incdir=None
##        self.sip_libdir=None
        self.compile = 1
        self.optimize = 0
        build_ext.initialize_options(self)

    def finalize_options(self):
        build_ext.finalize_options(self)
        self.set_undefined_options('install',
                                   ('install_platlib', 'install_platlib'))

        if not self.install_platlib:
            raise RuntimeError('install_platlib not defined')

##        if not self.sip_program:
##            self.sip_program = find_program_in_path('sip')

##        self.announce( 'sip_program = %s' % self.sip_program)
##        if not self.sip_incdir:
##            self.sip_incdir =
os.path.abspath(os.path.join(os.path.abspath(self.sip_program), '..',
'include', 'sip'))
##        self.announce( 'sip_incdir = %s' % self.sip_incdir)
##        if not self.sip_libdir:
##            self.sip_libdir =
os.path.abspath(os.path.join(os.path.abspath(self.sip_program), '..',
'lib', 'sip'))
##        self.announce( 'sip_libdir = %s' % self.sip_libdir)

        if not isinstance(self.optimize, types.IntType):
            try:
                self.optimize = int(self.optimize)
                assert 0 <= self.optimize <= 2
            except (ValueError, AssertionError):
                raise DistutilsOptionError, "optimize must be 0, 1, or 2"

    def rebuild_src(self, extension):
        build = self.get_finalized_command('build')
        name = extension.pkgname

        # call sip with appropriate arguments
        includes = []
        for dir in extension.sip_include_dirs:
            includes.append('-I')
            includes.append(dir)

        cmd = ['sip'] + includes + ['-c', name, extension.sipfile]
        self.spawn(cmd)

        # build & run sip_helper.
        compiler = new_compiler(compiler=self.compiler,
                                verbose=self.verbose,
                                dry_run=self.dry_run,
                                force=self.force)
        customize_compiler(compiler)
        compiler.set_include_dirs(extension.include_dirs)
        compiler.set_library_dirs(extension.library_dirs)
        compiler.set_runtime_library_dirs(extension.runtime_library_dirs)
        objects = compiler.compile(extension.sip_helper_srcs)
        compiler.link_executable(objects, extension.sip_helper, libraries
=['stdc++'])
        sipVersion = commands.getoutput(extension.sip_helper)

        # write sip_helper output if it really changes the version file
contents (can make builds quicker)
        old_sipVersion = ''
        try:
            old_sipVersion = open(extension.sipVersion_h).read()
        except:
            pass
        if sipVersion != old_sipVersion:
            open(extension.sipVersion_h,'w').write(sipVersion)
            self.announce('sip_helper output %s written' %
extension.sipVersion_h)
        else:
            self.announce('sip_helper output %s did not change, not
written' % extension.sipVersion_h)

# not really needed. No idea what it was originally meant for in distutils.
##    def get_outputs(self):
##        print 'sip_build_ext.get_outputs'
##        outputs = build_ext.get_outputs()
##        for ext in self.extensions:
##            if isinstance(ext, SipExtension):
##                fullname = self.get_ext_fullname(ext.name)
##                outputs.append(os.path.join(self.build_lib,
ext.sip_modfile))
##        print 'outputs =', outputs
##        return outputs

    def build_py_module (self, file):
        from distutils.util import byte_compile
        prefix = self.build_lib
        if prefix[-1] != os.sep:
            prefix = prefix + os.sep

        self.copy_file(file, self.build_lib)
        pyfile = os.path.join(self.build_lib, os.path.basename(file))
        if self.compile:
            byte_compile([pyfile], optimize=0,
                         force=self.force,
                         prefix=prefix,
                         verbose=self.verbose, dry_run=self.dry_run)
        if self.optimize > 0:
            byte_compile([pyfile], optimize=self.optimize,
                         force=self.force,
                         prefix=prefix,
                         verbose=self.verbose, dry_run=self.dry_run)


    def run(self):
        for ext in self.extensions:
            if isinstance(ext, SipExtension):
##                self.make_file([ext.sipfile] + ext.sipdepend,
ext.init_file, self.rebuild_src, (ext,))

                # build python module from sip sources
                self.make_file([ext.sipfile] + ext.sipdepend,
ext.sip_modfile, self.rebuild_src, (ext,))

                # extend the library_dirs and runtime_library_dirs to
include the directories of %Imported modules also.
                for module in ext.sipdepend_modules:
                    print 'library_dirs(1) =', ext.library_dirs
                    ext.libraries = [module + 'c'] + ext.libraries
                    # this is for the alternative package structure (qt
package as subdir with __init__.py)
                    print 'self.build_lib =', self.build_lib
                    libdir = os.path.join(self.build_lib, module)
                    # this is for the 'normal' way building PyQt
                    libdir = self.build_lib
                    if os.path.exists(libdir) and not libdir in
ext.library_dirs:
                        # use this mad way of appending because the
original lists may be the same python objects
                        ext.library_dirs = ext.library_dirs + [libdir]
                    # append
                    rt_libdir = os.path.join(self.install_platlib, module)
                    if not rt_libdir in ext.runtime_library_dirs:
                        ext.runtime_library_dirs = ext.runtime_library_dirs
+ [rt_libdir]

                print 'library_dirs =', ext.library_dirs
                print 'runtime_library_dirs =', ext.runtime_library_dirs
##                print ext.sources

        if self.sip_only:
            return 1

        build_ext.run(self)

        for ext in self.extensions:
            if isinstance(ext, SipExtension):
                self.build_py_module(ext.sip_modfile)

class SipExtension(Extension):
    # list of sections to ignore in sip input files
    skipSections=['Copying', 'Doc', 'ExportedDoc', 'Makefile']
    #             'C++Code', 'CanConvertToClassCode',
'ConvertFromClassCode',
    #             'ConvertToClassCode', 'ConvertToSubClassCode',

    # return the list of directly %Included and the list of directly or
    # indirectly %Imported sip modules as a 2-tuple
    def get_depend(self, sipfile):
        print 'get_depend:', sipfile
        sipdepend = []
        sipdepend_modules = []
        skiplines = 0
        for line in open(sipfile, 'r').readlines():
            if skiplines:
                if re.match(r'^%End', line):
                    skiplines = 0
            else:
                for s in self.skipSections:
                    if re.match(r'^%' + s, line):
                        skiplines = 1
                else:
                    m = re.match(r'^%Include (.*\.sip)', line)
                    if m:
                        include_file = m.group(1)
                        for incldir in ['.'] + self.sip_include_dirs:
                            if os.path.exists(os.path.join(incldir,
include_file)):
                               sipdepend.append(os.path.join(incldir,
include_file))
                               break
                        else:
                            raise Exception(include_file + ' not found')

                    m = re.match(r'^%Import (.*\.sip)', line)
                    if m:
                        include_file = m.group(1)
                        for incldir in ['.'] + self.sip_include_dirs:
                            if os.path.exists(os.path.join(incldir,
include_file)):
                               sipdepend.append(os.path.join(incldir,
include_file))
                               break
                        else:
                            raise Exception(include_file + ' not found')
                        (depmod, ext) = os.path.splitext(include_file)
                        sipdepend_modules.append(depmod)
                        (more_includes, add_depend) =
self.get_depend(os.path.join(incldir, include_file))
        ##                print 'add_depend:', add_depend
                        sipdepend_modules.extend(add_depend)
        return (sipdepend, sipdepend_modules)

    # scan each sipfile for class declarations through a simple regular
    # expression. The skipSections are ignored in the sip files.
    def get_classes(self, sipfiles):
        classes = {}                                        # such that
each class is inserted once only
        for sipfile in sipfiles:
            skiplines=0
            for line in open(sipfile, 'r').readlines():
                if skiplines:
                    if re.match(r'^%End', line):
                        skiplines = 0
                else:
                    for s in self.skipSections:
                        if re.match(r'^%' + s, line):
                            skiplines = 1
                    else:
                        m = re.match(r'^class *(\w+)', line)
                        if m:
##                            print sipfile, m.group(0), m.group(1)
                            classes[m.group(1)]=sipfile

        classes = classes.keys()
        classes.sort()
        return classes

    def __init__(self, name, sip_include_dirs=['sip'], **kwargs):
        self.pkgname = name                                 # different
from extension name (which is the name of the
                                                            # shared
library)
        extname = 'lib%sc' % name
        self.sipfile = os.path.join('sip', name + '.sip')
        self.sipdepend = []
        self.sipdepend_modules = []
        classes = {}
        self.sip_include_dirs=sip_include_dirs
        self.sip_modfile = os.path.join(name, name + '.py')
##        self.init_file = os.path.join(name, '__init__.py')
        self.sip_helper = os.path.join(name, 'sip_helper')
        self.sip_helper_srcs = [os.path.join(name, 'sip_helper.cpp')]
        self.sipVersion_h = os.path.join(name, 'sip%sVersion.h' % name)
        (self.sipdepend, self.sipdepend_modules) =
self.get_depend(self.sipfile)
        self.classes = self.get_classes(self.sipdepend)
##        print self.classes
        sources = map(lambda c, pkgname=self.pkgname: os.path.join(pkgname,
'sip%s%s.cpp' % (pkgname, c)),
                      self.classes)
        sources.sort()
        sources.append(os.path.join(name, name + 'cmodule.cpp'))

        # now call the base class constructor with the sources we've found
        apply(Extension.__init__, (self, extname, sources), kwargs)
        self.include_dirs.append(os.path.join(os.getcwd(), name))
        print 'library_dirs(0) =', self.library_dirs

### PyQt/sip_setup.py end

### PyQt/setup.py start
#!/usr/bin/env python

"""
Setup script for the PyKDE module distribution.  Check sip_setup.py in the
PyQt source directory for qt/kde/sip installation directories and other
configurable stuff.
"""

__revision__ = "$Id: setup.py,v 1.1.1.1 2001/03/08 16:25:33 cvsuser Exp $"

import os

# where the PyQt sources are installed (../PyQt-2.4 assumed)
pyqt_srcdir = os.path.abspath(os.path.join(os.getcwd(), '..', 'PyQt-2.4'))

execfile(os.path.join(pyqt_srcdir, 'sip_setup.py'), globals(), locals())

# common include directories for all modules
include_dirs = [qt_incdir, x11_incdir, sip_incdir]
# common link library search directories for all modules
library_dirs = [stdcpp_libdir, qt_libdir]
# common runtime library search directories for all modules
runtime_library_dirs = [stdcpp_libdir, qt_libdir]

setup (# Distribution meta-data
       name = "PyQt",
       version = "2.4",
       description = "python qt binding",
       author = "phil thompson",
       author_email = "<phil at river-bank.demon.co.uk>",
       url = "<www.river-bank.demon.co.uk>",
       cmdclass = { 'build_ext': sip_build_ext, 'sip_build_ext':
sip_build_ext},
       ext_modules = [ SipExtension('qt',
                                    sip_include_dirs=sip_include_dirs,
                                    include_dirs=include_dirs,
                                    library_dirs=library_dirs,
                                    libraries=['qt', 'stdc++'],
                                    extra_objects=extra_objects,

runtime_library_dirs=runtime_library_dirs ),
                       ]

      )

### PyQt/setup.py end

### PyKDEsetup.py start
#!/usr/bin/env python

"""
Setup script for the PyKDE module distribution.  Check sip_setup.py in the
PyQt source directory for qt/kde/sip installation directories and other
configurable stuff.
"""

__revision__ = "$Id: template_setup.py,v 1.1.1.1 2001/03/08 16:25:33
cvsuser Exp $"

import os

# where the PyQt sources are installed (../PyQt-2.4 assumed)
pyqt_srcdir = os.path.abspath(os.path.join(os.getcwd(), '..', 'PyQt-2.4'))

execfile(os.path.join(pyqt_srcdir, 'sip_setup.py'), globals(), locals())

# common include directories for all modules
include_dirs = [qt_incdir, kde_incdir, x11_incdir, sip_incdir]
# common link library search directories for all modules
library_dirs = [stdcpp_libdir, qt_libdir, kde_libdir, pyqt_builddir]
# common runtime library search directories for all modules (libqtc's
directory will be added automatically)
runtime_library_dirs = [stdcpp_libdir, qt_libdir, kde_libdir]

setup (# Distribution meta-data
       name = "PyKDE",
       version = "2.4",
       description = "python kde binding",
       author = "phil thompson",
       author_email = "<phil at river-bank.demon.co.uk>",
       url = "<www.river-bank.demon.co.uk>",
       cmdclass = { 'build_ext': sip_build_ext, 'sip_build_ext':
sip_build_ext},
       ext_modules = [ SipExtension('kdecore',
                                    sip_include_dirs=sip_include_dirs,
                                    include_dirs=include_dirs,
                                    library_dirs=library_dirs,
                                    libraries=['kdecore', 'qt', 'stdc++'],
                                    extra_objects=extra_objects,

runtime_library_dirs=runtime_library_dirs ),
                       SipExtension('kdeui',
                                    sip_include_dirs=sip_include_dirs,
                                    include_dirs=include_dirs,
                                    library_dirs=library_dirs,
                                    libraries=['kdeui', 'kdecore', 'qt',
'stdc++'],
                                    extra_objects=extra_objects,

runtime_library_dirs=runtime_library_dirs ),
                       SipExtension('kfm',
                                    sip_include_dirs=sip_include_dirs,
                                    include_dirs=include_dirs,
                                    library_dirs=library_dirs,
                                    libraries=['kdecore', 'kfm', 'qt',
'stdc++'],
                                    extra_objects=extra_objects,

runtime_library_dirs=runtime_library_dirs ),
                       SipExtension('kfile',
                                    sip_include_dirs=sip_include_dirs,
                                    include_dirs=include_dirs,
                                    library_dirs=library_dirs,
                                    libraries=['kdeui', 'kdecore', 'kfile',
'qt', 'stdc++'],
                                    extra_objects=extra_objects,

runtime_library_dirs=runtime_library_dirs ),
                       SipExtension('khtmlw',
                                    sip_include_dirs=sip_include_dirs,
                                    include_dirs=include_dirs,
                                    library_dirs=library_dirs,
                                    libraries=['khtmlw', 'kdeui', 'kimgio',
'kdecore', 'jscript', 'qt', 'stdc++'],
                                    extra_objects=extra_objects,

runtime_library_dirs=runtime_library_dirs ),
                       SipExtension('kspell',
                                    sip_include_dirs=sip_include_dirs,
                                    include_dirs=include_dirs,
                                    library_dirs=library_dirs,
                                    libraries=['kdecore', 'kspell', 'qt',
'stdc++'],
                                    extra_objects=extra_objects,

runtime_library_dirs=runtime_library_dirs ),
                       ]

      )

### PyKDE/setup.py end

--

Thomas Malik
Landesbank Baden-Wuerttemberg (Stuttgart, Germany)
Abt. 2340 Tel. (+49 711) 124-7049
Thomas_Malik%lgbank at lbbw.de


-------------------------------------------------------



--

Thomas Malik
Landesbank Baden-Wuerttemberg (Stuttgart, Germany)
Abt. 2340 Tel. (+49 711) 124-7049
Thomas_Malik%lgbank at lbbw.de

______________________________________________________________________

--------------------------------------------------------------------------------------------
Bitte beachten Sie, dass der Inhalt dieser E-Mail einschließlich eventuell
angehängter Dokumente vertraulich ist. Falls Sie nicht der angegebene
Empfänger sind oder falls diese E-Mail irrtümlich an Sie adressiert wurde,
dürfen Sie die E-Mail und eventuell angehängte Dokumente weder öffnen,
lesen, kopieren, verbreiten noch ihren Inhalt in irgendeiner Weise nutzen.
Bitte verständigen Sie den Absender sofort und löschen Sie Die E-Mail
sodann.

Die Sicherheit von Übermittlungen per E-Mail kann nicht garantiert werden.
Per E-Mail übermittelte Informationen können abgefangen oder geändert
werden, verloren gehen oder zerstört werden, verspätet oder unvollständig
ankommen, oder Viren enthalten. Der Absender übernimmt daher keine Gewähr
für Irrtümer oder Auslassungen jeder Art im Inhalt sowie sonstige Risiken,
die auf die Übermittlung per E-Mail zurückzuführen sind. Falls Sie eine
Bestätigung wünschen, fordern Sie bitte den Inhalt der E-Mail als Hardcopy
an.


This e-mail and any attached files are confidential. If you are not the
named addressee or if this transmission has been addressed to you in error,
any disclosure, reproduction, copying, distrubtion, or other dissemination
or use of this communication is prohibited. If you have received this
transmission in error please notify the sender immediately and then delete
this e-mail.

E-mail transmission cannot be guaranteed to be secure or free from error as
information could be intercepted, corrupted, lost, destroyed, arrive late
or incomplete, or contain viruses. The sender therefore does not accept
liability for any errors or omissions in the contents of this message or
any other of such risks which arise as a result of e-mail transmission. If
verification is required, please request a hard copy version.
---------------------------------------------------------------------------------------------







More information about the PyQt mailing list