#!/usr/bin/env python # Copyright (C) 2017 LiveCode Ltd. # # This file is part of LiveCode. # # LiveCode is free software; you can redistribute it and/or modify it under # the terms of the GNU General Public License v3 as published by the Free # Software Foundation. # # LiveCode is distributed in the hope that it will be useful, but WITHOUT ANY # WARRANTY; without even the implied warranty of MERCHANTABILITY or # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License # for more details. # # You should have received a copy of the GNU General Public License # along with LiveCode. If not see . import sys import platform import re import os import subprocess import shutil # The set of platforms for which this branch supports automated builds BUILDBOT_PLATFORM_TRIPLES = ( 'x86-linux-debian8', 'x86_64-linux-debian8', 'armv7-android-ndk16r15', 'arm64-android-ndk16r15', 'x86-android-ndk16r15', 'x86_64-android-ndk16r15', 'universal-mac-macosx10.9', # Minimum deployment target 'universal-ios-iphoneos14.5', 'universal-ios-iphoneos14.4', 'universal-ios-iphoneos13.2', 'universal-ios-iphoneos12.1', 'universal-ios-iphoneos11.2', 'universal-ios-iphonesimulator14.5', 'universal-ios-iphonesimulator14.4', 'universal-ios-iphonesimulator13.2', 'universal-ios-iphonesimulator12.1', 'universal-ios-iphonesimulator11.2', 'x86-win32', # TODO[2017-03-23] More specific ABI 'x86_64-win32', 'js-emscripten-sdk1.35', ) KNOWN_PLATFORMS = ( 'linux-x86', 'linux-x86_64', 'linux-armv6hf', 'linux-armv7', 'android-armv6', 'android-armv7', 'android-arm64', 'android-x86', 'android-x86_64', 'mac', 'ios', 'win-x86', 'win-x86_64', 'emscripten' ) def usage(exit_status): print( """Use gyp to generate project files when compiling LiveCode. Usage: config.py [--platform PLATFORM] [OPTION...] [GYP_OPTION ...] Options: -p, --platform PLATFORM Choose which platform to build for -h, --help Print this message --sysroot SYSROOT Use the given folder for system headers and libraries (only useful when cross-compiling). --aux-sysroot SYSROOT Like --sysroot but --sysroot's headers and libraries come first. Passed to the compiler as -I/-L options instead of a --sysroot option. --triple TRIPLE Required if --aux-sysroot has a `multilib' setup where some headers and libraries are under a subdirectory named with the target triple. This is often the case for Debian/ Ubuntu derived distributions. --cc-prefix PREFIX Compiler prefix path e.g. ${HOME}/toolchain/bin/arm-linux-gnueabi- --cross Indicates cross-compilation (you probably want to specify --sysroot/--aux-sysroot and --cc-prefix too). --use-lto [EXPERIMENTAL] Use link-time optimisation when building. gyp options: --generator-output DIR Put generated build files under DIR --depth PATH Set DEPTH gyp variable to a relative path to PATH -f, --format FORMATS Output formats to generate -Gmsvs_version=WIN_MSVS_VERSION Version of Microsoft Visual Studio to use -Gandroid_ndk_version=ANDROID_NDK_VERSION Version of Android Native Development Kit to use -DOS=OS Target operating system -Dtarget_arch=TARGET_ARCH Target LiveCode to run on ARCH processors -Dtarget_sdk=XCODE_TARGET_SDK Compile LiveCode using the specified SDK in Xcode -Dhost_sdk=XCODE_HOST_SDK Compile build tools using the specified SDK in Xcode All unrecognised options get passed directly to gyp. If you don't specify a required option, config.py will try to guess a suitable value. The currently-supported PLATFORMs are: """) for p in KNOWN_PLATFORMS: print(" " + p) sys.exit(exit_status) def error(message): print('ERROR: ' + message) sys.exit(1) def guess_platform(): system = platform.system() arch = platform.machine() if system == 'Darwin': return 'mac' if system == 'Linux': if re.match('^(x|i.?)86$', arch) is not None: return 'linux-x86' else: return 'linux-' + arch if system == 'Windows': if arch == 'AMD64': return 'win-x86_64' else: return 'win-x86' def exec_gyp(args): gyp_lib = os.path.join(os.path.dirname(sys.argv[0]), 'gyp', 'pylib') sys.path.insert(0, gyp_lib) import gyp print('gyp ' + ' '.join(args)) sys.exit(gyp.main(args)) ################################################################ # Parse command-line options ################################################################ def process_env_options(opts): vars = ('OS', 'PLATFORM', 'GENERATOR_OUTPUT', 'FORMATS', 'DEPTH', 'WIN_MSVS_VERSION', 'XCODE_TARGET_SDK', 'XCODE_HOST_SDK', 'TARGET_ARCH', 'PERL', 'ANDROID_NDK_VERSION', 'ANDROID_LIB_PATH', 'ANDROID_NDK_PLATFORM_VERSION', 'ANDROID_PLATFORM', 'ANDROID_SDK', 'ANDROID_NDK', 'ANDROID_BUILD_TOOLS', 'LTO', 'ANDROID_TOOLCHAIN_DIR', 'ANDROID_TOOLCHAIN', 'ANDROID_API_VERSION', 'AR', 'CC', 'CXX', 'LINK', 'OBJCOPY', 'OBJDUMP', 'STRIP', 'JAVA_SDK', 'NODE_JS', 'BUILD_EDITION', 'CC_PREFIX', 'CROSS', 'SYSROOT', 'AUX_SYSROOT', 'TRIPLE', 'MS_SPEECH_SDK5', 'QUICKTIME_SDK', ) for v in vars: opts[v] = os.getenv(v) if opts['FORMATS'] is not None: opts['FORMATS'] = opts['FORMATS'].split() else: opts['FORMATS'] = [] def process_arg_options(opts, args): gyp_options = [] offset = 0 while offset < len(args): key = args[offset] if offset + 1 < len(args): value = args[offset + 1] else: value = None if key in ('-h', '--help'): usage(0) if key in ('-p', '--platform'): opts['PLATFORM'] = value offset += 2 continue if key in ('--use-lto'): opts['LTO'] = True offset += 1 continue if key in ('--cross'): opts['CROSS'] = True offset += 1 continue if key in ('--sysroot'): opts['SYSROOT'] = value offset += 2 continue if key in ('--aux-sysroot'): opts['AUX_SYSROOT'] = value offset += 2 continue if key in ('--triple'): opts['TRIPLE'] = value offset += 2 continue if key in ('--cc-prefix'): opts['CC_PREFIX'] = value offset += 2 continue if key in ('--generator-output'): opts['GENERATOR_OUTPUT'] = value offset += 2 continue if key in ('--depth'): opts['DEPTH'] = value offset += 2 continue if key in ('-f', '--format'): opts['FORMATS'].insert(0, value) offset += 2 continue # Intercept -D & -G options that config.py tries to generate intercepted_options = { '-Dhost_sdk': 'XCODE_HOST_SDK', '-Dtarget_sdk': 'XCODE_TARGET_SDK', '-Dtarget_arch': 'TARGET_ARCH', '-DOS': 'OS', '-Dperl': 'PERL', '-Dms_speech_sdk5': 'MS_SPEECH_SDK5', '-Dquicktime_sdk': 'QUICKTIME_SDK', '-Gmsvs_version': 'WIN_MSVS_VERSION', '-Gandroid_ndk_version': 'ANDROID_NDK_VERSION', } if key.startswith('-D') or key.startswith('-G'): prefix, suffix = key.split('=',2) if prefix in intercepted_options: opts[intercepted_options[prefix]] = suffix else: gyp_options.append(key) offset += 1 continue # Unrecognised option error("Unrecognised option '{}'".format(key)) opts['GYP_OPTIONS'] = gyp_options ################################################################ # Guess and validate platform and OS ################################################################ def validate_platform(opts): platform = opts['PLATFORM'] if platform is None: platform = guess_platform() if platform is None: error("Cannot guess platform; specify '--platform -'") if not platform in KNOWN_PLATFORMS: error("Unrecognised platform: '{}'".format(platform)) opts['PLATFORM'] = platform def validate_os(opts): validate_platform(opts) # Windows systems may have $OS set automatically in the # environment if opts['OS'] == 'Windows_NT': opts['OS'] = 'win' if opts['OS'] is None: opts['OS'] = opts['PLATFORM'].split('-')[0] def host_platform(opts): opts['HOST_PLATFORM'] = guess_platform() def guess_xcode_arch(target_sdk): sdk, ver = re.match('^([^\d]*)(\d*)', target_sdk).groups() if sdk == 'macosx': return 'x86_64' if sdk == 'iphoneos': if int(ver) < 8: return 'armv7' else: return 'armv7 arm64' if sdk == 'iphonesimulator': return 'x86_64' def validate_target_arch(opts): if opts['TARGET_ARCH'] is None: validate_platform(opts) platform = opts['PLATFORM'] if platform == 'emscripten': opts['TARGET_ARCH'] = 'js' opts['UNIFORM_ARCH'] = opts['TARGET_ARCH'] return platform_arch = re.search('-(x86|x86_64|arm(64|v(6(hf)?|7)))$', platform) if platform_arch is not None: opts['TARGET_ARCH'] = platform_arch.group(1) opts['UNIFORM_ARCH'] = opts['TARGET_ARCH'] return if re.match('^(ios|mac)', platform) is not None: validate_xcode_sdks(opts) arch = guess_xcode_arch(opts['XCODE_TARGET_SDK']) if arch is not None: opts['TARGET_ARCH'] = arch opts['UNIFORM_ARCH'] = opts['TARGET_ARCH'] return error("Couldn't guess target architecture for '{}'".format(platform)) else: opts['UNIFORM_ARCH'] = opts['TARGET_ARCH'] ################################################################ # Guess other general options ################################################################ def validate_gyp_settings(opts): if opts['GENERATOR_OUTPUT'] is None: validate_platform(opts) opts['GENERATOR_OUTPUT'] = \ os.path.join('build-' + opts['PLATFORM'], 'livecode') if len(opts['FORMATS']) < 1: validate_os(opts) build_os = opts['OS'] if build_os in ('linux', 'android', 'emscripten'): format = 'make-linux' elif build_os in ('mac', 'ios'): format = 'xcode' elif build_os in ('win'): format = 'msvs' opts['FORMATS'] = [format,] if opts['DEPTH'] is None: opts['DEPTH'] = '.' if opts['BUILD_EDITION'] is None: opts['BUILD_EDITION'] = 'community' def guess_java_home(platform): if platform.startswith('linux'): try: javac_str = '/bin/javac' javac_path = subprocess.check_output(['/usr/bin/env', 'readlink', '-f', '/usr' + javac_str]).strip() if (os.path.isfile(javac_path) and javac_path.endswith(javac_str)): return javac_path[:-len(javac_str)] except subprocess.CalledProcessError as e: print(e) pass # Fall through to other ways of guessing # More guesses try: if os.path.isfile('/usr/libexec/java_home'): return subprocess.check_output('/usr/libexec/java_home').strip() except subprocess.CalledProcessError as e: print(e) pass for d in ('/usr/lib/jvm/default', '/usr/lib/jvm/default-java'): if os.path.isdir(d): return d def validate_java_tools(opts): if opts['JAVA_SDK'] is None: validate_platform(opts) sdk = guess_java_home(opts['HOST_PLATFORM']) if sdk is None: error('Java SDK not found; set $JAVA_SDK') opts['JAVA_SDK'] = sdk def configure_toolchain(opts): ccprefix = '' if opts['CC_PREFIX'] is not None: ccprefix = opts['CC_PREFIX'] if opts['CC'] is None: opts['CC'] = ccprefix + 'cc' if opts['CXX'] is None: opts['CXX'] = ccprefix + 'c++' if opts['AR'] is None: opts['AR'] = ccprefix + 'ar' if opts['LINK'] is None: opts['LINK'] = opts['CXX'] if opts['STRIP'] is None: opts['STRIP'] = ccprefix + 'strip' if opts['OBJCOPY'] is None: opts['OBJCOPY'] = ccprefix + 'objcopy' if opts['OBJDUMP'] is None: opts['OBJDUMP'] = ccprefix + 'objdump' # Enable LTO if requested if opts['LTO'] is True: for key in ('CC', 'CXX', 'LINK'): opts[key] += ' -flto -ffunction-sections -fdata-sections -fuse-linker-plugin -fuse-ld=gold' # If cross-compiling, link libgcc and libstdc++ statically. # This is done because the cross-compilers are likely to be different # versions to those available on the target system. if opts['CROSS'] is True: for key in ('CC', 'CXX', 'LINK'): opts[key] += ' -static-libgcc -static-libstdc++' # Append a --sysroot option for the compilers and linker if opts['SYSROOT'] is not None: for key in ('CC', 'CXX', 'LINK'): opts[key] += ' --sysroot="' + opts['SYSROOT'] + '"' opts[key] += ' -Wl,--sysroot,"' + opts['SYSROOT'] + '"' # Configure an auxiliary sysroot, if one is specified. # # The -L options beginning '-L=/' are required to ensure the original # sysroot gets searched before the auxiliary one. Similarly with # -idirafter; these come after the sysroot include directories. if opts['AUX_SYSROOT'] is not None: for key in ('CC', 'CXX', 'LINK'): opts[key] += ' -idirafter "' + opts['AUX_SYSROOT'] + '/usr/include"' opts[key] += ' -L=/lib' opts[key] += ' -L=/usr/lib' if opts['TRIPLE'] is not None: opts[key] += ' -L"=/lib/' + opts['TRIPLE'] + '"' opts[key] += ' -L"=/usr/lib/' + opts['TRIPLE'] + '"' opts[key] += ' -L"' + opts['AUX_SYSROOT'] + '/lib"' opts[key] += ' -L"' + opts['AUX_SYSROOT'] + '/usr/lib"' opts[key] += ' -Wl,-rpath-link,"' + opts['AUX_SYSROOT'] + '/lib"' opts[key] += ' -Wl,-rpath-link,"' + opts['AUX_SYSROOT'] + '/usr/lib"' if opts['TRIPLE'] is not None: opts[key] += ' -idirafter "' + opts['AUX_SYSROOT'] + '/usr/include/' + opts['TRIPLE'] + '"' opts[key] += ' -L"' + opts['AUX_SYSROOT'] + '/lib/' + opts['TRIPLE'] + '"' opts[key] += ' -L"' + opts['AUX_SYSROOT'] + '/usr/lib/' + opts['TRIPLE'] + '"' opts[key] += ' -Wl,-rpath-link,"' + opts['AUX_SYSROOT'] + '/lib/' + opts['TRIPLE'] + '"' opts[key] += ' -Wl,-rpath-link,"' + opts['AUX_SYSROOT'] + '/usr/lib/' + opts['TRIPLE'] + '"' # Add LD as an alias for LINK opts['LD'] = opts['LINK'] ################################################################ # Windows-specific options ################################################################ def get_program_files_x86(): return os.environ.get('ProgramFiles(x86)', os.environ.get('ProgramFiles', 'C:\\Program Files\\')) def guess_windows_perl(): # Check the PATH first if (any(os.access(os.path.join(p, 'perl.exe'), os.X_OK) for p in os.environ['PATH'].split(os.pathsep))): return 'perl.exe' for p in ('C:\\perl64\\bin', 'C:\\perl\\bin'): perl = os.path.join(p, 'perl.exe') if os.access(perl, os.X_OK): return perl # If this is running on a non-Windows platform, default to "perl" if platform.system() != 'windows': return 'perl' error('Perl not found; set $PERL') def guess_ms_speech_sdk5(): d = os.path.join(get_program_files_x86(), 'Microsoft Speech SDK 5.1') if not os.path.isdir(d): return None return d def guess_quicktime_sdk(): d = os.path.join(get_program_files_x86(), 'QuickTime SDK') if not os.path.isdir(d): return None return d def validate_windows_tools(opts): if opts['PERL'] is None: opts['PERL'] = guess_windows_perl() if opts['MS_SPEECH_SDK5'] is None: opts['MS_SPEECH_SDK5'] = guess_ms_speech_sdk5() if opts['QUICKTIME_SDK'] is None: opts['QUICKTIME_SDK'] = guess_quicktime_sdk() if opts['WIN_MSVS_VERSION'] is None: # TODO [2017-04-11]: This should be 2017, but it is not # compatible with our gyp as is. opts['WIN_MSVS_VERSION'] = '2015' ################################################################ # Mac & iOS-specific options ################################################################ def validate_xcode_sdks(opts): if opts['XCODE_TARGET_SDK'] is None: validate_os(opts) if opts['OS'] == 'mac': opts['XCODE_TARGET_SDK'] = 'macosx10.9' elif opts['OS'] == 'ios': opts['XCODE_TARGET_SDK'] = 'iphoneos' if opts['XCODE_HOST_SDK'] is None: validate_os(opts) if opts['OS'] == 'mac': opts['XCODE_HOST_SDK'] = opts['XCODE_TARGET_SDK'] elif opts['OS'] == 'ios': opts['XCODE_HOST_SDK'] = 'macosx' ################################################################ # Android-specific options ################################################################ # We suggest some symlinks for Android toolchain components in the # INSTALL-android.md file. This checks if a directory is present def guess_android_tooldir(toolchain, name): if toolchain is None: dir = os.path.join(os.path.expanduser('~'), 'android', 'toolchain', name) else: dir = os.path.join(toolchain, name) if os.path.isdir(dir): return dir return None # Attempt to guess the Android build tools version by looking for directories # in the SDK's build-tools subdirectory. This is pretty fragile if someone # has (potentially?) multiple sets of build tools installed. def guess_android_build_tools(sdkdir): dirs = os.listdir(os.path.join(sdkdir, 'build-tools')) if len(dirs) == 1: return dirs[0] return None # Guess the standalone toolchain directory name. def guess_standalone_toolchain_dir_name(target_arch): if target_arch == 'armv6' or target_arch == 'armv7': return 'standalone-arm' else: return 'standalone-' + target_arch # Guess the triple to use for a given Android target architecture. def guess_android_triple(target_arch): if target_arch == 'armv6': return 'arm-linux-androideabi' elif target_arch == 'armv7': return 'armv7-linux-androideabi' elif target_arch == 'arm64': return 'aarch64-linux-android' elif target_arch == 'x86': return 'i686-linux-android' elif target_arch == 'x86_64': return 'x86_64-linux-android' else: return target_arch # Guess the value to pass with the -march flag for Android builds. def guess_android_march(target_arch): if target_arch == 'armv7': return 'armv7-a' elif target_arch == 'arm64': # The -march flag is not used for baseline arm64. return '' elif target_arch == 'x86': return 'i686' elif target_arch == 'x86_64': # The -march flag is not used for baseline x86_64 return '' return target_arch # Guess the prefix used on the compiler's name. def guess_compiler_prefix(target_arch): if target_arch == 'armv7': # The ARMv7 triple is different from its compiler's prefix. triple = guess_android_triple('armv6') else: triple = guess_android_triple(target_arch) if triple == target_arch: return '' return triple + '-' # Returns any extra C/C++ compiler flags required when targeting Android on the # given architecture. def android_extra_cflags(target_arch): if target_arch == 'armv7': # The first three flags are required in order to guarantee ABI compatibility. # Additionally, Google recommends generating thumb instructions on Android. return '-mfloat-abi=softfp -mfpu=vfpv3-d16 -Wl,--fix-cortex-a8 -mthumb' elif target_arch == 'armv6': # Google recommends generating thumb instructions on Android. return '-mthumb' return '' # Returns any extra linker flags required when targeting Android on the given # architecture. def android_extra_ldflags(target_arch): if target_arch == 'armv7': return '-Wl,--fix-cortex-a8' return '' def validate_android_tools(opts): if opts['ANDROID_NDK_VERSION'] is None: opts['ANDROID_NDK_VERSION'] = 'r15' ndk_ver = opts['ANDROID_NDK_VERSION'] toolchain_dir = opts['ANDROID_TOOLCHAIN_DIR'] if opts['ANDROID_NDK'] is None: ndk = guess_android_tooldir(toolchain_dir, 'android-ndk') if ndk is None: error('Android NDK not found; set $ANDROID_NDK') opts['ANDROID_NDK'] = ndk if opts['ANDROID_NDK_PLATFORM_VERSION'] is None: opts['ANDROID_NDK_PLATFORM_VERSION'] = '16' if opts['ANDROID_API_VERSION'] is None: opts['ANDROID_API_VERSION'] = '29' api_ver = opts['ANDROID_API_VERSION'] if opts['ANDROID_PLATFORM'] is None: opts['ANDROID_PLATFORM'] = 'android-' + api_ver if opts['ANDROID_SDK'] is None: sdk = guess_android_tooldir(toolchain_dir, 'android-sdk') if sdk is None: error('Android SDK not found; set $ANDROID_SDK') opts['ANDROID_SDK'] = sdk if opts['ANDROID_BUILD_TOOLS'] is None: tools = guess_android_build_tools(opts['ANDROID_SDK']) if tools is None: error('Android build tools not found; set $ANDROID_BUILD_TOOLS') opts['ANDROID_BUILD_TOOLS'] = tools if opts['ANDROID_TOOLCHAIN'] is None: dir = guess_android_tooldir(toolchain_dir, guess_standalone_toolchain_dir_name(opts['TARGET_ARCH'])) if dir is None: error('Android toolchain not found for architecture {}; set $ANDROID_TOOLCHAIN'.format(opts['TARGET_ARCH'])) prefix = guess_compiler_prefix(opts['TARGET_ARCH']) opts['ANDROID_TOOLCHAIN'] = os.path.join(dir,'bin',prefix) def android_tool(name, env, extra=""): if opts[env] is None: tool = opts['ANDROID_TOOLCHAIN'] + name if extra is not None: tool += ' ' + extra opts[env] = tool target_arch = opts['TARGET_ARCH'] march = guess_android_march(target_arch) triple = guess_android_triple(target_arch) cflags = android_extra_cflags(target_arch) ldflags = android_extra_ldflags(target_arch) if opts['ANDROID_LIB_PATH'] is None: dir =guess_standalone_toolchain_dir_name(opts['TARGET_ARCH']) if dir is None: error('Android standalone toolchain not found for architecture {}'.format(opts['TARGET_ARCH'])) opts['ANDROID_LIB_PATH'] = os.path.join(dir,triple,'lib') # All Android builds use Clang and make a lot of noise about unused # arguments (e.g. linker-specific arguments). Suppress them. cflags += ' -Qunused-arguments' if march != '': march = '-march=' + march android_tool('ar', 'AR') android_tool('clang', 'CC', '-target {} {} -integrated-as {}'.format(triple,march,cflags)) android_tool('clang++', 'CXX', '-target {} {} -integrated-as {}'.format(triple,march,cflags)) android_tool('clang++', 'LINK', '-target {} {} -integrated-as -fuse-ld=bfd {}'.format(triple,march,ldflags)) android_tool('objcopy', 'OBJCOPY') android_tool('objdump', 'OBJDUMP') android_tool('strip', 'STRIP') ################################################################ # Emscripten-specific options ################################################################ def validate_emscripten_tools(opts): if opts['NODE_JS'] is None: opts['NODE_JS'] = 'node' ################################################################ # Linux-specific options ################################################################ ################################################################ # Gyp invocation ################################################################ def core_gyp_args(opts): validate_gyp_settings(opts) validate_os(opts) args = [] for f in opts['FORMATS']: args += ['--format', f] args += ['--depth', opts['DEPTH'], '--generator-output', opts['GENERATOR_OUTPUT'], '-DOS=' + opts['OS']] if opts['PERL'] is not None: args.append('-Dperl=' + opts['PERL']) if opts['BUILD_EDITION'] == 'commercial': args.append(os.path.join('..', 'livecode-commercial.gyp')) if opts['CROSS'] is not None: args.append('-Dcross_compile=1') args.append('-Dbuild_edition=' + opts['BUILD_EDITION']) args.append('-Duniform_arch=' + opts['UNIFORM_ARCH']) return args def export_opts(opts, names): for n in names: if opts[n] is not None: print (n + '=' + opts[n]) os.environ[n] = opts[n] def gyp_define_args(opts, names): return ['-D{}={}'.format(key, opts[value]) for key, value in names.iteritems() if opts[value] is not None] def configure_linux(opts): host_platform(opts) validate_target_arch(opts) validate_java_tools(opts) configure_toolchain(opts) export_opts(opts, ('CC', 'CXX', 'AR', 'LINK', 'OBJCOPY', 'OBJDUMP', 'STRIP', 'LD')) args = core_gyp_args(opts) + ['-Dtarget_arch=' + opts['TARGET_ARCH'], '-Djavahome=' + opts['JAVA_SDK']] exec_gyp(args + opts['GYP_OPTIONS']) def configure_emscripten(opts): host_platform(opts) validate_target_arch(opts) validate_emscripten_tools(opts) export_opts(opts, ('NODE_JS',)) args = core_gyp_args(opts) + ['-Dtarget_arch=' + opts['TARGET_ARCH']] exec_gyp(args + opts['GYP_OPTIONS']) def configure_android(opts): host_platform(opts) validate_target_arch(opts) validate_android_tools(opts) validate_java_tools(opts) export_opts(opts, ('ANDROID_BUILD_TOOLS', 'ANDROID_NDK', 'ANDROID_PLATFORM', 'ANDROID_SDK', 'ANDROID_NDK_VERSION', 'ANDROID_NDK_PLATFORM_VERSION', 'ANDROID_API_VERSION', 'ANDROID_LIB_PATH', 'JAVA_SDK', 'AR', 'CC', 'CXX', 'LINK', 'OBJCOPY', 'OBJDUMP', 'STRIP')) args = core_gyp_args(opts) + ['-Dtarget_arch=' + opts['TARGET_ARCH'], '-Dcross_compile=1', '-Gandroid_ndk_version=' + opts['ANDROID_NDK_VERSION'], '-Djavahome=' + opts['JAVA_SDK']] exec_gyp(args + opts['GYP_OPTIONS']) def configure_win(opts): host_platform(opts) validate_target_arch(opts) validate_windows_tools(opts) # Make sure we strictly enforce TARGET_ARCH being x86 or x86_64 if opts['TARGET_ARCH'] != 'x86' and opts['TARGET_ARCH'] != 'x86_64': error("TARGET_ARCH must be x86 or x86_64") # Map target_arch for gyp - x86_64 -> x64 if opts['TARGET_ARCH'] == 'x86_64': opts['TARGET_ARCH'] = 'x64' args = core_gyp_args(opts) + ['-Gmsvs_version=' + opts['WIN_MSVS_VERSION']] args += gyp_define_args(opts, {'target_arch': 'TARGET_ARCH', 'ms_speech_sdk5': 'MS_SPEECH_SDK5', 'quicktime_sdk': 'QUICKTIME_SDK', }) if platform.system() != 'Windows': args.append('-Dunix_configure=1') exec_gyp(args + opts['GYP_OPTIONS']) def configure_mac(opts): host_platform(opts) validate_target_arch(opts) validate_xcode_sdks(opts) validate_java_tools(opts) copy_workspace_settings(opts) args = core_gyp_args(opts) + ['-Dtarget_sdk=' + opts['XCODE_TARGET_SDK'], '-Dhost_sdk=' + opts['XCODE_HOST_SDK'], '-Dtarget_arch=' + opts['TARGET_ARCH'], '-Djavahome=' + opts['JAVA_SDK']] exec_gyp(args + opts['GYP_OPTIONS']) def configure_ios(opts): configure_mac(opts) def configure(args): opts = {} process_env_options(opts) process_arg_options(opts, args) validate_os(opts) configure_procs = { 'linux': configure_linux, 'emscripten': configure_emscripten, 'android': configure_android, 'win': configure_win, 'mac': configure_mac, 'ios': configure_ios, } configure_procs[opts['OS']](opts) def copy_workspace_settings(opts): validate_gyp_settings(opts) if opts['BUILD_EDITION'] == 'commercial': project = os.path.join(opts['GENERATOR_OUTPUT'], '..', 'livecode-commercial.xcodeproj') else: project = os.path.join(opts['GENERATOR_OUTPUT'], 'livecode.xcodeproj') xcshareddata = os.path.join(project, 'project.xcworkspace', 'xcshareddata') if not os.path.exists(xcshareddata): os.makedirs(xcshareddata) workspacesettingsdest= os.path.join(xcshareddata, 'WorkspaceSettings.xcsettings') workspacesettingssource = os.path.join('config', 'WorkspaceSettings.xcsettings') if not os.path.exists(workspacesettingsdest): shutil.copyfile(workspacesettingssource, workspacesettingsdest) if __name__ == '__main__': configure(sys.argv[1:])