#! /usr/bin/env python # encoding: utf-8 import platform import sys from distutils import sysconfig as _sysconfig import Utils import Options # the following two variables are used by the target "waf dist" VERSION='' APPNAME='' # these variables are mandatory ('/' are converted automatically) top = '.' out = 'build' # TODO extensive testing with different configuration (should work with Python >= 2.3) def set_options(opt): myplatform = Utils.detect_platform() if myplatform.startswith('linux'): opt.add_option('--no-lsb', action = 'store_true', help = 'Prevent building LSB (Linux Standard Base) bootloader.', default = False, dest = 'nolsb') opt.add_option('--lsbcc-path', action = 'store', help = 'Path to lsbcc. By default PATH is searched for lsbcc otherwise is tried file /opt/lsb/bin/lsbcc. [Default: lsbcc]', default = 'lsbcc', dest = 'lsbcc_path') opt.add_option('--lsb-target-version', action = 'store', help = 'Specify LSB target version [Default: 4.0]', default = '4.0', dest = 'lsb_version') opt.tool_options('compiler_cc') opt.tool_options('python') def configure(conf): def achitecture(): return '32bit' conf.env.NAME = 'default' opt = Options.options myplatform = Utils.detect_platform() # on 64bit Mac function platform.architecture() returns 64bit even # for 32bit Python. This is the workaround for this. if myplatform == 'darwin' and sys.maxint <= 3**32: myarch = '32bit' else: myarch = platform.architecture()[0] # 32bit or 64bit conf.env.MYARCH = myarch Utils.pprint('CYAN', '%s-%s detected' % (platform.system(), myarch)) if myplatform == 'darwin' and myarch == '64bit': Utils.pprint('CYAN', 'WARNING: Building bootloader for Python 64-bit on Mac OSX') Utils.pprint('CYAN', 'For 32b-bit bootloader prepend the python command with:') Utils.pprint('CYAN', 'VERSIONER_PYTHON_PREFER_32_BIT=yes arch -i386 python') if myplatform.startswith('linux') and not opt.nolsb: Utils.pprint('CYAN', 'Building LSB bootloader.') ### C compiler if myplatform.startswith('win'): try: # mingw (gcc for Windows) conf.check_tool('gcc') except: try: # Newest detected MSVC version is used by default. # msvc 7.1 (Visual Studio 2003) # msvc 8.0 (Visual Studio 2005) # msvc 9.0 (Visual Studio 2008) #conf.env['MSVC_VERSIONS'] = ['msvc 7.1', 'msvc 8.0', 'msvc 9.0'] if myarch == '32bit': conf.env['MSVC_TARGETS'] = ['x86', 'ia32'] elif myarch == '64bit': conf.env['MSVC_TARGETS'] = ['x64', 'x86_amd64', 'intel64', 'em64t'] conf.check_tool('msvc') conf.print_all_msvc_detected() # Do not embed manifest file. # Manifest file will be added in the phase of packaging python application. conf.env.MSVC_MANIFEST = False # Path to Python development file pythonXY.lib is not detected correctly # by waf 1.5 on Windows in virtualenv. if _sysconfig.get_config_var('LIBDIR'): conf.env.append_value('LINKFLAGS', '/LIBPATH:' + _sysconfig.get_config_var('LIBDIR')) except: Utils.pprint('RED', 'GCC (MinGW) or MSVC compiler not found.') exit(1) else: # When using GCC, deactivate declarations after statements # (not supported by Visual Studio) conf.env.append_value('CCFLAGS', '-Wdeclaration-after-statement') conf.env.append_value('CCFLAGS', '-Werror') else: conf.check_tool('compiler_cc') conf.check_tool('python') conf.check_python_headers() # Do not link with libpython and libpthread. for lib in conf.env.LIB_PYEMBED: if lib.startswith('python') or lib.startswith('pthread'): conf.env.LIB_PYEMBED.remove(lib) ### build LSB (Linux Standard Base) boot loader if myplatform.startswith('linux') and not opt.nolsb: try: # custom lsbcc path if opt.lsbcc_path != 'lsbcc': conf.env.LSBCC = conf.find_program(opt.lsbcc_path, mandatory=True) # default values else: conf.env.LSBCC = conf.find_program(opt.lsbcc_path) if not conf.env.LSBCC: conf.env.LSBCC = conf.find_program('/opt/lsb/bin/lsbcc', mandatory=True) except: Utils.pprint('RED', 'LSB (Linux Standard Base) tools >= 4.0 are required.') Utils.pprint('RED', 'Try --no-lsb option if not interested in building LSB binary.') exit(2) # lsbcc as CC compiler conf.env.append_value('CCFLAGS', '--lsb-cc=%s' % conf.env.CC[0]) conf.env.append_value('LINKFLAGS', '--lsb-cc=%s' % conf.env.CC[0]) conf.env.CC = conf.env.LSBCC conf.env.LINK_CC = conf.env.LSBCC ## check LSBCC flags # --lsb-besteffort - binary will work on platforms without LSB stuff # --lsb-besteffort - available in LSB build tools >= 4.0 conf.check_cc(ccflags='--lsb-besteffort', msg='Checking for LSB build tools >= 4.0', errmsg='LSB >= 4.0 is required', mandatory=True) conf.env.append_value('CCFLAGS', '--lsb-besteffort') conf.env.append_value('LINKFLAGS', '--lsb-besteffort') # binary compatibility with a specific LSB version # LSB 4.0 can generate binaries compatible with 3.0, 3.1, 3.2, 4.0 # however because of using function 'mkdtemp', loader requires # using target version 4.0 lsb_target_flag = '--lsb-target-version=%s' % opt.lsb_version conf.env.append_value('CCFLAGS', lsb_target_flag) conf.env.append_value('LINKFLAGS', lsb_target_flag) ### Defines, Includes if myplatform.startswith('lin'): # make sure we don't use declarations after statement (break Visual Studio) conf.env.append_value('CCFLAGS', '-Wdeclaration-after-statement') conf.env.append_value('CCFLAGS', '-Werror') if myplatform.startswith('win'): conf.env.append_value('CCDEFINES', 'WIN32') conf.env.append_value('CPPPATH', '../zlib') if myplatform.startswith('sun'): conf.env.append_value('CCDEFINES', 'SUNOS') if myplatform.startswith('aix'): conf.env.append_value('CCDEFINES', 'AIX') conf.env.append_value('CPPPATH', '../common') ### Libraries if myplatform.startswith('win'): conf.check_cc(lib='user32', mandatory=True) conf.check_cc(lib='comctl32', mandatory=True) conf.check_cc(lib='kernel32', mandatory=True) conf.check_cc(lib='ws2_32', mandatory=True) else: conf.check_cc(lib='z', mandatory=True) if conf.check_cc(function_name='readlink', header_name='unistd.h'): conf.env.append_value('CCFLAGS', '-DHAVE_READLINK') ### ccflags if myplatform.startswith('win') and conf.env.CC_NAME == 'gcc': # Disables console - MinGW option conf.check_cc(ccflags='-mwindows', mandatory=True, msg='Checking for flags -mwindows') # Use Visual C++ compatible alignment conf.check_cc(ccflags='-mms-bitfields', mandatory=True, msg='Checking for flags -mms-bitfields') conf.env.append_value('CCFLAGS', '-mms-bitfields') elif myplatform.startswith('win') and conf.env.CC_NAME == 'msvc': if myarch == '32bit': conf.env.append_value('LINKFLAGS', '/MACHINE:X86') elif myarch == '64bit': conf.env.append_value('LINKFLAGS', '/MACHINE:X64') # enable 64bit porting warnings conf.env.append_value('CCFLAGS', '/Wp64') # We use SEH exceptions in winmain.c; make sure they are activated. conf.env.append_value('CCFLAGS', '/EHa') # Compile with 64bit gcc 32bit binaries or vice versa. if conf.env.CC_NAME == 'gcc': if myarch == '32bit' and conf.check_cc(ccflags='-m32', msg='Checking for flags -m32'): conf.env.append_value('CCFLAGS', '-m32') elif myarch == '64bit': conf.env.append_value('CCFLAGS', '-m64') # Ensure proper architecture flags on Mac OS X. # TODO Add support for universal binaries. if myplatform.startswith('darwin'): available_archs = {'32bit': 'i386', '64bit': 'x86_64'} mac_arch = available_archs[myarch] conf.env.append_value('CCFLAGS', '-arch') conf.env.append_value('CCFLAGS', mac_arch) conf.env.append_value('CXXFLAGS', '-arch') conf.env.append_value('CXXFLAGS', mac_arch) conf.env.append_value('LINKFLAGS', '-arch') conf.env.append_value('LINKFLAGS', mac_arch) # On linux link only with needed libraries. # -Wl,--as-needed is on some platforms detected during configure but # fails during build. (Mac OS X, Solaris, AIX) if myplatform.startswith('linux') and conf.check_cc(ccflags='-Wl,--as-needed', msg='Checking for flags -Wl,--as-needed'): conf.env.append_value('LINKFLAGS', '-Wl,--as-needed') ### Other stuff if myplatform.startswith('darwin'): conf.env.MACOSX_DEPLOYMENT_TARGET = '10.4' if myplatform.startswith('win'): # RC file - icon conf.check_tool('winres') ### DEBUG and RELEASE environments rel = conf.env.copy() dbg = conf.env.copy() rel.set_variant('release') # separate subfolder for building dbg.set_variant('debug') # separate subfolder for building rel.detach() # detach environment from default dbg.detach() ## setup DEBUG environment dbg.set_variant('debug') # separate subfolder for building conf.set_env_name('debug', dbg) conf.setenv('debug') conf.env.append_value('CCDEFINES', '_DEBUG LAUNCH_DEBUG'.split()) conf.env.append_value('CCFLAGS', conf.env.CCFLAGS_DEBUG) dbgw = conf.env.copy() # WINDOWED DEBUG environment dbgw.set_variant('debugw') # separate subfolder for building dbgw.detach() ## setup windowed DEBUG environment conf.set_env_name('debugw', dbgw) conf.setenv('debugw') conf.env.append_value('CCDEFINES', 'WINDOWED') # disables console - mingw option if myplatform.startswith('win') and conf.env.CC_NAME == 'gcc': conf.env.append_value('LINKFLAGS', '-mwindows') elif myplatform.startswith('darwin'): conf.env.append_value('CCFLAGS', '-I/Developer/Headers/FlatCarbon') conf.env.append_value('LINKFLAGS', '-framework') conf.env.append_value('LINKFLAGS', 'Carbon') ## setup RELEASE environment conf.set_env_name('release', rel) conf.setenv('release') conf.env.append_value('CCDEFINES', 'NDEBUG') conf.env.append_value('CCFLAGS', conf.env.CCFLAGS_RELEASE) relw = conf.env.copy() # WINDOWED RELEASE environment relw.set_variant('releasew') # separate subfolder for building relw.detach() ## setup windowed RELEASE environment conf.set_env_name('releasew', relw) conf.setenv('releasew') conf.env.append_value('CCDEFINES', 'WINDOWED') # disables console if myplatform.startswith('win') and conf.env.CC_NAME == 'gcc': conf.env.append_value('LINKFLAGS', '-mwindows') elif myplatform.startswith('darwin'): conf.env.append_value('LINKFLAGS', '-framework') conf.env.append_value('LINKFLAGS', 'ApplicationServices') def build(bld): # Force to run with 1 job (no parallel building). # There are reported build failures on multicore CPUs # with some msvc versions. Options.options.jobs = 1 myplatform = Utils.detect_platform() install_path = '../../support/loader/' + platform.system() + "-" + bld.env.MYARCH targets = dict(release='run', debug='run_d', releasew='runw', debugw='runw_d') if myplatform.startswith('win'): # static lib zlib for key in targets.keys(): bld( features = 'cc cstaticlib', source = bld.path.ant_glob('zlib/*.c'), target = 'staticlib_zlib', env = bld.env_of_name(key), ) # console for key in ('release', 'debug'): bld( features = 'cc cprogram pyembed', source = bld.path.ant_glob('windows/utils.c windows/run.rc common/*.c'), target = targets[key], install_path = install_path, uselib_local = 'staticlib_zlib', uselib = 'USER32 COMCTL32 KERNEL32 WS2_32', env = bld.env_of_name(key).copy(), ) # windowed for key in ('releasew', 'debugw'): bld( features = 'cc cprogram pyembed', source = bld.path.ant_glob('windows/utils.c windows/runw.rc common/*.c'), # uses different RC file (icon) target = targets[key], install_path = install_path, uselib_local = 'staticlib_zlib', uselib = 'USER32 COMCTL32 KERNEL32 WS2_32', env = bld.env_of_name(key).copy(), ) ## inprocsrvr console if bld.env.CC_NAME == 'msvc': linkflags_c = bld.env.CPPFLAGS_CONSOLE linkflags_w = bld.env.CPPFLAGS_WINDOWS else: linkflags_c = '' linkflags_w = '' for key, value in dict(release='inprocsrvr', debug='inprocsrvr_d').items(): bld( features = 'cc cshlib', source = bld.path.ant_glob('common/launch.c windows/dllmain.c'), target = value, install_path = install_path, uselib_local = 'staticlib_zlib', uselib = 'USER32 COMCTL32 KERNEL32 WS2_32', env = bld.env_of_name(key).copy(), linkflags = linkflags_c ) ## inprocsrvr windowed for key, value in dict(releasew='inprocsrvrw', debugw='inprocsrvrw_d').items(): bld( features = 'cc cshlib', source = bld.path.ant_glob('common/launch.c windows/dllmain.c'), target = value, install_path = install_path, uselib_local = 'staticlib_zlib', uselib = 'USER32 COMCTL32 KERNEL32 WS2_32', env = bld.env_of_name(key).copy(), linkflags = linkflags_w ) else: # linux, darwin (MacOSX) for key, value in targets.items(): bld( features = 'cc cprogram pyembed', source = bld.path.ant_glob('linux/*.c common/*.c'), target = value, install_path = install_path, uselib = 'Z', # zlib env = bld.env_of_name(key).copy(), )