diff --git a/BUILD.gn b/BUILD.gn index c1556f094a4..e80562652b1 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -1,4 +1,6 @@ import("//tools/grit/repack.gni") +import("//build/config/zip.gni") +import("//brave/build/config.gni") group("child_dependencies") { public_deps = [ @@ -76,7 +78,9 @@ if (is_mac) { } group("create_dist") { - deps = [] + deps = [ + ":create_dist_zips" + ] if (is_win) { deps += [ "//chrome/installer/mini_installer", @@ -87,3 +91,240 @@ group("create_dist") { deps += [ "build/mac:create_dist_mac" ] } } + +action("generate_version") { + script = "//brave/script/version.py" + + outputs = [ + "$root_out_dir/version" + ] +} + +copy("antimuon_dist_resources") { + if (is_mac) { + sources = [] + } else { + sources = antimuon_framework_sources + sources += [ + "$root_out_dir/brave_resources.pak", + "$root_out_dir/$antimuon_exe" + ] + } + + sources += get_target_outputs(":generate_version") + + deps = [ + ":brave", + ":generate_version", + ] + + outputs = [ + "$antimuon_dist_dir/{{source_file_part}}" + ] +} + +if (!is_mac) { + copy("antimuon_locale_dist_resources") { + deps = [ + "//chrome:packed_resources", + ] + + sources = [] + foreach(locale, locales) { + # print (locale) + if (is_mac) { + sources += [ "$root_gen_dir/repack/locales/$locale.pak" ] + } else { + sources += [ "$root_out_dir/locales/$locale.pak" ] + } + } + outputs = [ + "$antimuon_dist_dir/locales/{{source_file_part}}", + ] + } +} + +if (target_cpu == "x86") { + target_arch = "ia32" +} else { + target_arch = target_cpu +} + +chromedriver = "chromedriver" +if (is_win) { + chromedriver = "$chromedriver.exe" +} + +chromedriver_version = "2.33" + +copy("antimuon_chromedriver_dist_resources") { + sources = [ + "$root_out_dir/$chromedriver", + ] + + outputs = [ + "$antimuon_dist_dir/$chromedriver" + ] + + deps = [ "//chrome/test/chromedriver:chromedriver" ] +} + + +action("generate_chromium_licenses") { + license_file = "$root_gen_dir/LICENSES.chromium.html" + + script = "//tools/licenses.py" + + inputs = [ + rebase_path("//brave/resources/about_credits.tmpl"), + rebase_path("//brave/resources/about_credits_entry.tmpl"), + ] + + outputs = [ + license_file + ] + + args = [ + "--target-os=$target_os", + "credits", + rebase_path(license_file, root_build_dir), + ] +} + +copy("antimuon_license_dist_resources") { + sources = get_target_outputs(":generate_chromium_licenses") + sources += [ + "//brave/LICENSE", + ] + deps = [ + ":generate_chromium_licenses", + ] + + outputs = [ + "$antimuon_dist_dir/{{source_file_part}}" + ] +} + +zip("chromedriver_zip") { + inputs = get_target_outputs(":antimuon_chromedriver_dist_resources") + inputs += get_target_outputs(":antimuon_license_dist_resources") + output = "$antimuon_dist_dir/chromedriver-v$chromedriver_version-$antimuon_platform-$target_arch.zip" + + base_dir = antimuon_dist_dir + + deps = [ + "app/$current_os:chromedriver_dist_resources", + ":antimuon_chromedriver_dist_resources", + ":antimuon_license_dist_resources", + ] +} + + +action("create_symbols_dist") { + output = "$antimuon_dist_dir/$antimuon_project_name-v$antimuon_version-$antimuon_platform-$target_arch-symbols.zip" + + script = "//brave/script/create-dist.py" + + # inputs = get_target_outputs(":antimuon_chromedriver_dist_resources") + inputs = get_target_outputs(":antimuon_license_dist_resources") + dir_inputs = [ "$antimuon_project_name.breakpad.syms" ] + + file_inputs = [] + foreach(input, inputs) { + file_inputs += [ rebase_path(input, antimuon_dist_dir) ] + } + + rebase_output = rebase_path(output) + rebase_base_dir = rebase_path(antimuon_dist_dir) + + args = [ + "--base-dir=$rebase_base_dir", + "--inputs=$file_inputs", + "--dir-inputs=$dir_inputs", + "--output=$rebase_output", + ] + + outputs = [ output ] + + deps = [ + "app/$current_os:symbol_dist_resources", + ":antimuon_license_dist_resources", + ] +} + +action("create_dist_zips") { + output = "$antimuon_dist_dir/$antimuon_project_name-v$antimuon_version-$antimuon_platform-$target_arch.zip" + + script = "//brave/script/create-dist.py" + + inputs = get_target_outputs(":antimuon_license_dist_resources") + + if (!is_mac) { + inputs += get_target_outputs(":antimuon_dist_resources") + inputs += get_target_outputs(":antimuon_app_dist_resources") + inputs += get_target_outputs(":antimuon_locale_dist_resources") + } + + if (is_win) { + inputs += [ + "$antimuon_dist_dir/chrome_elf.dll", + "$antimuon_dist_dir/xinput1_3.dll", + "$antimuon_dist_dir/libEGL.dll", + "$antimuon_dist_dir/libGLESv2.dll", + "$antimuon_dist_dir/d3dcompiler_47.dll", + "$antimuon_dist_dir/$widevine_cdm_path/widevinecdmadapter.dll", + ] + } + + dist_dir = antimuon_dist_dir + + file_inputs = [] + foreach(input, inputs) { + file_inputs += [ rebase_path(input, dist_dir) ] + } + + dir_inputs = [] + if (is_mac) { + dir_inputs += [ + "$antimuon_exe", + ] + } + + outputs = [ + output + ] + + deps = [ + ":create_symbols_dist", + ":antimuon_license_dist_resources", + "app/$current_os:dist_resources", + ] + + deps += [ ":chromedriver_zip" ] + + if (!is_mac) { + deps += [ + ":antimuon_dist_resources", + ":antimuon_app_dist_resources", + ":antimuon_locale_dist_resources", + ] + } + if (is_win) { + deps += [ + "app/win:dist_widevine_resources", + ] + } + + rebase_output = rebase_path(output) + if (is_mac) { + rebase_base_dir = rebase_path(root_out_dir) + } else { + rebase_base_dir = rebase_path(dist_dir, root_out_dir) + } + args = [ + "--base-dir=$rebase_base_dir", + "--inputs=$file_inputs", + "--dir-inputs=$dir_inputs", + "--output=$rebase_output", + ] +} diff --git a/app/linux/BUILD.gn b/app/linux/BUILD.gn new file mode 100644 index 00000000000..077bfe527cc --- /dev/null +++ b/app/linux/BUILD.gn @@ -0,0 +1,138 @@ +import("//brave/build/config.gni") + +group("chromedriver_dist_resources") { + deps = [ + ":strip_and_dump_chromedriver_symbols" + ] +} + +action("strip_and_dump_chromedriver_symbols") { + script = "//build/linux/dump_app_syms.py" + dump_syms_label = "//third_party/breakpad:dump_syms($host_toolchain)" + dump_syms_binary = + get_label_info(dump_syms_label, "root_out_dir") + "/" + "dump_syms" + + chromedriver_binary = "$brave_dist_dir/chromedriver" + if (current_cpu == "x86") { + # Use "ia32" instead of "x86" for GYP compat. + chromedriver_symbol_file = "$root_out_dir/chromedriver.breakpad.ia32" + } else { + chromedriver_symbol_file = "$root_out_dir/chromedriver.breakpad.$current_cpu" + } + + inputs = [ chromedriver_binary, dump_syms_binary ] + outputs = [ chromedriver_symbol_file ] + + args = [ + "./" + rebase_path(dump_syms_binary, root_build_dir), + "1", # strip_binary = true + rebase_path(chromedriver_binary, root_build_dir), + rebase_path(chromedriver_symbol_file, root_build_dir), + ] + + deps = [ + dump_syms_label, + "//brave:antimuon_chromedriver_dist_resources", + ] +} + + +action("generate_breakpad_symbols") { + symbols_dir = "$antimuon_dist_dir/$antimuon_project_name.breakpad.syms" + outputs = [ + symbols_dir + ] + + deps = [ + "//chrome:chrome_app", + ] + + start = [ antimuon_project_name ] + + script = "//brave/tools/posix/generate_breakpad_symbols.py" + args = [ + "--symbols-dir=" + rebase_path(symbols_dir), + "--jobs=16", + "--build-dir=" + rebase_path(root_out_dir), + "--binary=$start", + "--libchromiumcontent-dir=" + rebase_path("//"), + "--clear", + ] + + deps += [ "//third_party/breakpad:dump_syms" ] +} + +action("strip_and_dump_symbols") { + script = "//build/linux/dump_app_syms.py" + + dump_syms_label = "//third_party/breakpad:dump_syms($host_toolchain)" + dump_syms_binary = + get_label_info(dump_syms_label, "root_out_dir") + "/" + "dump_syms" + + deps = [ + "//brave:antimuon_dist_resources", + # TODO(bridiver) - resolve duplicate symbol generation + ":generate_breakpad_symbols", + dump_syms_label, + ] + brave_binary = "$antimuon_dist_dir/brave" + if (current_cpu == "x86") { + # Use "ia32" instead of "x86" for GYP compat. + brave_symbol_file = "$root_out_dir/brave.breakpad.ia32" + } else { + brave_symbol_file = "$root_out_dir/brave.breakpad.$current_cpu" + } + + inputs = [ brave_binary, dump_syms_binary ] + outputs = [ brave_symbol_file ] + + args = [ + "./" + rebase_path(dump_syms_binary, root_build_dir), + "1", # strip_binary = true + rebase_path(brave_binary, root_build_dir), + rebase_path(brave_symbol_file, root_build_dir), + ] +} + +group("symbol_dist_resources") { + public_deps = [ + ":generate_breakpad_symbols", + ":strip_and_dump_symbols", + ] +} + +group("chromedriver_dist_resources") { + deps = [ + ":strip_and_dump_chromedriver_symbols" + ] +} + +action("strip_and_dump_chromedriver_symbols") { + script = "//build/linux/dump_app_syms.py" + dump_syms_label = "//third_party/breakpad:dump_syms($host_toolchain)" + dump_syms_binary = + get_label_info(dump_syms_label, "root_out_dir") + "/" + "dump_syms" + + chromedriver_binary = "$antimuon_dist_dir/chromedriver" + if (current_cpu == "x86") { + # Use "ia32" instead of "x86" for GYP compat. + chromedriver_symbol_file = "$root_out_dir/chromedriver.breakpad.ia32" + } else { + chromedriver_symbol_file = "$root_out_dir/chromedriver.breakpad.$current_cpu" + } + + inputs = [ chromedriver_binary, dump_syms_binary ] + outputs = [ chromedriver_symbol_file ] + + args = [ + "./" + rebase_path(dump_syms_binary, root_build_dir), + "1", # strip_binary = true + rebase_path(chromedriver_binary, root_build_dir), + rebase_path(chromedriver_symbol_file, root_build_dir), + ] + + deps = [ + dump_syms_label, + "//brave:antimuon_chromedriver_dist_resources", + ] +} diff --git a/app/mac/BUILD.gn b/app/mac/BUILD.gn new file mode 100644 index 00000000000..9f24243a3a2 --- /dev/null +++ b/app/mac/BUILD.gn @@ -0,0 +1,58 @@ +import("//build/util/branding.gni") +import("//brave/build/config.gni") + +group("chromedriver_dist_resources") {} + +chrome_framework_name = chrome_product_full_name + " Framework" +chrome_helper_name = chrome_product_full_name + " Helper" + +# This list must be updated with the two targets' deps list below, and +# the list of _dsyms in :antimuon_dsym_archive. +_antimuon_symbols_sources = [ + "$root_out_dir/$chrome_framework_name.framework/$chrome_framework_name", + "$root_out_dir/$chrome_helper_name.app/Contents/MacOS/$chrome_helper_name", + "$root_out_dir/$chrome_product_full_name.app/Contents/MacOS/$chrome_product_full_name", + "$root_out_dir/crashpad_handler", +] + +group("dist_resources") {} + +group("symbol_dist_resources") { + public_deps = [ + "//chrome:chrome_dump_syms", + "//chrome:chrome_dsym_archive", + ":generate_breakpad_symbols", + ] +} + +action("generate_breakpad_symbols") { + symbols_dir = "$antimuon_dist_dir/$antimuon_project_name.breakpad.syms" + outputs = [ + symbols_dir + ] + + sources = _antimuon_symbols_sources + + binaries = [] + foreach(_source, sources) { + binaries += [ rebase_path(_source) ] + } + + script = "//brave/tools/posix/generate_breakpad_symbols.py" + args = [ + "--symbols-dir=" + rebase_path(symbols_dir), + "--jobs=16", + "--build-dir=" + rebase_path(root_out_dir), + "--binary=$binaries", + "--libchromiumcontent-dir=" + rebase_path("//"), + "--clear", + ] + + deps = [ + "//chrome:chrome_app", + "//chrome:chrome_framework", + "//chrome:chrome_helper_app", + "//chrome:chrome_dump_syms", + "//third_party/crashpad/crashpad/handler:crashpad_handler", + ] +} diff --git a/app/win/BUILD.gn b/app/win/BUILD.gn new file mode 100644 index 00000000000..fc7a42af8d5 --- /dev/null +++ b/app/win/BUILD.gn @@ -0,0 +1,61 @@ +import("//build/util/branding.gni") +import("//brave/build/config.gni") + +action("generate_breakpad_symbols") { + symbols_dir = "$antimuon_dist_dir/$antimuon_project_name.breakpad.syms" + outputs = [ + symbols_dir + ] + + args = [ + "--symbols-dir=" + rebase_path(symbols_dir), + "--jobs=16", + rebase_path(root_out_dir) + ] + + deps = [ + "//chrome:chrome_app", + ] + + script = "//brave/tools/win/generate_breakpad_symbols.py" +} + +group("symbol_dist_resources") { + public_deps = [ ":generate_breakpad_symbols" ] +} + +copy("dist_widevine_resources") { + sources = [ + "$root_out_dir/$widevine_cdm_path/widevinecdmadapter.dll", + ] + outputs = [ + "$antimuon_dist_dir/$widevine_cdm_path/{{source_file_part}}" + ] + public_deps = [ + ":widevine_cdm_adapter", + ] +} + +copy("dist_resources") { + sources = [ + "$root_out_dir/chrome_elf.dll", + "$root_out_dir/xinput1_3.dll", + "$root_shlib_dir/libEGL.dll", + "$root_shlib_dir/libGLESv2.dll", + "$root_out_dir/d3dcompiler_47.dll", + ] + + outputs = [ + "$antimuon_dist_dir/{{source_file_part}}", + ] + + public_deps = [ + ":external_binaries", + "//chrome_elf", + "//third_party/angle:copy_compiler_dll", + "//third_party/angle:libEGL", + "//third_party/angle:libGLESv2", + ] +} + +group("chromedriver_dist_resources") {} diff --git a/build/config.gni b/build/config.gni new file mode 100644 index 00000000000..e2f9a306d2f --- /dev/null +++ b/build/config.gni @@ -0,0 +1,39 @@ +import("//build/toolchain/toolchain.gni") +import("//build/util/branding.gni") + +declare_args() { + antimuon_product_name = "" + antimuon_project_name = "" + executable_name = "" + antimuon_version_major = "" + antimuon_version_minor = "" + antimuon_version_build = "" + antimuon_version_patch = 0 +} + +antimuon_version = "$antimuon_version_major.$antimuon_version_minor.$antimuon_version_build" + +if (executable_name == "") { + executable_name = antimuon_project_name +} + +antimuon_dist_dir = "$root_out_dir/dist" +antimuon_exe = executable_name +if (is_win) { + antimuon_exe = "$antimuon_exe.exe" +} else if (is_mac) { + antimuon_exe = "$chrome_product_full_name.app" +} + +antimuon_icon_dir = "nightly" +if (is_component_build) { + antimuon_icon_dir = "dev" +} + +antimuon_platform = "darwin" +if (is_win) { + antimuon_platform = "win32" +} else if (is_linux) { + antimuon_platform = "linux" +} + diff --git a/resources/about_credits.tmpl b/resources/about_credits.tmpl new file mode 100644 index 00000000000..00b4d2ef8c2 --- /dev/null +++ b/resources/about_credits.tmpl @@ -0,0 +1,101 @@ + + + + +Credits + + + +Credits +Print +
+{{entries}} +
+ + + diff --git a/resources/about_credits_entry.tmpl b/resources/about_credits_entry.tmpl new file mode 100644 index 00000000000..a4fa4e1c901 --- /dev/null +++ b/resources/about_credits_entry.tmpl @@ -0,0 +1,8 @@ +
+{{name}} +show license +homepage +
+
{{license}}
+
+
diff --git a/script/bump-version.py b/script/bump-version.py index 58b6c350dcd..134b2c7c4ac 100755 --- a/script/bump-version.py +++ b/script/bump-version.py @@ -4,7 +4,7 @@ import os import re import sys -from lib.config import SOURCE_ROOT, get_electron_version, get_chrome_version +from lib.config import SOURCE_ROOT, get_antimuon_version, get_chrome_version from lib.util import execute, parse_version, scoped_cwd @@ -16,7 +16,7 @@ def main(): option = sys.argv[1] increments = ['major', 'minor', 'patch'] if option in increments: - version = get_electron_version() + version = get_antimuon_version() versions = parse_version(version.split('-')[0]) versions = increase_version(versions, increments.index(option)) chrome = get_chrome_version() diff --git a/script/create-dist.py b/script/create-dist.py new file mode 100644 index 00000000000..0cd0ab189d0 --- /dev/null +++ b/script/create-dist.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python + +import optparse +import sys +import glob +import os +import shutil + + +sys.path.append(os.path.join(os.path.dirname(__file__), + os.pardir, os.pardir, + "build")) +import gn_helpers + +from lib.util import scoped_cwd, make_zip + + +def main(): + parser = optparse.OptionParser() + + parser.add_option('--inputs', + help='GN format list of files to archive.') + parser.add_option('--dir-inputs', + help='GN format list of files to archive.') + parser.add_option('--output', help='Path to output archive.') + parser.add_option('--base-dir', + help='If provided, the paths in the archive will be ' + 'relative to this directory', default='.') + + options, _ = parser.parse_args() + + inputs = [] + if (options.inputs): + parser = gn_helpers.GNValueParser(options.inputs) + inputs = parser.ParseList() + + dir_inputs = [] + if options.dir_inputs: + parser = gn_helpers.GNValueParser(options.dir_inputs) + dir_inputs = parser.ParseList() + + output = options.output + base_dir = options.base_dir + + with scoped_cwd(base_dir): + make_zip(output, inputs, dir_inputs) + + +if __name__ == '__main__': + sys.exit(main()) + diff --git a/script/lib/config.py b/script/lib/config.py index 596fd6ed587..05cfc13cb39 100644 --- a/script/lib/config.py +++ b/script/lib/config.py @@ -15,7 +15,7 @@ PLATFORM = { SOURCE_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..')) CHROMIUM_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..')) -DIST_URL = 'https://brave-laptop-binaries.s3.amazonaws.com/atom-shell/dist/' +DIST_URL = 'https://brave-brave-binaries.s3.amazonaws.com/releases/' verbose_mode = False @@ -28,7 +28,7 @@ def output_dir(): return os.path.join(CHROMIUM_ROOT, 'out', 'Release') return os.path.join(CHROMIUM_ROOT, 'out_x86', 'Release') -def electron_package(): +def brave_package(): pjson = os.path.join(SOURCE_ROOT, 'package.json') with open(pjson) as f: obj = json.load(f); @@ -36,19 +36,19 @@ def electron_package(): def product_name(): - return os.environ.get('npm_config_electron_product_name') or electron_package()['name'] + return os.environ.get('npm_config_antimuon_product_name') or brave_package()['name'] def project_name(): - return os.environ.get('npm_config_electron_project_name') or electron_package()['name'] + return os.environ.get('npm_config_antimuon_project_name') or brave_package()['name'] def get_chrome_version(): - version = os.environ.get('npm_config_electron_version') or electron_package()['version'] + version = os.environ.get('npm_config_antimuon_version') or brave_package()['version'] return version.split('+')[1] -def get_electron_version(): - version = os.environ.get('npm_config_electron_version') or electron_package()['version'] +def get_antimuon_version(): + version = os.environ.get('npm_config_antimuon_version') or brave_package()['version'] return 'v' + version.split('+')[0] @@ -71,16 +71,16 @@ def get_chromedriver_version(): def get_env_var(name): - return os.environ.get('ELECTRON_' + name) or os.environ.get('npm_config_ELECTRON_' + name, '') + return os.environ.get('ANTIMUON_' + name) or os.environ.get('npm_config_ANTIMUON_' + name, '') def s3_config(): config = (get_env_var('S3_BUCKET'), get_env_var('S3_ACCESS_KEY'), get_env_var('S3_SECRET_KEY')) - message = ('Error: Please set the $ELECTRON_S3_BUCKET, ' - '$ELECTRON_S3_ACCESS_KEY, and ' - '$ELECTRON_S3_SECRET_KEY environment variables') + message = ('Error: Please set the $ANTIMUON_S3_BUCKET, ' + '$ANTIMUON_S3_ACCESS_KEY, and ' + '$ANTIMUON_S3_SECRET_KEY environment variables') assert all(len(c) for c in config), message return config diff --git a/script/upload.py b/script/upload.py new file mode 100644 index 00000000000..6ec1134a89c --- /dev/null +++ b/script/upload.py @@ -0,0 +1,224 @@ +#!/usr/bin/env python + +import argparse +import errno +import hashlib +import os +import shutil +import subprocess +import sys +import tempfile + +from io import StringIO +from lib.config import PLATFORM, DIST_URL, get_target_arch, get_chromedriver_version, \ + get_env_var, s3_config, get_zip_name, product_name, project_name, \ + SOURCE_ROOT, dist_dir, get_antimuon_version +from lib.util import execute, parse_version, scoped_cwd, s3put + +from lib.github import GitHub + + +ANTIMUON_REPO = "brave/brave" + +DIST_NAME = get_zip_name(project_name(), get_antimuon_version()) +SYMBOLS_NAME = get_zip_name(project_name(), get_antimuon_version(), 'symbols') +DSYM_NAME = get_zip_name(project_name(), get_antimuon_version(), 'dsym') +PDB_NAME = get_zip_name(project_name(), get_antimuon_version(), 'pdb') + + +def main(): + args = parse_args() + + if not args.publish_release: + build_version = get_antimuon_version() + if not get_antimuon_version().startswith(build_version): + error = 'Tag name ({0}) should match build version ({1})\n'.format( + get_antimuon_version(), build_version) + sys.stderr.write(error) + sys.stderr.flush() + return 1 + + github = GitHub(auth_token()) + releases = github.repos(ANTIMUON_REPO).releases.get() + tag_exists = False + for release in releases: + if not release['draft'] and release['tag_name'] == args.version: + tag_exists = True + break + + release = create_or_get_release_draft(github, releases, args.version, + tag_exists) + + if args.publish_release: + # Create and upload the Antimuon SHASUMS*.txt + release_antimuon_checksums(github, release) + + # Press the publish button. + # publish_release(github, release['id']) + + # Do not upload other files when passed "-p". + return + + # Upload antimuon with GitHub Releases API. + upload_antimuon(github, release, os.path.join(dist_dir(), DIST_NAME)) + upload_antimuon(github, release, os.path.join(dist_dir(), SYMBOLS_NAME)) + # if PLATFORM == 'darwin': + # upload_antimuon(github, release, os.path.join(dist_dir(), DSYM_NAME)) + # elif PLATFORM == 'win32': + # upload_antimuon(github, release, os.path.join(dist_dir(), PDB_NAME)) + + # Upload chromedriver and mksnapshot. + chromedriver = get_zip_name('chromedriver', get_chromedriver_version()) + upload_antimuon(github, release, os.path.join(dist_dir(), chromedriver)) + # mksnapshot = get_zip_name('mksnapshot', get_antimuon_version()) + # upload_antimuon(github, release, os.path.join(dist_dir(), mksnapshot)) + + # if PLATFORM == 'win32' and not tag_exists: + # # Upload PDBs to Windows symbol server. + # run_python_script('upload-windows-pdb.py') + + versions = parse_version(args.version) + version = '.'.join(versions[:3]) + + +def parse_args(): + parser = argparse.ArgumentParser(description='upload distribution file') + parser.add_argument('-v', '--version', help='Specify the version', + default=get_antimuon_version()) + parser.add_argument('-p', '--publish-release', + help='Publish the release', + action='store_true') + parser.add_argument('-d', '--dist-url', + help='The base dist url for download', + default=DIST_URL) + return parser.parse_args() + + +def run_python_script(script, *args): + script_path = os.path.join(SOURCE_ROOT, 'script', script) + return execute([sys.executable, script_path] + list(args)) + + +def dist_newer_than_head(): + with scoped_cwd(SOURCE_ROOT): + try: + head_time = subprocess.check_output(['git', 'log', '--pretty=format:%at', + '-n', '1']).strip() + dist_time = os.path.getmtime(os.path.join(dist_dir(), DIST_NAME)) + except OSError as e: + if e.errno != errno.ENOENT: + raise + return False + + return dist_time > int(head_time) + + +def get_text_with_editor(name): + editor = os.environ.get('EDITOR', 'nano') + initial_message = '\n# Please enter the body of your release note for %s.' \ + % name + + t = tempfile.NamedTemporaryFile(suffix='.tmp', delete=False) + t.write(initial_message) + t.close() + subprocess.call([editor, t.name]) + + text = '' + for line in open(t.name, 'r'): + if len(line) == 0 or line[0] != '#': + text += line + + os.unlink(t.name) + return text + +def create_or_get_release_draft(github, releases, tag, tag_exists): + # Search for existing draft. + for release in releases: + if release['draft']: + return release + + if tag_exists: + tag = 'do-not-publish-me' + + return create_release_draft(github, tag) + + +def create_release_draft(github, tag): + name = '{0} {1}'.format(project_name(), tag) + body = '(placeholder)' + data = dict(tag_name=tag, name=name, body=body, draft=True) + r = github.repos(ANTIMUON_REPO).releases.post(data=data) + return r + + +def release_antimuon_checksums(github, release): + checksums = run_python_script('merge-antimuon-checksums.py', + '-v', get_antimuon_version()) + upload_io_to_github(github, release, 'SHASUMS256.txt', + StringIO(checksums.decode('utf-8')), 'text/plain') + + +def upload_antimuon(github, release, file_path): + # Delete the original file before uploading. + filename = os.path.basename(file_path) + try: + for asset in release['assets']: + if asset['name'] == filename: + github.repos(ANTIMUON_REPO).releases.assets(asset['id']).delete() + except Exception: + pass + + # Upload the file. + with open(file_path, 'rb') as f: + upload_io_to_github(github, release, filename, f, 'application/zip') + + # Upload the checksum file. + upload_sha256_checksum(release['tag_name'], file_path) + + # Upload ARM assets without the v7l suffix for backwards compatibility + # TODO Remove for 2.0 + if 'armv7l' in filename: + arm_filename = filename.replace('armv7l', 'arm') + arm_file_path = os.path.join(os.path.dirname(file_path), arm_filename) + shutil.copy2(file_path, arm_file_path) + upload_antimuon(github, release, arm_file_path) + + +def upload_io_to_github(github, release, name, io, content_type): + params = {'name': name} + headers = {'Content-Type': content_type} + github.repos(ANTIMUON_REPO).releases(release['id']).assets.post( + params=params, headers=headers, data=io, verify=False) + + +def upload_sha256_checksum(version, file_path): + bucket, access_key, secret_key = s3_config() + checksum_path = '{}.sha256sum'.format(file_path) + sha256 = hashlib.sha256() + with open(file_path, 'rb') as f: + sha256.update(f.read()) + + filename = os.path.basename(file_path) + with open(checksum_path, 'w') as checksum: + checksum.write('{} *{}'.format(sha256.hexdigest(), filename)) + s3put(bucket, access_key, secret_key, os.path.dirname(checksum_path), + 'releases/tmp/{0}'.format(version), [checksum_path]) + + +def publish_release(github, release_id): + data = dict(draft=False) + github.repos(ANTIMUON_REPO).releases(release_id).patch(data=data) + + +def auth_token(): + token = get_env_var('GITHUB_TOKEN') + message = ('Error: Please set the $ANTIMUON_GITHUB_TOKEN ' + 'environment variable, which is your personal token') + assert token, message + return token + + +if __name__ == '__main__': + import sys + sys.exit(main()) + diff --git a/script/version.py b/script/version.py index be27888c36c..e032104c126 100644 --- a/script/version.py +++ b/script/version.py @@ -3,7 +3,7 @@ import os import sys -from lib.config import output_dir, get_electron_version +from lib.config import output_dir, get_antimuon_version def main(): @@ -13,7 +13,7 @@ def main(): def create_version(): version_path = os.path.join(output_dir(), 'version') with open(version_path, 'w') as version_file: - version_file.write(get_electron_version()) + version_file.write(get_antimuon_version()) if __name__ == '__main__': diff --git a/tools/posix/generate_breakpad_symbols.py b/tools/posix/generate_breakpad_symbols.py new file mode 100755 index 00000000000..32c9f8a085b --- /dev/null +++ b/tools/posix/generate_breakpad_symbols.py @@ -0,0 +1,290 @@ +#!/usr/bin/env python +# Copyright (c) 2013 GitHub, Inc. +# Copyright (c) 2013 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +"""A tool to generate symbols for a binary suitable for breakpad. + +Currently, the tool only supports Linux, Android, and Mac. Support for other +platforms is planned. +""" + +import errno +import optparse +import os +import Queue +import re +import shutil +import subprocess +import sys +import threading + +sys.path.append(os.path.join(os.path.dirname(__file__), + os.pardir, os.pardir, os.pardir, + "build")) +import gn_helpers + +CONCURRENT_TASKS=4 + + +def GetCommandOutput(command): + """Runs the command list, returning its output. + + Prints the given command (which should be a list of one or more strings), + then runs it and returns its output (stdout) as a string. + + From chromium_utils. + """ + devnull = open(os.devnull, 'w') + proc = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=devnull, + bufsize=1) + output = proc.communicate()[0] + return output + + +def GetDumpSymsBinary(build_dir=None): + """Returns the path to the dump_syms binary.""" + DUMP_SYMS = 'dump_syms' + dump_syms_bin = os.path.join(os.path.expanduser(build_dir), DUMP_SYMS) + if not os.access(dump_syms_bin, os.X_OK): + print 'Cannot find %s.' % DUMP_SYMS + sys.exit(1) + + return dump_syms_bin + + +def FindBundlePart(full_path): + if full_path.endswith(('.dylib', '.framework', '.app')): + return os.path.basename(full_path) + elif full_path != '' and full_path != '/': + return FindBundlePart(os.path.dirname(full_path)) + else: + return '' + + +def GetDSYMBundle(options, binary_path): + """Finds the .dSYM bundle to the binary.""" + if os.path.isabs(binary_path): + dsym_path = binary_path + '.dSYM' + if os.path.exists(dsym_path): + return dsym_path + + filename = FindBundlePart(binary_path) + search_dirs = [options.build_dir, options.libchromiumcontent_dir] + if filename.endswith(('.dylib', '.framework', '.app')): + for directory in search_dirs: + dsym_path = os.path.join(directory, os.path.splitext(filename)[0]) + '.dSYM' + if os.path.exists(dsym_path): + return dsym_path + dsym_path = os.path.join(directory, filename) + '.dSYM' + if os.path.exists(dsym_path): + return dsym_path + + return binary_path + + +def GetSymbolPath(options, binary_path): + """Finds the .dbg to the binary.""" + filename = os.path.basename(binary_path) + dbg_path = os.path.join(options.libchromiumcontent_dir, filename) + '.dbg' + if os.path.exists(dbg_path): + return dbg_path + + return binary_path + + +def Resolve(path, exe_path, loader_path, rpaths): + """Resolve a dyld path. + + @executable_path is replaced with |exe_path| + @loader_path is replaced with |loader_path| + @rpath is replaced with the first path in |rpaths| where the referenced file + is found + """ + path = path.replace('@loader_path', loader_path) + path = path.replace('@executable_path', exe_path) + if path.find('@rpath') != -1: + for rpath in rpaths: + new_path = Resolve(path.replace('@rpath', rpath), exe_path, loader_path, + []) + if os.access(new_path, os.F_OK): + return new_path + return '' + return path + + +def GetSharedLibraryDependenciesLinux(binary): + """Return absolute paths to all shared library dependecies of the binary. + + This implementation assumes that we're running on a Linux system.""" + ldd = GetCommandOutput(['ldd', binary]) + lib_re = re.compile('\t.* => (.+) \(.*\)$') + result = [] + for line in ldd.splitlines(): + m = lib_re.match(line) + if m: + result.append(m.group(1)) + return result + + +def GetSharedLibraryDependenciesMac(binary, exe_path): + """Return absolute paths to all shared library dependecies of the binary. + + This implementation assumes that we're running on a Mac system.""" + loader_path = os.path.dirname(binary) + otool = GetCommandOutput(['otool', '-l', binary]).splitlines() + rpaths = [] + for idx, line in enumerate(otool): + if line.find('cmd LC_RPATH') != -1: + m = re.match(' *path (.*) \(offset .*\)$', otool[idx+2]) + rpaths.append(m.group(1)) + + otool = GetCommandOutput(['otool', '-L', binary]).splitlines() + lib_re = re.compile('\t(.*) \(compatibility .*\)$') + deps = [] + for line in otool: + m = lib_re.match(line) + if m: + dep = Resolve(m.group(1), exe_path, loader_path, rpaths) + if dep: + deps.append(os.path.normpath(dep)) + return deps + + +def GetSharedLibraryDependencies(options, binary, exe_path): + """Return absolute paths to all shared library dependecies of the binary.""" + deps = [] + if sys.platform.startswith('linux'): + deps = GetSharedLibraryDependenciesLinux(binary) + elif sys.platform == 'darwin': + deps = GetSharedLibraryDependenciesMac(binary, exe_path) + else: + print "Platform not supported." + sys.exit(1) + + result = [] + build_dir = os.path.abspath(options.build_dir) + for dep in deps: + if (os.access(dep, os.F_OK)): + result.append(dep) + return result + + +def mkdir_p(path): + """Simulates mkdir -p.""" + try: + os.makedirs(path) + except OSError as e: + if e.errno == errno.EEXIST and os.path.isdir(path): + pass + else: raise + + +def GenerateSymbols(options, binaries): + """Dumps the symbols of binary and places them in the given directory.""" + + queue = Queue.Queue() + print_lock = threading.Lock() + + def _Worker(): + while True: + binary = queue.get() + + if options.verbose: + with print_lock: + print "Generating symbols for %s" % binary + + if sys.platform == 'darwin': + binary = GetDSYMBundle(options, binary) + elif sys.platform == 'linux2': + binary = GetSymbolPath(options, binary) + + syms = GetCommandOutput([GetDumpSymsBinary(options.build_dir), '-r', '-c', + binary]) + module_line = re.match("MODULE [^ ]+ [^ ]+ ([0-9A-F]+) (.*)\n", syms) + output_path = os.path.join(options.symbols_dir, module_line.group(2), + module_line.group(1)) + mkdir_p(output_path) + symbol_file = "%s.sym" % module_line.group(2) + f = open(os.path.join(output_path, symbol_file), 'w') + f.write(syms) + f.close() + + queue.task_done() + + for binary in binaries: + queue.put(binary) + + for _ in range(options.jobs): + t = threading.Thread(target=_Worker) + t.daemon = True + t.start() + + queue.join() + + +def main(): + parser = optparse.OptionParser() + parser.add_option('', '--build-dir', default='', + help='The build output directory.') + parser.add_option('', '--symbols-dir', default='', + help='The directory where to write the symbols file.') + parser.add_option('', '--libchromiumcontent-dir', default='', + help='The directory where libchromiumcontent is downloaded.') + parser.add_option('', '--binary', default='', + help='The path of the binary to generate symbols for.') + parser.add_option('', '--clear', default=False, action='store_true', + help='Clear the symbols directory before writing new ' + 'symbols.') + parser.add_option('-j', '--jobs', default=CONCURRENT_TASKS, action='store', + type='int', help='Number of parallel tasks to run.') + parser.add_option('-v', '--verbose', action='store_true', + help='Print verbose status output.') + + (options, _) = parser.parse_args() + + if not options.symbols_dir: + print "Required option --symbols-dir missing." + return 1 + + if not options.build_dir: + print "Required option --build-dir missing." + return 1 + + if not options.libchromiumcontent_dir: + print "Required option --libchromiumcontent-dir missing." + return 1 + + if not options.binary: + print "Required option --binary missing." + return 1 + + if options.clear: + try: + shutil.rmtree(options.symbols_dir) + except: + pass + + binary = [] + if options.binary: + parser = gn_helpers.GNValueParser(options.binary) + binary = parser.ParseList() + + # Build the transitive closure of all dependencies. + binaries = set(binary) + queue = binary + exe_path = os.path.dirname(binary[0]) + while queue: + deps = GetSharedLibraryDependencies(options, queue.pop(0), exe_path) + new_deps = set(deps) - binaries + binaries |= new_deps + queue.extend(list(new_deps)) + + GenerateSymbols(options, binaries) + + return 0 + + +if '__main__' == __name__: + sys.exit(main())