diff --git a/DEPS b/DEPS index acf5a7b413a1..bd78007271c1 100644 --- a/DEPS +++ b/DEPS @@ -141,7 +141,7 @@ vars = { "markdown_rev": "19aaded4300d24bedcbf52ade792b203ddf030b0", "material_color_utilities_rev": "799b6ba2f3f1c28c67cc7e0b4f18e0c7d7f3c03e", # dart-native-interop-team@ is rolling breaking changes manually while the assets features are in experimental. - "native_rev": "d1d9aa5e62d239580b8bf17e36db6d47c308fc89", # disable tools/rev_sdk_deps.dart + "native_rev": "3ed5d3d07246cd792693584c2c42216739a634b7", # disable tools/rev_sdk_deps.dart "protobuf_rev": "b7dd58cdbd879beee4c3fbf8ee80fce8e97bad26", "pub_rev": "710265bae23ad5860f33287fba10b5c369f19a93", # disable tools/rev_sdk_deps.dart "shelf_rev": "bf799519cda2898a7c5af06dcfdd5fe6443afd79", diff --git a/pkg/dartdev/lib/src/commands/build.dart b/pkg/dartdev/lib/src/commands/build.dart index 25ce5ccaee7b..386c2188215c 100644 --- a/pkg/dartdev/lib/src/commands/build.dart +++ b/pkg/dartdev/lib/src/commands/build.dart @@ -10,14 +10,9 @@ import 'package:dartdev/src/commands/compile.dart'; import 'package:dartdev/src/experiments.dart'; import 'package:dartdev/src/native_assets_bundling.dart'; import 'package:dartdev/src/sdk.dart'; -import 'package:dartdev/src/utils.dart'; -import 'package:file/local.dart'; import 'package:front_end/src/api_prototype/compiler_options.dart' show Verbosity; -import 'package:native_assets_builder/native_assets_builder.dart'; import 'package:native_assets_cli/code_assets_builder.dart'; -import 'package:native_assets_cli/data_assets_builder.dart'; -import 'package:package_config/package_config.dart' as package_config; import 'package:path/path.dart' as path; import 'package:vm/target_os.dart'; // For possible --target-os values. @@ -132,61 +127,23 @@ class BuildCommand extends DartdevCommand { } await outputDir.create(recursive: true); - // Start native asset generation here. stdout.writeln('Building native assets.'); - final packageConfig = await findPackageConfigUri(sourceUri); - final runPackageName = await findRootPackageName(sourceUri); - final workingDirectory = Directory.current.uri; - final packageLayout = PackageLayout.fromPackageConfig( - LocalFileSystem(), - await package_config.loadPackageConfigUri(packageConfig!), - packageConfig, + final packageConfig = await DartNativeAssetsBuilder.ensurePackageConfig( + sourceUri, ); - final target = Target.current; - final macOSConfig = target.os == OS.macOS - ? MacOSConfig(targetVersion: minimumSupportedMacOSVersion) - : null; - final nativeAssetsBuildRunner = NativeAssetsBuildRunner( - fileSystem: const LocalFileSystem(), - dartExecutable: Uri.file(sdk.dart), - logger: logger(verbose), + final runPackageName = await DartNativeAssetsBuilder.findRootPackageName( + sourceUri, ); - - final cCompilerConfig = getCCompilerConfig(); - - final buildResult = await nativeAssetsBuildRunner.build( - inputCreator: () => BuildInputBuilder() - ..config.setupCode( - targetOS: target.os, - linkModePreference: LinkModePreference.dynamic, - targetArchitecture: target.architecture, - macOS: macOSConfig, - cCompiler: cCompilerConfig, - ), - inputValidator: (config) async => [ - ...await validateDataAssetBuildInput(config), - ...await validateCodeAssetBuildInput(config), - ], - workingDirectory: workingDirectory, - packageLayout: packageLayout, - runPackageName: runPackageName, - linkingEnabled: true, - buildAssetTypes: [ - CodeAsset.type, - ], - buildValidator: (config, output) async => [ - ...await validateDataAssetBuildOutput(config, output), - ...await validateCodeAssetBuildOutput(config, output), - ], - applicationAssetValidator: (assets) async => [ - ...await validateCodeAssetInApplication(assets), - ], + final builder = DartNativeAssetsBuilder( + packageConfigUri: packageConfig!, + runPackageName: runPackageName!, + verbose: verbose, ); + final buildResult = await builder.buildNativeAssetsAOT(); if (buildResult == null) { stderr.writeln('Native assets build failed.'); return 255; } - // End native asset generation here. final tempDir = Directory.systemTemp.createTempSync(); try { @@ -211,38 +168,10 @@ class BuildCommand extends DartdevCommand { recordedUsagesFile: recordedUsagesPath, ); - // Start linking here. - final linkResult = await nativeAssetsBuildRunner.link( - inputCreator: () => LinkInputBuilder() - ..config.setupCode( - targetOS: target.os, - targetArchitecture: target.architecture, - linkModePreference: LinkModePreference.dynamic, - macOS: macOSConfig, - cCompiler: cCompilerConfig, - ), - inputValidator: (config) async => [ - ...await validateDataAssetLinkInput(config), - ...await validateCodeAssetLinkInput(config), - ], - resourceIdentifiers: - recordUseEnabled ? Uri.file(recordedUsagesPath!) : null, - workingDirectory: workingDirectory, - runPackageName: runPackageName, - packageLayout: packageLayout, + final linkResult = await builder.linkNativeAssetsAOT( + recordedUsagesPath: recordedUsagesPath, buildResult: buildResult, - buildAssetTypes: [ - CodeAsset.type, - ], - linkValidator: (config, output) async => [ - ...await validateDataAssetLinkOutput(config, output), - ...await validateCodeAssetLinkOutput(config, output), - ], - applicationAssetValidator: (assets) async => [ - ...await validateCodeAssetInApplication(assets), - ], ); - if (linkResult == null) { stderr.writeln('Native assets link failed.'); return 255; @@ -265,7 +194,7 @@ Use linkMode as dynamic library instead."""); if (allAssets.isNotEmpty) { final kernelAssets = await bundleNativeAssets( allAssets, - target, + builder.target, outputUri, relocatable: true, verbose: true, diff --git a/pkg/dartdev/lib/src/commands/compile.dart b/pkg/dartdev/lib/src/commands/compile.dart index 75cb77e9b9ad..fdc2d4c42058 100644 --- a/pkg/dartdev/lib/src/commands/compile.dart +++ b/pkg/dartdev/lib/src/commands/compile.dart @@ -558,23 +558,35 @@ Remove debugging information from the output and save it separately to the speci return compileErrorExitCode; } - if (!nativeAssetsExperimentEnabled) { - if (await warnOnNativeAssets()) { - return 255; - } - } else { - final assets = await compileNativeAssetsJit( - verbose: verbose, - runPackageName: await findRootPackageName(Directory.current.uri), + final packageConfig = await DartNativeAssetsBuilder.ensurePackageConfig( + Directory.current.uri, + ); + if (packageConfig != null) { + final runPackageName = await DartNativeAssetsBuilder.findRootPackageName( + Directory.current.uri, ); - if (assets == null) { - stderr.writeln('Native assets build failed.'); - return 255; - } - if (assets.isNotEmpty) { - stderr.writeln( - "'dart compile' does currently not support native assets."); - return 255; + if (runPackageName != null) { + final builder = DartNativeAssetsBuilder( + packageConfigUri: packageConfig, + runPackageName: runPackageName, + verbose: verbose, + ); + if (!nativeAssetsExperimentEnabled) { + if (await builder.warnOnNativeAssets()) { + return 255; + } + } else { + final assets = await builder.compileNativeAssetsJit(); + if (assets == null) { + stderr.writeln('Native assets build failed.'); + return 255; + } + if (assets.isNotEmpty) { + stderr.writeln( + "'dart compile' does currently not support native assets."); + return 255; + } + } } } diff --git a/pkg/dartdev/lib/src/commands/language_server.dart b/pkg/dartdev/lib/src/commands/language_server.dart index 1e0ff3b08923..65ec6280ead8 100644 --- a/pkg/dartdev/lib/src/commands/language_server.dart +++ b/pkg/dartdev/lib/src/commands/language_server.dart @@ -52,7 +52,7 @@ For more information about the server's capabilities and configuration, see: sdk.analysisServerSnapshot, args, packageConfigOverride: null, - useExecProcess : false, + useExecProcess: false, ); return 0; } catch (e, st) { diff --git a/pkg/dartdev/lib/src/commands/run.dart b/pkg/dartdev/lib/src/commands/run.dart index cb288823221f..74817db53913 100644 --- a/pkg/dartdev/lib/src/commands/run.dart +++ b/pkg/dartdev/lib/src/commands/run.dart @@ -371,22 +371,34 @@ class RunCommand extends DartdevCommand { } String? nativeAssets; - if (!nativeAssetsExperimentEnabled) { - if (await warnOnNativeAssets()) { - return errorExitCode; - } - } else { + final packageConfig = await DartNativeAssetsBuilder.ensurePackageConfig( + Directory.current.uri, + ); + if (packageConfig != null) { final runPackageName = getPackageForCommand(mainCommand) ?? - await findRootPackageName(Directory.current.uri); - final assetsYamlFileUri = await compileNativeAssetsJitYamlFile( - verbose: verbose, - runPackageName: runPackageName, - ); - if (assetsYamlFileUri == null) { - log.stderr('Error: Compiling native assets failed.'); - return errorExitCode; + await DartNativeAssetsBuilder.findRootPackageName( + Directory.current.uri, + ); + if (runPackageName != null) { + final builder = DartNativeAssetsBuilder( + packageConfigUri: packageConfig, + runPackageName: runPackageName, + verbose: verbose, + ); + if (!nativeAssetsExperimentEnabled) { + if (await builder.warnOnNativeAssets()) { + return errorExitCode; + } + } else { + final assetsYamlFileUri = + await builder.compileNativeAssetsJitYamlFile(); + if (assetsYamlFileUri == null) { + log.stderr('Error: Compiling native assets failed.'); + return errorExitCode; + } + nativeAssets = assetsYamlFileUri.toFilePath(); + } } - nativeAssets = assetsYamlFileUri.toFilePath(); } final String? residentCompilerInfoFileArg = diff --git a/pkg/dartdev/lib/src/commands/test.dart b/pkg/dartdev/lib/src/commands/test.dart index 7a2ea6267361..cfa73eeb9132 100644 --- a/pkg/dartdev/lib/src/commands/test.dart +++ b/pkg/dartdev/lib/src/commands/test.dart @@ -47,21 +47,33 @@ Run "${runner!.executableName} help" to see global options.'''); final args = argResults!; String? nativeAssets; - if (!nativeAssetsExperimentEnabled) { - if (await warnOnNativeAssets()) { - return DartdevCommand.errorExitCode; - } - } else { - final assetsYamlFileUri = - await compileNativeAssetsJitYamlFile( - verbose: verbose, - runPackageName: await findRootPackageName(Directory.current.uri), + final packageConfig = await DartNativeAssetsBuilder.ensurePackageConfig( + Directory.current.uri, + ); + if (packageConfig != null) { + final runPackageName = await DartNativeAssetsBuilder.findRootPackageName( + Directory.current.uri, ); - if (assetsYamlFileUri == null) { - log.stderr('Error: Compiling native assets failed.'); - return DartdevCommand.errorExitCode; + if (runPackageName != null) { + final builder = DartNativeAssetsBuilder( + packageConfigUri: packageConfig, + runPackageName: runPackageName, + verbose: verbose, + ); + if (!nativeAssetsExperimentEnabled) { + if (await builder.warnOnNativeAssets()) { + return DartdevCommand.errorExitCode; + } + } else { + final assetsYamlFileUri = + await builder.compileNativeAssetsJitYamlFile(); + if (assetsYamlFileUri == null) { + log.stderr('Error: Compiling native assets failed.'); + return DartdevCommand.errorExitCode; + } + nativeAssets = assetsYamlFileUri.toFilePath(); + } } - nativeAssets = assetsYamlFileUri.toFilePath(); } try { diff --git a/pkg/dartdev/lib/src/native_assets.dart b/pkg/dartdev/lib/src/native_assets.dart index ad6c371315b8..014e189cc81d 100644 --- a/pkg/dartdev/lib/src/native_assets.dart +++ b/pkg/dartdev/lib/src/native_assets.dart @@ -18,228 +18,304 @@ import 'package:package_config/package_config.dart' as package_config; import 'core.dart'; -/// Compiles all native assets for host OS in JIT mode. -/// -/// If provided, only native assets of all transitive dependencies of -/// [runPackageName] are built. -Future?> compileNativeAssetsJit({ - required bool verbose, - required String runPackageName, -}) async { - final workingDirectory = Directory.current.uri; - var packageConfig = await findPackageConfigUri(workingDirectory); - // TODO(https://github.com/dart-lang/package_config/issues/126): Use - // package config resolution from package:package_config. - if (packageConfig == null) { - final pubspecMaybe = await _findPubspec(workingDirectory); - if (pubspecMaybe != null) { - // Silently run `pub get`, this is what would happen in - // `getExecutableForCommand` later. - final result = await Process.run(sdk.dart, ['pub', 'get']); - if (result.exitCode != 0) { - return null; +class DartNativeAssetsBuilder { + final Uri packageConfigUri; + final String runPackageName; + final bool verbose; + + static const _fileSystem = LocalFileSystem(); + + late final Future _packageLayout = () async { + return PackageLayout.fromPackageConfig( + _fileSystem, + await package_config.loadPackageConfigUri(packageConfigUri), + packageConfigUri, + runPackageName, + ); + }(); + + late final _logger = Logger('') + ..onRecord.listen((LogRecord record) { + final levelValue = record.level.value; + if (levelValue >= Level.SEVERE.value) { + log.stderr(record.message); + } else if (levelValue >= Level.WARNING.value || + verbose && levelValue >= Level.INFO.value) { + log.stdout(record.message); + } else { + // Note, this is ignored by default. + log.trace(record.message); } - packageConfig = await findPackageConfigUri(workingDirectory); - } else { - return null; - } + }); + + late final Future _nativeAssetsBuildRunner = + () async { + return NativeAssetsBuildRunner( + // This always runs in JIT mode. + dartExecutable: Uri.file(sdk.dart), + logger: _logger, + fileSystem: const LocalFileSystem(), + packageLayout: await _packageLayout, + ); + }(); + + DartNativeAssetsBuilder({ + required this.packageConfigUri, + required this.runPackageName, + required this.verbose, + }); + + /// Compiles all native assets for host OS in JIT mode. + /// + /// If provided, only native assets of all transitive dependencies of + /// [runPackageName] are built. + Future?> compileNativeAssetsJit() async { + final buildResult = await _buildNativeAssetsShared(linkingEnabled: false); + if (buildResult == null) return null; + return buildResult.encodedAssets; } - final packageLayout = PackageLayout.fromPackageConfig( - LocalFileSystem(), - await package_config.loadPackageConfigUri(packageConfig!), - packageConfig, - ); - final nativeAssetsBuildRunner = NativeAssetsBuildRunner( - // This always runs in JIT mode. - dartExecutable: Uri.file(sdk.dart), - logger: logger(verbose), - fileSystem: const LocalFileSystem(), - ); - final target = Target.current; - final macOSConfig = target.os == OS.macOS - ? MacOSConfig(targetVersion: minimumSupportedMacOSVersion) - : null; - final cCompilerConfig = getCCompilerConfig(); - final buildResult = await nativeAssetsBuildRunner.build( - inputCreator: () => BuildInputBuilder() - ..config.setupCode( - targetOS: target.os, - targetArchitecture: target.architecture, - // When running in JIT mode, only dynamic libraries are supported. - linkModePreference: LinkModePreference.dynamic, - macOS: macOSConfig, - cCompiler: cCompilerConfig, - ), - inputValidator: (config) async => [ - ...await validateCodeAssetBuildInput(config), - ...await validateDataAssetBuildInput(config), - ], - workingDirectory: workingDirectory, - runPackageName: runPackageName, - packageLayout: packageLayout, - linkingEnabled: false, - buildAssetTypes: [ - CodeAsset.type, - ], - buildValidator: (config, output) async => [ - ...await validateDataAssetBuildOutput(config, output), - ...await validateCodeAssetBuildOutput(config, output), - ], - applicationAssetValidator: (assets) async => [ - ...await validateCodeAssetInApplication(assets), - ], - ); - if (buildResult == null) return null; - return buildResult.encodedAssets; -} -/// Compiles all native assets for host OS in JIT mode, and creates the -/// native assets yaml file. -/// -/// If provided, only native assets of all transitive dependencies of -/// [runPackageName] are built. -/// -/// Used in `dart run` and `dart test`. -Future compileNativeAssetsJitYamlFile({ - required bool verbose, - required String runPackageName, -}) async { - final assets = await compileNativeAssetsJit( - verbose: verbose, - runPackageName: runPackageName, - ); - if (assets == null) return null; - - final dartToolUri = Directory.current.uri.resolve('.dart_tool/'); - final outputUri = dartToolUri.resolve('native_assets/'); - await Directory.fromUri(outputUri).create(recursive: true); - - final kernelAssets = await bundleNativeAssets( - assets, - Target.current, - outputUri, - relocatable: false, - ); - - return await writeNativeAssetsYaml( - kernelAssets, - dartToolUri, - header: '''# Native assets mapping for host OS in JIT mode. + /// Compiles all native assets for host OS in JIT mode, and creates the + /// native assets yaml file. + /// + /// If provided, only native assets of all transitive dependencies of + /// [runPackageName] are built. + /// + /// Used in `dart run` and `dart test`. + Future compileNativeAssetsJitYamlFile() async { + final assets = await compileNativeAssetsJit(); + if (assets == null) return null; + + final dartToolUri = Directory.current.uri.resolve('.dart_tool/'); + final outputUri = dartToolUri.resolve('native_assets/'); + await Directory.fromUri(outputUri).create(recursive: true); + + final kernelAssets = await bundleNativeAssets( + assets, + Target.current, + outputUri, + relocatable: false, + ); + + return await writeNativeAssetsYaml( + kernelAssets, + dartToolUri, + header: '''# Native assets mapping for host OS in JIT mode. # Generated by dartdev and package:native_assets_builder. ''', - ); -} - -Future warnOnNativeAssets() async { - final workingDirectory = Directory.current.uri; - if (!await File.fromUri( - workingDirectory.resolve('.dart_tool/package_config.json')) - .exists()) { - // If `pub get` hasn't run, we can't know, so don't error. - return false; - } - try { - final packageLayout = - await PackageLayout.fromWorkingDirectory( - const LocalFileSystem(), - workingDirectory, ); - final packagesWithNativeAssets = [ - ...await packageLayout.packagesWithAssets(Hook.build), - ...await packageLayout.packagesWithAssets(Hook.link) - ]; - if (packagesWithNativeAssets.isEmpty) { - return false; + } + + Future warnOnNativeAssets() async { + final workingDirectory = Directory.current.uri; + + try { + final packageLayout = await PackageLayout.fromWorkingDirectory( + _fileSystem, + workingDirectory, + runPackageName, + ); + final packagesWithNativeAssets = [ + ...await packageLayout.packagesWithAssets(Hook.build), + ...await packageLayout.packagesWithAssets(Hook.link) + ]; + if (packagesWithNativeAssets.isEmpty) { + return false; + } + final packageNames = + packagesWithNativeAssets.map((p) => p.name).join(' '); + log.stderr( + 'Package(s) $packageNames require the native assets feature to be enabled. ' + 'Enable native assets with `--enable-experiment=native-assets`.', + ); + } on FormatException catch (e) { + // This can be thrown if the package_config.json is malformed or has + // duplicate entries. + log.stderr( + 'Error encountered while parsing package_config.json: ${e.message}', + ); } - final packageNames = packagesWithNativeAssets.map((p) => p.name).join(' '); - log.stderr( - 'Package(s) $packageNames require the native assets feature to be enabled. ' - 'Enable native assets with `--enable-experiment=native-assets`.', - ); - } on FormatException catch (e) { - // This can be thrown if the package_config.json is malformed or has - // duplicate entries. - log.stderr( - 'Error encountered while parsing package_config.json: ${e.message}', + return true; + } + + Future _buildNativeAssetsShared({ + required bool linkingEnabled, + }) async { + final buildResult = await (await _nativeAssetsBuildRunner).build( + inputCreator: () => BuildInputBuilder() + ..config.setupCode( + targetOS: target.os, + linkModePreference: LinkModePreference.dynamic, + targetArchitecture: target.architecture, + macOS: _macOSConfig, + cCompiler: _cCompilerConfig, + ), + inputValidator: (config) async => [ + ...await validateDataAssetBuildInput(config), + ...await validateCodeAssetBuildInput(config), + ], + linkingEnabled: linkingEnabled, + buildAssetTypes: [ + CodeAsset.type, + ], + buildValidator: (config, output) async => [ + ...await validateDataAssetBuildOutput(config, output), + ...await validateCodeAssetBuildOutput(config, output), + ], + applicationAssetValidator: (assets) async => [ + ...await validateCodeAssetInApplication(assets), + ], ); + return buildResult; } - return true; -} -Logger logger(bool verbose) => Logger('') - ..onRecord.listen((LogRecord record) { - final levelValue = record.level.value; - if (levelValue >= Level.SEVERE.value) { - log.stderr(record.message); - } else if (levelValue >= Level.WARNING.value || - verbose && levelValue >= Level.INFO.value) { - log.stdout(record.message); - } else { - // Note, this is ignored by default. - log.trace(record.message); - } - }); + Future buildNativeAssetsAOT() { + return _buildNativeAssetsShared(linkingEnabled: true); + } -CCompilerConfig? getCCompilerConfig() { - // Specifically for running our tests on Dart CI with the test runner, we - // recognize specific variables to setup the C Compiler configuration. - final env = Platform.environment; - final cc = env['DART_HOOK_TESTING_C_COMPILER__CC']; - final ar = env['DART_HOOK_TESTING_C_COMPILER__AR']; - final ld = env['DART_HOOK_TESTING_C_COMPILER__LD']; - final envScript = env['DART_HOOK_TESTING_C_COMPILER__ENV_SCRIPT']; - final envScriptArgs = - env['DART_HOOK_TESTING_C_COMPILER__ENV_SCRIPT_ARGUMENTS'] - ?.split(' ') - .map((arg) => arg.trim()) - .where((arg) => arg.isNotEmpty) - .toList(); - final hasEnvScriptArgs = envScriptArgs != null && envScriptArgs.isNotEmpty; - - if (cc != null && ar != null && ld != null) { - return CCompilerConfig( - archiver: Uri.file(ar), - compiler: Uri.file(cc), - envScript: envScript != null ? Uri.file(envScript) : null, - envScriptArgs: hasEnvScriptArgs ? envScriptArgs : null, - linker: Uri.file(ld), + Future linkNativeAssetsAOT({ + required String? recordedUsagesPath, + required BuildResult buildResult, + }) async { + final linkResult = await (await _nativeAssetsBuildRunner).link( + inputCreator: () => LinkInputBuilder() + ..config.setupCode( + targetOS: target.os, + targetArchitecture: target.architecture, + linkModePreference: LinkModePreference.dynamic, + macOS: _macOSConfig, + cCompiler: _cCompilerConfig, + ), + inputValidator: (config) async => [ + ...await validateDataAssetLinkInput(config), + ...await validateCodeAssetLinkInput(config), + ], + resourceIdentifiers: + recordedUsagesPath != null ? Uri.file(recordedUsagesPath) : null, + buildResult: buildResult, + buildAssetTypes: [ + CodeAsset.type, + ], + linkValidator: (config, output) async => [ + ...await validateDataAssetLinkOutput(config, output), + ...await validateCodeAssetLinkOutput(config, output), + ], + applicationAssetValidator: (assets) async => [ + ...await validateCodeAssetInApplication(assets), + ], ); + return linkResult; } - return null; -} -// TODO(https://github.com/dart-lang/package_config/issues/126): Expose this -// logic in package:package_config. -Future findPackageConfigUri(Uri uri) async { - while (true) { - final candidate = uri.resolve('.dart_tool/package_config.json'); - final file = File.fromUri(candidate); - if (await file.exists()) { - return file.uri; + /// Dart does not do cross compilation. Target is always host. + late final target = Target.current; + + late final _macOSConfig = target.os == OS.macOS + ? MacOSCodeConfig(targetVersion: minimumSupportedMacOSVersion) + : null; + + late final _cCompilerConfig = _getCCompilerConfig(target.os); + + CCompilerConfig? _getCCompilerConfig(OS targetOS) { + // Specifically for running our tests on Dart CI with the test runner, we + // recognize specific variables to setup the C Compiler configuration. + final env = Platform.environment; + final cc = env['DART_HOOK_TESTING_C_COMPILER__CC']; + final ar = env['DART_HOOK_TESTING_C_COMPILER__AR']; + final ld = env['DART_HOOK_TESTING_C_COMPILER__LD']; + final envScript = env['DART_HOOK_TESTING_C_COMPILER__ENV_SCRIPT']; + final envScriptArgs = + env['DART_HOOK_TESTING_C_COMPILER__ENV_SCRIPT_ARGUMENTS'] + ?.split(' ') + .map((arg) => arg.trim()) + .where((arg) => arg.isNotEmpty) + .toList(); + if (cc != null && ar != null && ld != null) { + return CCompilerConfig( + archiver: Uri.file(ar), + compiler: Uri.file(cc), + linker: Uri.file(ld), + windows: targetOS == OS.windows + ? WindowsCCompilerConfig( + developerCommandPrompt: envScript == null + ? null + : DeveloperCommandPrompt( + script: Uri.file(envScript), + arguments: envScriptArgs ?? [], + ), + ) + : null, + ); } - final parent = uri.resolve('..'); - if (parent == uri) { - return null; + return null; + } + + /// Runs `pub get` if no package config can be found. + /// + /// Returns `null` if no package config can be found, even after pub get. + static Future ensurePackageConfig(Uri uri) async { + var packageConfig = await _findPackageConfigUri(uri); + // TODO(https://github.com/dart-lang/package_config/issues/126): Use + // package config resolution from package:package_config. + if (packageConfig == null) { + final pubspecMaybe = await _findPubspec(uri); + if (pubspecMaybe != null) { + // Silently run `pub get`, this is what would happen in + // `getExecutableForCommand` later. + final result = await Process.run(sdk.dart, ['pub', 'get']); + if (result.exitCode != 0) { + return null; + } + packageConfig = await _findPackageConfigUri(uri); + } else { + return null; + } } - uri = parent; + return packageConfig; } -} -Future _findPubspec(Uri uri) async { - while (true) { - final candidate = uri.resolve('pubspec.yaml'); - if (await File.fromUri(candidate).exists()) { - return candidate; + /// Finds the package config uri. + /// + /// Returns `null` if no package config can be found. + // TODO(https://github.com/dart-lang/package_config/issues/126): Expose this + // logic in package:package_config. + static Future _findPackageConfigUri(Uri uri) async { + while (true) { + final candidate = uri.resolve('.dart_tool/package_config.json'); + final file = File.fromUri(candidate); + if (await file.exists()) { + return file.uri; + } + final parent = uri.resolve('..'); + if (parent == uri) { + return null; + } + uri = parent; } - final parent = uri.resolve('..'); - if (parent == uri) { - return null; + } + + static Future _findPubspec(Uri uri) async { + while (true) { + final candidate = uri.resolve('pubspec.yaml'); + if (await File.fromUri(candidate).exists()) { + return candidate; + } + final parent = uri.resolve('..'); + if (parent == uri) { + return null; + } + uri = parent; } - uri = parent; } -} -Future findRootPackageName(Uri uri) async { - final pubspec = await _findPubspec(uri); - return pubspec!.resolve('./').pathSegments.lastWhere((e) => e.isNotEmpty); + /// Tries to find the package name that [uri] is in. + /// + /// Returns `null` if package cannnot be determined. + static Future findRootPackageName(Uri uri) async { + final pubspec = await _findPubspec(uri); + if (pubspec == null) { + return null; + } + return pubspec.resolve('./').pathSegments.lastWhere((e) => e.isNotEmpty); + } } diff --git a/pkg/dartdev/lib/src/vm_interop_handler.dart b/pkg/dartdev/lib/src/vm_interop_handler.dart index 79f705e5af0b..169c62adc0fc 100644 --- a/pkg/dartdev/lib/src/vm_interop_handler.dart +++ b/pkg/dartdev/lib/src/vm_interop_handler.dart @@ -54,7 +54,7 @@ abstract class VmInteropHandler { final port = _port; if (port == null) return; final message = [ - useExecProcess? _kResultRunExec : _kResultRun, + useExecProcess ? _kResultRunExec : _kResultRun, script, packageConfigOverride, markMainIsolateAsSystemIsolate,