blob: db463ad2df188663fe7a998ae46fa08cc11f62c3 [file] [log] [blame]
// Copyright (c) 2022, 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 'dart:io';
import 'package:package_config/package_config.dart';
import 'find_sdk_root.dart';
import 'suite.dart';
Future<void> writePackageConfig(
Module module, Set<Module> transitiveDependencies, Uri root) async {
const packageConfigJsonPath = ".dart_tool/package_config.json";
var sdkRoot = await findRoot();
Uri packageConfigUri = sdkRoot.resolve(packageConfigJsonPath);
var packageConfig = await loadPackageConfigUri(packageConfigUri);
// We create a package_config.json file to support the CFE in (a) determine
// the default nullability if the current module is a package, and (b)
// resolve `package:` imports. Technically the latter shouldn't be necessary,
// but the CFE requires that if a `package:` URI of a dependency is used in an
// import, then we need that package entry in the associated file. In fact,
// after it checks that the definition exists, the CFE will not actually use
// the resolved URI if a library for the import URI is already found in one of
// the provide .dill files of the dependencies. For that reason, and to ensure
// that a step only has access to the files provided in a module, we generate
// a config file with invalid folders for other packages.
// TODO(sigmund): follow up with the CFE to see if we can remove the need
// for these dummy entries.
var packagesJson = [];
if (module.isPackage) {
packagesJson.add(_packageConfigEntry(, Uri.parse('../${module.packageBase}')));
int unusedNum = 0;
for (Module dependency in transitiveDependencies) {
if (dependency.isPackage) {
// rootUri should be ignored for dependent modules, so we pass in a
// bogus value.
var rootUri = Uri.parse('unused$unusedNum');
var dependentPackage = packageConfig[];
var packageJson = dependentPackage == null
? _packageConfigEntry(, rootUri)
: _packageConfigEntry(, rootUri,
version: dependentPackage.languageVersion);
await File.fromUri(root.resolve(packageConfigJsonPath))
.create(recursive: true);
await File.fromUri(root.resolve(packageConfigJsonPath)).writeAsString('{'
' "configVersion": ${packageConfig.version},'
' "packages": [ ${packagesJson.join(',')} ]'
String _packageConfigEntry(String name, Uri root,
{Uri? packageRoot, LanguageVersion? version}) {
var fields = [
'"name": "${name}"',
'"rootUri": "$root"',
if (packageRoot != null) '"packageUri": "$packageRoot"',
if (version != null) '"languageVersion": "$version"'
return '{${fields.join(',')}}';