generate package config during runhooks (#19428)
The dart SDK needs to ship several packages which have opted into null safety for the tech preview. This requires the use of a package_config.json for compilation as this file contains the language versions. Use a dart script to generate the package_config file from the .packages file, and include that in the DEPS hooks section.
Fixes flutter/flutter#60628
diff --git a/DEPS b/DEPS
index 91a5768..bd00afa 100644
--- a/DEPS
+++ b/DEPS
@@ -629,4 +629,12 @@
'src/build/linux/sysroot_scripts/install-sysroot.py',
'--arch=x64'],
},
+ {
+ 'name': 'dart package config',
+ 'pattern': '.',
+ 'action': [
+ 'python',
+ 'src/flutter/tools/run_third_party_dart.py',
+ ]
+ }
]
diff --git a/flutter_frontend_server/BUILD.gn b/flutter_frontend_server/BUILD.gn
index dbaa0e4..4ed9c11 100644
--- a/flutter_frontend_server/BUILD.gn
+++ b/flutter_frontend_server/BUILD.gn
@@ -67,10 +67,9 @@
application_snapshot("frontend_server") {
main_dart = "bin/starter.dart"
deps = [
- ":package_incremental_compiler",
"//flutter/lib/snapshot:kernel_platform_files",
]
- dot_packages = rebase_path(".packages")
+ dot_packages = rebase_path(".dart_tool/package_config.json")
flutter_patched_sdk = rebase_path("$root_out_dir/flutter_patched_sdk")
training_args = [
"--train",
@@ -80,27 +79,3 @@
inputs = frontend_server_files
}
-
-# For flutter/flutter#36738 we make the source files available so that
-# we can generate a local frontend_server snapshot in the tools cache.
-action("package_incremental_compiler") {
- script = "//flutter/flutter_frontend_server/package_incremental.py"
-
- inputs = frontend_server_files
-
- outputs = [
- "$root_gen_dir/dart-pkg/flutter_frontend_server/pubspec.yaml",
- "$root_gen_dir/dart-pkg/vm/pubspec.yaml",
- "$root_gen_dir/dart-pkg/build_integration/pubspec.yaml",
- "$root_gen_dir/dart-pkg/front_end/pubspec.yaml",
- "$root_gen_dir/dart-pkg/kernel/pubspec.yaml",
- "$root_gen_dir/dart-pkg/dev_compiler/pubspec.yaml",
- "$root_gen_dir/dart-pkg/frontend_server/pubspec.yaml",
- ]
-
- args = [
- "--input-root=" + rebase_path("//third_party/dart/pkg"),
- "--output-root=" + rebase_path("$root_gen_dir/dart-pkg"),
- "--frontend-server=" + rebase_path("//flutter"),
- ]
-}
diff --git a/flutter_frontend_server/bin/starter.dart b/flutter_frontend_server/bin/starter.dart
index 862a8a7..e95335c 100644
--- a/flutter_frontend_server/bin/starter.dart
+++ b/flutter_frontend_server/bin/starter.dart
@@ -1,3 +1,4 @@
+// @dart=2.8
library frontend_server;
import 'dart:io';
diff --git a/flutter_frontend_server/lib/server.dart b/flutter_frontend_server/lib/server.dart
index e4524a1..bd5125c 100644
--- a/flutter_frontend_server/lib/server.dart
+++ b/flutter_frontend_server/lib/server.dart
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// @dart=2.8
library flutter_frontend_server;
import 'dart:async';
diff --git a/flutter_frontend_server/package_incremental.py b/flutter_frontend_server/package_incremental.py
deleted file mode 100755
index 8c54f31..0000000
--- a/flutter_frontend_server/package_incremental.py
+++ /dev/null
@@ -1,150 +0,0 @@
-#!/usr/bin/env python
-# 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.
-
-import argparse
-import os
-import shutil
-import sys
-
-# The list of packages copied from the Dart SDK.
-PACKAGES = [
- "vm",
- "build_integration",
- "kernel",
- "front_end",
- "dev_compiler",
- "flutter_frontend_server",
- "frontend_server",
- "dev_compiler",
-]
-
-VM_PUBSPEC = r'''name: vm
-version: 0.0.1
-environment:
- sdk: ">=2.2.2 <3.0.0"
-
-dependencies:
- dev_compiler: any
- front_end: any
- kernel: any
- meta: any
- build_integration: any
-'''
-
-BUILD_INTEGRATION_PUBSPEC = r'''name: build_integration
-version: 0.0.1
-environment:
- sdk: ">=2.2.2 <3.0.0"
-
-dependencies:
- front_end: any
- meta: any
-'''
-
-FLUTTER_FRONTEND_SERVER_PUBSPEC = r'''name: flutter_frontend_server
-version: 0.0.1
-environment:
- sdk: ">=2.2.2 <3.0.0"
-
-dependencies:
- args: any
- path: any
- vm: any
-'''
-
-KERNEL_PUBSPEC = r'''name: kernel
-version: 0.0.1
-environment:
- sdk: '>=2.2.2 <3.0.0'
-
-dependencies:
- args: any
- meta: any
-'''
-
-FRONT_END_PUBSPEC = r'''name: front_end
-version: 0.0.1
-environment:
- sdk: '>=2.2.2 <3.0.0'
-dependencies:
- kernel: any
- package_config: any
- meta: any
-'''
-
-DEV_COMPILER_PUBSPEC = r'''name: dev_compiler
-version: 0.0.1
-environment:
- sdk: '>=2.2.2 <3.0.0'
-dependencies:
- analyzer: any
- bazel_worker: any
- build_integration: any
- cli_util: any
- source_maps: any
-'''
-
-FRONTEND_SERVER_PUBSPEC = r'''name: frontend_server
-version: 0.0.1
-environment:
- sdk: '>=2.2.2 < 3.0.0'
-dependencies:
- build_integration: any
- vm: any
- dev_compiler: any
- front_end: any
- kernel: any
- args: any
-'''
-
-PUBSPECS = {
- 'vm': VM_PUBSPEC,
- 'build_integration': BUILD_INTEGRATION_PUBSPEC,
- 'flutter_frontend_server': FLUTTER_FRONTEND_SERVER_PUBSPEC,
- 'kernel': KERNEL_PUBSPEC,
- 'front_end': FRONT_END_PUBSPEC,
- 'dev_compiler': DEV_COMPILER_PUBSPEC,
- 'frontend_server': FRONTEND_SERVER_PUBSPEC,
-}
-
-def main():
- parser = argparse.ArgumentParser()
- parser.add_argument('--frontend-server', type=str, dest='frontend', action='store')
- parser.add_argument('--input-root', type=str, dest='input', action='store')
- parser.add_argument('--output-root', type=str, dest='output', action='store')
-
- args = parser.parse_args()
- for package in PACKAGES:
- base = args.input
- # Handle different path for frontend_server
- if package == 'flutter_frontend_server':
- base = args.frontend
- package_root = os.path.join(base, package)
- for root, directories, files in os.walk(package_root):
- # We only care about actual source files, not generated code or tests.
- for skip_dir in ['.git', 'gen', 'test']:
- if skip_dir in directories:
- directories.remove(skip_dir)
-
- # Ensure we have a dest directory
- if not os.path.isdir(os.path.join(args.output, package)):
- os.makedirs(os.path.join(args.output, package))
-
- for filename in files:
- if filename.endswith('.dart') and not filename.endswith('_test.dart'):
- destination_file = os.path.join(args.output, package,
- os.path.relpath(os.path.join(root, filename), start=package_root))
- parent_path = os.path.abspath(os.path.join(destination_file, os.pardir))
- if not os.path.isdir(parent_path):
- os.makedirs(parent_path)
- shutil.copyfile(os.path.join(root, filename), destination_file)
-
- # Write the overriden pubspec for each package.
- pubspec_file = os.path.join(args.output, package, 'pubspec.yaml')
- with open(pubspec_file, 'w+') as output_file:
- output_file.write(PUBSPECS[package])
-
-if __name__ == '__main__':
- sys.exit(main())
diff --git a/tools/generate_package_config/bin/generate_from_legacy.dart b/tools/generate_package_config/bin/generate_from_legacy.dart
new file mode 100644
index 0000000..011e5e1
--- /dev/null
+++ b/tools/generate_package_config/bin/generate_from_legacy.dart
@@ -0,0 +1,96 @@
+// Copyright (c) 2020, 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.
+// @dart=2.8
+import 'dart:convert';
+import 'dart:io';
+
+import 'package:package_config/package_config.dart';
+import 'package:package_config/packages_file.dart'; // ignore: deprecated_member_use
+import 'package:package_config/src/package_config_json.dart';
+import 'package:pub_semver/pub_semver.dart';
+import 'package:yaml/yaml.dart';
+
+void main(List<String> args) async {
+ if (args.length != 1) {
+ throw ArgumentError('Unexpected arguments $args\n\n$usage');
+ }
+ if (args.first == 'help') {
+ print(usage);
+ return;
+ }
+ var packagesUri = Uri.base.resolve(args.first);
+ var packagesFile = File.fromUri(packagesUri);
+ if (!await packagesFile.exists()) {
+ throw ArgumentError('Unable to read file at `$packagesUri`');
+ }
+ var packageMap = parse(await packagesFile.readAsBytes(), packagesFile.uri);
+ var packages = <Package>[];
+ for (var packageEntry in packageMap.entries) {
+ var name = packageEntry.key;
+ var uri = packageEntry.value;
+ if (uri.scheme != 'file') {
+ throw ArgumentError(
+ 'Only file: schemes are supported, but the `$name` package has '
+ 'the following uri: ${uri}');
+ }
+ Uri packageRoot;
+ Uri pubspec;
+ LanguageVersion languageVersion;
+ // Pub packages will always have a path ending in `lib/`, and a pubspec
+ // directly above that.
+ if (uri.path.endsWith('lib/')) {
+ packageRoot = uri.resolve('../');
+ pubspec = packageRoot.resolve('pubspec.yaml');
+ if (!File.fromUri(pubspec).existsSync()) {
+ continue;
+ }
+ // Default to 2.8 if not found to prevent all packages from accidentally
+ // opting into NNBD.
+ languageVersion = await languageVersionFromPubspec(pubspec, name) ??
+ LanguageVersion(2, 8);
+ packages.add(Package(name, packageRoot,
+ languageVersion: languageVersion, packageUriRoot: uri));
+ }
+ }
+ var outputFile =
+ File.fromUri(packagesFile.uri.resolve('.dart_tool/package_config.json'));
+ if (!outputFile.parent.existsSync()) {
+ outputFile.parent.createSync();
+ }
+ var baseUri = outputFile.uri;
+ var sink = outputFile.openWrite(encoding: utf8);
+ writePackageConfigJsonUtf8(PackageConfig(packages), baseUri, sink);
+ await sink.close();
+}
+
+const usage = 'Usage: pub run package_config:generate_from_legacy <input-file>';
+
+Future<LanguageVersion> languageVersionFromPubspec(
+ Uri pubspec, String packageName) async {
+ var pubspecFile = File.fromUri(pubspec);
+ if (!await pubspecFile.exists()) {
+ return null;
+ }
+ var pubspecYaml =
+ loadYaml(await pubspecFile.readAsString(), sourceUrl: pubspec) as YamlMap;
+
+ // Find the sdk constraint, or return null if none is present
+ var environment = pubspecYaml['environment'] as YamlMap;
+ if (environment == null) {
+ return null;
+ }
+ var sdkConstraint = environment['sdk'] as String;
+ if (sdkConstraint == null) {
+ return null;
+ }
+
+ var parsedConstraint = VersionConstraint.parse(sdkConstraint);
+ var min = parsedConstraint is Version
+ ? parsedConstraint
+ : parsedConstraint is VersionRange
+ ? parsedConstraint.min
+ : throw 'Unsupported version constraint type $parsedConstraint';
+
+ return LanguageVersion(min.major, min.minor);
+}
diff --git a/tools/generate_package_config/pubspec.yaml b/tools/generate_package_config/pubspec.yaml
new file mode 100644
index 0000000..213dbb9
--- /dev/null
+++ b/tools/generate_package_config/pubspec.yaml
@@ -0,0 +1,8 @@
+name: generate_package_config
+environment:
+ sdk: ">=2.8.0 <3.0.0"
+
+dependencies:
+ yaml: any
+ pub_semver: any
+ package_config: any
diff --git a/tools/run_third_party_dart.py b/tools/run_third_party_dart.py
new file mode 100644
index 0000000..08df6b4
--- /dev/null
+++ b/tools/run_third_party_dart.py
@@ -0,0 +1,9 @@
+# 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.
+
+import subprocess
+
+if __name__ == '__main__':
+ subprocess.call(["src/third_party/dart/tools/sdks/dart-sdk/bin/dart", "pub", "global", "activate", "-spath", "./src/flutter/tools/generate_package_config"])
+ subprocess.call(["src/third_party/dart/tools/sdks/dart-sdk/bin/dart", "pub", "global", "run", "generate_package_config:generate_from_legacy", "src/flutter/flutter_frontend_server/.packages"])