123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370 |
- #!/usr/bin/env python
- import argparse
- import glob
- import os
- import re
- import shutil
- import subprocess
- import sys
- import stat
- if sys.platform == "win32":
- import _winreg
- from lib.config import BASE_URL, PLATFORM, enable_verbose_mode, \
- get_target_arch, get_zip_name, build_env
- from lib.util import scoped_cwd, rm_rf, get_electron_version, make_zip, \
- execute, electron_gyp, electron_features, parse_version
- from lib.env_util import get_vs_location
- ELECTRON_VERSION = get_electron_version()
- SOURCE_ROOT = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
- DIST_DIR = os.path.join(SOURCE_ROOT, 'dist')
- OUT_DIR = os.path.join(SOURCE_ROOT, 'out', 'R')
- CHROMIUM_DIR = os.path.join(SOURCE_ROOT, 'vendor', 'download',
- 'libchromiumcontent', 'static_library')
- NATIVE_MKSNAPSHOT_DIR = os.path.join(SOURCE_ROOT, 'vendor', 'native_mksnapshot')
- PROJECT_NAME = electron_gyp()['project_name%']
- PRODUCT_NAME = electron_gyp()['product_name%']
- PDF_VIEWER_ENABLED = electron_features()['enable_pdf_viewer%']
- TARGET_BINARIES = {
- 'darwin': [
- ],
- 'win32': [
- '{0}.exe'.format(PROJECT_NAME), # 'electron.exe'
- 'content_shell.pak',
- 'd3dcompiler_47.dll',
- 'icudtl.dat',
- 'libEGL.dll',
- 'libGLESv2.dll',
- 'ffmpeg.dll',
- 'node.dll',
- 'blink_image_resources_200_percent.pak',
- 'content_resources_200_percent.pak',
- 'ui_resources_200_percent.pak',
- 'views_resources_200_percent.pak',
- 'natives_blob.bin',
- 'snapshot_blob.bin',
- ],
- 'linux': [
- PROJECT_NAME, # 'electron'
- 'content_shell.pak',
- 'icudtl.dat',
- 'libffmpeg.so',
- 'libnode.so',
- 'blink_image_resources_200_percent.pak',
- 'content_resources_200_percent.pak',
- 'ui_resources_200_percent.pak',
- 'views_resources_200_percent.pak',
- 'natives_blob.bin',
- 'snapshot_blob.bin',
- ],
- }
- TARGET_BINARIES_EXT = []
- TARGET_DIRECTORIES = {
- 'darwin': [
- '{0}.app'.format(PRODUCT_NAME),
- ],
- 'win32': [
- 'resources',
- 'locales',
- ],
- 'linux': [
- 'resources',
- 'locales',
- ],
- }
- def main():
- args = parse_args()
- if args.chromium_dir:
- globals().update(CHROMIUM_DIR=args.chromium_dir)
- if args.verbose:
- enable_verbose_mode()
- rm_rf(DIST_DIR)
- os.makedirs(DIST_DIR)
- force_build()
- create_symbols()
- copy_binaries()
- copy_chrome_binary('chromedriver')
- copy_chrome_binary('mksnapshot')
- copy_license()
- if PLATFORM == 'win32':
- copy_vcruntime_binaries()
- copy_ucrt_binaries()
- if PLATFORM != 'win32' and not args.no_api_docs:
- create_api_json_schema()
- create_typescript_definitions()
- if PLATFORM == 'linux':
- strip_binaries()
- create_version()
- create_dist_zip()
- create_chrome_binary_zip('chromedriver', ELECTRON_VERSION)
- create_chrome_binary_zip('mksnapshot', ELECTRON_VERSION)
- create_ffmpeg_zip()
- create_symbols_zip()
- def force_build():
- build = os.path.join(SOURCE_ROOT, 'script', 'build.py')
- execute([sys.executable, build, '-c', 'Release'])
- def copy_binaries():
- for binary in TARGET_BINARIES[PLATFORM]:
- shutil.copy2(os.path.join(OUT_DIR, binary), DIST_DIR)
- if PLATFORM != 'darwin' and PDF_VIEWER_ENABLED:
- shutil.copy2(os.path.join(OUT_DIR, 'pdf_viewer_resources.pak'),
- DIST_DIR)
- for directory in TARGET_DIRECTORIES[PLATFORM]:
- shutil.copytree(os.path.join(OUT_DIR, directory),
- os.path.join(DIST_DIR, directory),
- symlinks=True)
- def copy_chrome_binary(binary):
- if PLATFORM == 'win32':
- binary += '.exe'
- src = os.path.join(CHROMIUM_DIR, binary)
- dest = os.path.join(DIST_DIR, binary)
- # Copy file and keep the executable bit.
- shutil.copyfile(src, dest)
- os.chmod(dest, os.stat(dest).st_mode | stat.S_IEXEC)
- def copy_vcruntime_binaries():
- arch = get_target_arch()
- if arch == "ia32":
- arch = "x86"
- subkey = r"SOFTWARE\Wow6432Node\Microsoft\VisualStudio\14.0\VC\Runtimes\\"
- with _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, subkey + arch, 0,
- _winreg.KEY_READ | _winreg.KEY_WOW64_32KEY) as key:
- runtime_version = _winreg.QueryValueEx(key, "Version")[0][1:]
- version_parts = parse_version(runtime_version)
- if len(version_parts) > 3:
- runtime_version = '.'.join(version_parts[0:3])
- vs_location = get_vs_location('[15.0,16.0)')
- crt_dir = os.path.join(vs_location, 'VC', 'Redist', 'MSVC', runtime_version,
- arch, 'Microsoft.VC141.CRT')
- dlls = ["msvcp140.dll", "vcruntime140.dll"]
- # Note: copyfile is used to remove the read-only flag
- for dll in dlls:
- shutil.copyfile(os.path.join(crt_dir, dll), os.path.join(DIST_DIR, dll))
- TARGET_BINARIES_EXT.append(dll)
- def copy_ucrt_binaries():
- with _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE,
- r"SOFTWARE\Microsoft\Windows Kits\Installed Roots"
- ) as key:
- ucrt_dir = _winreg.QueryValueEx(key, "KitsRoot10")[0]
- arch = get_target_arch()
- if arch == "ia32":
- arch = "x86"
- ucrt_dir += r"Redist\ucrt\DLLs\{0}".format(arch)
- dlls = glob.glob(os.path.join(ucrt_dir, '*.dll'))
- if len(dlls) == 0:
- raise Exception('UCRT files not found')
- for dll in dlls:
- shutil.copy2(dll, DIST_DIR)
- TARGET_BINARIES_EXT.append(os.path.basename(dll))
- def copy_license():
- shutil.copy2(os.path.join(CHROMIUM_DIR, '..', 'LICENSES.chromium.html'),
- DIST_DIR)
- shutil.copy2(os.path.join(SOURCE_ROOT, 'LICENSE'), DIST_DIR)
- def create_api_json_schema():
- node_bin_dir = os.path.join(SOURCE_ROOT, 'node_modules', '.bin')
- env = os.environ.copy()
- env['PATH'] = os.path.pathsep.join([node_bin_dir, env['PATH']])
- outfile = os.path.relpath(os.path.join(DIST_DIR, 'electron-api.json'))
- execute(['electron-docs-linter', 'docs', '--outfile={0}'.format(outfile),
- '--version={}'.format(ELECTRON_VERSION.replace('v', ''))],
- env=env)
- def create_typescript_definitions():
- node_bin_dir = os.path.join(SOURCE_ROOT, 'node_modules', '.bin')
- env = os.environ.copy()
- env['PATH'] = os.path.pathsep.join([node_bin_dir, env['PATH']])
- infile = os.path.relpath(os.path.join(DIST_DIR, 'electron-api.json'))
- outfile = os.path.relpath(os.path.join(DIST_DIR, 'electron.d.ts'))
- execute(['electron-typescript-definitions', '--in={0}'.format(infile),
- '--out={0}'.format(outfile)], env=env)
- def strip_binaries():
- for binary in TARGET_BINARIES[PLATFORM]:
- if binary.endswith('.so') or '.' not in binary:
- strip_binary(os.path.join(DIST_DIR, binary))
- def strip_binary(binary_path):
- if get_target_arch() == 'arm':
- strip = 'arm-linux-gnueabihf-strip'
- elif get_target_arch() == 'arm64':
- strip = 'aarch64-linux-gnu-strip'
- elif get_target_arch() == 'mips64el':
- strip = 'mips64el-redhat-linux-strip'
- else:
- strip = 'strip'
- execute([strip, binary_path], env=build_env())
- def create_version():
- version_path = os.path.join(SOURCE_ROOT, 'dist', 'version')
- with open(version_path, 'w') as version_file:
- version_file.write(ELECTRON_VERSION)
- def create_symbols():
- if get_target_arch() == 'mips64el':
- return
- destination = os.path.join(DIST_DIR, '{0}.breakpad.syms'.format(PROJECT_NAME))
- dump_symbols = os.path.join(SOURCE_ROOT, 'script', 'dump-symbols.py')
- execute([sys.executable, dump_symbols, destination])
- if PLATFORM == 'darwin':
- dsyms = glob.glob(os.path.join(OUT_DIR, '*.dSYM'))
- for dsym in dsyms:
- shutil.copytree(dsym, os.path.join(DIST_DIR, os.path.basename(dsym)))
- elif PLATFORM == 'win32':
- pdbs = glob.glob(os.path.join(OUT_DIR, '*.pdb'))
- for pdb in pdbs:
- shutil.copy2(pdb, DIST_DIR)
- def create_dist_zip():
- dist_name = get_zip_name(PROJECT_NAME, ELECTRON_VERSION)
- zip_file = os.path.join(SOURCE_ROOT, 'dist', dist_name)
- with scoped_cwd(DIST_DIR):
- files = TARGET_BINARIES[PLATFORM] + TARGET_BINARIES_EXT + ['LICENSE',
- 'LICENSES.chromium.html', 'version']
- if PLATFORM != 'darwin' and PDF_VIEWER_ENABLED:
- files += ['pdf_viewer_resources.pak']
- dirs = TARGET_DIRECTORIES[PLATFORM]
- make_zip(zip_file, files, dirs)
- def create_chrome_binary_zip(binary, version):
- file_suffix = ''
- create_native_mksnapshot = False
- if binary == 'mksnapshot':
- arch = get_target_arch()
- if arch.startswith('arm'):
- # if the arch is arm/arm64 the mksnapshot executable is an x64 binary,
- # so name it as such.
- file_suffix = 'x64'
- create_native_mksnapshot = True
- dist_name = get_zip_name(binary, version, file_suffix)
- zip_file = os.path.join(SOURCE_ROOT, 'dist', dist_name)
- files = ['LICENSE', 'LICENSES.chromium.html']
- if PLATFORM == 'win32':
- files += [binary + '.exe']
- else:
- files += [binary]
- with scoped_cwd(DIST_DIR):
- make_zip(zip_file, files, [])
- if create_native_mksnapshot == True:
- # Create a zip with the native version of the mksnapshot binary.
- src = os.path.join(NATIVE_MKSNAPSHOT_DIR, binary)
- dest = os.path.join(DIST_DIR, binary)
- # Copy file and keep the executable bit.
- shutil.copyfile(src, dest)
- os.chmod(dest, os.stat(dest).st_mode | stat.S_IEXEC)
- dist_name = get_zip_name(binary, version)
- zip_file = os.path.join(SOURCE_ROOT, 'dist', dist_name)
- with scoped_cwd(DIST_DIR):
- make_zip(zip_file, files, [])
- def create_ffmpeg_zip():
- dist_name = get_zip_name('ffmpeg', ELECTRON_VERSION)
- zip_file = os.path.join(SOURCE_ROOT, 'dist', dist_name)
- if PLATFORM == 'darwin':
- ffmpeg_name = 'libffmpeg.dylib'
- elif PLATFORM == 'linux':
- ffmpeg_name = 'libffmpeg.so'
- elif PLATFORM == 'win32':
- ffmpeg_name = 'ffmpeg.dll'
- shutil.copy2(os.path.join(CHROMIUM_DIR, '..', 'ffmpeg', ffmpeg_name),
- DIST_DIR)
- if PLATFORM == 'linux':
- strip_binary(os.path.join(DIST_DIR, ffmpeg_name))
- with scoped_cwd(DIST_DIR):
- make_zip(zip_file, [ffmpeg_name, 'LICENSE', 'LICENSES.chromium.html'], [])
- def create_symbols_zip():
- if get_target_arch() == 'mips64el':
- return
- dist_name = get_zip_name(PROJECT_NAME, ELECTRON_VERSION, 'symbols')
- zip_file = os.path.join(DIST_DIR, dist_name)
- licenses = ['LICENSE', 'LICENSES.chromium.html', 'version']
- with scoped_cwd(DIST_DIR):
- dirs = ['{0}.breakpad.syms'.format(PROJECT_NAME)]
- make_zip(zip_file, licenses, dirs)
- if PLATFORM == 'darwin':
- dsym_name = get_zip_name(PROJECT_NAME, ELECTRON_VERSION, 'dsym')
- with scoped_cwd(DIST_DIR):
- dsyms = glob.glob('*.dSYM')
- make_zip(os.path.join(DIST_DIR, dsym_name), licenses, dsyms)
- elif PLATFORM == 'win32':
- pdb_name = get_zip_name(PROJECT_NAME, ELECTRON_VERSION, 'pdb')
- with scoped_cwd(DIST_DIR):
- pdbs = glob.glob('*.pdb')
- make_zip(os.path.join(DIST_DIR, pdb_name), pdbs + licenses, [])
- def parse_args():
- parser = argparse.ArgumentParser(description='Create Electron Distribution')
- parser.add_argument('--no_api_docs',
- action='store_true',
- help='Skip generating the Electron API Documentation!')
- parser.add_argument('--chromium_dir',
- help='Specify a custom libchromiumcontent dist directory '
- + 'if manually compiled')
- parser.add_argument('-v', '--verbose',
- action='store_true',
- help='Prints the output of the subprocesses')
- return parser.parse_args()
- if __name__ == '__main__':
- sys.exit(main())
|