[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