setup.py revision 422
409N/A#!/usr/bin/python2.4
20N/A#
20N/A# CDDL HEADER START
20N/A#
20N/A# The contents of this file are subject to the terms of the
20N/A# Common Development and Distribution License (the "License").
20N/A# You may not use this file except in compliance with the License.
20N/A#
20N/A# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
20N/A# or http://www.opensolaris.org/os/licensing.
20N/A# See the License for the specific language governing permissions
20N/A# and limitations under the License.
20N/A#
20N/A# When distributing Covered Code, include this CDDL HEADER in each
20N/A# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
20N/A# If applicable, add the following below this CDDL HEADER, with the
20N/A# fields enclosed by brackets "[]" replaced with your own identifying
20N/A# information: Portions Copyright [yyyy] [name of copyright owner]
20N/A#
20N/A# CDDL HEADER END
20N/A#
260N/A# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
20N/A# Use is subject to license terms.
20N/A#
20N/A
22N/Aimport os
0N/Aimport stat
50N/Aimport sys
50N/Aimport platform
50N/Aimport shutil
50N/Aimport re
50N/Aimport subprocess
50N/Aimport tarfile
50N/Aimport tempfile
50N/Aimport urllib
50N/A
50N/Afrom distutils.core import setup, Extension
50N/Afrom distutils.cmd import Command
50N/Afrom distutils.command.install import install as _install
50N/Afrom distutils.command.build import build as _build
50N/Afrom distutils.command.build_py import build_py as _build_py
50N/Afrom distutils.command.bdist import bdist as _bdist
50N/Afrom distutils.command.clean import clean as _clean
382N/A
382N/Afrom distutils.sysconfig import get_python_inc
382N/Aimport distutils.file_util as file_util
382N/Aimport distutils.dir_util as dir_util
382N/Aimport distutils.util as util
382N/A
382N/Apwd = os.path.normpath(sys.path[0])
382N/A
382N/Aosname = platform.uname()[0].lower()
382N/Aostype = arch = 'unknown'
382N/Aif osname == 'sunos':
382N/A arch = platform.processor()
382N/A ostype = "posix"
382N/Aelif osname == 'linux':
382N/A arch = "linux_" + platform.machine()
382N/A ostype = "posix"
382N/Aelif osname == 'windows':
382N/A arch = osname
382N/A ostype = "windows"
382N/Aelif osname == 'darwin':
429N/A arch = osname
429N/A ostype = "posix"
382N/A
26N/Adist_dir = os.path.normpath(os.path.join(pwd, os.pardir, "proto", "dist_" + arch))
0N/Abuild_dir = os.path.normpath(os.path.join(pwd, os.pardir, "proto", "build_" + arch))
52N/Aroot_dir = os.path.normpath(os.path.join(pwd, os.pardir, "proto", "root_" + arch))
0N/A
382N/Apy_install_dir = 'usr/lib/python2.4/vendor-packages'
382N/A
382N/Ascripts_dir = 'usr/bin'
382N/Alib_dir = 'usr/lib'
382N/A
382N/Aman1_dir = 'usr/share/man/cat1'
382N/Aman1m_dir = 'usr/share/man/cat1m'
382N/Aman5_dir = 'usr/share/man/cat5'
382N/Aresource_dir = 'usr/share/lib/pkg'
382N/Asmf_dir = 'var/svc/manifest/application'
382N/Azones_dir = 'etc/zones'
22N/Abrand_dir = 'usr/lib/brand/ipkg'
114N/A
26N/Ascripts_sunos = {
382N/A scripts_dir: [
382N/A ['client.py', 'pkg'],
428N/A ['publish.py', 'pkgsend'],
428N/A ['pull.py', 'pkgrecv'],
23N/A ],
26N/A lib_dir: [
26N/A ['depot.py', 'pkg.depotd'],
157N/A ],
382N/A }
382N/A
135N/Ascripts_windows = {
157N/A scripts_dir: [
26N/A ['client.py', 'client.py'],
135N/A ['publish.py', 'publish.py'],
14N/A ['pull.py', 'pull.py'],
382N/A ['scripts/pkg.bat', 'pkg.bat'],
429N/A ['scripts/pkgsend.bat', 'pkgsend.bat'],
14N/A ['scripts/pkgrecv.bat', 'pkgrecv.bat'],
404N/A ],
404N/A lib_dir: [
30N/A ['depot.py', 'depot.py'],
382N/A ['scripts/pkg.depotd.bat', 'pkg.depotd.bat'],
30N/A ],
382N/A }
382N/A
382N/Ascripts_other_unix = {
382N/A scripts_dir: [
382N/A ['client.py', 'client.py'],
429N/A ['pull.py', 'pull.py'],
258N/A ['publish.py', 'publish.py'],
382N/A ['scripts/pkg.sh', 'pkg'],
382N/A ['scripts/pkgsend.sh', 'pkgsend'],
382N/A ['scripts/pkgrecv.sh', 'pkgrecv'],
382N/A ],
30N/A lib_dir: [
54N/A ['depot.py', 'depot.py'],
382N/A ['scripts/pkg.depotd.sh', 'pkg.depotd'],
382N/A ],
429N/A }
135N/A
382N/A# indexed by 'osname'
382N/Ascripts = {
382N/A "sunos": scripts_sunos,
382N/A "linux": scripts_other_unix,
382N/A "windows": scripts_windows,
382N/A "darwin": scripts_other_unix,
135N/A "unknown": scripts_sunos,
135N/A }
135N/A
382N/Aman1_files = [
135N/A 'man/pkg.1',
135N/A 'man/pkgsend.1',
382N/A 'man/pkgrecv.1',
382N/A ]
382N/Aman1m_files = [
382N/A 'man/pkg.depotd.1m'
382N/A ]
382N/Aman5_files = [
382N/A 'man/pkg.5'
382N/A ]
382N/Apackages = [
382N/A 'pkg',
135N/A 'pkg.actions',
382N/A 'pkg.bundle',
157N/A 'pkg.client',
382N/A 'pkg.portable',
429N/A 'pkg.publish',
429N/A 'pkg.server',
429N/A ]
429N/Aweb_files = [
429N/A 'web/pkg-block-icon.png',
429N/A 'web/pkg-block-logo.png',
429N/A 'web/pkg.css',
429N/A 'web/robots.txt',
429N/A ]
429N/Azones_files = [
429N/A 'brand/SUNWipkg.xml',
135N/A ]
404N/Abrand_files = [
382N/A 'brand/config.xml',
382N/A 'brand/platform.xml',
382N/A 'brand/pkgcreatezone',
382N/A ]
382N/Asmf_files = [
382N/A 'pkg-server.xml',
382N/A ]
135N/Aelf_srcs = [
429N/A 'modules/elf.c',
429N/A 'modules/elfextract.c',
429N/A 'modules/liblist.c',
429N/A ]
429N/Aarch_srcs = [
429N/A 'modules/arch.c'
429N/A ]
429N/Ainclude_dirs = [ 'modules' ]
386N/Alint_flags = [ '-u', '-axms', '-erroff=E_NAME_DEF_NOT_USED2' ]
382N/A
382N/A# Runs lint on the extension module source code
382N/Aclass lint_func(Command):
382N/A description = "Runs various lint tools over IPS extension source code"
382N/A user_options = []
382N/A
382N/A def initialize_options(self):
382N/A pass
382N/A
382N/A def finalize_options(self):
382N/A pass
382N/A
382N/A # Make string shell-friendly
382N/A @staticmethod
382N/A def escape(astring):
382N/A return astring.replace(' ', '\\ ')
382N/A
382N/A def run(self):
382N/A # assumes lint is on the $PATH
382N/A if osname == 'sunos' or osname == "linux":
382N/A archcmd = ['lint'] + lint_flags + ['-D_FILE_OFFSET_BITS=64'] + \
429N/A ["%s%s" % ("-I", k) for k in include_dirs] + \
429N/A ['-I' + self.escape(get_python_inc())] + \
429N/A arch_srcs
429N/A elfcmd = ['lint'] + lint_flags + \
429N/A ["%s%s" % ("-I", k) for k in include_dirs] + \
26N/A ['-I' + self.escape(get_python_inc())] + \
26N/A ["%s%s" % ("-l", k) for k in elf_libraries] + \
26N/A elf_srcs
428N/A
428N/A print(" ".join(archcmd))
428N/A os.system(" ".join(archcmd))
428N/A print(" ".join(elfcmd))
428N/A os.system(" ".join(elfcmd))
428N/A
382N/A proto = os.path.join(root_dir, py_install_dir)
382N/A sys.path.insert(0, proto)
382N/A
382N/A # Insert tests directory onto sys.path so any custom checkers
382N/A # can be found.
382N/A sys.path.insert(0, os.path.join(pwd, 'tests'))
382N/A print(sys.path)
382N/A
382N/A # assumes pylint is accessible on the sys.path
382N/A from pylint import lint
382N/A scriptlist = [ 'setup.py' ]
382N/A for d, m in scripts_sunos.items():
382N/A for a in m:
382N/A # specify the filenames of the scripts, in addition
382N/A # to the package names themselves
382N/A scriptlist.append(os.path.join(root_dir, d, a[1]))
382N/A
382N/A # For some reason, the load-plugins option, when used in the
382N/A # rcfile, does not work, so we put it here instead, to load
382N/A # our custom checkers.
382N/A lint.Run(['--load-plugins=multiplatform', '--rcfile',
382N/A os.path.join(pwd, 'tests', 'pylintrc')] +
382N/A scriptlist + packages)
382N/A
382N/Aclass install_func(_install):
382N/A def initialize_options(self):
145N/A _install.initialize_options(self)
217N/A # It's OK to have /'s here, python figures it out when writing files
382N/A self.install_purelib = py_install_dir
382N/A self.install_platlib = py_install_dir
382N/A self.root = root_dir
382N/A self.prefix = '.'
382N/A
217N/A def run(self):
"""
At the end of the install function, we need to rename some files
because distutils provides no way to rename files as they are
placed in their install locations.
Also, make sure that cherrypy is installed.
"""
for f in man1_files + man1m_files + man5_files:
file_util.copy_file(f + ".txt", f, update=1)
_install.run(self)
for d, files in scripts[osname].iteritems():
for (srcname, dstname) in files:
dst_dir = util.change_root(self.root, d)
dst_path = util.change_root(self.root,
os.path.join(d, dstname))
dir_util.mkpath(dst_dir, verbose = True)
file_util.copy_file(srcname, dst_path, update = True)
# make scripts executable
os.chmod(dst_path,
os.stat(dst_path).st_mode | stat.S_IEXEC)
install_cherrypy()
CP = 'CherryPy'
CPVER = '3.0.3'
CPARC = '%s-%s.tar.gz' % (CP, CPVER)
CPDIR = '%s-%s' % (CP, CPVER)
CPURL = 'http://download.cherrypy.org/cherrypy/%s/%s' % (CPVER, CPARC)
def install_cherrypy():
if not os.path.exists(CPARC):
print "downloading CherryPy"
try:
fname, hdr = urllib.urlretrieve(CPURL, CPARC)
except IOError:
pass
if not os.path.exists(CPARC) or \
hdr.gettype() != "application/x-gzip":
print "Unable to retrieve %s.\nPlease retrieve the file " \
"and place it at: %s\n" % (CPURL, CPARC)
# remove a partial download or error message from proxy
remove_cherrypy()
sys.exit(1)
if not os.path.exists(CPDIR):
print "unpacking CherryPy"
tar = tarfile.open(CPARC)
# extractall doesn't exist until python 2.5
for m in tar.getmembers():
tar.extract(m)
tar.close()
cherrypy_dir = os.path.join(root_dir, py_install_dir, "cherrypy")
if not os.path.exists(cherrypy_dir):
print "installing CherryPy"
subprocess.Popen(['python', 'setup.py', 'install',
'--install-lib=%s' % os.path.join(root_dir, py_install_dir),
'--install-data=%s' % os.path.join(root_dir, py_install_dir)],
cwd = CPDIR).wait()
def remove_cherrypy():
if os.path.exists(CPARC):
os.unlink(CPARC)
shutil.rmtree(CPDIR, True)
class build_func(_build):
def initialize_options(self):
_build.initialize_options(self)
self.build_base = build_dir
def get_hg_version():
try:
p = subprocess.Popen(['hg', 'id', '-i'], stdout = subprocess.PIPE)
return p.communicate()[0].strip()
except OSError:
print >> sys.stderr, "ERROR: unable to obtain mercurial version"
return "unknown"
class build_py_func(_build_py):
# override the build_module method to do VERSION substitution on pkg/__init__.py
def build_module (self, module, module_file, package):
if module == "__init__" and package == "pkg":
versionre = '(?m)^VERSION[^"]*"([^"]*)"'
# Grab the previously-built version out of the build
# tree.
try:
ocontent = \
file(self.get_module_outfile(self.build_lib,
[package], module)).read()
ov = re.search(versionre, ocontent).group(1)
except IOError:
ov = None
v = get_hg_version()
vstr = 'VERSION = "%s"' % v
# If the versions haven't changed, there's no need to
# recompile.
if v == ov:
return
mcontent = file(module_file).read()
mcontent = re.sub(versionre, vstr, mcontent)
tmpfd, tmp_file = tempfile.mkstemp()
os.write(tmpfd, mcontent)
os.close(tmpfd)
print "doing version substitution: ", v
rv = _build_py.build_module(self, module, tmp_file, package)
os.unlink(tmp_file)
return rv
return _build_py.build_module(self, module, module_file, package)
class clean_func(_clean):
def initialize_options(self):
_clean.initialize_options(self)
self.build_base = build_dir
class clobber_func(Command):
user_options = []
description = "Deletes any and all files created by setup"
def initialize_options(self):
pass
def finalize_options(self):
pass
def run(self):
# nuke everything
print("deleting " + dist_dir)
shutil.rmtree(dist_dir, True)
print("deleting " + build_dir)
shutil.rmtree(build_dir, True)
print("deleting " + root_dir)
shutil.rmtree(root_dir, True)
print("deleting cherrypy")
remove_cherrypy()
class test_func(Command):
user_options = []
description = "Runs unit and functional tests"
def initialize_options(self):
pass
def finalize_options(self):
pass
def run(self):
os.putenv('PYEXE', sys.executable)
os.chdir(os.path.join(pwd, "tests"))
testlogfd, testlogpath = tempfile.mkstemp(suffix = '.pkg-test.log')
testlogfp = os.fdopen(testlogfd, "w")
print "logging to %s" % testlogpath
subprocess.call([sys.executable, "api-complete.py"],
stdout = testlogfp)
if ostype == 'posix':
subprocess.call([sys.executable, "cli-complete.py"],
stdout = testlogfp)
if osname == 'sunos':
subprocess.call(["/bin/ksh", "memleaks.ksh"],
stdout = testlogfp)
testlogfp.close()
class dist_func(_bdist):
def initialize_options(self):
_bdist.initialize_options(self)
self.dist_dir = dist_dir
# These are set to real values based on the platform, down below
ext_modules = None
compile_args = None
link_args = None
elf_libraries = None
data_files = [ (resource_dir, web_files) ]
cmdclasses = {
'install': install_func,
'build': build_func,
'build_py': build_py_func,
'bdist': dist_func,
'lint': lint_func,
'clean': clean_func,
'clobber': clobber_func,
'test': test_func,
}
# all builds of IPS should have manpages
data_files += [
(man1_dir, man1_files),
(man1m_dir, man1m_files),
(man5_dir, man5_files),
]
if osname == 'sunos':
# Solaris-specific extensions are added here
data_files += [
(zones_dir, zones_files),
(brand_dir, brand_files),
(smf_dir, smf_files),
]
if osname == 'sunos' or osname == "linux":
# Unix platforms which the elf extension has been ported to
# are specified here, so they are built automatically
elf_libraries = ['elf']
ext_modules = [
Extension(
'elf',
elf_srcs,
include_dirs = include_dirs,
libraries = elf_libraries,
extra_compile_args = compile_args,
extra_link_args = link_args
),
]
# Solaris has built-in md library and Solaris-specific arch extension
# All others use OpenSSL and cross-platform arch module
if osname == 'sunos':
elf_libraries += [ 'md' ]
ext_modules += [
Extension(
'arch',
arch_srcs,
include_dirs = include_dirs,
extra_compile_args = compile_args,
extra_link_args = link_args,
define_macros = [('_FILE_OFFSET_BITS', '64')]
),
]
else:
elf_libraries += [ 'ssl' ]
setup(cmdclass = cmdclasses,
name = 'ips',
version = '1.0',
package_dir = {'pkg':'modules'},
packages = packages,
data_files = data_files,
ext_package = 'pkg',
ext_modules = ext_modules,
)