1#!/usr/bin/env python 2 3import ez_setup 4ez_setup.use_setuptools() 5 6import sys 7import os 8import glob 9import site 10import platform 11 12if 'MallocStackLogging' in os.environ: 13 del os.environ['MallocStackLogging'] 14if 'MallocStackLoggingNoCompact' in os.environ: 15 del os.environ['MallocStackLoggingNoCompact'] 16 17# See the news file: 18#os.environ['MACOSX_DEPLOYMENT_TARGET']='10.5' 19 20# We need at least Python 2.3 21MIN_PYTHON = (2, 3) 22 23if sys.version_info < MIN_PYTHON: 24 vstr = '.'.join(map(str, MIN_PYTHON)) 25 raise SystemExit('PyObjC: Need at least Python ' + vstr) 26 27USE_SYSTEM_FFI = False 28if int(os.uname()[2].split('.')[0]) >= 10: 29 USE_SYSTEM_FFI = True 30 31SDKROOT = os.environ.get('SDKROOT') 32if SDKROOT is None or SDKROOT is '': 33 SDKROOT = '/' 34 35 36# Some PiPy stuff 37LONG_DESCRIPTION=""" 38PyObjC is a bridge between Python and Objective-C. It allows full 39featured Cocoa applications to be written in pure Python. It is also 40easy to use other frameworks containing Objective-C class libraries 41from Python and to mix in Objective-C, C and C++ source. 42 43Python is a highly dynamic programming language with a shallow learning 44curve. It combines remarkable power with very clear syntax. 45 46The installer package installs a number of Xcode templates for 47easily creating new Cocoa-Python projects. 48 49PyObjC also supports full introspection of Objective-C classes and 50direct invocation of Objective-C APIs from the interactive interpreter. 51 52PyObjC requires MacOS X 10.4 or later. This beta release requires 53MacOS X 10.5. 54""" 55 56from setuptools import setup, Extension, find_packages 57from setuptools.command import build_ext, install_lib 58import os 59 60class pyobjc_install_lib (install_lib.install_lib): 61 def get_exclusions(self): 62 result = install_lib.install_lib.get_exclusions(self) 63 for fn in install_lib._install_lib.get_outputs(self): 64 if 'PyObjCTest' in fn: 65 result[fn] = 1 66 67 return result 68 69class pyobjc_build_ext (build_ext.build_ext): 70 def run(self): 71 build_ext.build_ext.run(self) 72 extensions = self.extensions 73 self.extensions = [ 74 e for e in extensions if e.name.startswith('PyObjCTest') ] 75 self.copy_extensions_to_source() 76 self.extensions = extensions 77 78def frameworks(*args): 79 lst = [] 80 for arg in args: 81 lst.extend(['-framework', arg]) 82 return lst 83 84def IfFrameWork(name, packages, extensions, headername=None): 85 """ 86 Return the packages and extensions if the framework exists, or 87 two empty lists if not. 88 """ 89 import os 90 for pth in ('/System/Library/Frameworks', '/Library/Frameworks'): 91 basedir = os.path.join(pth, name) 92 if os.path.exists(basedir): 93 if (headername is None) or os.path.exists(os.path.join(basedir, "Headers", headername)): 94 return packages, extensions 95 return [], [] 96 97# Double-check 98if sys.platform != 'darwin': 99 print "You're not running on MacOS X, and don't use GNUstep" 100 print "I don't know how to build PyObjC on such a platform." 101 print "Please read the ReadMe." 102 print "" 103 raise SystemExit("ObjC runtime not found") 104 105from distutils.sysconfig import get_config_var 106cc = get_config_var('CC') 107 108CFLAGS=[ ] 109 110if cc == 'XXXgcc': 111 # This is experimental code that tries to avoid refering to files in 112 # /Library/Frameworks or /usr/local. 113 # 114 # NOTE: This is not enabled by default because the linker will still look 115 # in /usr/local/lib and /Library/Frameworks... 116 117 fp = os.popen('cpp -v </dev/null 2>&1', 'r') 118 dirs = [] 119 started = False 120 for ln in fp: 121 if not started: 122 if ln.startswith('#include <...> search starts here:'): 123 started=True 124 continue 125 126 else: 127 ln = ln.strip() 128 if not ln.startswith('/'): 129 break 130 131 if ln == '/usr/local/include': 132 continue 133 134 elif ln == '/Library/Frameworks': 135 continue 136 137 if ln.endswith('(framework directory)'): 138 dirs.append(('framework', ln.split()[0])) 139 else: 140 dirs.append(('system', ln)) 141 142 if dirs: 143 CFLAGS.append('-nostdinc') 144 for k, d in dirs: 145 CFLAGS.append('-i%s%s'%(k,d)) 146 147# Enable 'PyObjC_STRICT_DEBUGGING' to enable some costly internal 148# assertions. 149CFLAGS.extend([ 150 151# The following flags are an attempt at getting rid of /usr/local 152# in the compiler search path. 153 "-DPyObjC_STRICT_DEBUGGING", 154 "-DMACOSX", # For libffi 155 "-DPyObjC_BUILD_RELEASE=%02d%02d"%(tuple(map(int, platform.mac_ver()[0].split('.')[:2]))), 156 #"-Wno-long-double", 157 #"-Wselector", 158 #"-Wstrict-overflow", 159 "-g", 160 #"-fobjc-gc", 161 "-fexceptions", 162 163 ## Arghh, a stupid compiler flag can cause problems. Don't 164 ## enable -O0 if you value your sanity. With -O0 PyObjC will crash 165 ## on i386 systems when a method returns a struct that isn't returned 166 ## in registers. 167 #"-O0", 168 "-O1", 169 #"-O2", 170 #"-O3", 171 #'-arch', 'x86_64', '-arch', 'ppc64', 172 173 # Loads of warning flags 174 "-Wall", "-Wstrict-prototypes", "-Wmissing-prototypes", 175 "-Wformat=2", "-W", "-Wshadow", 176 "-Wpointer-arith", #"-Wwrite-strings", 177 "-Wmissing-declarations", 178 "-Wnested-externs", 179 "-Wno-long-long", 180 #"-Wfloat-equal", 181 182 # These two are fairly useless: 183 #"-Wunreachable-code", 184 #"-pedantic", 185 186 "-Wno-import", 187 #"-Werror", 188 189 # use the same optimization as Python, probably -O3, 190 # but can be overrided by one of the following: 191 192 # no optimization, for debugging 193 #"-O0", 194 195 # g4 optimized 196 #"-fast", "-fPIC", "-mcpu=7450", 197 198 # g5 optimized 199 #"-fast", "-fPIC", 200 ]) 201 202 203OBJC_LDFLAGS = frameworks('CoreFoundation', 'Foundation', 'Carbon') 204 205if not os.path.exists(os.path.join(SDKROOT, 'usr/include/objc/runtime.h')): 206 CFLAGS.append('-DNO_OBJC2_RUNTIME') 207 208else: 209 # Force compilation with the local SDK, compilation of PyObC will result in 210 # a binary that runs on other releases of the OS without using a particular SDK. 211 CFLAGS.extend([]) 212 OBJC_LDFLAGS.extend([]) 213 214 215# We're using xml2, check for the flags to use: 216def xml2config(arg): 217 import os, shlex 218 ln = os.popen('xml2-config %s'%(arg,), 'r').readline() 219 ln = ln.strip() 220 221 return shlex.split(ln) 222 223CFLAGS.extend(xml2config('--cflags')) 224OBJC_LDFLAGS.extend(xml2config('--libs')) 225 226 227 228CFLAGS.append('-Ibuild/codegen/') 229 230# Patch distutils: it needs to compile .S files as well. 231from distutils.unixccompiler import UnixCCompiler 232UnixCCompiler.src_extensions.append('.S') 233del UnixCCompiler 234 235 236# 237# Support for an embedded copy of libffi 238# 239FFI_CFLAGS=['-Ilibffi-src/include', '-Ilibffi-src/powerpc'] 240 241# The list below includes the source files for all CPU types that we run on 242# this makes it easier to build fat binaries on Mac OS X. 243FFI_SOURCE=[ 244 "libffi-src/ffi.c", 245 "libffi-src/types.c", 246 "libffi-src/powerpc/ppc-darwin.S", 247 "libffi-src/powerpc/ppc-darwin_closure.S", 248 "libffi-src/powerpc/ppc-ffi_darwin.c", 249 "libffi-src/powerpc/ppc64-darwin_closure.S", 250 "libffi-src/x86/darwin64.S", 251 "libffi-src/x86/x86-darwin.S", 252 "libffi-src/x86/x86-ffi64.c", 253 "libffi-src/x86/x86-ffi_darwin.c", 254] 255 256 257 258# 259# Calculate the list of extensions: objc._objc + extensions for the unittests 260# 261 262if USE_SYSTEM_FFI: 263 ExtensionList = [ 264 Extension("objc._objc", 265 list(glob.glob(os.path.join('Modules', 'objc', '*.m'))), 266 extra_compile_args=CFLAGS + ['-I' + os.path.join(SDKROOT, "usr/include/ffi")], 267 extra_link_args=OBJC_LDFLAGS + ["-lffi"], 268 ) 269 ] 270 271else: 272 ExtensionList = [ 273 Extension("objc._objc", 274 FFI_SOURCE + list(glob.glob(os.path.join('Modules', 'objc', '*.m'))), 275 extra_compile_args=CFLAGS + FFI_CFLAGS, 276 extra_link_args=OBJC_LDFLAGS, 277 ) 278 ] 279 280for test_source in glob.glob(os.path.join('Modules', 'objc', 'test', '*.m')): 281 name, ext = os.path.splitext(os.path.basename(test_source)) 282 283 ExtensionList.append(Extension('PyObjCTest.' + name, 284 [test_source], 285 extra_compile_args=['-IModules/objc'] + CFLAGS, 286 extra_link_args=OBJC_LDFLAGS)) 287 288def package_version(): 289 fp = open('Modules/objc/pyobjc.h', 'r') 290 for ln in fp.readlines(): 291 if ln.startswith('#define OBJC_VERSION'): 292 fp.close() 293 return ln.split()[-1][1:-1] 294 295 raise ValueError, "Version not found" 296 297CLASSIFIERS = filter(None, 298""" 299Development Status :: 5 - Production/Stable 300Environment :: Console 301Environment :: MacOS X :: Cocoa 302Intended Audience :: Developers 303License :: OSI Approved :: MIT License 304Natural Language :: English 305Operating System :: MacOS :: MacOS X 306Programming Language :: Python 307Programming Language :: Objective C 308Topic :: Software Development :: Libraries :: Python Modules 309Topic :: Software Development :: User Interfaces 310""".splitlines()) 311 312dist = setup( 313 name = "pyobjc-core", 314 version = package_version(), 315 description = "Python<->ObjC Interoperability Module", 316 long_description = LONG_DESCRIPTION, 317 author = "Ronald Oussoren, bbum, SteveM, LeleG, many others stretching back through the reaches of time...", 318 author_email = "pyobjc-dev@lists.sourceforge.net", 319 url = "http://pyobjc.sourceforge.net/", 320 platforms = [ 'MacOS X' ], 321 ext_modules = ExtensionList, 322 packages = [ 'objc', 'PyObjCTools' ], 323 #namespace_packages = ['PyObjCTools'], 324 package_dir = { '': 'Lib', 'PyObjCTest': 'PyObjCTest' }, 325 extra_path = "PyObjC", 326 cmdclass = {'build_ext': pyobjc_build_ext, 'install_lib': pyobjc_install_lib }, 327 options = {'egg_info': {'egg_base': 'Lib'}}, 328 classifiers = CLASSIFIERS, 329 license = 'MIT License', 330 download_url = 'http://pyobjc.sourceforge.net/software/index.php', 331 test_suite='PyObjCTest.loader.makeTestSuite', 332 zip_safe = False, 333) 334