1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
|
#!/usr/bin/env python3
import subprocess
import os
import shlex
import shutil
import re
# Preprocesses wtf/Platform.h with clang, extracts macro definitions, and saves
# the platform flags to a Swift-style response file containing -D arguments.
# For build settings which may be undefined, behave like a shell and implicitly
# fall back to the empty string.
os.environ.setdefault('FRAMEWORK_SEARCH_PATHS', '')
os.environ.setdefault('HEADER_SEARCH_PATHS', '')
os.environ.setdefault('SYSTEM_FRAMEWORK_SEARCH_PATHS', '')
os.environ.setdefault('SYSTEM_HEADER_SEARCH_PATHS', '')
os.environ.setdefault('GCC_PREPROCESSOR_DEFINITIONS', '')
framework_search_paths = shlex.split(
'{BUILT_PRODUCTS_DIR} {FRAMEWORK_SEARCH_PATHS}'.format_map(os.environ))
header_search_paths = shlex.split(
'{BUILT_PRODUCTS_DIR} {HEADER_SEARCH_PATHS}'.format_map(os.environ))
system_framework_search_paths = shlex.split(
'{SYSTEM_FRAMEWORK_SEARCH_PATHS}'.format_map(os.environ))
system_header_search_paths = shlex.split(
'{SYSTEM_HEADER_SEARCH_PATHS}'.format_map(os.environ))
preprocessor_definitions = shlex.split(
'__WK_GENERATING_PLATFORM_ARGS__ RELEASE_WITHOUT_OPTIMIZATIONS '
'{GCC_PREPROCESSOR_DEFINITIONS}'.format_map(os.environ))
archs = shlex.split(os.environ['ARCHS'])
if 'SWIFT_MODULE_ONLY_ARCHS' in os.environ:
archs.extend(shlex.split(os.environ['SWIFT_MODULE_ONLY_ARCHS']))
output_dir = os.path.dirname(os.environ['SCRIPT_OUTPUT_FILE_0'])
combined_depfile_fd = open(
'{DERIVED_FILES_DIR}/generate-platform-args.d'.format_map(os.environ), 'w')
# This script is run as a build phase, which Xcode runs once with
# $arch=undefined, so we have to handle multi-arch builds manually. We generate
# argument lists for all active architectures, and the build script phase
# declares all known output paths as outputs.
#
# FIXME: Computing search path arguments is duplicated by migrate-header-rule
# in WebKitLegacy. We could share this implementation and generate
# bash-compatible variables for these use cases as well.
with open(f'{output_dir}/rdar150228472.swift', 'w') as fd:
fd.write('// generate-platform-args: empty file to work around dependency '
'bug in rdar://150228472\n')
for arch in archs:
output_name = f'platform-enabled-swift-args.{arch}.resp'
output_file = f'{output_dir}/{output_name}'
depfile = f'{{DERIVED_FILES_DIR}}/{output_name}.d'.format_map(os.environ)
target_triple = (f'{arch}-'
'{LLVM_TARGET_TRIPLE_VENDOR}-{LLVM_TARGET_TRIPLE_OS_VERSION}').format_map(os.environ)
target_triple += os.environ.get('LLVM_TARGET_TRIPLE_SUFFIX', '')
feature_and_platform_defines = subprocess.check_output(
('xcrun', 'clang', '-x', 'c++', '-std={CLANG_CXX_LANGUAGE_STANDARD}'.format_map(os.environ),
'-target', target_triple, '-E', '-P', '-dM', '-MD', '-MF', depfile, '-MT', output_name,
*(f'-D{token}' for token in preprocessor_definitions),
*(arg for path in framework_search_paths for arg in ('-F', path)),
*(arg for path in header_search_paths for arg in ('-I', path)),
*(arg for path in system_framework_search_paths for arg in ('-iframework', path)),
*(arg for path in system_header_search_paths for arg in ('-isystem', path)),
'-include', 'wtf/Platform.h', '/dev/zero'), text=True)
# Concatenate all the depfiles, in case a header is only imported on specific architectures.
shutil.copyfileobj(open(depfile), combined_depfile_fd)
definitions = {}
for m in re.finditer(r'^#define (\w+) (.+)', feature_and_platform_defines, re.MULTILINE):
name = m.group(1)
value = m.group(2)
if value == '1':
definitions[name] = 1
elif value == '0':
definitions[name] = 0
else:
definitions[name] = value
# Resolve macros which are defined as the value of another macro. clang -dM
# prints macros in alphabetical order, so we cannot rely on macros being in
# topological order. Limit the maximum amount of indirection to prevent a
# recursive definition from causing the script to loop forever.
for _ in range(10):
changed = False
for name, value in definitions.items():
if type(value) == str and value in definitions:
definitions[name] = definitions[value]
changed = True
if not changed:
break
swift_args = '\n'.join(
f'-D{name}'
for name, value in definitions.items()
if value == 1 and (name.startswith('HAVE_') or name.startswith('USE_') or
name.startswith('ENABLE_') or name.startswith('WTF_PLATFORM') or
name.startswith('ASSERT_'))
)
print(f'{output_file}:\t', swift_args.replace('\n', ' '))
open(output_file, 'w').write(swift_args)
|