setup.py :  » Development » PyObjC » trunk » pyobjc » pyobjc-core » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Development » PyObjC 
PyObjC » trunk » pyobjc » pyobjc core » setup.py
#!/usr/bin/env python

import sys
import subprocess
import shutil
import re
import os

# We need at least Python 2.5
MIN_PYTHON = (2, 5)

# Set USE_SYSTEM_FFI to True to link to the system version
# of libffi
USE_SYSTEM_FFI = False

# Set USE_SYSTEM_LIBXML to True to link to the system version
# of libxml2 (defaults to False to avoid problems when building
# on 10.6 and running on an earlier release)
USE_SYSTEM_LIBXML = False

if sys.version_info < MIN_PYTHON:
    vstr = '.'.join(map(str, MIN_PYTHON))
    raise SystemExit('PyObjC: Need at least Python ' + vstr)


if sys.version_info[:2] < (3, 0):
    import ez_setup
    ez_setup.use_setuptools()

    extra_args=dict()
    from setuptools.command.build_py import build_py
    from setuptools.command.test import test

else:
    import distribute_setup
    distribute_setup.use_setuptools()


    extra_args=dict(
        use_2to3 = True,
    )

    from setuptools.command import build_py
    from setuptools.command import test
    from distutils import log
    class oc_build_py (build_py.build_py):
        def run_2to3(self, files, doctests=True):
            files = [ fn for fn in files if not os.path.basename(fn).startswith('test3_') ]
            super(oc_build_py, self).run_2to3(files, doctests)

        def build_packages(self):
            log.info("Overriding build_packages to copy PyObjCTest")        
            p = self.packages
            self.packages = list(self.packages) + ['PyObjCTest']
            try:
                build_py.build_py.build_packages(self)
            finally:
                self.packages = p

    from pkg_resources import working_set,normalize_path,add_activation_listener,require

    class oc_test (test.test):
        def run_tests(self):
            import sys, os
            rootdir =  os.path.dirname(os.path.abspath(__file__))
            if rootdir in sys.path:
                sys.path.remove(rootdir)
            from PyObjCTest.loader import makeTestSuite
            import unittest
           
            unittest.main(None, None, [unittest.__file__]+self.test_args)

from setuptools.command import egg_info

def write_header(cmd, basename, filename):
    data = open(os.path.join('Modules/objc/', os.path.basename(basename)), 'rU').read()
    if not cmd.dry_run:
        if not os.path.exists(os.path.dirname(filename)):
            os.makedirs(os.path.dirname(filename))

    cmd.write_file(basename, filename, data)


# This is a workaround for a bug in setuptools: I'd like
# to use the 'egg_info.writers' entry points in the setup()
# call, but those don't work when also using a package_base
# argument as we do.
# (issue 123 in the distribute tracker)
class egg_info (orig_egg_info.egg_info):
    def run(self):
        orig_egg_info.egg_info.run(self)

        for hdr in ("pyobjc-compat.h", "pyobjc-api.h"):
            fn = os.path.join("include", hdr)

            write_header(self, fn, os.path.join(self.egg_info, fn))

if sys.version_info[0] == 3:
    # FIXME: add custom test command that does the work.
    # - Patch sys.path
    # - Ensure PyObjCTest gets translated by 2to3
    from distutils.util import get_platform
    build_dir = 'build/lib.%s-%d.%d'%(
        get_platform(), sys.version_info[0], sys.version_info[1])
    if hasattr(sys, 'gettotalrefcount'):
        build_dir += '-pydebug'
    sys.path.insert(0,  build_dir)


import os
import glob
import site
import platform

if 'MallocStackLogging' in os.environ:
    del os.environ['MallocStackLogging']
if 'MallocStackLoggingNoCompact' in os.environ:
    del os.environ['MallocStackLoggingNoCompact']

# See the news file:
#os.environ['MACOSX_DEPLOYMENT_TARGET']='10.5'



#if int(os.uname()[2].split('.')[0]) >= 10:
#        USE_SYSTEM_FFI = True


# Some PiPy stuff
LONG_DESCRIPTION="""
PyObjC is a bridge between Python and Objective-C.  It allows full
featured Cocoa applications to be written in pure Python.  It is also
easy to use other frameworks containing Objective-C class libraries
from Python and to mix in Objective-C, C and C++ source.

Python is a highly dynamic programming language with a shallow learning
curve.  It combines remarkable power with very clear syntax.

The installer package installs a number of Xcode templates for
easily creating new Cocoa-Python projects.

PyObjC also supports full introspection of Objective-C classes and
direct invocation of Objective-C APIs from the interactive interpreter.

PyObjC requires MacOS X 10.4 or later.  This beta release requires
MacOS X 10.5.
"""

from setuptools import setup,Extension,find_packages
from setuptools.command import build_ext,install_lib
import os

