• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright (c) 2011 The Chromium Embedded Framework Authors. All rights
2# reserved. Use of this source code is governed by a BSD-style license that
3# can be found in the LICENSE file.
4
5from __future__ import absolute_import
6from __future__ import print_function
7from cef_version import VersionFormatter
8from date_util import *
9from exec_util import exec_cmd
10from file_util import *
11import git_util as git
12from io import open
13from make_cmake import process_cmake_template
14from optparse import OptionParser
15import os
16import re
17import shlex
18import subprocess
19import sys
20import tarfile
21import zipfile
22
23
24def create_zip_archive(input_dir):
25  """ Creates a zip archive of the specified input directory. """
26  zip_file = input_dir + '.zip'
27  zf = zipfile.ZipFile(zip_file, 'w', zipfile.ZIP_DEFLATED, True)
28
29  def addDir(dir):
30    for f in os.listdir(dir):
31      full_path = os.path.join(dir, f)
32      if os.path.isdir(full_path):
33        addDir(full_path)
34      else:
35        zf.write(full_path, os.path.relpath(full_path, \
36                 os.path.join(input_dir, os.pardir)))
37
38  addDir(input_dir)
39  zf.close()
40
41
42def create_tar_archive(input_dir, format):
43  """ Creates a tar archive of the specified input directory. """
44  # Supported formats include "gz" and "bz2".
45  tar_file = input_dir + '.tar.' + format
46  tf = tarfile.open(tar_file, "w:" + format)
47  # The default tar format changed from GNU_FORMAT to PAX_FORMAT in Python 3.8.
48  # However, PAX_FORMAT generates additional @PaxHeader entries and truncates file
49  # names on Windows, so we'll stick with the previous default.
50  tf.format = tarfile.GNU_FORMAT
51  tf.add(input_dir, arcname=os.path.basename(input_dir))
52  tf.close()
53
54
55def create_7z_archive(input_dir, format):
56  """ Creates a 7z archive of the specified input directory. """
57  # CEF_COMMAND_7ZIP might be "c:\Program Files (x86)\7Zip\7z.exe" or /usr/bin/7za
58  # or simply 7z if the user knows that it's in the PATH var. Supported formats
59  # depend on the 7za version -- check the 7-zip documentation for details.
60  command = os.environ['CEF_COMMAND_7ZIP']
61  working_dir = os.path.abspath(os.path.join(input_dir, os.pardir))
62
63  tar_file = None
64  if format in ('xz', 'gzip', 'bzip2'):
65    # These formats only support one file per archive. Create a tar file first.
66    tar_file = input_dir + '.tar'
67    run('"%s" a -ttar -y %s %s' % (command, tar_file, input_dir), working_dir)
68    zip_file = tar_file + '.' + format
69    zip_input = tar_file
70  else:
71    zip_file = input_dir + '.' + format
72    zip_input = input_dir
73
74  # Create the compressed archive.
75  run('"%s" a -t%s -y %s %s' % (command, format, zip_file, zip_input),
76      working_dir)
77
78  if not tar_file is None:
79    remove_file(tar_file)
80
81
82def create_output_dir(name, parent_dir):
83  """ Creates an output directory and adds the path to the archive list. """
84  output_dir = os.path.abspath(os.path.join(parent_dir, name))
85  remove_dir(output_dir, options.quiet)
86  make_dir(output_dir, options.quiet)
87  archive_dirs.append(output_dir)
88  return output_dir
89
90
91def get_readme_component(name):
92  """ Loads a README file component. """
93  paths = []
94  # platform directory
95  if platform == 'windows':
96    platform_cmp = 'win'
97  elif platform == 'mac':
98    platform_cmp = 'mac'
99  elif platform == 'linux':
100    platform_cmp = 'linux'
101  paths.append(os.path.join(script_dir, 'distrib', platform_cmp))
102
103  # shared directory
104  paths.append(os.path.join(script_dir, 'distrib'))
105
106  # load the file if it exists
107  for path in paths:
108    file = os.path.join(path, 'README.' + name + '.txt')
109    if path_exists(file):
110      return read_file(file)
111
112  raise Exception('Readme component not found: ' + name)
113
114
115def create_readme():
116  """ Creates the README.TXT file. """
117  # gather the components
118  header_data = get_readme_component('header')
119  mode_data = get_readme_component(mode)
120  redistrib_data = get_readme_component('redistrib')
121  footer_data = get_readme_component('footer')
122
123  # format the file
124  data = header_data + '\n\n' + mode_data
125  if mode != 'sandbox':
126    data += '\n\n' + redistrib_data
127  data += '\n\n' + footer_data
128  data = data.replace('$CEF_URL$', cef_url)
129  data = data.replace('$CEF_REV$', cef_rev)
130  data = data.replace('$CEF_VER$', cef_ver)
131  data = data.replace('$CHROMIUM_URL$', chromium_url)
132  data = data.replace('$CHROMIUM_REV$', chromium_rev)
133  data = data.replace('$CHROMIUM_VER$', chromium_ver)
134  data = data.replace('$DATE$', date)
135
136  if platform == 'windows':
137    platform_str = 'Windows'
138  elif platform == 'mac':
139    platform_str = 'MacOS'
140  elif platform == 'linux':
141    platform_str = 'Linux'
142
143  data = data.replace('$PLATFORM$', platform_str)
144
145  if mode == 'standard':
146    distrib_type = 'Standard'
147    distrib_desc = 'This distribution contains all components necessary to build and distribute an\n' \
148                   'application using CEF on the ' + platform_str + ' platform. Please see the LICENSING\n' \
149                   'section of this document for licensing terms and conditions.'
150  elif mode == 'minimal':
151    distrib_type = 'Minimal'
152    distrib_desc = 'This distribution contains the minimial components necessary to build and\n' \
153                   'distribute an application using CEF on the ' + platform_str + ' platform. Please see\n' \
154                   'the LICENSING section of this document for licensing terms and conditions.'
155  elif mode == 'client':
156    distrib_type = 'Client'
157    if platform == 'linux':
158      client_app = 'cefsimple'
159    else:
160      client_app = 'cefclient'
161    distrib_desc = 'This distribution contains a release build of the ' + client_app + ' sample application\n' \
162                   'for the ' + platform_str + ' platform. Please see the LICENSING section of this document for\n' \
163                   'licensing terms and conditions.'
164  elif mode == 'sandbox':
165    distrib_type = 'Sandbox'
166    distrib_desc = 'This distribution contains only the cef_sandbox static library. Please see\n' \
167                   'the LICENSING section of this document for licensing terms and conditions.'
168
169  data = data.replace('$DISTRIB_TYPE$', distrib_type)
170  data = data.replace('$DISTRIB_DESC$', distrib_desc)
171
172  write_file(os.path.join(output_dir, 'README.txt'), data)
173  if not options.quiet:
174    sys.stdout.write('Creating README.TXT file.\n')
175
176
177def copy_gtest(tests_dir):
178  """ Copy GTest files to the expected directory structure. """
179  if not options.quiet:
180    sys.stdout.write('Building gtest directory structure.\n')
181
182  src_gtest_dir = os.path.join(cef_dir, 'tools', 'distrib', 'gtest')
183  target_gtest_dir = os.path.join(tests_dir, 'gtest')
184
185  # gtest header file at tests/gtest/include/gtest/gtest.h
186  target_gtest_header_dir = os.path.join(target_gtest_dir, 'include', 'gtest')
187  make_dir(target_gtest_header_dir, options.quiet)
188  copy_file(
189      os.path.join(src_gtest_dir, 'gtest.h'), target_gtest_header_dir,
190      options.quiet)
191
192  # gtest source file at tests/gtest/src/gtest-all.cc
193  target_gtest_cpp_dir = os.path.join(target_gtest_dir, 'src')
194  make_dir(target_gtest_cpp_dir, options.quiet)
195  copy_file(
196      os.path.join(src_gtest_dir, 'gtest-all.cc'), target_gtest_cpp_dir,
197      options.quiet)
198
199  # gtest LICENSE file at tests/gtest/LICENSE
200  copy_file(
201      os.path.join(src_gtest_dir, 'LICENSE'), target_gtest_dir, options.quiet)
202
203  # CEF README file at tests/gtest/README.cef
204  copy_file(
205      os.path.join(src_gtest_dir, 'README.cef'),
206      os.path.join(target_gtest_dir, 'README.cef'), options.quiet)
207
208  # Copy tests/gtest/teamcity files
209  copy_dir(
210      os.path.join(cef_dir, 'tests', 'gtest', 'teamcity'),
211      os.path.join(target_gtest_dir, 'teamcity'), options.quiet)
212
213
214def transfer_gypi_files(src_dir, gypi_paths, gypi_path_prefix, dst_dir, quiet):
215  """ Transfer files from one location to another. """
216  for path in gypi_paths:
217    src = os.path.join(src_dir, path)
218    dst = os.path.join(dst_dir, path.replace(gypi_path_prefix, ''))
219    dst_path = os.path.dirname(dst)
220    make_dir(dst_path, quiet)
221    copy_file(src, dst, quiet)
222
223
224def normalize_headers(file, new_path=''):
225  """ Normalize headers post-processing. Remove the path component from any
226      project include directives. """
227  data = read_file(file)
228  data = re.sub(r'''#include \"(?!include\/)[a-zA-Z0-9_\/]+\/+([a-zA-Z0-9_\.]+)\"''', \
229                "// Include path modified for CEF Binary Distribution.\n#include \""+new_path+"\\1\"", data)
230  write_file(file, data)
231
232
233def eval_transfer_file(cef_dir, script_dir, transfer_cfg, output_dir, quiet):
234  """ Transfer files based on the specified configuration. """
235  if not path_exists(transfer_cfg):
236    return
237
238  configs = eval_file(transfer_cfg)
239  for cfg in configs:
240    dst = os.path.join(output_dir, cfg['target'])
241
242    # perform a copy if source is specified
243    if not cfg['source'] is None:
244      src = os.path.join(cef_dir, cfg['source'])
245      dst_path = os.path.dirname(dst)
246      make_dir(dst_path, quiet)
247      copy_file(src, dst, quiet)
248
249      # place a readme file in the destination directory
250      readme = os.path.join(dst_path, 'README-TRANSFER.txt')
251      if not path_exists(readme):
252        copy_file(
253            os.path.join(script_dir, 'distrib/README-TRANSFER.txt'), readme)
254
255      str = cfg['source'] + "\n"
256      with open(readme, 'a', encoding='utf-8') as fp:
257        if sys.version_info.major == 2:
258          fp.write(str.decode('utf-8'))
259        else:
260          fp.write(str)
261
262    # perform any required post-processing
263    if 'post-process' in cfg:
264      post = cfg['post-process']
265      if post == 'normalize_headers':
266        new_path = ''
267        if 'new_header_path' in cfg:
268          new_path = cfg['new_header_path']
269        normalize_headers(dst, new_path)
270
271
272def transfer_files(cef_dir, script_dir, transfer_cfg_dir, mode, output_dir,
273                   quiet):
274  # Non-mode-specific transfers.
275  transfer_cfg = os.path.join(transfer_cfg_dir, 'transfer.cfg')
276  eval_transfer_file(cef_dir, script_dir, transfer_cfg, output_dir, quiet)
277  # Mode-specific transfers.
278  transfer_cfg = os.path.join(transfer_cfg_dir, 'transfer_%s.cfg' % mode)
279  eval_transfer_file(cef_dir, script_dir, transfer_cfg, output_dir, quiet)
280
281
282# |paths| is a list of dictionary values with the following keys:
283# path        [required]  Input file or directory path relative to |build_dir|.
284#                         By default this will also be the output path relative
285#                         to |dst_dir|.
286# out_path    [optional]  Override the output path relative to |dst_dir|.
287# conditional [optional]  Set to True if the path is conditional on build
288#                         settings. Missing conditional paths will not be
289#                         treated as an error.
290# delete      [optional]  Glob pattern of files to delete after the copy.
291def copy_files_list(build_dir, dst_dir, paths):
292  ''' Copy the files listed in |paths| from |build_dir| to |dst_dir|. '''
293  for entry in paths:
294    source_path = os.path.join(build_dir, entry['path'])
295    if os.path.exists(source_path):
296      target_path = os.path.join(dst_dir, entry['out_path']
297                                 if 'out_path' in entry else entry['path'])
298      make_dir(os.path.dirname(target_path), options.quiet)
299      if os.path.isdir(source_path):
300        copy_dir(source_path, target_path, options.quiet)
301        if 'delete' in entry:
302          for delete_path in get_files(
303              os.path.join(target_path, entry['delete'])):
304            if not os.path.isdir(delete_path):
305              remove_file(delete_path, options.quiet)
306            else:
307              raise Exception('Refusing to delete directory: %s' % delete_path)
308      else:
309        copy_file(source_path, target_path, options.quiet)
310    else:
311      if 'conditional' in entry and entry['conditional']:
312        sys.stdout.write('Missing conditional path: %s.\n' % source_path)
313      else:
314        raise Exception('Missing required path: %s' % source_path)
315
316
317def get_exported_symbols(file):
318  """ Returns the global symbols exported by |file|. """
319  symbols = []
320
321  # Each symbol line has a value like:
322  # 0000000000000000 T _cef_sandbox_initialize
323  cmdline = 'nm -g -U %s' % file
324  result = exec_cmd(cmdline, os.path.join(cef_dir, 'tools'))
325  if len(result['err']) > 0:
326    raise Exception('ERROR: nm failed: %s' % result['err'])
327  for line in result['out'].split('\n'):
328    if line.find(' T ') < 0:
329      continue
330    symbol = line[line.rfind(' ') + 1:]
331    symbols.append(symbol)
332
333  return symbols
334
335
336def get_undefined_symbols(file):
337  """ Returns the undefined symbols imported by |file|. """
338  symbols = []
339
340  # Each symbol line has a value like:
341  # cef_sandbox.a:cef_sandbox.o: _memcpy
342  cmdline = 'nm -u -A %s' % file
343  result = exec_cmd(cmdline, os.path.join(cef_dir, 'tools'))
344  if len(result['err']) > 0:
345    raise Exception('ERROR: nm failed: %s' % result['err'])
346  for line in result['out'].split('\n'):
347    if line.find(': ') < 0:
348      continue
349    symbol = line[line.rfind(': ') + 2:]
350    symbols.append(symbol)
351
352  return symbols
353
354
355def combine_libs(platform, build_dir, libs, dest_lib):
356  """ Combine multiple static libraries into a single static library. """
357  intermediate_obj = None
358  if platform == 'windows':
359    cmdline = 'msvs_env.bat win%s "%s" combine_libs.py -o "%s"' % (
360        platform_arch, sys.executable, dest_lib)
361  elif platform == 'mac':
362    # Find CEF_EXPORT symbols from libcef_sandbox.a (include/cef_sandbox_mac.h)
363    # Export only symbols that include these strings.
364    symbol_match = [
365        '_cef_',  # C symbols
366        'Cef',  # C++ symbols
367    ]
368
369    print('Finding exported symbols...')
370    assert 'libcef_sandbox.a' in libs[0], libs[0]
371    symbols = []
372    for symbol in get_exported_symbols(os.path.join(build_dir, libs[0])):
373      for match in symbol_match:
374        if symbol.find(match) >= 0:
375          symbols.append(symbol)
376          break
377    assert len(symbols) > 0
378
379    # Create an intermediate object file that combines all other object files.
380    # Symbols not identified above will be made private (local).
381    intermediate_obj = os.path.splitext(dest_lib)[0] + '.o'
382    arch = 'arm64' if options.arm64build else 'x86_64'
383    cmdline = 'ld -arch %s -r -o "%s"' % (arch, intermediate_obj)
384    for symbol in symbols:
385      cmdline += ' -exported_symbol %s' % symbol
386
387  for lib in libs:
388    lib_path = os.path.join(build_dir, lib)
389    for path in get_files(lib_path):  # Expand wildcards in |lib_path|.
390      if not path_exists(path):
391        raise Exception('File not found: ' + path)
392      cmdline += ' "%s"' % path
393  run(cmdline, os.path.join(cef_dir, 'tools'))
394
395  if not intermediate_obj is None:
396    # Create an archive file containing the new object file.
397    cmdline = 'libtool -static -o "%s" "%s"' % (dest_lib, intermediate_obj)
398    run(cmdline, os.path.join(cef_dir, 'tools'))
399    remove_file(intermediate_obj)
400
401    # Verify that only the expected symbols are exported from the archive file.
402    print('Verifying exported symbols...')
403    result_symbols = get_exported_symbols(dest_lib)
404    if set(symbols) != set(result_symbols):
405      print('Expected', symbols)
406      print('Got', result_symbols)
407      raise Exception('Failure verifying exported symbols')
408
409    # Verify that no C++ symbols are imported by the archive file. If the
410    # archive imports C++ symbols and the client app links an incompatible C++
411    # library, the result will be undefined behavior.
412    # For example, to avoid importing libc++ symbols the cef_sandbox target
413    # should have a dependency on libc++abi. This dependency can be verified
414    # with the following command:
415    # gn path out/[config] //cef:cef_sandbox //buildtools/third_party/libc++abi
416    print('Verifying imported (undefined) symbols...')
417    undefined_symbols = get_undefined_symbols(dest_lib)
418    cpp_symbols = list(
419        filter(lambda symbol: symbol.startswith('__Z'), undefined_symbols))
420    if cpp_symbols:
421      print('Found C++ symbols:', cpp_symbols)
422      raise Exception('Failure verifying imported (undefined) symbols')
423
424
425def run(command_line, working_dir):
426  """ Run a command. """
427  sys.stdout.write('-------- Running "'+command_line+'" in "'+\
428                   working_dir+'"...'+"\n")
429  args = shlex.split(command_line.replace('\\', '\\\\'))
430  return subprocess.check_call(
431      args, cwd=working_dir, env=os.environ, shell=(sys.platform == 'win32'))
432
433
434def print_error(msg):
435  print('Error: %s\nSee --help for usage.' % msg)
436
437
438# cannot be loaded as a module
439if __name__ != "__main__":
440  sys.stderr.write('This file cannot be loaded as a module!')
441  sys.exit()
442
443# parse command-line options
444disc = """
445This utility builds the CEF Binary Distribution.
446"""
447
448parser = OptionParser(description=disc)
449parser.add_option(
450    '--output-dir',
451    dest='outputdir',
452    metavar='DIR',
453    help='output directory [required]')
454parser.add_option(
455    '--distrib-subdir',
456    dest='distribsubdir',
457    help='name of the subdirectory for the distribution',
458    default='')
459parser.add_option(
460    '--distrib-subdir-suffix',
461    dest='distribsubdirsuffix',
462    help='suffix added to name of the subdirectory for the distribution',
463    default='')
464parser.add_option(
465    '--allow-partial',
466    action='store_true',
467    dest='allowpartial',
468    default=False,
469    help='allow creation of partial distributions')
470parser.add_option(
471    '--no-symbols',
472    action='store_true',
473    dest='nosymbols',
474    default=False,
475    help='don\'t create symbol files')
476parser.add_option(
477    '--no-docs',
478    action='store_true',
479    dest='nodocs',
480    default=False,
481    help='don\'t create documentation')
482parser.add_option(
483    '--no-archive',
484    action='store_true',
485    dest='noarchive',
486    default=False,
487    help='don\'t create archives for output directories')
488parser.add_option(
489    '--ninja-build',
490    action='store_true',
491    dest='ninjabuild',
492    default=False,
493    help='build was created using ninja')
494parser.add_option(
495    '--x64-build',
496    action='store_true',
497    dest='x64build',
498    default=False,
499    help='create a 64-bit binary distribution')
500parser.add_option(
501    '--arm-build',
502    action='store_true',
503    dest='armbuild',
504    default=False,
505    help='create an ARM binary distribution (Linux only)')
506parser.add_option(
507    '--arm64-build',
508    action='store_true',
509    dest='arm64build',
510    default=False,
511    help='create an ARM64 binary distribution (Linux only)')
512parser.add_option(
513    '--minimal',
514    action='store_true',
515    dest='minimal',
516    default=False,
517    help='include only release build binary files')
518parser.add_option(
519    '--client',
520    action='store_true',
521    dest='client',
522    default=False,
523    help='include only the sample application')
524parser.add_option(
525    '--sandbox',
526    action='store_true',
527    dest='sandbox',
528    default=False,
529    help='include only the cef_sandbox static library (macOS and Windows only)')
530parser.add_option(
531    '--ozone',
532    action='store_true',
533    dest='ozone',
534    default=False,
535    help='include ozone build related files (Linux only)')
536parser.add_option(
537    '-q',
538    '--quiet',
539    action='store_true',
540    dest='quiet',
541    default=False,
542    help='do not output detailed status information')
543(options, args) = parser.parse_args()
544
545# Test the operating system.
546platform = ''
547if sys.platform == 'win32':
548  platform = 'windows'
549elif sys.platform == 'darwin':
550  platform = 'mac'
551elif sys.platform.startswith('linux'):
552  platform = 'linux'
553
554# the outputdir option is required
555if options.outputdir is None:
556  print_error('--output-dir is required.')
557  sys.exit()
558
559if options.minimal and options.client:
560  print_error('Cannot specify both --minimal and --client.')
561  sys.exit()
562
563if options.x64build + options.armbuild + options.arm64build > 1:
564  print_error('Invalid combination of build options.')
565  sys.exit()
566
567if options.armbuild and platform != 'linux':
568  print_error('--arm-build is only supported on Linux.')
569  sys.exit()
570
571if options.sandbox and not platform in ('mac', 'windows'):
572  print_error('--sandbox is only supported on macOS and Windows.')
573  sys.exit()
574
575if not options.ninjabuild:
576  print_error('--ninja-build is required.')
577  sys.exit()
578
579if options.ozone and platform != 'linux':
580  print_error('--ozone is only supported on Linux.')
581  sys.exit()
582
583# script directory
584script_dir = os.path.dirname(__file__)
585
586# CEF root directory
587cef_dir = os.path.abspath(os.path.join(script_dir, os.pardir))
588
589# src directory
590src_dir = os.path.abspath(os.path.join(cef_dir, os.pardir))
591
592if not git.is_checkout(cef_dir):
593  raise Exception('Not a valid checkout: %s' % (cef_dir))
594
595# retrieve information for CEF
596cef_url = git.get_url(cef_dir)
597cef_rev = git.get_hash(cef_dir)
598cef_commit_number = git.get_commit_number(cef_dir)
599
600if not git.is_checkout(src_dir):
601  raise Exception('Not a valid checkout: %s' % (src_dir))
602
603# retrieve information for Chromium
604chromium_url = git.get_url(src_dir)
605chromium_rev = git.get_hash(src_dir)
606
607date = get_date()
608
609# format version strings
610formatter = VersionFormatter()
611cef_ver = formatter.get_version_string()
612chromium_ver = formatter.get_chromium_version_string()
613
614# list of output directories to be archived
615archive_dirs = []
616
617if options.x64build:
618  platform_arch = '64'
619  binary_arch = 'x64'
620elif options.armbuild:
621  platform_arch = 'arm'
622  binary_arch = 'arm'
623elif options.arm64build:
624  platform_arch = 'arm64'
625  binary_arch = 'arm64'
626else:
627  platform_arch = '32'
628  binary_arch = 'x86'
629
630# output directory
631output_dir_base = 'cef_binary_' + cef_ver
632
633if options.distribsubdir == '':
634  if platform == 'mac':
635    # For backwards compatibility keep the old default directory name on mac.
636    platform_name = 'macos' + ('x' if platform_arch == '64' else '')
637  else:
638    platform_name = platform
639
640  output_dir_name = output_dir_base + '_' + platform_name + platform_arch
641  if options.distribsubdirsuffix != '':
642    output_dir_name += '_' + options.distribsubdirsuffix
643else:
644  output_dir_name = options.distribsubdir
645
646if options.minimal:
647  mode = 'minimal'
648  output_dir_name = output_dir_name + '_minimal'
649elif options.client:
650  mode = 'client'
651  output_dir_name = output_dir_name + '_client'
652elif options.sandbox:
653  mode = 'sandbox'
654  output_dir_name = output_dir_name + '_sandbox'
655else:
656  mode = 'standard'
657
658if options.ozone:
659  output_dir_name = output_dir_name + '_ozone'
660
661output_dir = create_output_dir(output_dir_name, options.outputdir)
662
663# create the README.TXT file
664create_readme()
665
666# transfer the LICENSE.txt file
667copy_file(os.path.join(cef_dir, 'LICENSE.txt'), output_dir, options.quiet)
668
669# read the variables list from the autogenerated cef_paths.gypi file
670cef_paths = eval_file(os.path.join(cef_dir, 'cef_paths.gypi'))
671cef_paths = cef_paths['variables']
672
673# read the variables list from the manually edited cef_paths2.gypi file
674cef_paths2 = eval_file(os.path.join(cef_dir, 'cef_paths2.gypi'))
675cef_paths2 = cef_paths2['variables']
676
677# Determine the build directory suffix. CEF uses a consistent directory naming
678# scheme for GN via GetAllPlatformConfigs in gn_args.py.
679if options.x64build:
680  build_dir_suffix = '_GN_x64'
681elif options.armbuild:
682  build_dir_suffix = '_GN_arm'
683elif options.arm64build:
684  build_dir_suffix = '_GN_arm64'
685else:
686  build_dir_suffix = '_GN_x86'
687
688# Determine the build directory paths.
689out_dir = os.path.join(src_dir, 'out')
690build_dir_debug = os.path.join(out_dir, 'Debug' + build_dir_suffix)
691build_dir_release = os.path.join(out_dir, 'Release' + build_dir_suffix)
692
693if mode == 'standard' or mode == 'minimal':
694  # create the include directory
695  include_dir = os.path.join(output_dir, 'include')
696  make_dir(include_dir, options.quiet)
697
698  # create the cmake directory
699  cmake_dir = os.path.join(output_dir, 'cmake')
700  make_dir(cmake_dir, options.quiet)
701
702  # create the libcef_dll_wrapper directory
703  libcef_dll_dir = os.path.join(output_dir, 'libcef_dll')
704  make_dir(libcef_dll_dir, options.quiet)
705
706  # transfer common include files
707  transfer_gypi_files(cef_dir, cef_paths2['includes_common'], \
708                      'include/', include_dir, options.quiet)
709  transfer_gypi_files(cef_dir, cef_paths2['includes_common_capi'], \
710                      'include/', include_dir, options.quiet)
711  transfer_gypi_files(cef_dir, cef_paths2['includes_capi'], \
712                      'include/', include_dir, options.quiet)
713  transfer_gypi_files(cef_dir, cef_paths2['includes_wrapper'], \
714                      'include/', include_dir, options.quiet)
715  transfer_gypi_files(cef_dir, cef_paths['autogen_cpp_includes'], \
716                      'include/', include_dir, options.quiet)
717  transfer_gypi_files(cef_dir, cef_paths['autogen_capi_includes'], \
718                      'include/', include_dir, options.quiet)
719
720  # Transfer generated include files.
721  generated_includes = [
722      'cef_config.h',
723      'cef_pack_resources.h',
724      'cef_pack_strings.h',
725  ]
726  for include in generated_includes:
727    # Debug and Release build should be the same so grab whichever exists.
728    src_path = os.path.join(build_dir_release, 'includes', 'include', include)
729    if not os.path.exists(src_path):
730      src_path = os.path.join(build_dir_debug, 'includes', 'include', include)
731      if not os.path.exists(src_path):
732        raise Exception('Missing generated header file: %s' % include)
733    copy_file(src_path, os.path.join(include_dir, include), options.quiet)
734
735  # transfer common libcef_dll_wrapper files
736  transfer_gypi_files(cef_dir, cef_paths2['libcef_dll_wrapper_sources_base'], \
737                      'libcef_dll/', libcef_dll_dir, options.quiet)
738  transfer_gypi_files(cef_dir, cef_paths2['libcef_dll_wrapper_sources_common'], \
739                      'libcef_dll/', libcef_dll_dir, options.quiet)
740  transfer_gypi_files(cef_dir, cef_paths['autogen_client_side'], \
741                      'libcef_dll/', libcef_dll_dir, options.quiet)
742
743  if mode == 'standard' or mode == 'minimal':
744    # transfer additional files
745    transfer_files(cef_dir, script_dir, os.path.join(script_dir, 'distrib'), \
746                   mode, output_dir, options.quiet)
747
748  # process cmake templates
749  variables = cef_paths.copy()
750  variables.update(cef_paths2)
751  process_cmake_template(os.path.join(cef_dir, 'CMakeLists.txt.in'), \
752                         os.path.join(output_dir, 'CMakeLists.txt'), \
753                         variables, options.quiet)
754  process_cmake_template(os.path.join(cef_dir, 'cmake', 'cef_macros.cmake.in'), \
755                         os.path.join(cmake_dir, 'cef_macros.cmake'), \
756                         variables, options.quiet)
757  process_cmake_template(os.path.join(cef_dir, 'cmake', 'cef_variables.cmake.in'), \
758                         os.path.join(cmake_dir, 'cef_variables.cmake'), \
759                         variables, options.quiet)
760  process_cmake_template(os.path.join(cef_dir, 'cmake', 'FindCEF.cmake.in'), \
761                         os.path.join(cmake_dir, 'FindCEF.cmake'), \
762                         variables, options.quiet)
763  process_cmake_template(os.path.join(cef_dir, 'libcef_dll', 'CMakeLists.txt.in'), \
764                         os.path.join(libcef_dll_dir, 'CMakeLists.txt'), \
765                         variables, options.quiet)
766
767if mode == 'standard':
768  # create the tests directory
769  tests_dir = os.path.join(output_dir, 'tests')
770  make_dir(tests_dir, options.quiet)
771
772  # create the tests/shared directory
773  shared_dir = os.path.join(tests_dir, 'shared')
774  make_dir(shared_dir, options.quiet)
775
776  if not options.ozone:
777    # create the tests/cefclient directory
778    cefclient_dir = os.path.join(tests_dir, 'cefclient')
779    make_dir(cefclient_dir, options.quiet)
780
781  # create the tests/cefsimple directory
782  cefsimple_dir = os.path.join(tests_dir, 'cefsimple')
783  make_dir(cefsimple_dir, options.quiet)
784
785  # create the tests/ceftests directory
786  ceftests_dir = os.path.join(tests_dir, 'ceftests')
787  make_dir(ceftests_dir, options.quiet)
788
789  # transfer common shared files
790  transfer_gypi_files(cef_dir, cef_paths2['shared_sources_browser'], \
791                      'tests/shared/', shared_dir, options.quiet)
792  transfer_gypi_files(cef_dir, cef_paths2['shared_sources_common'], \
793                      'tests/shared/', shared_dir, options.quiet)
794  transfer_gypi_files(cef_dir, cef_paths2['shared_sources_renderer'], \
795                      'tests/shared/', shared_dir, options.quiet)
796  transfer_gypi_files(cef_dir, cef_paths2['shared_sources_resources'], \
797                      'tests/shared/', shared_dir, options.quiet)
798
799  if not options.ozone:
800    # transfer common cefclient files
801    transfer_gypi_files(cef_dir, cef_paths2['cefclient_sources_browser'], \
802                        'tests/cefclient/', cefclient_dir, options.quiet)
803    transfer_gypi_files(cef_dir, cef_paths2['cefclient_sources_common'], \
804                        'tests/cefclient/', cefclient_dir, options.quiet)
805    transfer_gypi_files(cef_dir, cef_paths2['cefclient_sources_renderer'], \
806                        'tests/cefclient/', cefclient_dir, options.quiet)
807    transfer_gypi_files(cef_dir, cef_paths2['cefclient_sources_resources'], \
808                        'tests/cefclient/', cefclient_dir, options.quiet)
809    transfer_gypi_files(cef_dir, cef_paths2['cefclient_sources_resources_extensions_set_page_color'], \
810                        'tests/cefclient/', cefclient_dir, options.quiet)
811
812  # transfer common cefsimple files
813  transfer_gypi_files(cef_dir, cef_paths2['cefsimple_sources_common'], \
814                      'tests/cefsimple/', cefsimple_dir, options.quiet)
815
816  # transfer common ceftests files
817  transfer_gypi_files(cef_dir, cef_paths2['ceftests_sources_common'], \
818                      'tests/ceftests/', ceftests_dir, options.quiet)
819
820  # copy GTest files
821  copy_gtest(tests_dir)
822
823  # process cmake templates
824  if not options.ozone:
825    process_cmake_template(os.path.join(cef_dir, 'tests', 'cefclient', 'CMakeLists.txt.in'), \
826                           os.path.join(cefclient_dir, 'CMakeLists.txt'), \
827                           variables, options.quiet)
828  process_cmake_template(os.path.join(cef_dir, 'tests', 'cefsimple', 'CMakeLists.txt.in'), \
829                         os.path.join(cefsimple_dir, 'CMakeLists.txt'), \
830                         variables, options.quiet)
831  process_cmake_template(os.path.join(cef_dir, 'tests', 'gtest', 'CMakeLists.txt.in'), \
832                         os.path.join(tests_dir, 'gtest', 'CMakeLists.txt'), \
833                         variables, options.quiet)
834  process_cmake_template(os.path.join(cef_dir, 'tests', 'ceftests', 'CMakeLists.txt.in'), \
835                         os.path.join(ceftests_dir, 'CMakeLists.txt'), \
836                         variables, options.quiet)
837
838  # transfer gypi files
839  copy_file(os.path.join(cef_dir, 'cef_paths.gypi'), \
840            os.path.join(output_dir, 'cef_paths.gypi'), options.quiet)
841  copy_file(os.path.join(cef_dir, 'cef_paths2.gypi'), \
842            os.path.join(output_dir, 'cef_paths2.gypi'), options.quiet)
843
844if platform == 'windows':
845  libcef_dll = 'libcef.dll'
846  libcef_dll_lib = '%s.lib' % libcef_dll
847  libcef_dll_pdb = '%s.pdb' % libcef_dll
848  # yapf: disable
849  binaries = [
850      {'path': 'chrome_elf.dll'},
851      {'path': libcef_dll},
852      {'path': 'libEGL.dll'},
853      {'path': 'libGLESv2.dll'},
854      {'path': 'snapshot_blob.bin', 'conditional': True},
855      {'path': 'v8_context_snapshot.bin', 'conditional': True},
856      {'path': 'vk_swiftshader.dll'},
857      {'path': 'vk_swiftshader_icd.json'},
858      {'path': 'vulkan-1.dll'},
859      {'path': 'swiftshader\\libEGL.dll'},
860      {'path': 'swiftshader\\libGLESv2.dll'},
861  ]
862  # yapf: enable
863
864  if mode == 'client':
865    binaries.append({
866        'path': 'cefsimple.exe' if platform_arch == 'arm64' else 'cefclient.exe'
867    })
868  else:
869    binaries.append({'path': libcef_dll_lib, 'out_path': 'libcef.lib'})
870
871  # yapf: disable
872  resources = [
873      {'path': 'chrome_100_percent.pak'},
874      {'path': 'chrome_200_percent.pak'},
875      {'path': 'resources.pak'},
876      {'path': 'icudtl.dat'},
877      {'path': 'locales', 'delete': '*.info'},
878  ]
879  # yapf: enable
880
881  cef_sandbox_lib = 'obj\\cef\\cef_sandbox.lib'
882  sandbox_libs = [
883      'obj\\base\\base.lib',
884      'obj\\base\\base_static.lib',
885      'obj\\base\\third_party\\double_conversion\\double_conversion.lib',
886      'obj\\base\\third_party\\dynamic_annotations\\dynamic_annotations.lib',
887      'obj\\base\\win\\pe_image.lib',
888      cef_sandbox_lib,
889      'obj\\sandbox\\win\\sandbox.lib',
890      'obj\\third_party\\abseil-cpp\\absl\\base\\**\\*.obj',
891      'obj\\third_party\\abseil-cpp\\absl\\debugging\\**\\*.obj',
892      'obj\\third_party\\abseil-cpp\\absl\\numeric\\**\\*.obj',
893      'obj\\third_party\\abseil-cpp\\absl\\synchronization\\**\\*.obj',
894      'obj\\third_party\\abseil-cpp\\absl\\time\\**\\*.obj',
895      'obj\\third_party\\abseil-cpp\\absl\\types\\**\\*.obj',
896  ]
897
898  # Generate the cef_sandbox.lib merged library. A separate *_sandbox build
899  # should exist when GN is_official_build=true.
900  if mode in ('standard', 'minimal', 'sandbox'):
901    dirs = {
902        'Debug': (build_dir_debug + '_sandbox', build_dir_debug),
903        'Release': (build_dir_release + '_sandbox', build_dir_release)
904    }
905    for dir_name in dirs.keys():
906      for src_dir in dirs[dir_name]:
907        if path_exists(os.path.join(src_dir, cef_sandbox_lib)):
908          dst_dir = os.path.join(output_dir, dir_name)
909          make_dir(dst_dir, options.quiet)
910          combine_libs(platform, src_dir, sandbox_libs,
911                       os.path.join(dst_dir, 'cef_sandbox.lib'))
912          break
913
914  valid_build_dir = None
915
916  if mode == 'standard':
917    # transfer Debug files
918    build_dir = build_dir_debug
919    if not options.allowpartial or path_exists(
920        os.path.join(build_dir, libcef_dll)):
921      valid_build_dir = build_dir
922      dst_dir = os.path.join(output_dir, 'Debug')
923      copy_files_list(build_dir, dst_dir, binaries)
924      copy_files(
925          os.path.join(script_dir, 'distrib/win/%s/*.dll' % binary_arch),
926          dst_dir, options.quiet)
927
928      if not options.nosymbols:
929        # create the symbol output directory
930        symbol_output_dir = create_output_dir(
931            output_dir_name + '_debug_symbols', options.outputdir)
932        # transfer contents
933        copy_file(
934            os.path.join(build_dir, libcef_dll_pdb), symbol_output_dir,
935            options.quiet)
936    else:
937      sys.stdout.write("No Debug build files.\n")
938
939  if mode != 'sandbox':
940    # transfer Release files
941    build_dir = build_dir_release
942    if not options.allowpartial or path_exists(
943        os.path.join(build_dir, libcef_dll)):
944      valid_build_dir = build_dir
945      dst_dir = os.path.join(output_dir, 'Release')
946      copy_files_list(build_dir, dst_dir, binaries)
947      copy_files(
948          os.path.join(script_dir, 'distrib/win/%s/*.dll' % binary_arch),
949          dst_dir, options.quiet)
950
951      if not options.nosymbols:
952        # create the symbol output directory
953        symbol_output_dir = create_output_dir(
954            output_dir_name + '_release_symbols', options.outputdir)
955        # transfer contents
956        copy_file(
957            os.path.join(build_dir, libcef_dll_pdb), symbol_output_dir,
958            options.quiet)
959    else:
960      sys.stdout.write("No Release build files.\n")
961
962  if not valid_build_dir is None:
963    # transfer resource files
964    build_dir = valid_build_dir
965    if mode == 'client':
966      dst_dir = os.path.join(output_dir, 'Release')
967    else:
968      dst_dir = os.path.join(output_dir, 'Resources')
969    copy_files_list(build_dir, dst_dir, resources)
970
971  if mode == 'standard' or mode == 'minimal':
972    # transfer include files
973    transfer_gypi_files(cef_dir, cef_paths2['includes_win'], \
974                        'include/', include_dir, options.quiet)
975    transfer_gypi_files(cef_dir, cef_paths2['includes_win_capi'], \
976                        'include/', include_dir, options.quiet)
977
978    # transfer additional files, if any
979    transfer_files(cef_dir, script_dir, os.path.join(script_dir, 'distrib', 'win'), \
980                   mode, output_dir, options.quiet)
981
982  if mode == 'standard':
983    # transfer shared files
984    transfer_gypi_files(cef_dir, cef_paths2['shared_sources_win'], \
985                        'tests/shared/', shared_dir, options.quiet)
986
987    # transfer cefclient files
988    transfer_gypi_files(cef_dir, cef_paths2['cefclient_sources_win'], \
989                        'tests/cefclient/', cefclient_dir, options.quiet)
990    transfer_gypi_files(cef_dir, cef_paths2['cefclient_sources_resources_win'], \
991                        'tests/cefclient/', cefclient_dir, options.quiet)
992
993    # transfer cefsimple files
994    transfer_gypi_files(cef_dir, cef_paths2['cefsimple_sources_win'], \
995                        'tests/cefsimple/', cefsimple_dir, options.quiet)
996    transfer_gypi_files(cef_dir, cef_paths2['cefsimple_sources_resources_win'], \
997                        'tests/cefsimple/', cefsimple_dir, options.quiet)
998
999    # transfer ceftests files
1000    transfer_gypi_files(cef_dir, cef_paths2['ceftests_sources_win'], \
1001                        'tests/ceftests/', ceftests_dir, options.quiet)
1002    transfer_gypi_files(cef_dir, cef_paths2['ceftests_sources_resources_win'], \
1003                        'tests/ceftests/', ceftests_dir, options.quiet)
1004
1005  if not options.nodocs:
1006    # generate doc files
1007    os.popen('make_cppdocs.bat ' + cef_rev)
1008
1009    src_dir = os.path.join(cef_dir, 'docs')
1010    if path_exists(src_dir):
1011      # create the docs output directory
1012      docs_output_dir = create_output_dir(output_dir_base + '_docs',
1013                                          options.outputdir)
1014      # transfer contents
1015      copy_dir(src_dir, docs_output_dir, options.quiet)
1016
1017elif platform == 'mac':
1018  framework_name = 'Chromium Embedded Framework'
1019  framework_dsym = '%s.dSYM' % framework_name
1020  cefclient_app = 'cefclient.app'
1021
1022  cef_sandbox_lib = 'obj/cef/libcef_sandbox.a'
1023  sandbox_libs = [
1024      cef_sandbox_lib,
1025      'obj/sandbox/mac/libseatbelt.a',
1026      'obj/sandbox/mac/libseatbelt_proto.a',
1027      'obj/third_party/protobuf/libprotobuf_lite.a',
1028      'obj/buildtools/third_party/libc++/libc++/*.o',
1029      'obj/buildtools/third_party/libc++abi/libc++abi/*.o',
1030  ]
1031
1032  # Generate the cef_sandbox.a merged library. A separate *_sandbox build
1033  # should exist when GN is_official_build=true.
1034  if mode in ('standard', 'minimal', 'sandbox'):
1035    dirs = {
1036        'Debug': (build_dir_debug + '_sandbox', build_dir_debug),
1037        'Release': (build_dir_release + '_sandbox', build_dir_release)
1038    }
1039    for dir_name in dirs.keys():
1040      for src_dir in dirs[dir_name]:
1041        if path_exists(os.path.join(src_dir, cef_sandbox_lib)):
1042          dst_dir = os.path.join(output_dir, dir_name)
1043          make_dir(dst_dir, options.quiet)
1044          combine_libs(platform, src_dir, sandbox_libs,
1045                       os.path.join(dst_dir, 'cef_sandbox.a'))
1046          break
1047
1048  valid_build_dir = None
1049
1050  if mode == 'standard':
1051    # transfer Debug files
1052    build_dir = build_dir_debug
1053    if not options.allowpartial or path_exists(
1054        os.path.join(build_dir, cefclient_app)):
1055      valid_build_dir = build_dir
1056      dst_dir = os.path.join(output_dir, 'Debug')
1057      make_dir(dst_dir, options.quiet)
1058      framework_src_dir = os.path.join(
1059          build_dir, '%s/Contents/Frameworks/%s.framework/Versions/A' %
1060          (cefclient_app, framework_name))
1061      framework_dst_dir = os.path.join(dst_dir, '%s.framework' % framework_name)
1062      copy_dir(framework_src_dir, framework_dst_dir, options.quiet)
1063
1064      if not options.nosymbols:
1065        # create the symbol output directory
1066        symbol_output_dir = create_output_dir(
1067            output_dir_name + '_debug_symbols', options.outputdir)
1068
1069        # The real dSYM already exists, just copy it to the output directory.
1070        # dSYMs are only generated when is_official_build=true or enable_dsyms=true.
1071        # See //build/config/mac/symbols.gni.
1072        copy_dir(
1073            os.path.join(build_dir, framework_dsym),
1074            os.path.join(symbol_output_dir, framework_dsym), options.quiet)
1075    else:
1076      sys.stdout.write("No Debug build files.\n")
1077
1078  if mode != 'sandbox':
1079    # transfer Release files
1080    build_dir = build_dir_release
1081    if not options.allowpartial or path_exists(
1082        os.path.join(build_dir, cefclient_app)):
1083      valid_build_dir = build_dir
1084      dst_dir = os.path.join(output_dir, 'Release')
1085      make_dir(dst_dir, options.quiet)
1086      framework_src_dir = os.path.join(
1087          build_dir, '%s/Contents/Frameworks/%s.framework/Versions/A' %
1088          (cefclient_app, framework_name))
1089      if mode != 'client':
1090        framework_dst_dir = os.path.join(dst_dir,
1091                                         '%s.framework' % framework_name)
1092      else:
1093        copy_dir(
1094            os.path.join(build_dir, cefclient_app),
1095            os.path.join(dst_dir, cefclient_app), options.quiet)
1096        # Replace the versioned framework with an unversioned framework in the sample app.
1097        framework_dst_dir = os.path.join(
1098            dst_dir, '%s/Contents/Frameworks/%s.framework' % (cefclient_app,
1099                                                              framework_name))
1100        remove_dir(framework_dst_dir, options.quiet)
1101      copy_dir(framework_src_dir, framework_dst_dir, options.quiet)
1102
1103      if not options.nosymbols:
1104        # create the symbol output directory
1105        symbol_output_dir = create_output_dir(
1106            output_dir_name + '_release_symbols', options.outputdir)
1107
1108        # The real dSYM already exists, just copy it to the output directory.
1109        # dSYMs are only generated when is_official_build=true or enable_dsyms=true.
1110        # See //build/config/mac/symbols.gni.
1111        copy_dir(
1112            os.path.join(build_dir, framework_dsym),
1113            os.path.join(symbol_output_dir, framework_dsym), options.quiet)
1114    else:
1115      sys.stdout.write("No Release build files.\n")
1116
1117  if mode == 'standard' or mode == 'minimal':
1118    # transfer include files
1119    transfer_gypi_files(cef_dir, cef_paths2['includes_mac'], \
1120                        'include/', include_dir, options.quiet)
1121    transfer_gypi_files(cef_dir, cef_paths2['includes_mac_capi'], \
1122                        'include/', include_dir, options.quiet)
1123    transfer_gypi_files(cef_dir, cef_paths2['includes_wrapper_mac'], \
1124                        'include/', include_dir, options.quiet)
1125
1126    # transfer libcef_dll_wrapper files
1127    transfer_gypi_files(cef_dir, cef_paths2['libcef_dll_wrapper_sources_mac'], \
1128                      'libcef_dll/', libcef_dll_dir, options.quiet)
1129
1130    # transfer additional files, if any
1131    transfer_files(cef_dir, script_dir, os.path.join(script_dir, 'distrib', 'mac'), \
1132                   mode, output_dir, options.quiet)
1133
1134  if mode == 'standard':
1135    # transfer shared files
1136    transfer_gypi_files(cef_dir, cef_paths2['shared_sources_mac'], \
1137                        'tests/shared/', shared_dir, options.quiet)
1138    transfer_gypi_files(cef_dir, cef_paths2['shared_sources_mac_helper'], \
1139                        'tests/shared/', shared_dir, options.quiet)
1140
1141    # transfer cefclient files
1142    transfer_gypi_files(cef_dir, cef_paths2['cefclient_sources_mac'], \
1143                        'tests/cefclient/', cefclient_dir, options.quiet)
1144
1145    # transfer cefclient/resources/mac files
1146    copy_dir(os.path.join(cef_dir, 'tests/cefclient/resources/mac'), \
1147             os.path.join(cefclient_dir, 'resources/mac'), \
1148             options.quiet)
1149
1150    # transfer cefsimple files
1151    transfer_gypi_files(cef_dir, cef_paths2['cefsimple_sources_mac'], \
1152                        'tests/cefsimple/', cefsimple_dir, options.quiet)
1153    transfer_gypi_files(cef_dir, cef_paths2['cefsimple_sources_mac_helper'], \
1154                        'tests/cefsimple/', cefsimple_dir, options.quiet)
1155
1156    # transfer cefsimple/mac files
1157    copy_dir(os.path.join(cef_dir, 'tests/cefsimple/mac'), \
1158             os.path.join(cefsimple_dir, 'mac'), \
1159             options.quiet)
1160
1161    # transfer ceftests files
1162    transfer_gypi_files(cef_dir, cef_paths2['ceftests_sources_mac'], \
1163                        'tests/ceftests/', ceftests_dir, options.quiet)
1164    transfer_gypi_files(cef_dir, cef_paths2['ceftests_sources_mac_helper'], \
1165                        'tests/ceftests/', ceftests_dir, options.quiet)
1166
1167    # transfer ceftests/resources/mac files
1168    copy_dir(os.path.join(cef_dir, 'tests/ceftests/resources/mac'), \
1169             os.path.join(ceftests_dir, 'resources/mac'), \
1170             options.quiet)
1171
1172elif platform == 'linux':
1173  libcef_so = 'libcef.so'
1174  # yapf: disable
1175  binaries = [
1176      {'path': 'chrome_sandbox', 'out_path': 'chrome-sandbox'},
1177      {'path': libcef_so},
1178      {'path': 'libEGL.so'},
1179      {'path': 'libGLESv2.so'},
1180      {'path': 'libvk_swiftshader.so'},
1181      {'path': 'libvulkan.so.1'},
1182      {'path': 'snapshot_blob.bin', 'conditional': True},
1183      {'path': 'v8_context_snapshot.bin', 'conditional': True},
1184      {'path': 'vk_swiftshader_icd.json'},
1185      {'path': 'swiftshader/libEGL.so'},
1186      {'path': 'swiftshader/libGLESv2.so'},
1187  ]
1188  # yapf: enable
1189  if options.ozone:
1190    binaries.append({'path': 'libminigbm.so', 'conditional': True})
1191
1192  if mode == 'client':
1193    binaries.append({'path': 'cefsimple'})
1194
1195  # yapf: disable
1196  resources = [
1197      {'path': 'chrome_100_percent.pak'},
1198      {'path': 'chrome_200_percent.pak'},
1199      {'path': 'resources.pak'},
1200      {'path': 'icudtl.dat'},
1201      {'path': 'locales', 'delete': '*.info'},
1202  ]
1203  # yapf: enable
1204
1205  valid_build_dir = None
1206
1207  if mode == 'standard':
1208    # transfer Debug files
1209    build_dir = build_dir_debug
1210    libcef_path = os.path.join(build_dir, libcef_so)
1211    if not options.allowpartial or path_exists(libcef_path):
1212      valid_build_dir = build_dir
1213      dst_dir = os.path.join(output_dir, 'Debug')
1214      copy_files_list(build_dir, dst_dir, binaries)
1215    else:
1216      sys.stdout.write("No Debug build files.\n")
1217
1218  # transfer Release files
1219  build_dir = build_dir_release
1220  libcef_path = os.path.join(build_dir, libcef_so)
1221  if not options.allowpartial or path_exists(libcef_path):
1222    valid_build_dir = build_dir
1223    dst_dir = os.path.join(output_dir, 'Release')
1224    copy_files_list(build_dir, dst_dir, binaries)
1225  else:
1226    sys.stdout.write("No Release build files.\n")
1227
1228  if not valid_build_dir is None:
1229    # transfer resource files
1230    build_dir = valid_build_dir
1231    if mode == 'client':
1232      dst_dir = os.path.join(output_dir, 'Release')
1233    else:
1234      dst_dir = os.path.join(output_dir, 'Resources')
1235    copy_files_list(build_dir, dst_dir, resources)
1236
1237  if mode == 'standard' or mode == 'minimal':
1238    # transfer include files
1239    transfer_gypi_files(cef_dir, cef_paths2['includes_linux'], \
1240                        'include/', include_dir, options.quiet)
1241    transfer_gypi_files(cef_dir, cef_paths2['includes_linux_capi'], \
1242                        'include/', include_dir, options.quiet)
1243
1244    # transfer additional files, if any
1245    transfer_files(cef_dir, script_dir, os.path.join(script_dir, 'distrib', 'linux'), \
1246                   mode, output_dir, options.quiet)
1247
1248  if mode == 'standard':
1249    # transfer shared files
1250    transfer_gypi_files(cef_dir, cef_paths2['shared_sources_linux'], \
1251                        'tests/shared/', shared_dir, options.quiet)
1252
1253    if not options.ozone:
1254      # transfer cefclient files
1255      transfer_gypi_files(cef_dir, cef_paths2['cefclient_sources_linux'], \
1256                          'tests/cefclient/', cefclient_dir, options.quiet)
1257
1258    # transfer cefsimple files
1259    transfer_gypi_files(cef_dir, cef_paths2['cefsimple_sources_linux'], \
1260                        'tests/cefsimple/', cefsimple_dir, options.quiet)
1261
1262    # transfer ceftests files
1263    transfer_gypi_files(cef_dir, cef_paths2['ceftests_sources_linux'], \
1264                        'tests/ceftests/', ceftests_dir, options.quiet)
1265
1266if not options.noarchive:
1267  # create an archive for each output directory
1268  archive_format = os.getenv('CEF_ARCHIVE_FORMAT', 'zip')
1269  if archive_format not in ('zip', 'tar.gz', 'tar.bz2'):
1270    raise Exception('Unsupported archive format: %s' % archive_format)
1271
1272  if os.getenv('CEF_COMMAND_7ZIP', '') != '':
1273    archive_format = os.getenv('CEF_COMMAND_7ZIP_FORMAT', '7z')
1274
1275  for dir in archive_dirs:
1276    if not options.quiet:
1277      sys.stdout.write("Creating %s archive for %s...\n" %
1278                       (archive_format, os.path.basename(dir)))
1279    if archive_format == 'zip':
1280      create_zip_archive(dir)
1281    elif archive_format == 'tar.gz':
1282      create_tar_archive(dir, 'gz')
1283    elif archive_format == 'tar.bz2':
1284      create_tar_archive(dir, 'bz2')
1285    else:
1286      create_7z_archive(dir, archive_format)
1287