dart-sdk/tools/bots/dart_sdk.py
Martin Kustermann 168539d61d Reland "[vm] Build dart2native dependencies with the normal "create_sdk" target"
The flutter engine DEPS got new icu/boringssl so this CL can safely
land and roll into engine. A small change is made in Patchset 1..3.

This removes special logic for creating the `dart-sdk` we distribute
which used to build release and product mode and copied some binaries
from the latter into the former, before the SDK was actuallly ready to
test and distribute.

This changes the GN build rules to build the necessary
gen_snapshot/dart_precompiled_runtime product binaries during the normal
release build.

Normally during --mode=product builds the global build config in
//build/config/BUILDCONFIG.gn will set `-fvisibility=false`.

=> Doing so results in much smaller binaries - because only explicitly
   exported symbols are visible, the rest can be tree shaken by the linker.

Since we are building --mode=release, the `-fvisibility=false` will not
be set. In order to set the flag for the 2 special product-mode binaries
we need to add -fvisibility=hidden manually, in:

  * dart_product_config: Which is used for compiling VM sources.
  * 3rd party double-conversion library
  * 3rd party boringssl library
  * 3rd party icu library

The upstream CLs are:

  * BoringSSL: https://dart-review.googlesource.com/c/boringssl_gen/+/150482
  * ICU: https://chromium-review.googlesource.com/c/chromium/deps/icu/+/2236407

Issue https://github.com/dart-lang/sdk/issues/42230

Change-Id: I8d9b37acbb5eb94e44d97652f838948a946fd372
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/151505
Commit-Queue: Martin Kustermann <kustermann@google.com>
Reviewed-by: Alexander Thomas <athom@google.com>
2020-06-17 16:12:26 +00:00

253 lines
8.8 KiB
Python
Executable file