class pyobjc_install_lib (install_lib.install_lib):
    def get_exclusions(self):
        result = install_lib.install_lib.get_exclusions(self)
        for fn in install_lib._install_lib.get_outputs(self):
            if 'PyObjCTest' in fn:
                result[fn] = 1

        return result

class pyobjc_build_ext (build_ext.build_ext):
    def run(self):
        if not USE_SYSTEM_LIBXML:
            build = self.get_finalized_command('build')
            xmldir=os.path.join(build.build_base, 'libxml')
            if not os.path.exists(xmldir):
                builddir=os.path.join(build.build_base, 'libxml-build')
                if os.path.exists(builddir):
                    shutil.rmtree(builddir)
                os.makedirs(builddir)

                cflags = get_config_var('CFLAGS')
                if '-isysroot' in cflags:
                    cflags = re.sub(r'-isysroot\s*\S*', '-isysroot /', cflags)

                p = subprocess.Popen(
                        ['../../libxml2-src/configure',
                            '--disable-dependency-tracking',
                            '--enable-static',
                            '--disable-shared',
                            '--prefix=%s'%(os.path.abspath(xmldir),),
                            '--with-minimum',
                            'CFLAGS=%s'%(cflags,),
                            'CC=%s'%(get_config_var('CC')),
                            ], 
                        cwd=builddir)
                xit=p.wait()
                if xit != 0:
                    shutil.rmtree(builddir)
                    raise RuntimeError("libxml configure failed")
                p = subprocess.Popen(
                        ['make', 'install'],
                        cwd=builddir)
                xit=p.wait()
                if xit != 0:
                    raise RuntimeError("libxml install failed")

            os.environ['PATH'] = xmldir + "/bin:" + os.environ['PATH']

        for ext in self.extensions:
            if ext.name == "objc._objc":
                if not USE_SYSTEM_LIBXML:
                    ext.extra_link_args.append('-Wl,-search_paths_first')
                ext.extra_compile_args.extend(xml2config('--cflags'))
                ext.extra_link_args.extend(xml2config('--libs'))

        build_ext.build_ext.run(self)
        extensions = self.extensions
        self.extensions = [
                e for e in extensions if e.name.startswith('PyObjCTest') ]
        self.copy_extensions_to_source()
        self.extensions = extensions

def frameworks(*args):
    lst = []
    for arg in args:
        lst.extend(['-framework', arg])
    return lst

def IfFrameWork(name, packages, extensions, headername=None):
    """
    Return the packages and extensions if the framework exists, or
    two empty lists if not.
    """
    import os
    for pth in ('/System/Library/Frameworks', '/Library/Frameworks'):
        basedir = os.path.join(pth, name)
        if os.path.exists(basedir):
            if (headername is None) or os.path.exists(os.path.join(basedir, "Headers", headername)):
                return packages, extensions
    return [], []

# Double-check
if sys.platform != 'darwin':
    print("You're not running on MacOS X, and don't use GNUstep")
    print("I don't know how to build PyObjC on such a platform.")
    print("Please read the ReadMe.")
    print("")
    raise SystemExit("ObjC runtime not found")

from distutils.sysconfig import get_config_var

CFLAGS=[ ]

# Enable 'PyObjC_STRICT_DEBUGGING' to enable some costly internal 
# assertions. 
CFLAGS.extend([
    
    # Use this to analyze with clang
    #"--analyze",

# The following flags are an attempt at getting rid of /usr/local
# in the compiler search path.
    "-DPyObjC_STRICT_DEBUGGING",
    "-DMACOSX", # For libffi
    "-DPyObjC_BUILD_RELEASE=%02d%02d"%(tuple(map(int, platform.mac_ver()[0].split('.')[:2]))),
    "-no-cpp-precomp",
    "-DMACOSX",
    "-g",
    "-fexceptions",


    # Loads of warning flags
    "-Wall", "-Wstrict-prototypes", "-Wmissing-prototypes",
    "-Wformat=2", "-W", 
    #"-Wshadow", # disabled due to warnings from Python headers
    "-Wpointer-arith", #"-Wwrite-strings",
    "-Wmissing-declarations",
    "-Wnested-externs",
    "-Wno-long-long",

    "-Wno-import",
    ])

## Arghh, a stupid compiler flag can cause problems. Don't 
## enable -O0 if you value your sanity. With -O0 PyObjC will crash
## on i386 systems when a method returns a struct that isn't returned
## in registers. 
if '-O0' in get_config_var('CFLAGS'):
    CFLAGS.append('-O1')

OBJC_LDFLAGS = frameworks('CoreFoundation', 'Foundation', 'Carbon')

if not os.path.exists('/usr/include/objc/runtime.h'):
    CFLAGS.append('-DNO_OBJC2_RUNTIME')

# Force compilation with the local SDK, compilation of PyObC will result in
# a binary that runs on other releases of the OS without using a particular SDK.
CFLAGS.extend(['-isysroot', '/'])
OBJC_LDFLAGS.extend(['-isysroot', '/'])


