Skip to content

Commit

Permalink
[ CLI ] Update dart compile {exe, aot-snapshot} to allow for compil…
Browse files Browse the repository at this point in the history
…ation from kernel

Also updates `dart compile kernel` to use `gen_kernel_aot.dart.snapshot`
instead of the VM's `--snapshot` flag.

Fixes #53971

Change-Id: Ifa6afed2428e41fdcff97183f3f3a2ddefec5042
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/349280
Reviewed-by: Alexander Markov <[email protected]>
Commit-Queue: Ben Konyi <[email protected]>
  • Loading branch information
bkonyi authored and Commit Queue committed Feb 7, 2024
1 parent 53056b6 commit 5a38644
Show file tree
Hide file tree
Showing 8 changed files with 528 additions and 142 deletions.
117 changes: 87 additions & 30 deletions pkg/dart2native/lib/dart2native.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,81 @@
import 'dart:io';
import 'dart:typed_data';

import 'package:collection/collection.dart';
import 'package:kernel/binary/tag.dart' show Tag;
import 'package:path/path.dart' as path;

import 'dart2native_macho.dart' show writeAppendedMachOExecutable;
import 'dart2native_pe.dart' show writeAppendedPortableExecutable;

final binDir = File(Platform.resolvedExecutable).parent;
final executableSuffix = Platform.isWindows ? '.exe' : '';
final genKernel = path.join(
binDir.path,
'snapshots',
'gen_kernel_aot.dart.snapshot',
);
final genSnapshot = path.join(
binDir.path,
'utils',
'gen_snapshot$executableSuffix',
);
final platformDill = path.join(
binDir.parent.path,
'lib',
'_internal',
'vm_platform_strong.dill',
);
final productPlatformDill = path.join(
binDir.parent.path,
'lib',
'_internal',
'vm_platform_strong_product.dill',
);

// Maximum page size across all supported architectures (arm64 macOS has 16K
// pages, some arm64 Linux distributions have 64K pages).
const elfPageSize = 65536;
const appjitMagicNumber = <int>[0xdc, 0xdc, 0xf6, 0xf6, 0, 0, 0, 0];
const kernelMagicNumber = <int>[0x90, 0xab, 0xcd, 0xef];

Future<bool> isKernelFile(String path) async {
const kernelMagicNumber = Tag.ComponentFile;
// Convert the 32-bit header into a list of 4 bytes.
final kernelMagicNumberList = Uint8List(4)
..buffer.asByteData().setInt32(
0,
kernelMagicNumber,
Endian.big,
);

enum Kind { aot, exe }
final header = await File(path)
.openRead(
0,
kernelMagicNumberList.length,
)
.first;

Future writeAppendedExecutable(
String dartaotruntimePath, String payloadPath, String outputPath) async {
return header.equals(kernelMagicNumberList);
}

// WARNING: this method is used within google3, so don't try to refactor so
// [dartaotruntime] is a constant inside this file.
Future<void> writeAppendedExecutable(
String dartaotruntime,
String payloadPath,
String outputPath,
) async {
if (Platform.isMacOS) {
return await writeAppendedMachOExecutable(
dartaotruntimePath, payloadPath, outputPath);
dartaotruntime, payloadPath, outputPath);
} else if (Platform.isWindows) {
return await writeAppendedPortableExecutable(
dartaotruntimePath, payloadPath, outputPath);
dartaotruntime, payloadPath, outputPath);
}

final dartaotruntime = File(dartaotruntimePath);
final int dartaotruntimeLength = dartaotruntime.lengthSync();
final dartaotruntimeFile = File(dartaotruntime);
final int dartaotruntimeLength = dartaotruntimeFile.lengthSync();

