import errno
import collections
from contextlib import contextmanager
import itertools
import os
import re
import shutil
import subprocess
import sys
import tempfile
import TestCmd
import TestCommon
from TestCommon import __all__
__all__.extend([
'TestGyp',
])
def remove_debug_line_numbers(contents):
lines = contents.splitlines()
lines = [l.split(":", 3) for l in lines]
lines = [len(l) > 3 and ":".join(l[3:]) or l for l in lines]
return "\n".join(lines)
def match_modulo_line_numbers(contents_a, contents_b):
contents_a = remove_debug_line_numbers(contents_a)
contents_b = remove_debug_line_numbers(contents_b)
return TestCommon.match_exact(contents_a, contents_b)
@contextmanager
def LocalEnv(local_env):
old_env = os.environ.copy()
os.environ.update(local_env)
try:
yield
finally:
os.environ.clear()
os.environ.update(old_env)
class TestGypBase(TestCommon.TestCommon):
formats = []
build_tool = None
build_tool_list = []
_exe = TestCommon.exe_suffix
_obj = TestCommon.obj_suffix
shobj_ = TestCommon.shobj_prefix
_shobj = TestCommon.shobj_suffix
lib_ = TestCommon.lib_prefix
_lib = TestCommon.lib_suffix
dll_ = TestCommon.dll_prefix
_dll = TestCommon.dll_suffix
module_ = TestCommon.module_prefix
_module = TestCommon.module_suffix
ALL = '__all__'
DEFAULT = '__default__'
EXECUTABLE = '__executable__'
STATIC_LIB = '__static_lib__'
SHARED_LIB = '__shared_lib__'
LOADABLE_MODULE = '__loadable_module__'
def __init__(self, gyp=None, *args, **kw):
self.origin_cwd = os.path.abspath(os.path.dirname(sys.argv[0]))
self.extra_args = sys.argv[1:]
if not gyp:
gyp = os.environ.get('TESTGYP_GYP')
if not gyp:
if sys.platform == 'win32':
gyp = 'gyp.bat'
else:
gyp = 'gyp'
self.gyp = os.path.abspath(gyp)
self.no_parallel = False
self.formats = [self.format]
self.initialize_build_tool()
kw.setdefault('match', TestCommon.match_exact)
workdir = os.path.join('out', kw.get('workdir', 'testworkarea'))
if not os.path.isdir(workdir):
os.makedirs(workdir)
kw['workdir'] = tempfile.mktemp(prefix='testgyp.', dir=workdir)
formats = kw.pop('formats', [])
super(TestGypBase, self).__init__(*args, **kw)
real_format = self.format.split('-')[-1]
excluded_formats = set([f for f in formats if f[0] == '!'])
included_formats = set(formats) - excluded_formats
if ('!'+real_format in excluded_formats or
included_formats and real_format not in included_formats):
msg = 'Invalid test for %r format; skipping test.\n'
self.skip_test(msg % self.format)
self.copy_test_configuration(self.origin_cwd, self.workdir)
self.set_configuration(None)
os.environ['HOME'] = self.workpath()
if 'GYP_DEFINES' in os.environ:
del os.environ['GYP_DEFINES']
os.environ['LC_ALL'] = 'C'
def built_file_must_exist(self, name, type=None, **kw):
return self.must_exist(self.built_file_path(name, type, **kw))
def built_file_must_not_exist(self, name, type=None, **kw):
return self.must_not_exist(self.built_file_path(name, type, **kw))
def built_file_must_match(self, name, contents, **kw):
return self.must_match(self.built_file_path(name, **kw), contents)
def built_file_must_not_match(self, name, contents, **kw):
return self.must_not_match(self.built_file_path(name, **kw), contents)
def built_file_must_not_contain(self, name, contents, **kw):
return self.must_not_contain(self.built_file_path(name, **kw), contents)
def copy_test_configuration(self, source_dir, dest_dir):
for root, dirs, files in os.walk(source_dir):
if '.svn' in dirs:
dirs.remove('.svn')
dirs = [ d for d in dirs if not d.startswith('gyptest') ]
files = [ f for f in files if not f.startswith('gyptest') ]
for dirname in dirs:
source = os.path.join(root, dirname)
destination = source.replace(source_dir, dest_dir)
os.mkdir(destination)
if sys.platform != 'win32':
shutil.copystat(source, destination)
for filename in files:
source = os.path.join(root, filename)
destination = source.replace(source_dir, dest_dir)
shutil.copy2(source, destination)
if sys.platform == 'darwin':
old_keychain = GetDefaultKeychainPath()
old_provisioning_profiles = os.path.join(
os.environ['HOME'], 'Library', 'MobileDevice',
'Provisioning Profiles')
new_keychain = os.path.join(dest_dir, 'Library', 'Keychains')
MakeDirs(new_keychain)
os.symlink(old_keychain, os.path.join(new_keychain, 'login.keychain'))
if os.path.exists(old_provisioning_profiles):
new_provisioning_profiles = os.path.join(
dest_dir, 'Library', 'MobileDevice')
MakeDirs(new_provisioning_profiles)
os.symlink(old_provisioning_profiles,
os.path.join(new_provisioning_profiles, 'Provisioning Profiles'))
def initialize_build_tool(self):
for build_tool in self.build_tool_list:
if not build_tool:
continue
if os.path.isabs(build_tool):
self.build_tool = build_tool
return
build_tool = self.where_is(build_tool)
if build_tool:
self.build_tool = build_tool
return
if self.build_tool_list:
self.build_tool = self.build_tool_list[0]
def relocate(self, source, destination):
destination_dir = os.path.dirname(destination)
if not os.path.exists(destination_dir):
self.subdir(destination_dir)
os.rename(source, destination)
def report_not_up_to_date(self):
print "Build is not up-to-date:"
print self.banner('STDOUT ')
print self.stdout()
stderr = self.stderr()
if stderr:
print self.banner('STDERR ')
print stderr
def run_gyp(self, gyp_file, *args, **kw):
if kw.pop('ignore_line_numbers', False):
kw.setdefault('match', match_modulo_line_numbers)
depth = kw.pop('depth', '.')
run_args = ['--depth='+depth]
run_args.extend(['--format='+f for f in self.formats])
run_args.append(gyp_file)
if self.no_parallel:
run_args += ['--no-parallel']
run_args.extend(self.extra_args)
xcode_ninja_target_pattern = kw.pop('xcode_ninja_target_pattern', '.*')
if self is TestGypXcodeNinja:
run_args.extend(
['-G', 'xcode_ninja_target_pattern=%s' % xcode_ninja_target_pattern])
run_args.extend(args)
return self.run(program=self.gyp, arguments=run_args, **kw)
def run(self, *args, **kw):
if kw.has_key('SYMROOT'):
del kw['SYMROOT']
super(TestGypBase, self).run(*args, **kw)
def set_configuration(self, configuration):
self.configuration = configuration
def configuration_dirname(self):
if self.configuration:
return self.configuration.split('|')[0]
else:
return 'Default'
def configuration_buildname(self):
if self.configuration:
return self.configuration
else:
return 'Default'
def build(self, gyp_file, target=None, **kw):
raise NotImplementedError
def built_file_path(self, name, type=None, **kw):
raise NotImplementedError
def built_file_basename(self, name, type=None, **kw):
if not kw.get('bare'):
if type == self.EXECUTABLE:
name = name + self._exe
elif type == self.STATIC_LIB:
name = self.lib_ + name + self._lib
elif type == self.SHARED_LIB:
name = self.dll_ + name + self._dll
elif type == self.LOADABLE_MODULE:
name = self.module_ + name + self._module
return name
def run_built_executable(self, name, *args, **kw):
raise NotImplementedError
def up_to_date(self, gyp_file, target=None, **kw):
raise NotImplementedError
class TestGypGypd(TestGypBase):
format = 'gypd'
def __init__(self, gyp=None, *args, **kw):
super(TestGypGypd, self).__init__(*args, **kw)
self.no_parallel = True
class TestGypCustom(TestGypBase):
def __init__(self, gyp=None, *args, **kw):
self.format = kw.pop("format")
super(TestGypCustom, self).__init__(*args, **kw)
class TestGypCMake(TestGypBase):
format = 'cmake'
build_tool_list = ['cmake']
ALL = 'all'
def cmake_build(self, gyp_file, target=None, **kw):
arguments = kw.get('arguments', [])[:]
self.build_tool_list = ['cmake']
self.initialize_build_tool()
chdir = os.path.join(kw.get('chdir', '.'),
'out',
self.configuration_dirname())
kw['chdir'] = chdir
arguments.append('-G')
arguments.append('Ninja')
kw['arguments'] = arguments
stderr = kw.get('stderr', None)
if stderr:
kw['stderr'] = stderr.split('$$$')[0]
self.run(program=self.build_tool, **kw)
def ninja_build(self, gyp_file, target=None, **kw):
arguments = kw.get('arguments', [])[:]
self.build_tool_list = ['ninja']
self.initialize_build_tool()
arguments.append('-C')
arguments.append(os.path.join('out', self.configuration_dirname()))
if target not in (None, self.DEFAULT):
arguments.append(target)
kw['arguments'] = arguments
stderr = kw.get('stderr', None)
if stderr:
stderrs = stderr.split('$$$')
kw['stderr'] = stderrs[1] if len(stderrs) > 1 else ''
return self.run(program=self.build_tool, **kw)
def build(self, gyp_file, target=None, status=0, **kw):
if status is None:
kw['status'] = None
else:
if not isinstance(status, collections.Iterable): status = (status,)
kw['status'] = list(itertools.chain((0,), status))
self.cmake_build(gyp_file, target, **kw)
kw['status'] = status
self.ninja_build(gyp_file, target, **kw)
def run_built_executable(self, name, *args, **kw):
program = [self.built_file_path(name, type=self.EXECUTABLE, **kw)]
if sys.platform == 'darwin':
configuration = self.configuration_dirname()
os.environ['DYLD_LIBRARY_PATH'] = os.path.join('out', configuration)
return self.run(program=program, *args, **kw)
def built_file_path(self, name, type=None, **kw):
result = []
chdir = kw.get('chdir')
if chdir:
result.append(chdir)
result.append('out')
result.append(self.configuration_dirname())
if type == self.STATIC_LIB:
if sys.platform != 'darwin':
result.append('obj.target')
elif type == self.SHARED_LIB:
if sys.platform != 'darwin' and sys.platform != 'win32':
result.append('lib.target')
subdir = kw.get('subdir')
if subdir and type != self.SHARED_LIB:
result.append(subdir)
result.append(self.built_file_basename(name, type, **kw))
return self.workpath(*result)
def up_to_date(self, gyp_file, target=None, **kw):
result = self.ninja_build(gyp_file, target, **kw)
if not result:
stdout = self.stdout()
if 'ninja: no work to do' not in stdout:
self.report_not_up_to_date()
self.fail_test()
return result
class TestGypMake(TestGypBase):
format = 'make'
build_tool_list = ['make']
ALL = 'all'
def build(self, gyp_file, target=None, **kw):
arguments = kw.get('arguments', [])[:]
if self.configuration:
arguments.append('BUILDTYPE=' + self.configuration)
if target not in (None, self.DEFAULT):
arguments.append(target)
chdir = kw.get('chdir', '')
if not os.path.exists(os.path.join(chdir, 'Makefile')):
print "NO Makefile in " + os.path.join(chdir, 'Makefile')
arguments.insert(0, '-f')
arguments.insert(1, os.path.splitext(gyp_file)[0] + '.Makefile')
kw['arguments'] = arguments
return self.run(program=self.build_tool, **kw)
def up_to_date(self, gyp_file, target=None, **kw):
if target in (None, self.DEFAULT):
message_target = 'all'
else:
message_target = target
kw['stdout'] = "make: Nothing to be done for `%s'.\n" % message_target
return self.build(gyp_file, target, **kw)
def run_built_executable(self, name, *args, **kw):
configuration = self.configuration_dirname()
libdir = os.path.join('out', configuration, 'lib')
if sys.platform == 'darwin':
configuration = self.configuration_dirname()
os.environ['DYLD_LIBRARY_PATH'] = (
libdir + '.host:' + os.path.join('out', configuration))
else:
os.environ['LD_LIBRARY_PATH'] = libdir + '.host:' + libdir + '.target'
program = [self.built_file_path(name, type=self.EXECUTABLE, **kw)]
return self.run(program=program, *args, **kw)
def built_file_path(self, name, type=None, **kw):
result = []
chdir = kw.get('chdir')
if chdir:
result.append(chdir)
configuration = self.configuration_dirname()
result.extend(['out', configuration])
if type == self.STATIC_LIB and sys.platform != 'darwin':
result.append('obj.target')
elif type == self.SHARED_LIB and sys.platform != 'darwin':
result.append('lib.target')
subdir = kw.get('subdir')
if subdir and type != self.SHARED_LIB:
result.append(subdir)
result.append(self.built_file_basename(name, type, **kw))
return self.workpath(*result)
def ConvertToCygpath(path):
if sys.platform == 'cygwin':
p = subprocess.Popen(['cygpath', path], stdout=subprocess.PIPE)
path = p.communicate()[0].strip()
return path
def MakeDirs(new_dir):
try:
os.makedirs(new_dir)
except OSError as e:
if e.errno != errno.EEXIST:
raise
def GetDefaultKeychainPath():
assert sys.platform == 'darwin'
path = subprocess.check_output(['security', 'default-keychain']).strip()
return path[1:-1]
def FindMSBuildInstallation(msvs_version = 'auto'):
import TestWin
registry = TestWin.Registry()
msvs_to_msbuild = {
'2013': r'12.0',
'2012': r'4.0', '2010': r'4.0'}
msbuild_basekey = r'HKLM\SOFTWARE\Microsoft\MSBuild\ToolsVersions'
if not registry.KeyExists(msbuild_basekey):
print 'Error: could not find MSBuild base registry entry'
return None
msbuild_version = None
if msvs_version in msvs_to_msbuild:
msbuild_test_version = msvs_to_msbuild[msvs_version]
if registry.KeyExists(msbuild_basekey + '\\' + msbuild_test_version):
msbuild_version = msbuild_test_version
else:
print ('Warning: Environment variable GYP_MSVS_VERSION specifies "%s" '
'but corresponding MSBuild "%s" was not found.' %
(msvs_version, msbuild_version))
if not msbuild_version:
for msvs_version in sorted(msvs_to_msbuild, reverse=True):
msbuild_test_version = msvs_to_msbuild[msvs_version]
if registry.KeyExists(msbuild_basekey + '\\' + msbuild_test_version):
msbuild_version = msbuild_test_version
break
if not msbuild_version:
print 'Error: could not find MSBuild registry entry'
return None
msbuild_path = registry.GetValue(msbuild_basekey + '\\' + msbuild_version,
'MSBuildToolsPath')
if not msbuild_path:
print 'Error: could not get MSBuild registry entry value'
return None
return os.path.join(msbuild_path, 'MSBuild.exe')
def FindVisualStudioInstallation():
override_build_tool = os.environ.get('GYP_BUILD_TOOL')
if override_build_tool:
return override_build_tool, True, override_build_tool
possible_roots = ['%s:\\Program Files%s' % (chr(drive), suffix)
for drive in range(ord('C'), ord('Z') + 1)
for suffix in ['', ' (x86)']]
possible_paths = {
'2017': r'Microsoft Visual Studio\2017',
'2015': r'Microsoft Visual Studio 14.0\Common7\IDE\devenv.com',
'2013': r'Microsoft Visual Studio 12.0\Common7\IDE\devenv.com',
'2012': r'Microsoft Visual Studio 11.0\Common7\IDE\devenv.com',
'2010': r'Microsoft Visual Studio 10.0\Common7\IDE\devenv.com',
'2008': r'Microsoft Visual Studio 9.0\Common7\IDE\devenv.com',
'2005': r'Microsoft Visual Studio 8\Common7\IDE\devenv.com'}
possible_roots = [ConvertToCygpath(r) for r in possible_roots]
msvs_version = 'auto'
for flag in (f for f in sys.argv if f.startswith('msvs_version=')):
msvs_version = flag.split('=')[-1]
msvs_version = os.environ.get('GYP_MSVS_VERSION', msvs_version)
if msvs_version in ['2017', 'auto']:
msbuild_exes = []
try:
path = possible_paths['2017']
for r in possible_roots:
build_tool = os.path.join(r, path)
if os.path.exists(build_tool):
break;
else:
build_tool = None
if not build_tool:
args1 = ['reg', 'query',
'HKLM\Software\Microsoft\VisualStudio\SxS\VS7',
'/v', '15.0', '/reg:32']
build_tool = subprocess.check_output(args1)\
.strip().split('\r\n').pop().split(' ').pop()
if build_tool:
args2 = ['cmd.exe', '/d', '/c',
'cd', '/d', build_tool,
'&', 'dir', '/b', '/s', 'msbuild.exe']
msbuild_exes = subprocess.check_output(args2).strip().split('\r\n')
if len(msbuild_exes):
msbuild_Path = os.path.join(build_tool, msbuild_exes[0])
if os.path.exists(msbuild_Path):
os.environ['GYP_MSVS_VERSION'] = '2017'
os.environ['GYP_BUILD_TOOL'] = msbuild_Path
return msbuild_Path, True, msbuild_Path
except Exception as e:
pass
if msvs_version in possible_paths:
path = possible_paths[msvs_version]
for r in possible_roots:
build_tool = os.path.join(r, path)
if os.path.exists(build_tool):
uses_msbuild = msvs_version >= '2010'
msbuild_path = FindMSBuildInstallation(msvs_version)
return build_tool, uses_msbuild, msbuild_path
else:
print ('Warning: Environment variable GYP_MSVS_VERSION specifies "%s" '
'but corresponding "%s" was not found.' % (msvs_version, path))
for version in sorted(possible_paths, reverse=True):
path = possible_paths[version]
for r in possible_roots:
build_tool = os.path.join(r, path)
if os.path.exists(build_tool):
uses_msbuild = msvs_version >= '2010'
msbuild_path = FindMSBuildInstallation(msvs_version)
return build_tool, uses_msbuild, msbuild_path
print 'Error: could not find devenv'
sys.exit(1)
class TestGypOnMSToolchain(TestGypBase):
@staticmethod
def _ComputeVsvarsPath(devenv_path):
devenv_dir = os.path.split(devenv_path)[0]
vsvars_path = os.path.join(devenv_path, '../../Tools/vsvars32.bat')
return vsvars_path
def initialize_build_tool(self):
super(TestGypOnMSToolchain, self).initialize_build_tool()
if sys.platform in ('win32', 'cygwin'):
build_tools = FindVisualStudioInstallation()
self.devenv_path, self.uses_msbuild, self.msbuild_path = build_tools
self.vsvars_path = TestGypOnMSToolchain._ComputeVsvarsPath(
self.devenv_path)
def run_dumpbin(self, *dumpbin_args):
assert sys.platform in ('win32', 'cygwin')
cmd = os.environ.get('COMSPEC', 'cmd.exe')
arguments = [cmd, '/c', self.vsvars_path, '&&', 'dumpbin']
arguments.extend(dumpbin_args)
proc = subprocess.Popen(arguments, stdout=subprocess.PIPE)
output = proc.communicate()[0]
assert not proc.returncode
return output
class TestGypNinja(TestGypOnMSToolchain):
format = 'ninja'
build_tool_list = ['ninja']
ALL = 'all'
DEFAULT = 'all'
def run_gyp(self, gyp_file, *args, **kw):
TestGypBase.run_gyp(self, gyp_file, *args, **kw)
def build(self, gyp_file, target=None, **kw):
arguments = kw.get('arguments', [])[:]
arguments.append('-C')
arguments.append(os.path.join('out', self.configuration_dirname()))
if target is None:
target = 'all'
arguments.append(target)
kw['arguments'] = arguments
return self.run(program=self.build_tool, **kw)
def run_built_executable(self, name, *args, **kw):
program = [self.built_file_path(name, type=self.EXECUTABLE, **kw)]
if sys.platform == 'darwin':
configuration = self.configuration_dirname()
os.environ['DYLD_LIBRARY_PATH'] = os.path.join('out', configuration)
return self.run(program=program, *args, **kw)
def built_file_path(self, name, type=None, **kw):
result = []
chdir = kw.get('chdir')
if chdir:
result.append(chdir)
result.append('out')
result.append(self.configuration_dirname())
if type == self.STATIC_LIB:
if sys.platform != 'darwin':
result.append('obj')
elif type == self.SHARED_LIB:
if sys.platform != 'darwin' and sys.platform != 'win32':
result.append('lib')
subdir = kw.get('subdir')
if subdir and type != self.SHARED_LIB:
result.append(subdir)
result.append(self.built_file_basename(name, type, **kw))
return self.workpath(*result)
def up_to_date(self, gyp_file, target=None, **kw):
result = self.build(gyp_file, target, **kw)
if not result:
stdout = self.stdout()
if 'ninja: no work to do' not in stdout:
self.report_not_up_to_date()
self.fail_test()
return result
class TestGypMSVS(TestGypOnMSToolchain):
format = 'msvs'
u = r'=== Build: 0 succeeded, 0 failed, (\d+) up-to-date, 0 skipped ==='
up_to_date_re = re.compile(u, re.M)
build_tool_list = [None, 'devenv.com']
def initialize_build_tool(self):
super(TestGypMSVS, self).initialize_build_tool()
self.build_tool = self.devenv_path
def build(self, gyp_file, target=None, rebuild=False, clean=False, **kw):
if '15.0' in self.build_tool:
configuration = '/p:Configuration=' + (
self.configuration or self.configuration_buildname())
build = '/t'
if target not in (None, self.ALL, self.DEFAULT):
build += ':' + target
if clean:
build += ':Clean'
elif rebuild:
build += ':Rebuild'
elif ':' not in build:
build += ':Build'
arguments = kw.get('arguments', [])[:]
arguments.extend([gyp_file.replace('.gyp', '.sln'),
build, configuration])
else:
configuration = self.configuration_buildname()
if clean:
build = '/Clean'
elif rebuild:
build = '/Rebuild'
else:
build = '/Build'
arguments = kw.get('arguments', [])[:]
arguments.extend([gyp_file.replace('.gyp', '.sln'),
build, configuration])
if target not in (None, self.ALL, self.DEFAULT):
arguments.extend(['/Project', target])
if self.configuration:
arguments.extend(['/ProjectConfig', self.configuration])
kw['arguments'] = arguments
return self.run(program=self.build_tool, **kw)
def up_to_date(self, gyp_file, target=None, **kw):
result = self.build(gyp_file, target, **kw)
if not result:
stdout = self.stdout()
m = self.up_to_date_re.search(stdout)
up_to_date = m and int(m.group(1)) > 0
if not up_to_date:
self.report_not_up_to_date()
self.fail_test()
return result
def run_built_executable(self, name, *args, **kw):
configuration = self.configuration_dirname()
program = [self.built_file_path(name, type=self.EXECUTABLE, **kw)]
return self.run(program=program, *args, **kw)
def built_file_path(self, name, type=None, **kw):
result = []
chdir = kw.get('chdir')
if chdir:
result.append(chdir)
result.append(self.configuration_dirname())
if type == self.STATIC_LIB:
result.append('lib')
result.append(self.built_file_basename(name, type, **kw))
return self.workpath(*result)
class TestGypMSVSNinja(TestGypNinja):
format = 'msvs-ninja'
def initialize_build_tool(self):
super(TestGypMSVSNinja, self).initialize_build_tool()
self.formats.insert(0, 'ninja')
def build(self, gyp_file, target=None, rebuild=False, clean=False, **kw):
arguments = kw.get('arguments', [])[:]
if target in (None, self.ALL, self.DEFAULT):
arguments.extend([gyp_file.replace('.gyp', '.sln')])
else:
arguments.extend([target+'.vcxproj'])
if clean:
build = 'Clean'
elif rebuild:
build = 'Rebuild'
else:
build = 'Build'
arguments.extend(['/target:'+build])
configuration = self.configuration_buildname()
config = configuration.split('|')
arguments.extend(['/property:Configuration='+config[0]])
if len(config) > 1:
arguments.extend(['/property:Platform='+config[1]])
arguments.extend(['/property:BuildInParallel=false'])
arguments.extend(['/verbosity:minimal'])
kw['arguments'] = arguments
return self.run(program=self.msbuild_path, **kw)
class TestGypXcode(TestGypBase):
format = 'xcode'
build_tool_list = ['xcodebuild']
phase_script_execution = ("\n"
"PhaseScriptExecution /\\S+/Script-[0-9A-F]+\\.sh\n"
" cd /\\S+\n"
" /bin/sh -c /\\S+/Script-[0-9A-F]+\\.sh\n"
"(make: Nothing to be done for `all'\\.\n)?")
strip_up_to_date_expressions = [
re.compile(phase_script_execution, re.S),
re.compile('__________Shutting down distcc-pump include server\n', re.S),
]
up_to_date_endings = (
'Checking Dependencies...\n** BUILD SUCCEEDED **\n', 'Check dependencies\n** BUILD SUCCEEDED **\n\n', 'Check dependencies\n\n\n** BUILD SUCCEEDED **\n\n', 'Check dependencies\n\n** BUILD SUCCEEDED **\n\n', )
def build(self, gyp_file, target=None, **kw):
arguments = kw.get('arguments', [])[:]
arguments.extend(['-project', gyp_file.replace('.gyp', '.xcodeproj')])
if target == self.ALL:
arguments.append('-alltargets',)
elif target not in (None, self.DEFAULT):
arguments.extend(['-target', target])
if self.configuration:
arguments.extend(['-configuration', self.configuration])
symroot = kw.get('SYMROOT', '$SRCROOT/build')
if symroot:
arguments.append('SYMROOT='+symroot)
kw['arguments'] = arguments
match = kw.pop('match', self.match)
def match_filter_xcode(actual, expected):
if actual:
if not TestCmd.is_List(actual):
actual = actual.split('\n')
if not TestCmd.is_List(expected):
expected = expected.split('\n')
actual = [a for a in actual
if 'No recorder, buildTask: <Xcode3BuildTask:' not in a and
'Beginning test session' not in a and
'Writing diagnostic log' not in a and
'Logs/Test/' not in a]
return match(actual, expected)
kw['match'] = match_filter_xcode
return self.run(program=self.build_tool, **kw)
def up_to_date(self, gyp_file, target=None, **kw):
result = self.build(gyp_file, target, **kw)
if not result:
output = self.stdout()
for expression in self.strip_up_to_date_expressions:
output = expression.sub('', output)
if not output.endswith(self.up_to_date_endings):
self.report_not_up_to_date()
self.fail_test()
return result
def run_built_executable(self, name, *args, **kw):
configuration = self.configuration_dirname()
os.environ['DYLD_LIBRARY_PATH'] = os.path.join('build', configuration)
program = [self.built_file_path(name, type=self.EXECUTABLE, **kw)]
return self.run(program=program, *args, **kw)
def built_file_path(self, name, type=None, **kw):
result = []
chdir = kw.get('chdir')
if chdir:
result.append(chdir)
configuration = self.configuration_dirname()
result.extend(['build', configuration])
result.append(self.built_file_basename(name, type, **kw))
return self.workpath(*result)
class TestGypXcodeNinja(TestGypXcode):
format = 'xcode-ninja'
def initialize_build_tool(self):
super(TestGypXcodeNinja, self).initialize_build_tool()
self.formats.insert(0, 'ninja')
def build(self, gyp_file, target=None, **kw):
build_config = self.configuration
if build_config and build_config.endswith(('-iphoneos',
'-iphonesimulator')):
build_config, sdk = self.configuration.split('-')
kw['arguments'] = kw.get('arguments', []) + ['-sdk', sdk]
with self._build_configuration(build_config):
return super(TestGypXcodeNinja, self).build(
gyp_file.replace('.gyp', '.ninja.gyp'), target, **kw)
@contextmanager
def _build_configuration(self, build_config):
config = self.configuration
self.configuration = build_config
try:
yield
finally:
self.configuration = config
def built_file_path(self, name, type=None, **kw):
result = []
chdir = kw.get('chdir')
if chdir:
result.append(chdir)
result.append('out')
result.append(self.configuration_dirname())
subdir = kw.get('subdir')
if subdir and type != self.SHARED_LIB:
result.append(subdir)
result.append(self.built_file_basename(name, type, **kw))
return self.workpath(*result)
def up_to_date(self, gyp_file, target=None, **kw):
result = self.build(gyp_file, target, **kw)
if not result:
stdout = self.stdout()
if 'ninja: no work to do' not in stdout:
self.report_not_up_to_date()
self.fail_test()
return result
def run_built_executable(self, name, *args, **kw):
configuration = self.configuration_dirname()
os.environ['DYLD_LIBRARY_PATH'] = os.path.join('out', configuration)
program = [self.built_file_path(name, type=self.EXECUTABLE, **kw)]
return self.run(program=program, *args, **kw)
format_class_list = [
TestGypGypd,
TestGypCMake,
TestGypMake,
TestGypMSVS,
TestGypMSVSNinja,
TestGypNinja,
TestGypXcode,
TestGypXcodeNinja,
]
def TestGyp(*args, **kw):
format = kw.pop('format', os.environ.get('TESTGYP_FORMAT'))
for format_class in format_class_list:
if format == format_class.format:
return format_class(*args, **kw)
raise Exception, "unknown format %r" % format