# We're using xml2, check for the flags to use:
def xml2config(arg):
    import os, shlex
    ln = os.popen('xml2-config %s'%(arg,), 'r').readline()
    ln = ln.strip()

    return shlex.split(ln)

#CFLAGS.extend(xml2config('--cflags'))
#OBJC_LDFLAGS.extend(xml2config('--libs'))



CFLAGS.append('-Ibuild/codegen/')

# Patch distutils: it needs to compile .S files as well.
from distutils.unixccompiler import UnixCCompiler
UnixCCompiler.src_extensions.append('.S')
del UnixCCompiler


# 
# Support for an embedded copy of libffi
#
FFI_CFLAGS=['-Ilibffi-src/include', '-Ilibffi-src/powerpc']

# The list below includes the source files for all CPU types that we run on
# this makes it easier to build fat binaries on Mac OS X.
FFI_SOURCE=[
    "libffi-src/ffi.c",
    "libffi-src/types.c",
    "libffi-src/powerpc/ppc-darwin.S",
    "libffi-src/powerpc/ppc-darwin_closure.S",
    "libffi-src/powerpc/ppc-ffi_darwin.c",
    "libffi-src/powerpc/ppc64-darwin_closure.S",
    "libffi-src/x86/darwin64.S",
    "libffi-src/x86/x86-darwin.S",
    "libffi-src/x86/x86-ffi64.c",
    "libffi-src/x86/x86-ffi_darwin.c",
]



#
# Calculate the list of extensions: objc._objc + extensions for the unittests
#

if USE_SYSTEM_FFI:
    ExtensionList =  [ 
        Extension("objc._objc",
            list(glob.glob(os.path.join('Modules', 'objc', '*.m'))),
            extra_compile_args=CFLAGS + ["-I/usr/include/ffi"],
            extra_link_args=OBJC_LDFLAGS + ["-lffi"],
            depends=list(glob.glob(os.path.join('Modules', 'objc', '*.h'))),
        ),
    ]

else:
    ExtensionList =  [ 
        Extension("objc._objc",
            FFI_SOURCE + list(glob.glob(os.path.join('Modules', 'objc', '*.m'))),
            extra_compile_args=CFLAGS + FFI_CFLAGS,
            extra_link_args=OBJC_LDFLAGS,
            depends=list(glob.glob(os.path.join('Modules', 'objc', '*.h'))),
        ),
    ]

for test_source in glob.glob(os.path.join('Modules', 'objc', 'test', '*.m')):
    name, ext = os.path.splitext(os.path.basename(test_source))

    ExtensionList.append(Extension('PyObjCTest.' + name,
        [test_source],
        extra_compile_args=['-IModules/objc'] + CFLAGS,
        extra_link_args=OBJC_LDFLAGS))

def package_version():
    fp = open('Modules/objc/pyobjc.h', 'r')
    for ln in fp.readlines():
        if ln.startswith('#define OBJC_VERSION'):
            fp.close()
            return ln.split()[-1][1:-1]

    raise ValueError("Version not found")

CLASSIFIERS = filter(None,
"""
Development Status :: 5 - Production/Stable
Environment :: Console
Environment :: MacOS X :: Cocoa
Intended Audience :: Developers
License :: OSI Approved :: MIT License
Natural Language :: English
Operating System :: MacOS :: MacOS X
Programming Language :: Python
Programming Language :: Objective C
Topic :: Software Development :: Libraries :: Python Modules
Topic :: Software Development :: User Interfaces
""".splitlines())


dist = setup(
    name = "pyobjc-core", 
    version = package_version(),
    description = "Python<->ObjC Interoperability Module",
    long_description = LONG_DESCRIPTION,
    author = "Ronald Oussoren, bbum, SteveM, LeleG, many others stretching back through the reaches of time...",
    author_email = "pyobjc-dev@lists.sourceforge.net",
    url = "http://pyobjc.sourceforge.net/",
    platforms = [ 'MacOS X' ],
    ext_modules = ExtensionList,
    packages = [ 'objc', 'PyObjCTools', ], 
    namespace_packages = ['PyObjCTools'],
    package_dir = { '': 'Lib', 'PyObjCTest': 'PyObjCTest' },
    extra_path = "PyObjC",
    cmdclass = {'build_ext': pyobjc_build_ext, 'install_lib': pyobjc_install_lib, 'build_py': oc_build_py, 'test': oc_test, 'egg_info':egg_info },
    options = {'egg_info': {'egg_base': 'Lib'}},
    classifiers = CLASSIFIERS,
    license = 'MIT License',
    download_url = 'http://pyobjc.sourceforge.net/software/index.php',
    test_suite='PyObjCTest.loader.makeTestSuite',
    zip_safe = False,
#    entry_points = {
#        "egg_info.writers": [
#            "include/pyobjc-api.h = __main__:write_header",
#            "include/pyobjc-compat.h = __main__:write_header",
#        ],
#    },
    **extra_args
)
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.