blob: d89c33de5fa227f325a9e8b91c62e7a48fe34c0f [file] [log] [blame]
// Copyright (c) 2019, 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 'dart:typed_data';
import 'dart2native_macho.dart' show writeAppendedMachOExecutable;
import 'dart2native_pe.dart' show writeAppendedPortableExecutable;
// 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];
enum Kind { aot, exe }
Future writeAppendedExecutable(
String dartaotruntimePath, String payloadPath, String outputPath) async {
if (Platform.isMacOS) {
return await writeAppendedMachOExecutable(
dartaotruntimePath, payloadPath, outputPath);
} else if (Platform.isWindows) {
return await writeAppendedPortableExecutable(
dartaotruntimePath, payloadPath, outputPath);
}
final dartaotruntime = File(dartaotruntimePath);
final int dartaotruntimeLength = dartaotruntime.lengthSync();
final padding = ((elfPageSize - dartaotruntimeLength) % elfPageSize);
final padBytes = Uint8List(padding);
final offset = dartaotruntimeLength + padding;
// Note: The offset is always Little Endian regardless of host.
final offsetBytes = ByteData(8) // 64 bit in bytes.
..setUint64(0, offset, Endian.little);
final outputFile = File(outputPath).openWrite();
outputFile.add(dartaotruntime.readAsBytesSync());
outputFile.add(padBytes);
outputFile.add(File(payloadPath).readAsBytesSync());
outputFile.add(offsetBytes.buffer.asUint8List());
outputFile.add(appjitMagicNumber);
await outputFile.close();
}
Future markExecutable(String outputFile) {
return Process.run('chmod', ['+x', outputFile]);
}
Future<ProcessResult> generateAotKernel(
String dart,
String genKernel,
String platformDill,
String sourceFile,
String kernelFile,
String? packages,
List<String> defines,
{String enableExperiment = '',
List<String> extraGenKernelOptions = const []}) {
return Process.run(dart, [
genKernel,
'--platform',
platformDill,
if (enableExperiment.isNotEmpty) '--enable-experiment=$enableExperiment',
'--aot',
'-Ddart.vm.product=true',
...(defines.map((d) => '-D$d')),
if (packages != null) ...['--packages', packages],
'-o',
kernelFile,
...extraGenKernelOptions,
sourceFile
]);
}
Future generateAotSnapshot(
String genSnapshot,
String kernelFile,
String snapshotFile,
String? debugFile,
bool enableAsserts,
List<String> extraGenSnapshotOptions) {
return Process.run(genSnapshot, [
'--snapshot-kind=app-aot-elf',
'--elf=$snapshotFile',
if (debugFile != null) '--save-debugging-info=$debugFile',
if (debugFile != null) '--dwarf-stack-traces',
if (debugFile != null) '--strip',
if (enableAsserts) '--enable-asserts',
...extraGenSnapshotOptions,
kernelFile
]);
}