Skip to content

Commit

Permalink
Add an option to use a prebuilt Dart SDK
Browse files Browse the repository at this point in the history
  • Loading branch information
zanderso committed Jun 28, 2021
1 parent cc2c361 commit b080f27
Show file tree
Hide file tree
Showing 9 changed files with 333 additions and 98 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -130,3 +130,6 @@ app.*.symbols
!**/ios/**/default.perspectivev3
!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
!/dev/ci/**/Gemfile.lock

# Prebuilt binaries.
/prebuilts/
41 changes: 33 additions & 8 deletions BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import("//flutter/common/config.gni")
import("//flutter/shell/platform/config.gni")
import("//flutter/shell/platform/glfw/config.gni")
import("//flutter/testing/testing.gni")
import("//third_party/dart/build/dart/copy_tree.gni")

# Whether to build the dartdevc sdk, libraries, and source files
# required for the flutter web sdk.
Expand Down Expand Up @@ -43,6 +44,35 @@ config("export_dynamic_symbols") {
}
}

if (flutter_prebuilt_dart_sdk) {
copy_trees("_copy_trees") {
sources = [
{
target = "copy_dart_sdk"
visibility = [ ":dart_sdk" ]
source = target_prebuilt_dart_sdk
dest = "$root_out_dir/dart-sdk"
ignore_patterns = "{}"
},
]
}
}

# Flutter SDK artifacts should only be built when either doing host builds, or
# for cross-compiled desktop targets.
_build_engine_artifacts =
current_toolchain == host_toolchain || (is_linux && !is_chromeos) || is_mac

group("dart_sdk") {
if (_build_engine_artifacts) {
if (flutter_prebuilt_dart_sdk) {
public_deps = [ ":copy_dart_sdk" ]
} else {
public_deps = [ "//third_party/dart:create_sdk" ]
}
}
}

