[frontend_server] native-assets-only compilation

This CL adds a `--native-assets-only` CLI option to the
frontend_server startup for single shot compilation.

This CL adds a `native-assets-only` instruction to the
frontend_server protocol.

TEST=pkg/frontend_server/test/native_assets_test.dart
Unit test producing kernel file.

Closes: https://github.com/dart-lang/sdk/issues/55503
Change-Id: Ice6281162460032e669d2dda2a128b357e81bc50
Cq-Include-Trybots: dart/try:pkg-linux-debug-try,pkg-linux-release-arm64-try,pkg-mac-release-try,pkg-mac-release-arm64-try,pkg-win-release-try,pkg-win-release-arm64-try
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/363567
Reviewed-by: Jens Johansen <jensj@google.com>
Commit-Queue: Daco Harkes <dacoharkes@google.com>
This commit is contained in:
Daco Harkes
2024-04-19 14:37:26 +00:00
committed by Alexander Thomas
parent 2946586ef2
commit 81af7ebbf4
4 changed files with 130 additions and 2 deletions
+79 -1
View File
@@ -100,6 +100,9 @@ ArgParser argParser = new ArgParser(allowTrailingOptions: true)
defaultsTo: const <String>[])
..addOption('native-assets',
help: 'Provide the native-assets mapping for @Native external functions.')
..addFlag('native-assets-only',
help: "Only compile the native-assets mapping. "
"Don't compile the dart program.")
..addOption('target',
help: 'Target model that determines what core libraries are available',
allowed: <String>[
@@ -291,6 +294,14 @@ abstract class CompilerInterface {
IncrementalCompiler? generator,
});
/// Compiles the native_assets.yaml into a dill file.
///
/// Returns [true] if compilation was successful and produced no errors.
Future<bool> compileNativeAssetsOnly(
ArgResults options, {
IncrementalCompiler? generator,
});
/// Sets the native assets mapping to be embedded in the kernel.
Future<bool> setNativeAssets(String nativeAssets);
@@ -480,7 +491,9 @@ class FrontendCompiler implements CompilerInterface {
_additionalSources =
(options['source'] as List<String>).map(resolveInputUri).toList();
final String? nativeAssets = options['native-assets'] as String?;
_nativeAssets = nativeAssets != null ? resolveInputUri(nativeAssets) : null;
if (_nativeAssets == null && nativeAssets != null) {
_nativeAssets = resolveInputUri(nativeAssets);
}
_kernelBinaryFilenameFull = _options['output-dill'] ?? '$entryPoint.dill';
_kernelBinaryFilenameIncremental = _options['output-incremental-dill'] ??
(_options['output-dill'] != null
@@ -694,6 +707,55 @@ class FrontendCompiler implements CompilerInterface {
return errors.isEmpty;
}
@override
Future<bool> compileNativeAssetsOnly(
ArgResults options, {
IncrementalCompiler? generator,
}) async {
_fileSystem = createFrontEndFileSystem(
options['filesystem-scheme'],
options['filesystem-root'],
allowHttp: options['enable-http-uris'],
);
_options = options;
final String? nativeAssets = options['native-assets'] as String?;
if (_nativeAssets == null && nativeAssets != null) {
_nativeAssets = resolveInputUri(nativeAssets);
}
if (_nativeAssets == null) {
print(
'Error: When --native-assets-only is specified it is required to'
' specify --native-assets option that points to physical file system'
' location of a source native_assets.yaml file.',
);
return false;
}
if (_options['output-dill'] == null) {
print(
'Error: When --native-assets-only is specified it is required to'
' specify --output-dill option that points to physical file system'
' location of a target dill file.',
);
return false;
}
_kernelBinaryFilename = _options['output-dill'];
final CompilerOptions compilerOptions = new CompilerOptions();
_compilerOptions = compilerOptions;
final String boundaryKey = generateV4UUID();
_outputStream.writeln('result $boundaryKey');
await _compileNativeAssets();
await writeDillFileNativeAssets(
_nativeAssetsLibrary!,
_kernelBinaryFilename,
);
_outputStream.writeln(boundaryKey);
_outputStream.writeln('+${await asFileUri(_fileSystem, _nativeAssets!)}');
_outputStream
.writeln('$boundaryKey $_kernelBinaryFilename ${errors.length}');
return true;
}
@override
Future<bool> setNativeAssets(String nativeAssets) async {
_nativeAssetsLibrary = null; // Purge compiled cache.
@@ -875,6 +937,19 @@ class FrontendCompiler implements CompilerInterface {
}
}
Future<void> writeDillFileNativeAssets(
Library nativeAssetsLibrary,
String filename,
) async {
final IOSink sink = new File(filename).openWrite();
final BinaryPrinter printer = new BinaryPrinter(sink);
printer.writeComponentFile(new Component(
libraries: [nativeAssetsLibrary],
mode: nativeAssetsLibrary.nonNullableByDefaultCompiledMode,
));
await sink.close();
}
Future<void> invalidateIfInitializingFromDill() async {
if (_assumeInitializeFromDillUpToDate) return;
if (_kernelBinaryFilename != _kernelBinaryFilenameFull) return;
@@ -1297,6 +1372,7 @@ StreamSubscription<String> listenAndCompile(CompilerInterface compiler,
const String COMPILE_INSTRUCTION_SPACE = 'compile ';
const String RECOMPILE_INSTRUCTION_SPACE = 'recompile ';
const String NATIVE_ASSETS_INSTRUCTION_SPACE = 'native-assets ';
const String NATIVE_ASSETS_ONLY_INSTRUCTION = 'native-assets-only';
const String COMPILE_EXPRESSION_INSTRUCTION_SPACE =
'compile-expression ';
const String COMPILE_EXPRESSION_TO_JS_INSTRUCTION_SPACE =
@@ -1305,6 +1381,8 @@ StreamSubscription<String> listenAndCompile(CompilerInterface compiler,
final String entryPoint =
string.substring(COMPILE_INSTRUCTION_SPACE.length);
await compiler.compile(entryPoint, options, generator: generator);
} else if (string == NATIVE_ASSETS_ONLY_INSTRUCTION) {
await compiler.compileNativeAssetsOnly(options, generator: generator);
} else if (string.startsWith(RECOMPILE_INSTRUCTION_SPACE)) {
// 'recompile [<entryPoint>] <boundarykey>'
// where <boundarykey> can't have spaces
+8
View File
@@ -97,6 +97,14 @@ Future<int> starter(
canaryFeatures: options['dartdevc-canary'],
);
if (options['native-assets-only']) {
final bool compileResult = await compiler.compileNativeAssetsOnly(
options,
generator: generator,
);
return compileResult ? 0 : 254;
}
if (options.rest.isNotEmpty) {
return await compiler.compile(options.rest[0], options,
generator: generator)
@@ -3328,6 +3328,12 @@ class FrontendServer {
.codeUnits);
}
/// Compiles the native assets in isolation.
void compileNativeAssetsOnly() {
outputParser.expectSources = true;
inputStreamController.add('native-assets-only\n'.codeUnits);
}
/// Sets the native assets yaml [uri].
void setNativeAssets({required Uri uri}) {
outputParser.expectSources = true;
@@ -187,8 +187,8 @@ void main() {
expect(await dillFile.exists(), equals(true));
expect(result.filename, dillFile.path);
expect(result.errorsCount, 0);
count += 1;
frontendServer.accept();
frontendServer.quit();
final Component component =
loadComponentFromBinary(dillFile.path);
@@ -196,7 +196,21 @@ void main() {
_findNativeAssetsLibrary(component);
expect(nativeAssetsLibrary, isNotNull);
frontendServer.compileNativeAssetsOnly();
break;
case 2:
expect(await dillFile.exists(), equals(true));
expect(result.filename, dillFile.path);
expect(result.errorsCount, 0);
count += 1;
final Component component =
loadComponentFromBinary(dillFile.path);
final Library? nativeAssetsLibrary =
_findNativeAssetsLibrary(component);
expect(nativeAssetsLibrary, isNotNull);
frontendServer.quit();
}
});
expect(await result, 0);
@@ -320,6 +334,28 @@ void main() {
_findNativeAssetsLibrary(component);
expect(nativeAssetsLibrary, isNotNull);
});
test('pass in native assets only at startup', () async {
final FrontendServer frontendServer = new FrontendServer();
Future<int> frontendServerResult = frontendServer.open(<String>[
'--sdk-root=${sdkRoot.toFilePath()}',
'--platform=${platformKernel.path}',
'--aot',
'--tfa',
'--output-dill=${dillFile.path}',
'--native-assets=${nativeAssetsYamlFile.path}',
'--native-assets-only',
]);
expect(await frontendServerResult, 0);
frontendServer.close();
expect(await dillFile.exists(), equals(true));
final Component component = loadComponentFromBinary(dillFile.path);
final Library? nativeAssetsLibrary =
_findNativeAssetsLibrary(component);
expect(nativeAssetsLibrary, isNotNull);
});
});
});
}