diff --git a/pkg/dart2native/bin/dart2aot.dart b/pkg/dart2native/bin/dart2aot.dart new file mode 100644 index 00000000000..b406184475d --- /dev/null +++ b/pkg/dart2native/bin/dart2aot.dart @@ -0,0 +1,81 @@ +#!/usr/bin/env dart +// 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 'package:args/args.dart'; +import 'package:path/path.dart'; + +const clearLine = '\r\x1b[2K'; + +void aot(String sourceFile, String snapshotFile, bool enableAsserts, + bool buildElf, bool tfa, bool noTfa, String packages, List ds) { + if (!FileSystemEntity.isFileSync(sourceFile)) { + print('Error: $sourceFile is not a file'); + return; + } + + String genSnapshotOption = buildElf + ? '--snapshot-kind=app-aot-assembly' + : '--snapshot-kind=app-aot-blobs'; + String genSnapshotFilename = buildElf + ? '--assembly=$snapshotFile.S' + : '--blobs_container_filename=$snapshotFile'; + + String snapDir = dirname(Platform.script.path); + String binDir = canonicalize(join(snapDir, '..')); + String sdkDir = canonicalize(join(binDir, '..')); + String dartCommand = join(binDir, 'dart'); + String snapshot = join(snapDir, 'gen_kernel.dart.snapshot'); + + stdout.write('${clearLine}Generating AOT snapshot'); + List dartArgs = [ + snapshot, + '--platform', + '${sdkDir}//lib/_internal/vm_platform_strong.dill', + '--aot', + '-Ddart.vm.product=true', + if (tfa) '--tfa', + if (noTfa) '--no-tfa', + ...ds, + if (packages != null) ...['--packages', packages], + '-o', + '$snapshotFile.dill', + sourceFile + ]; + + var cmdResult = Process.runSync(dartCommand, dartArgs); + if (cmdResult.exitCode != 0) { + print('\nGenerating AOT snapshot failed\n'); + print(cmdResult.stdout); + print(cmdResult.stderr); + return; + } + + stdout.write("${clearLine}Generating AOT .dill"); + String genSnapshotCommand = join(binDir, 'utils', 'gen_snapshot'); + List genSnapshotArgs = [ + genSnapshotOption, + genSnapshotFilename, + if (enableAsserts) '--enable-asserts', + '$snapshotFile.dill' + ]; + cmdResult = Process.runSync(genSnapshotCommand, genSnapshotArgs); + if (cmdResult.exitCode != 0) { + print('\nGenerating AOT .dill failed\n'); + print(cmdResult.stdout); + print(cmdResult.stderr); + return; + } + stdout.write("${clearLine}Done.\n"); + stdout.flush(); +} + +void setupAOTArgs(ArgParser parser) { + parser.addFlag('build-elf'); + parser.addFlag('enable-asserts'); + parser.addFlag('tfa'); + parser.addFlag('no-tfa'); + parser.addOption('packages'); +} diff --git a/pkg/dart2native/bin/dart2native.dart b/pkg/dart2native/bin/dart2native.dart new file mode 100644 index 00000000000..ac9cf354808 --- /dev/null +++ b/pkg/dart2native/bin/dart2native.dart @@ -0,0 +1,70 @@ +#!/usr/bin/env dart +// 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 'package:args/args.dart'; +import 'dart2aot.dart'; + +typedef void Command(ArgResults args, List ds); + +void main(List args) { + Map commands = {}; + commands['aot'] = callAOT; + + // Read -D args that the ArgParser can't handle. + List ds = []; + args = filterDArgs(args, ds); + + ArgParser parser = ArgParser(); + parser.addFlag('help'); + ArgParser aotParser = parser.addCommand('aot'); + setupAOTArgs(aotParser); + + ArgResults result = null; + try { + result = parser.parse(args); + } catch (ArgParserException) { + // We handle this case as result == null below. + } + + if (result == null || result.command == null || result['help']) { + print('dart2native \n'); + print(' command: '); + print(' aot - Compile script into one ahead of time dart snapshot'); + return; + } + + if (commands.containsKey(result.command.name)) { + commands[result.command.name](result.command, ds); + return; + } +} + +void callAOT(ArgResults args, List ds) { + List rest = args.rest; + if (rest.length != 2) { + print( + 'Usage: dart2native aot [options] \n'); + print( + 'Dart AOT (ahead-of-time) compile Dart source code into native machine code.'); + return; + } + + aot(rest[0], rest[1], args['build-elf'], args['enable-asserts'], args['tfa'], + args['no-tfa'], args['packages'], ds); +} + +List filterDArgs(List args, List ds) { + List result = []; + + args.forEach((String arg) { + if (!arg.startsWith('-D')) { + result.add(arg); + } else { + ds.add(arg); + } + }); + + return result; +} diff --git a/pkg/dart2native/pubspec.yaml b/pkg/dart2native/pubspec.yaml new file mode 100644 index 00000000000..be267fc4206 --- /dev/null +++ b/pkg/dart2native/pubspec.yaml @@ -0,0 +1,16 @@ +name: dart2native +version: 0.0.1 +author: Dart Team +homepage: https://github.com/dart-lang/sdk/tree/master/pkg/aot + + +# Add the bin/dart2native.dart script to the scripts pub installs. +executables: + dart2native: + +dependencies: + args: ^1.4.0 + path: + +dev_dependencies: + diff --git a/sdk/BUILD.gn b/sdk/BUILD.gn index 73624b0cf95..135c6bd680d 100644 --- a/sdk/BUILD.gn +++ b/sdk/BUILD.gn @@ -116,6 +116,10 @@ _platform_sdk_snapshots = [ "dartanalyzer", "../utils/dartanalyzer:generate_dartanalyzer_snapshot", ], + [ + "dart2native", + "../utils/dart2native:generate_dart2native_snapshot", + ], [ "dartdoc", "../utils/dartdoc", @@ -155,6 +159,10 @@ _full_sdk_snapshots = [ "dartanalyzer", "../utils/dartanalyzer:generate_dartanalyzer_snapshot", ], + [ + "dart2native", + "../utils/dart2native:generate_dart2native_snapshot", + ], [ "dartdevc", "../utils/dartdevc", @@ -442,6 +450,23 @@ copy("copy_dart2aot") { ] } +copy("copy_dart2native") { + deps = [ + ":copy_gen_kernel_snapshot", + ":copy_gen_snapshot", + ] + ext = "" + if (is_win) { + ext = ".bat" + } + sources = [ + "bin/dart2native$ext", + ] + outputs = [ + "$root_out_dir/dart-sdk/bin/{{source_file_part}}", + ] +} + copy("copy_gen_kernel_snapshot") { deps = [ "../utils/gen_kernel", @@ -978,6 +1003,7 @@ group("create_common_sdk") { ":copy_analysis_summaries", ":copy_api_readme", ":copy_dart", + ":copy_dart2native", ":copy_dartdoc_files", ":copy_headers", ":copy_libraries_dart", diff --git a/sdk/bin/dart2native b/sdk/bin/dart2native new file mode 100755 index 00000000000..29f29d751f7 --- /dev/null +++ b/sdk/bin/dart2native @@ -0,0 +1,25 @@ +#!/usr/bin/env bash +# 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. + +# Run dart2native.dart.snapshot on the Dart VM + +function follow_links() { + file="$1" + while [ -h "$file" ]; do + # On Mac OS, readlink -f doesn't work. + file="$(readlink "$file")" + done + echo "$file" +} + +# Unlike $0, $BASH_SOURCE points to the absolute path of this file. +PROG_NAME="$(follow_links "$BASH_SOURCE")" + +# Handle the case where dart-sdk/bin has been symlinked to. +BIN_DIR="$(cd "${PROG_NAME%/*}" ; pwd -P)" +SNAPSHOTS_DIR="${BIN_DIR}/snapshots" +DART="$BIN_DIR/dart" + +exec "$DART" "${SNAPSHOTS_DIR}/dart2native.dart.snapshot" $* diff --git a/sdk/bin/dart2native.bat b/sdk/bin/dart2native.bat new file mode 100644 index 00000000000..631dce8d080 --- /dev/null +++ b/sdk/bin/dart2native.bat @@ -0,0 +1,43 @@ +@echo off +REM Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file +REM for details. All rights reserved. Use of this source code is governed by a +REM BSD-style license that can be found in the LICENSE file. + +setlocal +rem Handle the case where dart-sdk/bin has been symlinked to. +set DIR_NAME_WITH_SLASH=%~dp0 +set DIR_NAME=%DIR_NAME_WITH_SLASH:~0,-1%% +call :follow_links "%DIR_NAME%", RETURNED_BIN_DIR +rem Get rid of surrounding quotes. +for %%i in ("%RETURNED_BIN_DIR%") do set BIN_DIR=%%~fi + +set DART=%BIN_DIR%\dart + +"%DART%" "%BIN_DIR%\snapshots\dart2native.dart.snapshot" %* + +endlocal + +exit /b %errorlevel% + +rem Follow the symbolic links (junctions points) using `dir to determine the +rem canonical path. Output with a link looks something like this +rem +rem 01/03/2013 10:11 PM abc def +rem [c:\dart_bleeding\dart-repo.9\dart\out\ReleaseIA32\dart-sdk] +rem +rem So in the output of 'dir /a:l "targetdir"' we are looking for a filename +rem surrounded by right angle bracket and left square bracket. Once we get +rem the filename, which is name of the link, we recursively follow that. +:follow_links +setlocal +for %%i in (%1) do set result=%%~fi +set current= +for /f "usebackq tokens=2 delims=[]" %%i in (`dir /a:l "%~dp1" 2^>nul ^ + ^| %SystemRoot%\System32\find.exe "> %~n1 [" 2^>nul`) do ( + set current=%%i +) +if not "%current%"=="" call :follow_links "%current%", result +endlocal & set %~2=%result% +goto :eof + +:end diff --git a/utils/dart2native/BUILD.gn b/utils/dart2native/BUILD.gn new file mode 100644 index 00000000000..fcc4efb5a17 --- /dev/null +++ b/utils/dart2native/BUILD.gn @@ -0,0 +1,19 @@ +# Copyright (c) 2016, 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("../application_snapshot.gni") + +group("dart2native") { + deps = [ + ":generate_dart2native_snapshot", + ] +} + +application_snapshot("generate_dart2native_snapshot") { + main_dart = "../../pkg/dart2native/bin/dart2native.dart" + training_args = [ + "--help", + ] + name = "dart2native" +}