[dartdevc] enable sdk compilation from dartdevc

Kernel mode only

Build with:
> dart bin/dartdevc.dart -k --compile-sdk dart:core --modules amd -o dart_sdk.js

For now, this doesn't support building only parts of the SDK - dart:core brings everything in.

Change-Id: I23cda3064408778dc93c9b3d4be757f1e99bae0e
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/104811
Reviewed-by: Jake Macdonald <jakemac@google.com>
Reviewed-by: Sigmund Cherem <sigmund@google.com>
Commit-Queue: Vijay Menon <vsm@google.com>
diff --git a/pkg/dev_compiler/lib/src/kernel/command.dart b/pkg/dev_compiler/lib/src/kernel/command.dart
index 7507c3a..c4bcc5b 100644
--- a/pkg/dev_compiler/lib/src/kernel/command.dart
+++ b/pkg/dev_compiler/lib/src/kernel/command.dart
@@ -93,7 +93,9 @@
             'specified multi-root scheme.',
         defaultsTo: [Uri.base.path])
     ..addOption('dart-sdk',
-        help: '(unsupported with --kernel) path to the Dart SDK.', hide: true);
+        help: '(unsupported with --kernel) path to the Dart SDK.', hide: true)
+    ..addFlag('compile-sdk',
+        help: 'Build an SDK module.', defaultsTo: false, hide: true);
   SharedCompilerOptions.addArguments(argParser);
 
   var declaredVariables = parseAndRemoveDeclaredVariables(args);
@@ -217,6 +219,7 @@
   bool trackWidgetCreation =
       argResults['track-widget-creation'] as bool ?? false;
 
+  var compileSdk = argResults['compile-sdk'] == true;
   var oldCompilerState = compilerState;
   List<Component> doneInputSummaries;
   fe.IncrementalCompiler incrementalCompiler;