group("flutter") {
testonly = true

Expand All @@ -52,22 +82,17 @@ group("flutter") {
"//flutter/sky",
]

# Flutter SDK artifacts should only be built when either doing host builds, or
# for cross-compiled desktop targets.
build_engine_artifacts = current_toolchain == host_toolchain ||
(is_linux && !is_chromeos) || is_mac

# If enbaled, compile the SDK / snapshot.
if (!is_fuchsia) {
public_deps += [
"//flutter/lib/snapshot:generate_snapshot_bin",
"//flutter/lib/snapshot:kernel_platform_files",
]

if (build_engine_artifacts) {
if (_build_engine_artifacts) {
public_deps += [
":dart_sdk",
"//flutter/flutter_frontend_server:frontend_server",
"//third_party/dart:create_sdk",

# This must be listed explicitly for desktop cross-builds since
# //flutter/lib/snapshot:generate_snapshot_bin will only build
Expand All @@ -81,7 +106,7 @@ group("flutter") {
}
}

if (build_engine_artifacts) {
if (_build_engine_artifacts) {
public_deps += [
"//flutter/shell/testing",
"//flutter/tools/const_finder",
Expand Down
8 changes: 8 additions & 0 deletions DEPS
Original file line number Diff line number Diff line change
Expand Up @@ -713,6 +713,14 @@ hooks = [
'src/build/win/generate_winrt_headers.py',
]
},
{
'name': 'Download prebuilt Dart SDK',
'pattern': '.',
'action': [
'python3',
'src/flutter/tools/download_dart_sdk.py',
]
},
{
'name': 'Setup githooks',
'pattern': '.',
Expand Down
17 changes: 17 additions & 0 deletions common/config.gni
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ declare_args() {

# Whether to use the legacy embedder when building for Fuchsia.
flutter_enable_legacy_fuchsia_embedder = true

# Whether to use a prebuilt Dart SDK instead of building one.
flutter_prebuilt_dart_sdk = false
}

# feature_defines_list ---------------------------------------------------------
Expand Down Expand Up @@ -65,3 +68,17 @@ if (is_ios || is_mac) {
flutter_cflags_objc_arc = flutter_cflags_objc + [ "-fobjc-arc" ]
flutter_cflags_objcc_arc = flutter_cflags_objc_arc
}

# prebuilt Dart SDK location

if (flutter_prebuilt_dart_sdk) {
_os_name = target_os
if (_os_name == "mac") {
_os_name = "macos"
} else if (_os_name == "win" || _os_name == "winuwp") {
_os_name = "windows"
}
target_prebuilt_dart_sdk =
"//flutter/prebuilts/$_os_name-$target_cpu/dart-sdk"
host_prebuilt_dart_sdk = "//flutter/prebuilts/$_os_name-$host_cpu/dart-sdk"
}
20 changes: 13 additions & 7 deletions testing/testing.gni
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import("//build/compiled_action.gni")
import("//flutter/common/config.gni")
import("//third_party/dart/build/dart/dart_action.gni")
import("//third_party/dart/sdk_args.gni")

is_aot_test =
flutter_runtime_mode == "profile" || flutter_runtime_mode == "release"
Expand Down Expand Up @@ -56,18 +57,23 @@ template("dart_snapshot_kernel") {
dart_action(target_name) {
testonly = true

deps = [
# This generates the Frontend server snapshot used in this Dart action as
# well as the patched SDK.
"//third_party/dart/utils/kernel-service:frontend_server",
]
if (flutter_prebuilt_dart_sdk) {
deps = [ "//flutter:dart_sdk" ]
script =
"$root_out_dir/dart-sdk/bin/snapshots/frontend_server.dart.snapshot"
} else {
deps = [
# This generates the Frontend server snapshot used in this Dart action as
# well as the patched SDK.
"//third_party/dart/utils/kernel-service:frontend_server",
]
script = "$root_out_dir/frontend_server.dart.snapshot"
}

if (is_aot_test) {
deps += [ "//flutter/lib/snapshot:strong_platform" ]
}

script = "$root_out_dir/frontend_server.dart.snapshot"

inputs = [ invoker.dart_main ]

outputs = [ invoker.dart_kernel ]
Expand Down
162 changes: 162 additions & 0 deletions tools/download_dart_sdk.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
#!/usr/bin/env python3
# Copyright 2013 The Flutter Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

# This python script downloads the Dart dev channel SDK that matches the
# version in the source tree and puts it in prebuilts/.
# TODO(zra): Eliminate the script and download through the DEPS file if/when
# the SDKs pulled by this script are uploaded to cipd.

import os
import platform
import re
import shutil
import subprocess
import sys
import zipfile


SRC_ROOT = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
FLUTTER_DIR = os.path.join(SRC_ROOT, 'flutter')
FLUTTER_PREBUILTS_DIR = os.path.join(FLUTTER_DIR, 'prebuilts')
DART_DIR = os.path.join(SRC_ROOT, 'third_party', 'dart')
DART_VERSION = os.path.join(DART_DIR, 'tools', 'VERSION')

# The Dart SDK script is the source of truth about the sematic version.
sys.path.append(os.path.join(DART_DIR, 'tools'))
import utils


def eprint(*args, **kwargs):
print(*args, file=sys.stderr, **kwargs)


# Try to guess the host operating system.
def GuessOS():
os_name = utils.GuessOS()
if os_name == 'win32':
os_name == 'windows'
if os_name not in ['linux', 'macos', 'windows']:
eprint('Could not determine the OS: "%s"' % os_id)
return None
return os_name


def ArchitecturesForOS(os_name):
if os_name == 'linux':
return ['x64', 'arm64']
elif os_name == 'macos':
return ['x64', 'arm64']
elif os_name =='windows':
return ['x64']

eprint('Could not determine architectures for os "%s"' % os_name)
return None


def DownloadDartSDK(version, semantic_version, os_name, arch):
channel = version.channel
if channel == 'be':
eprint('Only dev, beta, and stable channels can be used for prebuilt SDKs')
return None
file = 'dartsdk-{}-{}-release.zip'.format(os_name, arch)
url = 'https://storage.googleapis.com/dart-archive/channels/{}/raw/{}/sdk/{}'.format(
channel, semantic_version, file,
)
dest = os.path.join(FLUTTER_PREBUILTS_DIR, file)

stamp_file = '{}.stamp'.format(dest)
version_stamp = None
try:
with open(stamp_file) as fd:
version_stamp = fd.read()
except:
version_stamp = 'none'

if version == version_stamp:
# Prebuilt Dart SDK already up-to-date. Skipping download.
return ''

if os.path.isfile(dest):
os.unlink(dest)

curl_command = ['curl', url, '-o', dest]
curl_result = subprocess.run(
curl_command,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
universal_newlines=True,
)
if curl_result.returncode != 0:
eprint('Failed to download: stdout:\n{}\nstderr:\n{}'.format(
curl_result.stdout, curl_result.stderr,
))
return None

return dest


class ZipFileWithPermissions(zipfile.ZipFile):
""" Custom ZipFile class handling file permissions. """
def _extract_member(self, member, targetpath, pwd):
if not isinstance(member, zipfile.ZipInfo):
member = self.getinfo(member)

targetpath = super()._extract_member(member, targetpath, pwd)

attr = member.external_attr >> 16
if attr != 0:
os.chmod(targetpath, attr)
return targetpath


def ExtractDartSDK(archive, os_name, arch):
os_arch = '{}-{}'.format(os_name, arch)
dart_sdk = os.path.join(FLUTTER_PREBUILTS_DIR, os_arch, 'dart-sdk')
if os.path.isdir(dart_sdk):
shutil.rmtree(dart_sdk)

extract_dest = os.path.join(FLUTTER_PREBUILTS_DIR, os_arch)
os.makedirs(extract_dest, exist_ok=True)

with ZipFileWithPermissions(archive, "r") as z:
z.extractall(extract_dest)


def Main():
os.makedirs(FLUTTER_PREBUILTS_DIR, exist_ok=True)

version = utils.ReadVersionFile()
if version == None:
return 1
semantic_version = utils.GetSemanticSDKVersion()

os_name = GuessOS()
if os_name == None:
return 1

architectures = ArchitecturesForOS(os_name)
if architectures == None:
return 1

for arch in ArchitecturesForOS(os_name):
archive = DownloadDartSDK(version, semantic_version, os_name, arch)
if archive == None:
return 1
if archive == '':
return 0
ExtractDartSDK(archive, os_name, arch)
try:
stamp_file = '{}.stamp'.format(archive)
with open(stamp_file, "w") as fd:
fd.write(semantic_version)
except Exception as e:
eprint('Failed to write Dart SDK version stamp file:\n{}'.format(e))
return 1

return 0


if __name__ == '__main__':
sys.exit(Main())
26 changes: 23 additions & 3 deletions tools/gn
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,18 @@ def cpu_for_target_arch(arch):
if arch in ['x64', 'arm64', 'simarm64', 'simdbc64', 'armsimdbc64']:
return 'x64'

def can_use_prebuilt_dart(args):
# Targeting the host
if args.target_os == None:
return True
elif args.target_os == 'linux':
return args.linux_cpu in ['x64', 'arm64']
elif args.target_os == 'mac':
return args.mac_cpu in ['x64', 'arm64']
elif args.target_os in ['win', 'winuwp']:
return args.windows_cpu == 'x64'
return False

def to_gn_args(args):
if args.simulator:
if args.target_os == 'android':
Expand Down Expand Up @@ -300,9 +312,15 @@ def to_gn_args(args):
if args.arm_float_abi:
gn_args['arm_float_abi'] = args.arm_float_abi

# dart_platform_sdk is only defined for host builds, linux arm host builds
# specify target_os=linux
if args.target_os is None or args.target_os == 'linux':
# If we have a prebuilt for the Dart SDK for the target architecture, then
# use it instead of building a new one.
if args.prebuilt_dart_sdk and can_use_prebuilt_dart(args):
gn_args['flutter_prebuilt_dart_sdk'] = True
gn_args['dart_sdk_output'] = 'built-dart-sdk'
gn_args['verify_sdk_hash'] = False
elif args.target_os is None or args.target_os == 'linux':
# dart_platform_sdk is only defined for host builds, linux arm host builds
# specify target_os=linux.
# dart_platform_sdk=True means exclude web-related files, e.g. dart2js,
# dartdevc, web SDK kernel and source files.
gn_args['dart_platform_sdk'] = not args.full_dart_sdk
Expand Down Expand Up @@ -446,6 +464,8 @@ def parse_args(args):
help='Strip debug symbols from the output. This defaults to true and has no effect on iOS.')
parser.add_argument('--no-stripped', dest='stripped', action='store_false')

parser.add_argument('--prebuilt-dart-sdk', default=False, action='store_true')

# Sanitizers.
parser.add_argument('--asan', default=False, action='store_true')
parser.add_argument('--lsan', default=False, action='store_true')
Expand Down
1 change: 1 addition & 0 deletions tools/licenses/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2128,6 +2128,7 @@ class _RepositoryFlutterDirectory extends _RepositoryDirectory {
// None of the web_sdk code is linked into Flutter apps. It's only used
// by engine tests and tools.
&& entry.name != 'web_sdk'
&& entry.name != 'prebuilts'
&& super.shouldRecurse(entry);
}

Expand Down
Loading

0 comments on commit b080f27

Please sign in to comment.