final padding = ((elfPageSize - dartaotruntimeLength) % elfPageSize);
final padBytes = Uint8List(padding);
Expand All @@ -37,7 +90,7 @@ Future writeAppendedExecutable(
..setUint64(0, offset, Endian.little);

final outputFile = File(outputPath).openWrite();
outputFile.add(dartaotruntime.readAsBytesSync());
outputFile.add(dartaotruntimeFile.readAsBytesSync());
outputFile.add(padBytes);
outputFile.add(File(payloadPath).readAsBytesSync());
outputFile.add(offsetBytes.buffer.asUint8List());
Expand All @@ -49,45 +102,49 @@ Future markExecutable(String outputFile) {
return Process.run('chmod', ['+x', outputFile]);
}

/// Generates the AOT kernel by running the provided [genKernel] path.
/// Generates kernel by running the provided [genKernel] path.
///
/// Also takes a path to the [resourcesFile] JSON file, where the method calls
/// to static functions annotated with [Resource] will be collected.
Future<ProcessResult> generateAotKernel(
String dart,
String genKernel,
String platformDill,
String sourceFile,
String kernelFile,
Future<ProcessResult> generateKernelHelper({
required String dartaotruntime,
required String sourceFile,
required String kernelFile,
String? packages,
List<String> defines, {
List<String> defines = const [],
String enableExperiment = '',
String? targetOS,
List<String> extraGenKernelOptions = const [],
String? nativeAssets,
String? resourcesFile,
bool fromDill = false,
bool aot = false,
bool embedSources = false,
bool linkPlatform = true,
bool product = true,
}) {
return Process.run(dart, [
final args = [
genKernel,
'--platform',
platformDill,
'--platform=${product ? productPlatformDill : platformDill}',
if (product) '-Ddart.vm.product=true',
if (enableExperiment.isNotEmpty) '--enable-experiment=$enableExperiment',
if (targetOS != null) '--target-os=$targetOS',
'--aot',
'-Ddart.vm.product=true',
if (fromDill) '--from-dill=$sourceFile',
if (aot) '--aot',
if (!embedSources) '--no-embed-sources',
if (!linkPlatform) '--no-link-platform',
...(defines.map((d) => '-D$d')),
if (packages != null) ...['--packages', packages],
'-o',
kernelFile,
if (packages != null) '--packages=$packages',
if (nativeAssets != null) '--native-assets=$nativeAssets',
if (resourcesFile != null) '--resources-file=$resourcesFile',
'--output=$kernelFile',
...extraGenKernelOptions,
if (nativeAssets != null) ...['--native-assets', nativeAssets],
if (resourcesFile != null) ...['--resources-file', resourcesFile],
sourceFile
]);
sourceFile,
];
return Process.run(dartaotruntime, args);
}

Future generateAotSnapshot(
String genSnapshot,
Future<ProcessResult> generateAotSnapshotHelper(
String kernelFile,
String snapshotFile,
String? debugFile,
Expand Down
3 changes: 3 additions & 0 deletions pkg/dart2native/lib/dart2native_macho.dart
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ class _MacOSVersion {

// Writes an "appended" dart runtime + script snapshot file in a format
// compatible with MachO executables.
//
// WARNING: this method is used within google3, so don't try to refactor so
// [dartaotruntimePath] is a constant inside this file.
Future writeAppendedMachOExecutable(
String dartaotruntimePath, String payloadPath, String outputPath) async {
final aotRuntimeFile = File(dartaotruntimePath);
Expand Down
3 changes: 3 additions & 0 deletions pkg/dart2native/lib/dart2native_pe.dart
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,9 @@ class PortableExecutable {

// Writes an "appended" dart runtime + script snapshot file in a format
// compatible with Portable Executable files.
//
// WARNING: this method is used within google3, so don't try to refactor so
// [dartaotruntimePath] is a constant inside this file.
Future writeAppendedPortableExecutable(
String dartaotruntimePath, String payloadPath, String outputPath) async {
File originalExecutableFile = File(dartaotruntimePath);
Expand Down
Loading

0 comments on commit 5a38644

Please sign in to comment.