#!/usr/bin/env python
#
# Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.
import os
import os.path
import shutil
import sys
import subprocess
import bot
import bot_utils
utils = bot_utils.GetUtils()
BUILD_OS = utils.GuessOS()
BUILD_ARCHITECTURE = utils.GuessArchitecture()
(bot_name, _) = bot.GetBotName()
CHANNEL = bot_utils.GetChannelFromName(bot_name)
def BuildArchitectures():
if BUILD_OS == 'linux':
return ['ia32', 'x64', 'arm', 'arm64']
elif BUILD_OS == 'macos':
return ['x64']
else:
return ['ia32', 'x64']
def BuildRootPath(path, arch=BUILD_ARCHITECTURE, build_mode='release'):
return os.path.join(bot_utils.DART_DIR,
utils.GetBuildRoot(BUILD_OS, build_mode, arch), path)
def BuildDartdocAPIDocs(dirname):
dart_sdk = BuildRootPath('dart-sdk')
dart_exe = os.path.join(dart_sdk, 'bin', 'dart')
dartdoc_dart = os.path.join(bot_utils.DART_DIR, 'third_party', 'pkg',
'dartdoc', 'bin', 'dartdoc.dart')
footer_file = os.path.join(bot_utils.DART_DIR, 'tools', 'bots',
'dartdoc_footer.html')
url = 'https://api.dartlang.org/stable'
with bot.BuildStep('Build API docs by dartdoc'):
bot_utils.run([
dart_exe, dartdoc_dart, '--sdk-docs', '--output', dirname,
'--enable-experiment', 'non-nullable', '--footer', footer_file,
'--rel-canonical-prefix=' + url
])
def CreateUploadVersionFile():
file_path = BuildRootPath('VERSION')
with open(file_path, 'w') as fd:
fd.write(utils.GetVersionFileContent())
DartArchiveUploadVersionFile(file_path)
def DartArchiveUploadVersionFile(version_file):
namer = bot_utils.GCSNamer(CHANNEL, bot_utils.ReleaseType.RAW)
revision = utils.GetArchiveVersion()
for revision in [revision, 'latest']:
destination = namer.version_filepath(revision)
DartArchiveFile(version_file, destination, checksum_files=False)
def CreateAndUploadSDKZip(arch, sdk_path):
sdk_zip = BuildRootPath('dartsdk-%s-%s.zip' % (BUILD_OS, arch), arch=arch)
FileDelete(sdk_zip)
CreateZip(sdk_path, sdk_zip)
DartArchiveUploadSDKs(BUILD_OS, arch, sdk_zip)
def DartArchiveUploadSDKs(system, arch, sdk_zip):
namer = bot_utils.GCSNamer(CHANNEL, bot_utils.ReleaseType.RAW)
git_number = utils.GetArchiveVersion()
git_hash = 'hash/%s' % utils.GetGitRevision()
for revision in [git_number, git_hash, 'latest']:
path = namer.sdk_zipfilepath(revision, system, arch, 'release')
DartArchiveFile(sdk_zip, path, checksum_files=True)
def DartArchiveUnstrippedBinaries():
namer = bot_utils.GCSNamer(CHANNEL, bot_utils.ReleaseType.RAW)
revision = utils.GetArchiveVersion()
binary = namer.unstripped_filename(BUILD_OS)
for arch in BuildArchitectures():
binary = BuildRootPath(binary, arch=arch)
gs_path = namer.unstripped_filepath(revision, BUILD_OS, arch)
DartArchiveFile(binary, gs_path)
def CreateUploadAPIDocs():
dartdoc_dir = BuildRootPath('gen-dartdocs')
dartdoc_zip = BuildRootPath('dartdocs-api.zip')
if CHANNEL == bot_utils.Channel.TRY:
BuildDartdocAPIDocs(dartdoc_dir)
else:
UploadApiLatestFile()
BuildDartdocAPIDocs(dartdoc_dir)
UploadDartdocApiDocs(dartdoc_dir)
CreateZip(dartdoc_dir, dartdoc_zip)
DartArchiveUploadDartdocAPIDocs(dartdoc_zip)
def DartArchiveUploadDartdocAPIDocs(api_zip):
namer = bot_utils.GCSNamer(CHANNEL, bot_utils.ReleaseType.RAW)
revision = utils.GetArchiveVersion()
for revision in [revision, 'latest']:
destination = (namer.apidocs_directory(revision) + '/' +
namer.dartdocs_zipfilename())
DartArchiveFile(api_zip, destination, checksum_files=False)
def UploadDartdocApiDocs(dir_name):
apidocs_namer = bot_utils.GCSNamerApiDocs(CHANNEL)
revision = utils.GetArchiveVersion()
dartdocs_destination_gcsdir = apidocs_namer.dartdocs_dirpath(revision)
# Return early if the documents have already been uploaded.
# This can happen if a build was forced, or a commit had no changes in the
# dart repository (e.g. DEPS file update).
if GsutilExists(dartdocs_destination_gcsdir):
print("Not uploading api docs, since %s is already present." %
dartdocs_destination_gcsdir)
return
# Upload everything inside the built apidocs directory.
gsutil = bot_utils.GSUtil()
gsutil.upload(
dir_name,
dartdocs_destination_gcsdir,
recursive=True,
public=True,
multithread=True)
def UploadApiLatestFile():
apidocs_namer = bot_utils.GCSNamerApiDocs(CHANNEL)
revision = utils.GetArchiveVersion()
apidocs_destination_latestfile = apidocs_namer.docs_latestpath(revision)
# Update latest.txt to contain the newest revision.
with utils.TempDir('latest_file') as temp_dir:
latest_file = os.path.join(temp_dir, 'latest.txt')
with open(latest_file, 'w') as f:
f.write('%s' % revision)
DartArchiveFile(latest_file, apidocs_destination_latestfile)
def GsutilExists(gsu_path):
# This is a little hackish, but it is basically a one off doing very
# specialized check that we don't use elsewhere.
gsutilTool = os.path.join(bot_utils.DART_DIR, 'third_party', 'gsutil',
'gsutil')
(_, stderr, returncode) = bot_utils.run([gsutilTool, 'ls', gsu_path],
throw_on_error=False)
# If the returncode is nonzero and we can find a specific error message,
# we know there are no objects with a prefix of [gsu_path].
missing = (
returncode and
'CommandException: One or more URLs matched no objects.' in stderr)
# Either the returncode has to be zero or the object must be missing,
# otherwise throw an exception.
if not missing and returncode:
raise Exception("Failed to determine whether %s exists" % gsu_path)
return not missing
def CreateZip(directory, target_file):
if 'win' in BUILD_OS:
CreateZipWindows(directory, target_file)
else:
CreateZipPosix(directory, target_file)
def CreateZipPosix(directory, target_file):
with utils.ChangedWorkingDirectory(os.path.dirname(directory)):
command = ['zip', '-yrq9', target_file, os.path.basename(directory)]
Run(command)
def CreateZipWindows(directory, target_file):
with utils.ChangedWorkingDirectory(os.path.dirname(directory)):
zip_win = os.path.join(bot_utils.DART_DIR, 'third_party', '7zip', '7za')
command = [
zip_win, 'a', '-tzip', target_file,
os.path.basename(directory)
]
Run(command)
def FileDelete(f):
if os.path.exists(f):
os.remove(f)
def CopyBetween(src_path, dst_path, *relatives):
try:
os.makedirs(os.path.join(dst_path, *relatives[:-1]))
except OSError:
# This is fine.
pass
shutil.copy2(
os.path.join(src_path, *relatives),
os.path.join(dst_path, *relatives[:-1]))
def GuessExtension(binary):
if 'win' in BUILD_OS:
return binary + '.exe'
return binary
def DartArchiveFile(local_path, remote_path, checksum_files=False):
gsutil = bot_utils.GSUtil()
gsutil.upload(local_path, remote_path, public=True)
if checksum_files:
# 'local_path' may have a different filename than 'remote_path'. So we need
# to make sure the *.md5sum file contains the correct name.
assert '/' in remote_path and not remote_path.endswith('/')
mangled_filename = remote_path[remote_path.rfind('/') + 1:]
local_md5sum = bot_utils.CreateMD5ChecksumFile(local_path,
mangled_filename)
gsutil.upload(local_md5sum, remote_path + '.md5sum', public=True)
local_sha256 = bot_utils.CreateSha256ChecksumFile(
local_path, mangled_filename)
gsutil.upload(local_sha256, remote_path + '.sha256sum', public=True)
def Run(command, env=None):
print "Running %s" % ' '.join(command)
print "Environment %s" % env
return bot.RunProcess(command, env=env)
if __name__ == '__main__':
if len(sys.argv) > 1 and sys.argv[1] == 'api_docs':
if BUILD_OS == 'linux':
CreateUploadAPIDocs()
elif CHANNEL != bot_utils.Channel.TRY:
for arch in BuildArchitectures():
sdk_path = BuildRootPath('dart-sdk', arch=arch)
with bot.BuildStep('Create and upload sdk zip for ' + arch):
CreateAndUploadSDKZip(arch, sdk_path)
DartArchiveUnstrippedBinaries()
if BUILD_OS == 'linux':
CreateUploadVersionFile()