diff --git a/setup.py b/setup.py index 0058f0d73..797130fc1 100644 --- a/setup.py +++ b/setup.py @@ -1,59 +1,16 @@ +# +# Kivy - Crossplatform NUI toolkit +# http://kivy.org/ +# + import sys -from fnmatch import filter as fnfilter -from os.path import join, dirname, realpath, sep, exists +from copy import deepcopy +from os.path import join, dirname, sep, exists from os import walk, environ from distutils.core import setup from distutils.extension import Extension -platform = sys.platform - -# -# Detect Python for android project -# FIXME: add a specific var for this project, not just guess -# -ndkplatform = environ.get('NDKPLATFORM') -if ndkplatform is not None and environ.get('LIBLINK'): - platform = 'android' -if environ.get('KIVYIOSROOT'): - platform = 'ios' - -try: - # check for cython - from Cython.Distutils import build_ext - have_cython = True -except ImportError: - if platform not in ('android', 'ios'): - print '\nCython is missing, its required for compiling kivy !\n\n' - raise - # on python-for-android, cython usage is external - have_cython = False - from distutils.command.build_ext import build_ext - -# extract version (simulate doc generation, kivy will be not imported) -environ['KIVY_DOC_INCLUDE'] = '1' -import kivy - -# extra build commands go in the cmdclass dict {'command-name': CommandClass} -# see tools.packaging.{platform}.build.py for custom build commands for -# portable packages. also e.g. we use build_ext command from cython if its -# installed for c extensions. -cmdclass = {} - -try: - # add build rules for portable packages to cmdclass - if platform == 'win32': - from kivy.tools.packaging.win32.build import WindowsPortableBuild - cmdclass['build_portable'] = WindowsPortableBuild - elif platform == 'darwin': - from kivy.tools.packaging.osx.build import OSXPortableBuild - cmdclass['build_portable'] = OSXPortableBuild -except ImportError: - print 'User distribution detected, avoid portable command.' - -from kivy.tools.packaging.factory import FactoryBuild -cmdclass['build_factory'] = FactoryBuild - -# +# ----------------------------------------------------------------------------- # Detect options # c_options = { @@ -72,37 +29,35 @@ for key in c_options.keys(): print 'Environ change %s -> %s' % (key, value) c_options[key] = value -# check if we are in a kivy-ios build +# ----------------------------------------------------------------------------- +# Determine on which platform we are + +platform = sys.platform + +# Detect Python for android project (http://github.com/kivy/python-for-android) +ndkplatform = environ.get('NDKPLATFORM') +if ndkplatform is not None and environ.get('LIBLINK'): + platform = 'android' kivy_ios_root = environ.get('KIVYIOSROOT', None) if kivy_ios_root is not None: - print 'Kivy-IOS project environment detect, use it.' - print 'Kivy-IOS project located at %r' % kivy_ios_root - print 'Activate SDL compilation.' - c_options['use_ios'] = True - c_options['use_sdl'] = True - -# Detect which opengl version headers to use -if platform in ('android', 'darwin', 'ios'): - pass -elif platform == 'win32': - print 'Windows platform detected, force GLEW usage.' - c_options['use_glew'] = True -else: - # searching GLES headers - default_header_dirs = ['/usr/include', '/usr/local/include'] - found = False - for hdir in default_header_dirs: - filename = join(hdir, 'GLES2', 'gl2.h') - if exists(filename): - found = True - print 'Found GLES 2.0 headers at', filename - break - if not found: - print 'WARNING: GLES 2.0 headers are not found' - print 'Fallback to Desktop opengl headers.' - c_options['use_opengl_es2'] = False + platform = 'ios' +# ----------------------------------------------------------------------------- +# Cython check +try: + # check for cython + from Cython.Distutils import build_ext + have_cython = True +except ImportError: + if platform not in ('android', 'ios'): + print '\nCython is missing, its required for compiling kivy !\n\n' + raise + # on python-for-android, cython usage is external + have_cython = False + from distutils.command.build_ext import build_ext +# ----------------------------------------------------------------------------- +# Setup classes class KivyBuildExt(build_ext): def build_extensions(self): @@ -125,185 +80,282 @@ class KivyBuildExt(build_ext): build_ext.build_extensions(self) -cmdclass['build_ext'] = KivyBuildExt -# extension modules -ext_modules = [] +# ----------------------------------------------------------------------------- +# extract version (simulate doc generation, kivy will be not imported) +environ['KIVY_DOC_INCLUDE'] = '1' +import kivy -# list all files to compile -pyx_files = [] -pxd_files = [] -kivy_libs_dir = realpath(join(kivy.kivy_base_dir, 'libs')) -for root, dirnames, filenames in walk(join(dirname(__file__), 'kivy')): - # ignore lib directory - if realpath(root).startswith(kivy_libs_dir): - continue - for filename in fnfilter(filenames, '*.pxd'): - pxd_files.append(join(root, filename)) - for filename in fnfilter(filenames, '*.pyx'): - pyx_files.append(join(root, filename)) +# extra build commands go in the cmdclass dict {'command-name': CommandClass} +# see tools.packaging.{platform}.build.py for custom build commands for +# portable packages. also e.g. we use build_ext command from cython if its +# installed for c extensions. +from kivy.tools.packaging.factory import FactoryBuild +cmdclass = { + 'build_factory': FactoryBuild, + 'build_ext': KivyBuildExt } -if not have_cython: - pyx_files = pyx_files = ['%s.c' % x[:-4] for x in pyx_files] - pxd_files = [] - -# add cython core extension modules if cython is available - -if True: - libraries = ['m'] - include_dirs = [] - extra_link_args = [] +try: + # add build rules for portable packages to cmdclass if platform == 'win32': - libraries.append('opengl32') + from kivy.tools.packaging.win32.build import WindowsPortableBuild + cmdclass['build_portable'] = WindowsPortableBuild elif platform == 'darwin': - # On OSX, it's not -lGL, but -framework OpenGL... - extra_link_args = ['-framework', 'OpenGLES'] - elif platform.startswith('freebsd'): - include_dirs += ['/usr/local/include'] - extra_link_args += ['-L', '/usr/local/lib'] - elif platform == 'android': - include_dirs += [join(ndkplatform, 'usr', 'include')] - extra_link_args += ['-L', join(ndkplatform, 'usr', 'lib')] - libraries.append('GLESv2') - else: - libraries.append('GLESv2') + from kivy.tools.packaging.osx.build import OSXPortableBuild + cmdclass['build_portable'] = OSXPortableBuild +except ImportError: + print 'User distribution detected, avoid portable command.' +# Detect which opengl version headers to use +if platform in ('android', 'darwin', 'ios'): + pass +elif platform == 'win32': + print 'Windows platform detected, force GLEW usage.' + c_options['use_glew'] = True +else: + # searching GLES headers + default_header_dirs = ['/usr/include', '/usr/local/include'] + found = False + for hdir in default_header_dirs: + filename = join(hdir, 'GLES2', 'gl2.h') + if exists(filename): + found = True + print 'Found GLES 2.0 headers at', filename + break + if not found: + print 'WARNING: GLES 2.0 headers are not found' + print 'Fallback to Desktop opengl headers.' + c_options['use_opengl_es2'] = False + +# check if we are in a kivy-ios build +if platform == 'ios': + print 'Kivy-IOS project environment detect, use it.' + print 'Kivy-IOS project located at %r' % kivy_ios_root + print 'Activate SDL compilation.' + c_options['use_ios'] = True + c_options['use_sdl'] = True + +# ----------------------------------------------------------------------------- +# declare flags +def get_modulename_from_file(filename): + pyx = '.'.join(filename.split('.')[:-1]) + pyxl = pyx.split(sep) + while pyxl[0] != 'kivy': + pyxl.pop(0) + if pyxl[1] == 'kivy': + pyxl.pop(0) + return '.'.join(pyxl) + +class CythonExtension(Extension): + + def __init__(self, *args, **kwargs): + Extension.__init__(self, *args, **kwargs) + self.pyrex_directives = { + 'profile': 'USE_PROFILE' in environ, + 'embedsignature': True} + # XXX with pip, setuptools is imported before distutils, and change + # our pyx to c, then, cythonize doesn't happen. So force again our + # sources + self.sources = args[1] + +def merge(d1, *args): + d1 = deepcopy(d1) + for d2 in args: + for key, value in d2.iteritems(): + if key in d1: + d1[key].extend(value) + else: + d1[key] = value + return d1 + +def determine_base_flags(): + flags = { + 'libraries': ['m'], + 'include_dirs': [], + 'extra_link_args': [], + 'extra_compile_args': []} + if c_options['use_ios']: + sysroot = '/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk' + flags['include_dirs'] += [sysroot] + flags['extra_compile_args'] += ['-isysroot', sysroot] + flags['extra_link_args'] += ['-isysroot', sysroot] + elif platform == 'darwin': + sysroot = '/System/Library/Frameworks/ApplicationServices.framework/Frameworks' + flags['extra_compile_args'] += ['-F%s' % sysroot] + flags['extra_link_args'] += ['-F%s' % sysroot] + return flags + +def determine_gl_flags(): + flags = {'libraries': []} + if platform == 'win32': + flags['libraries'] = ['opengl32'] + elif platform == 'ios': + flags['libraries'] = ['GLESv2'] + flags['extra_link_args'] = ['-framework', 'OpenGLES'] + elif platform == 'darwin': + flags['extra_link_args'] = ['-framework', 'OpenGL', '-arch', 'x86_64'] + flags['extra_compile_args'] = ['-arch', 'x86_64'] + elif platform.startswith('freebsd'): + flags['include_dirs'] = ['/usr/local/include'] + flags['extra_link_args'] = ['-L', '/usr/local/lib'] + elif platform == 'android': + flags['include_dirs'] += [join(ndkplatform, 'usr', 'include')] + flags['extra_link_args'] += ['-L', join(ndkplatform, 'usr', 'lib')] + flags['libraries'] = ['GLESv2'] + else: + flags['libraries'] = ['GL'] if c_options['use_glew']: if platform == 'win32': - libraries.append('glew32') + flags['libraries'] += ['glew32'] else: - libraries.append('GLEW') + flags['libraries'] += ['GLEW'] + return flags - def get_modulename_from_file(filename): - pyx = '.'.join(filename.split('.')[:-1]) - pyxl = pyx.split(sep) - while pyxl[0] != 'kivy': - pyxl.pop(0) - if pyxl[1] == 'kivy': - pyxl.pop(0) - return '.'.join(pyxl) +def determine_sdl(): + flags = {} + if not c_options['use_sdl']: + return flags - if c_options['use_sdl']: - sdl_libraries = ['SDL', 'SDL_ttf', 'freetype', 'z', 'bz2', 'm'] - sdl_includes = [] - sdl_extra_link_args = [] - sdl_extra_compile_args = [] - if platform in ('ios', 'darwin'): - # Paths as per homebrew (modified formula to use hg checkout) - if c_options['use_ios']: - # Note: on IOS, SDL is already loaded by the launcher/main.m - # So if we add it here, it will just complain about duplicate - # symbol, cause libSDL.a would be included in main.m binary + - # text_sdlttf.so - # At the result, we are linking without SDL explicitly, and add - # -undefined dynamic_lookup - # (/tito) - sdl_libraries = ['SDL_ttf', 'freetype', 'bz2'] - sdl_includes += [join(kivy_ios_root, 'build', 'include')] - sdl_includes += [join(kivy_ios_root, 'build', 'include', 'SDL')] - sdl_includes += [join(kivy_ios_root, 'build', 'include', 'freetype')] - sdl_extra_link_args += ['-L', join(kivy_ios_root, 'build', 'lib')] - sdl_extra_link_args += ['-undefined', 'dynamic_lookup'] - sdl_extra_link_args += ['-framework', 'Foundation'] - sdl_extra_link_args += ['-framework', 'UIKit'] - sdl_extra_link_args += ['-framework', 'AudioToolbox'] - sdl_extra_link_args += ['-framework', 'CoreGraphics'] - sdl_extra_link_args += ['-framework', 'QuartzCore'] - sdl_extra_link_args += ['-framework', 'ImageIO'] - else: - sdl_includes = ['/usr/local/include/SDL'] - sdl_extra_link_args += ['-L/usr/local/lib/'] + flags['libraries'] = ['SDL', 'SDL_ttf', 'freetype', 'z', 'bz2'] + flags['includes ']= [] + flags['extra_link_args'] = [] + flags['extra_compile_args'] = [] - class CythonExtension(Extension): + # Paths as per homebrew (modified formula to use hg checkout) + if c_options['use_ios']: + # Note: on IOS, SDL is already loaded by the launcher/main.m + # So if we add it here, it will just complain about duplicate + # symbol, cause libSDL.a would be included in main.m binary + + # text_sdlttf.so + # At the result, we are linking without SDL explicitly, and add + # -undefined dynamic_lookup + # (/tito) + flags['libraries'] = ['SDL_ttf', 'freetype', 'bz2'] + flags['includes'] += [ + join(kivy_ios_root, 'build', 'include'), + join(kivy_ios_root, 'build', 'include', 'SDL'), + join(kivy_ios_root, 'build', 'include', 'freetype')] + flags['extra_link_args'] += [ + '-L', join(kivy_ios_root, 'build', 'lib'), + '-undefined', 'dynamic_lookup'] + else: + flags['includes'] = ['/usr/local/include/SDL'] + flags['extra_link_args'] += ['-L/usr/local/lib/'] - def __init__(self, *args, **kwargs): - # Small hack to only compile for x86_64 on OSX. - # Is there a better way to do this? - if platform == 'darwin': - extra_args = ['-arch', 'x86_64'] - kwargs['extra_compile_args'] = extra_args + \ - kwargs.get('extra_compile_args', []) - kwargs['extra_link_args'] = extra_args + \ - kwargs.get('extra_link_args', []) - Extension.__init__(self, *args, **kwargs) - self.pyrex_directives = { - 'profile': 'USE_PROFILE' in environ, - 'embedsignature': True} - # XXX with pip, setuptools is imported before distutils, and change - # our pyx to c, then, cythonize doesn't happen. So force again our - # sources - self.sources = args[1] + if platform == 'ios': + flags['extra_link_args'] += [ + '-framework', 'Foundation', + '-framework', 'UIKit', + '-framework', 'AudioToolbox', + '-framework', 'CoreGraphics', + '-framework', 'QuartzCore', + '-framework', 'ImageIO'] + elif platform == 'darwin': + flags['extra_link_args'] += [ + '-framework', 'ApplicationServices'] + return flags - # simple extensions - #for pyx in (x for x in pyx_files if not 'graphics' in x): - # pxd = [x for x in pxd_files if not 'graphics' in x] - # module_name = get_modulename_from_file(pyx) - # ext_modules.append(CythonExtension(module_name, [pyx] + pxd)) +def determine_graphics_pxd(): + flags = {'depends': [join(dirname(__file__), 'kivy', x) for x in [ + 'graphics/buffer.pxd', + 'graphics/c_opengl.pxd', + 'graphics/c_opengl_debug.pxd', + 'graphics/compiler.pxd', + 'graphics/context_instructions.pxd', + 'graphics/fbo.pxd', + 'graphics/instructions.pxd', + 'graphics/opengl_utils.pxd', + 'graphics/shader.pxd', + 'graphics/texture.pxd', + 'graphics/transformation.pxd', + 'graphics/vbo.pxd', + 'graphics/vertex.pxd']]} + return flags - for pyx in pyx_files: +base_flags = determine_base_flags() +gl_flags = determine_gl_flags() +graphics_flags = determine_graphics_pxd() + +# ----------------------------------------------------------------------------- +# sources to compile +sources = { + '_event.pyx': base_flags, + 'properties.pyx': base_flags, + 'graphics/buffer.pyx': base_flags, + 'graphics/c_opengl_debug.pyx': merge(base_flags, gl_flags, graphics_flags), + 'graphics/compiler.pyx': merge(base_flags, gl_flags, graphics_flags), + 'graphics/context_instructions.pyx': merge(base_flags, gl_flags, graphics_flags), + 'graphics/fbo.pyx': merge(base_flags, gl_flags, graphics_flags), + 'graphics/instructions.pyx': merge(base_flags, gl_flags, graphics_flags), + 'graphics/opengl.pyx': merge(base_flags, gl_flags, graphics_flags), + 'graphics/opengl_utils.pyx': merge(base_flags, gl_flags, graphics_flags), + 'graphics/shader.pyx': merge(base_flags, gl_flags, graphics_flags), + 'graphics/stencil_instructions.pyx': merge(base_flags, gl_flags, graphics_flags), + 'graphics/texture.pyx': merge(base_flags, gl_flags, graphics_flags), + 'graphics/transformation.pyx': merge(base_flags, gl_flags, graphics_flags), + 'graphics/vbo.pyx': merge(base_flags, gl_flags, graphics_flags), + 'graphics/vertex.pyx': merge(base_flags, gl_flags, graphics_flags), + 'graphics/vertex_instructions.pyx': merge(base_flags, gl_flags, graphics_flags), +} + +if c_options['use_sdl']: + sdl_flags = determine_sdl() + sources['core/window/sdl.pyx'] = merge( + base_flags, gl_flags, sdl_flags) + sources['core/text/text_sdlttf.pyx'] = merge( + base_flags, gl_flags, sdl_flags) + +if platform in ('darwin', 'ios'): + # activate ImageIO provider for our core image + if platform == 'ios': + osx_flags = {'extra_link_args': [ + '-framework', 'Foundation', + '-framework', 'UIKit', + '-framework', 'AudioToolbox', + '-framework', 'CoreGraphics', + '-framework', 'QuartzCore', + '-framework', 'ImageIO']} + else: + osx_flags = {'extra_link_args': [ + '-framework', 'ApplicationServices']} + sources['core/image/img_imageio.pyx'] = merge( + base_flags, osx_flags) + + +# ----------------------------------------------------------------------------- +# extension modules +def get_extensions_from_sources(sources): + ext_modules = [] + for pyx, flags in sources.iteritems(): + pyx = join(dirname(__file__), 'kivy', pyx) + if not have_cython: + pyx = '%s.c' % pyx[:-4] module_name = get_modulename_from_file(pyx) - ext_files = [pyx] - ext_libraries = libraries[:] - ext_include_dirs = include_dirs[:] - ext_extra_link_args = extra_link_args[:] - ext_extra_compile_args = [] + depends = flags.pop('depends', []) + ext_modules.append(CythonExtension(module_name, + [pyx] + depends, **flags)) + return ext_modules - if c_options['use_ios']: - isysroot = ['-isysroot', '/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk'] - ext_include_dirs += ['/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk/usr/include/'] - ext_extra_compile_args += isysroot - ext_extra_link_args += isysroot +ext_modules = get_extensions_from_sources(sources) - if pyx.endswith('sdl.pyx') or pyx.endswith('sdl.c') \ - or pyx.endswith('text_sdlttf.pyx') \ - or pyx.endswith('text_sdlttf.c'): - if c_options['use_sdl'] is False: - continue - ext_libraries += sdl_libraries - ext_include_dirs += sdl_includes - ext_extra_link_args += sdl_extra_link_args - ext_extra_compile_args += sdl_extra_compile_args - - - elif pyx.endswith('osxcoreimage.pyx') or pyx.endswith('osxcoreimage.c'): - if c_options['use_ios'] is False: - continue - ext_extra_link_args += ['-framework', 'Foundation'] - ext_extra_link_args += ['-framework', 'UIKit'] - ext_extra_link_args += ['-framework', 'AudioToolbox'] - ext_extra_link_args += ['-framework', 'CoreGraphics'] - ext_extra_link_args += ['-framework', 'QuartzCore'] - ext_extra_link_args += ['-framework', 'ImageIO'] - - ext_modules.append(CythonExtension( - module_name, ext_files, - libraries=ext_libraries, - extra_compile_args=ext_extra_compile_args, - include_dirs=ext_include_dirs, - extra_link_args=ext_extra_link_args)) - - -#setup datafiles to be included in the disytibution, liek examples... -#extracts all examples files except sandbox +# ----------------------------------------------------------------------------- +# automatically detect data files data_file_prefix = 'share/kivy-' examples = {} examples_allowed_ext = ('readme', 'py', 'wav', 'png', 'jpg', 'svg', 'json', 'avi', 'gif', 'txt', 'ttf', 'obj', 'mtl', 'kv') for root, subFolders, files in walk('examples'): - if 'sandbox' in root: - continue - for file in files: - ext = file.split('.')[-1].lower() + for fn in files: + ext = fn.split('.')[-1].lower() if ext not in examples_allowed_ext: continue - filename = join(root, file) + filename = join(root, fn) directory = '%s%s' % (data_file_prefix, dirname(filename)) if not directory in examples: examples[directory] = [] examples[directory].append(filename) - - +# ----------------------------------------------------------------------------- # setup ! setup( name='Kivy', @@ -339,8 +391,7 @@ setup( 'kivy.network', 'kivy.tools', 'kivy.tools.packaging', - 'kivy.uix', - ], + 'kivy.uix', ], package_dir={'kivy': 'kivy'}, package_data={'kivy': [ 'data/*.kv',