in tools/make_distrib.py [0:0]
def eval_transfer_file(cef_dir, script_dir, transfer_cfg, output_dir, quiet):
""" Transfer files based on the specified configuration. """
if not path_exists(transfer_cfg):
return
configs = eval_file(transfer_cfg)
for cfg in configs:
dst = os.path.join(output_dir, cfg['target'])
# perform a copy if source is specified
if not cfg['source'] is None:
src = os.path.join(cef_dir, cfg['source'])
dst_path = os.path.dirname(dst)
make_dir(dst_path, quiet)
copy_file(src, dst, quiet)
# place a readme file in the destination directory
readme = os.path.join(dst_path, 'README-TRANSFER.txt')
if not path_exists(readme):
copy_file(
os.path.join(script_dir, 'distrib/README-TRANSFER.txt'), readme)
str = cfg['source'] + "\n"
with open(readme, 'a', encoding='utf-8') as fp:
if sys.version_info.major == 2:
fp.write(str.decode('utf-8'))
else:
fp.write(str)
# perform any required post-processing
if 'post-process' in cfg:
post = cfg['post-process']
if post == 'normalize_headers':
new_path = ''
if 'new_header_path' in cfg:
new_path = cfg['new_header_path']
normalize_headers(dst, new_path)
def transfer_files(cef_dir, script_dir, transfer_cfg_dir, mode, output_dir,
quiet):
# Non-mode-specific transfers.
transfer_cfg = os.path.join(transfer_cfg_dir, 'transfer.cfg')
eval_transfer_file(cef_dir, script_dir, transfer_cfg, output_dir, quiet)
# Mode-specific transfers.
transfer_cfg = os.path.join(transfer_cfg_dir, 'transfer_%s.cfg' % mode)
eval_transfer_file(cef_dir, script_dir, transfer_cfg, output_dir, quiet)
# |paths| is a list of dictionary values with the following keys:
# path [required] Input file or directory path relative to |build_dir|.
# By default this will also be the output path relative
# to |dst_dir|.
# out_path [optional] Override the output path relative to |dst_dir|.
# conditional [optional] Set to True if the path is conditional on build
# settings. Missing conditional paths will not be
# treated as an error.
# delete [optional] Glob pattern of files to delete after the copy.
def copy_files_list(build_dir, dst_dir, paths):
''' Copy the files listed in |paths| from |build_dir| to |dst_dir|. '''
for entry in paths:
source_path = os.path.join(build_dir, entry['path'])
if os.path.exists(source_path):
target_path = os.path.join(dst_dir, entry['out_path']
if 'out_path' in entry else entry['path'])
make_dir(os.path.dirname(target_path), options.quiet)
if os.path.isdir(source_path):
copy_dir(source_path, target_path, options.quiet)
if 'delete' in entry:
for delete_path in get_files(
os.path.join(target_path, entry['delete'])):
if not os.path.isdir(delete_path):
remove_file(delete_path, options.quiet)
else:
raise Exception('Refusing to delete directory: %s' % delete_path)
else:
copy_file(source_path, target_path, options.quiet)
else:
if 'conditional' in entry and entry['conditional']:
sys.stdout.write('Missing conditional path: %s.\n' % source_path)
else:
raise Exception('Missing required path: %s' % source_path)
def get_exported_symbols(file):
""" Returns the global symbols exported by |file|. """
symbols = []
# Each symbol line has a value like:
# 0000000000000000 T _cef_sandbox_initialize
cmdline = 'nm -g -U %s' % file
result = exec_cmd(cmdline, os.path.join(cef_dir, 'tools'))
if len(result['err']) > 0:
raise Exception('ERROR: nm failed: %s' % result['err'])
for line in result['out'].split('\n'):
if line.find(' T ') < 0:
continue
symbol = line[line.rfind(' ') + 1:]
symbols.append(symbol)
return symbols
def get_undefined_symbols(file):
""" Returns the undefined symbols imported by |file|. """
symbols = []
# Each symbol line has a value like:
# cef_sandbox.a:cef_sandbox.o: _memcpy
cmdline = 'nm -u -A %s' % file
result = exec_cmd(cmdline, os.path.join(cef_dir, 'tools'))
if len(result['err']) > 0:
raise Exception('ERROR: nm failed: %s' % result['err'])
for line in result['out'].split('\n'):
if line.find(': ') < 0:
continue
symbol = line[line.rfind(': ') + 2:]
symbols.append(symbol)
return symbols
def combine_libs(platform, build_dir, libs, dest_lib):
""" Combine multiple static libraries into a single static library. """
intermediate_obj = None
if platform == 'windows':
cmdline = 'msvs_env.bat win%s "%s" combine_libs.py -o "%s"' % (
platform_arch, sys.executable, dest_lib)
elif platform == 'mac':
# Find CEF_EXPORT symbols from libcef_sandbox.a (include/cef_sandbox_mac.h)
# Export only symbols that include these strings.
symbol_match = [
'_cef_', # C symbols
'Cef', # C++ symbols
]
print('Finding exported symbols...')
assert 'libcef_sandbox.a' in libs[0], libs[0]
symbols = []
for symbol in get_exported_symbols(os.path.join(build_dir, libs[0])):
for match in symbol_match:
if symbol.find(match) >= 0:
symbols.append(symbol)
break
assert len(symbols) > 0
# Create an intermediate object file that combines all other object files.
# Symbols not identified above will be made private (local).
intermediate_obj = os.path.splitext(dest_lib)[0] + '.o'
arch = 'arm64' if options.arm64build else 'x86_64'
cmdline = 'ld -arch %s -r -o "%s"' % (arch, intermediate_obj)
for symbol in symbols:
cmdline += ' -exported_symbol %s' % symbol
for lib in libs:
lib_path = os.path.join(build_dir, lib)
for path in get_files(lib_path): # Expand wildcards in |lib_path|.
if not path_exists(path):
raise Exception('File not found: ' + path)
cmdline += ' "%s"' % path
run(cmdline, os.path.join(cef_dir, 'tools'))
if not intermediate_obj is None:
# Create an archive file containing the new object file.
cmdline = 'libtool -static -o "%s" "%s"' % (dest_lib, intermediate_obj)
run(cmdline, os.path.join(cef_dir, 'tools'))
remove_file(intermediate_obj)
# Verify that only the expected symbols are exported from the archive file.
print('Verifying exported symbols...')
result_symbols = get_exported_symbols(dest_lib)
if set(symbols) != set(result_symbols):
print('Expected', symbols)
print('Got', result_symbols)
raise Exception('Failure verifying exported symbols')
# Verify that no C++ symbols are imported by the archive file. If the
# archive imports C++ symbols and the client app links an incompatible C++
# library, the result will be undefined behavior.
# For example, to avoid importing libc++ symbols the cef_sandbox target
# should have a dependency on libc++abi. This dependency can be verified
# with the following command:
# gn path out/[config] //cef:cef_sandbox //buildtools/third_party/libc++abi
print('Verifying imported (undefined) symbols...')
undefined_symbols = get_undefined_symbols(dest_lib)
cpp_symbols = list(
filter(lambda symbol: symbol.startswith('__Z'), undefined_symbols))
if cpp_symbols:
print('Found C++ symbols:', cpp_symbols)
raise Exception('Failure verifying imported (undefined) symbols')
def run(command_line, working_dir):
""" Run a command. """