@@ -224,7 +227,9 @@
   if (useAnalyzer || !useIncrementalCompiler) {
     compilerState = await fe.initializeCompiler(
         oldCompilerState,
-        sourcePathToUri(sdkSummaryPath),
+        compileSdk,
+        sourcePathToUri(getSdkPath()),
+        compileSdk ? null : sourcePathToUri(sdkSummaryPath),
         sourcePathToUri(packageFile),
         sourcePathToUri(librarySpecPath),
         summaryModules.keys.toList(),
@@ -237,7 +242,9 @@
     compilerState = await fe.initializeIncrementalCompiler(
         oldCompilerState,
         doneInputSummaries,
-        sourcePathToUri(sdkSummaryPath),
+        compileSdk,
+        sourcePathToUri(getSdkPath()),
+        compileSdk ? null : sourcePathToUri(sdkSummaryPath),
         sourcePathToUri(packageFile),
         sourcePathToUri(librarySpecPath),
         summaryModules.keys.toList(),
@@ -456,7 +463,7 @@
 
 bool _checkForDartMirrorsImport(Component component) {
   for (var library in component.libraries) {
-    if (library.isExternal) continue;
+    if (library.isExternal || library.importUri.scheme == 'dart') continue;
     for (var dep in library.dependencies) {
       var uri = dep.targetLibrary.importUri;
       if (uri.scheme == 'dart' && uri.path == 'mirrors') {
diff --git a/pkg/dev_compiler/test/modular/modular_test.dart b/pkg/dev_compiler/test/modular/modular_test.dart
index 8e96f72..a917ed1 100644
--- a/pkg/dev_compiler/test/modular/modular_test.dart
+++ b/pkg/dev_compiler/test/modular/modular_test.dart
@@ -62,7 +62,7 @@
     //
     // Files in packages are defined in terms of `package:` URIs, while
     // non-package URIs are defined using the `dart-dev-app` scheme.
-    String rootScheme = module.isSdk ? 'dart-dev-sdk' : 'dev-dart-app';
+    String rootScheme = module.isSdk ? 'dev-dart-sdk' : 'dev-dart-app';
     String sourceToImportUri(Uri relativeUri) =>
         _sourceToImportUri(module, rootScheme, relativeUri);
 
@@ -134,55 +134,50 @@
     Set<Module> transitiveDependencies = computeTransitiveDependencies(module);
     _createPackagesFile(module, root, transitiveDependencies);
 
-    List<String> args;
+    String rootScheme = module.isSdk ? 'dev-dart-sdk' : 'dev-dart-app';
+    List<String> sources;
+    List<String> extraArgs;
     if (module.isSdk) {
-      // TODO(sigmund): this produces an error because kernel_sdk doesn't have a
-      // way to provide a .packages file. Technically is not needed, but it
-      // would be nice to proceed without any error messages.
-      args = [
-        '--packages=${sdkRoot.toFilePath()}/.packages',
-        sdkRoot.resolve('pkg/dev_compiler/tool/kernel_sdk.dart').toFilePath(),
-        '--libraries',
-        'sdk/lib/libraries.json',
-        '--output',
-        '${toUri(module, jsId)}.ignored_dill',
-      ];
-      var result = await _runProcess(
-          Platform.resolvedExecutable, args, root.toFilePath());
-      _checkExitCode(result, this, module);
-      await File.fromUri(root.resolve('es6/dart_sdk.js'))
-          .copy(root.resolveUri(toUri(module, jsId)).toFilePath());
+      sources = ['dart:core'];
+      extraArgs = ['--compile-sdk'];
+      assert(transitiveDependencies.isEmpty);
     } else {
-      Uri output = toUri(module, jsId);
       Module sdkModule = module.dependencies.firstWhere((m) => m.isSdk);
-      String sourceToImportUri(Uri relativeUri) =>
-          _sourceToImportUri(module, 'dev-dart-app', relativeUri);
-
-      args = [
-        '--packages=${sdkRoot.toFilePath()}/.packages',
-        sdkRoot.resolve('pkg/dev_compiler/bin/dartdevc.dart').toFilePath(),
-        '--kernel',
-        '--modules=es6',
-        '--no-summarize',
-        '--no-source-map',
-        '--multi-root-scheme',
-        'dev-dart-app',
+      sources = module.sources
+          .map((relativeUri) =>
+              _sourceToImportUri(module, rootScheme, relativeUri))
+          .toList();
+      extraArgs = [
         '--dart-sdk-summary',
         '${toUri(sdkModule, dillId)}',
         '--packages',
         '.packages',
-        ...module.sources.map(sourceToImportUri),
-        for (String flag in flags) '--enable-experiment=$flag',
-        ...(transitiveDependencies
-            .where((m) => !m.isSdk)
-            .expand((m) => ['-s', '${toUri(m, dillId)}=${m.name}'])),
-        '-o',
-        '$output',
       ];
-      var result = await _runProcess(
-          Platform.resolvedExecutable, args, root.toFilePath());
-      _checkExitCode(result, this, module);
     }
+
+    Uri output = toUri(module, jsId);
+
+    List<String> args = [
+      '--packages=${sdkRoot.toFilePath()}/.packages',
+      sdkRoot.resolve('pkg/dev_compiler/bin/dartdevc.dart').toFilePath(),
+      '--kernel',
+      '--modules=es6',
+      '--no-summarize',
+      '--no-source-map',
+      '--multi-root-scheme',
+      rootScheme,
+      ...sources,
+      ...extraArgs,
+      for (String flag in flags) '--enable-experiment=$flag',
+      ...(transitiveDependencies
+          .where((m) => !m.isSdk)
+          .expand((m) => ['-s', '${toUri(m, dillId)}=${m.name}'])),
+      '-o',
+      '$output',
+    ];
+    var result =
+        await _runProcess(Platform.resolvedExecutable, args, root.toFilePath());
+    _checkExitCode(result, this, module);
   }
 
   @override
diff --git a/pkg/dev_compiler/test/nullable_inference_test.dart b/pkg/dev_compiler/test/nullable_inference_test.dart
index 2390343..7690119 100644
--- a/pkg/dev_compiler/test/nullable_inference_test.dart
+++ b/pkg/dev_compiler/test/nullable_inference_test.dart
@@ -576,8 +576,8 @@
   var mainUri = Uri.file('/memory/test.dart');
   _fileSystem.entityForUri(mainUri).writeAsStringSync(code);
   var oldCompilerState = _compilerState;
-  _compilerState = await fe.initializeCompiler(oldCompilerState, sdkUri,
-      packagesUri, null, [], DevCompilerTarget(TargetFlags()),
+  _compilerState = await fe.initializeCompiler(oldCompilerState, false, null,
+      sdkUri, packagesUri, null, [], DevCompilerTarget(TargetFlags()),
       fileSystem: _fileSystem, experiments: const {});
   if (!identical(oldCompilerState, _compilerState)) inference = null;
   fe.DdcResult result =
diff --git a/pkg/front_end/lib/src/api_unstable/ddc.dart b/pkg/front_end/lib/src/api_unstable/ddc.dart
index 852cd60..4c2076b 100644
--- a/pkg/front_end/lib/src/api_unstable/ddc.dart
+++ b/pkg/front_end/lib/src/api_unstable/ddc.dart
@@ -73,6 +73,8 @@
 
 Future<InitializedCompilerState> initializeCompiler(
     InitializedCompilerState oldState,
+    bool compileSdk,
+    Uri sdkRoot,
     Uri sdkSummary,
     Uri packagesFile,
     Uri librariesSpecificationUri,
@@ -83,6 +85,7 @@
   inputSummaries.sort((a, b) => a.toString().compareTo(b.toString()));
 
   if (oldState != null &&
+      oldState.options.compileSdk == compileSdk &&
       oldState.options.sdkSummary == sdkSummary &&
       oldState.options.packagesFileUri == packagesFile &&
       oldState.options.librariesSpecificationUri == librariesSpecificationUri &&
@@ -104,6 +107,8 @@
   }
 
   CompilerOptions options = new CompilerOptions()
+    ..compileSdk = compileSdk
+    ..sdkRoot = sdkRoot
     ..sdkSummary = sdkSummary
     ..packagesFileUri = packagesFile
     ..inputSummaries = inputSummaries
@@ -120,6 +125,8 @@
 Future<InitializedCompilerState> initializeIncrementalCompiler(
     InitializedCompilerState oldState,
     List<Component> doneInputSummaries,
+    bool compileSdk,
+    Uri sdkRoot,
     Uri sdkSummary,
     Uri packagesFile,
     Uri librariesSpecificationUri,
@@ -140,9 +147,12 @@
 
   if (oldState == null ||
       oldState.incrementalCompiler == null ||
+      oldState.options.compileSdk != compileSdk ||
       cachedSdkInput == null) {
     // No previous state.
     options = new CompilerOptions()
+      ..compileSdk = compileSdk
+      ..sdkRoot = sdkRoot
       ..sdkSummary = sdkSummary
       ..packagesFileUri = packagesFile
       ..inputSummaries = inputSummaries