|  | #!/usr/bin/env dart | 
|  | // Copyright (c) 2018, 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. | 
|  |  | 
|  | /// Compiles code with DDC and runs the resulting code with either node or | 
|  | /// chrome. | 
|  | /// | 
|  | /// The first script supplied should be the one with `main()`. | 
|  | /// | 
|  | /// Saves the output in the same directory as the sources for convenient | 
|  | /// inspection, modification or rerunning the code. | 
|  |  | 
|  | import 'dart:io'; | 
|  | import 'dart:ffi'; | 
|  |  | 
|  | import 'package:args/args.dart' show ArgParser; | 
|  | import 'package:dev_compiler/src/compiler/js_names.dart' as js_names; | 
|  | import 'package:path/path.dart' as p; | 
|  |  | 
|  | enum NullSafety { strict, weak, disabled } | 
|  |  | 
|  | void main(List<String> args) async { | 
|  | void printUsage() { | 
|  | print('Usage: ddb [options] <dart-script-file>\n'); | 
|  | print('Compiles <dart-script-file> with the dev_compiler and runs it on a ' | 
|  | 'JS platform.\n' | 
|  | 'Optionally, multiple Dart source files can be passed as arguments and ' | 
|  | 'they will be compiled into separate modules in the order provided. ' | 
|  | 'The order will be treated as an import DAG with the last file as the ' | 
|  | 'application entrypoint. The .dill file outputs from each compile will ' | 
|  | 'be collected and passed as dependency summaries for the next compile ' | 
|  | 'step.'); | 
|  | } | 
|  |  | 
|  | // Parse flags. | 
|  | var parser = ArgParser(usageLineLength: 80) | 
|  | ..addOption('arch', | 
|  | abbr: 'a', | 
|  | help: "Target platform's machine architecture.", | 
|  | allowed: ['x64', 'arm64']) | 
|  | ..addOption('binary', abbr: 'b', help: 'Runtime binary path.') | 
|  | ..addOption('compile-vm-options', | 
|  | help: 'DART_VM_OPTIONS for the compilation VM.') | 
|  | ..addFlag('debug', | 
|  | abbr: 'd', | 
|  | help: 'Use current source instead of built SDK.', | 
|  | defaultsTo: false) | 
|  | ..addMultiOption('enable-experiment', | 
|  | help: 'Run with specified experiments enabled.') | 
|  | ..addFlag('help', abbr: 'h', help: 'Display this message.') | 
|  | ..addOption('mode', | 
|  | help: 'Option to (compile|run|all). Default is all (compile and run).', | 
|  | allowed: ['compile', 'run', 'all'], | 
|  | defaultsTo: 'all') | 
|  | ..addFlag('sound-null-safety', | 
|  | help: 'Compile for sound null safety at runtime. Passed through to the ' | 
|  | 'DDC binary. Defaults to false.', | 
|  | negatable: true, | 
|  | defaultsTo: true) | 
|  | ..addFlag('emit-debug-symbols', | 
|  | help: 'Pass through flag for DDC, emits debug symbols file along with ' | 
|  | 'the compiled module.', | 
|  | defaultsTo: false) | 
|  | ..addFlag('null-assertions', | 
|  | help: 'Run with assertions that values passed to non-nullable method ' | 
|  | 'parameters are not null.', | 
|  | defaultsTo: false) | 
|  | ..addFlag('native-null-assertions', | 
|  | help: 'Run with assertions on non-nullable values returned from native ' | 
|  | 'APIs.', | 
|  | negatable: true) | 
|  | ..addFlag('interop-null-assertions', | 
|  | help: 'Run with assertions on non-nullable values returned from ' | 
|  | 'non-static JavaScript interop APIs.', | 
|  | defaultsTo: false) | 
|  | ..addFlag('weak-null-safety-errors', | 
|  | help: 'Treat weak null safety warnings as errors.', defaultsTo: false) | 
|  | ..addFlag('ddc-modules', | 
|  | help: 'Emit modules in the ddc format. Currently supported in Chrome ' | 
|  | '(amd modules by default) and D8 (already uses ddc modules by ' | 
|  | 'default).', | 
|  | defaultsTo: false) | 
|  | ..addFlag('canary', | 
|  | help: 'Enable all compiler features under active development.', | 
|  | defaultsTo: false) | 
|  | ..addFlag('observe', | 
|  | help: | 
|  | 'Run the compiler in the Dart VM with --observe. Implies --debug.', | 
|  | defaultsTo: false) | 
|  | ..addOption('out', help: 'Output file.') | 
|  | ..addOption('packages', help: 'Where to find a package spec file.') | 
|  | ..addOption('port', | 
|  | abbr: 'p', | 
|  | help: 'Run with the corresponding chrome/V8 debugging port open.', | 
|  | defaultsTo: '9222') | 
|  | ..addOption('runtime', | 
|  | abbr: 'r', | 
|  | help: 'Platform to run on (node|d8|chrome).  Default is node.', | 
|  | allowed: ['node', 'd8', 'chrome'], | 
|  | defaultsTo: 'node') | 
|  | ..addFlag('summarize-text', | 
|  | help: 'Emit API summary in a .js.txt file.', defaultsTo: false) | 
|  | ..addMultiOption('summary', | 
|  | abbr: 's', | 
|  | help: 'summary file(s) of imported libraries, optionally with module ' | 
|  | 'import path: -s path.sum=js/import/path') | 
|  | ..addFlag('verbose', | 
|  | abbr: 'v', | 
|  | help: 'Echos the commands, arguments, and environment this script is ' | 
|  | 'running.', | 
|  | defaultsTo: false) | 
|  | ..addOption('vm-service-port', | 
|  | help: 'Specify the observatory port. Implied --observe.'); | 
|  |  | 
|  | var options = parser.parse(args); | 
|  | if (options['help'] as bool) { | 
|  | printUsage(); | 
|  | print('Available options:'); | 
|  | print(parser.usage); | 
|  | exit(0); | 
|  | } | 
|  | if (options.rest.isEmpty) { | 
|  | print('Dart script file required.\n'); | 
|  | printUsage(); | 
|  | exit(1); | 
|  | } | 
|  | var arch = options['arch'] as String?; | 
|  | var debug = options['debug'] as bool || | 
|  | options['observe'] as bool || | 
|  | options.wasParsed('vm-service-port'); | 
|  | var summarizeText = options['summarize-text'] as bool; | 
|  | var binary = options['binary'] as String?; | 
|  | var experiments = options['enable-experiment'] as List<String>; | 
|  | var summaries = options['summary'] as List<String>; | 
|  | var port = int.parse(options['port'] as String); | 
|  | var mode = options['mode'] as String; | 
|  | var compile = mode == 'compile' || mode == 'all'; | 
|  | var run = mode == 'run' || mode == 'all'; | 
|  | var verbose = options['verbose'] as bool; | 
|  | var soundNullSafety = options['sound-null-safety'] as bool; | 
|  | var emitDebugSymbols = options['emit-debug-symbols'] as bool; | 
|  | var nonNullAsserts = options['null-assertions'] as bool; | 
|  | var nativeNonNullAsserts = options.wasParsed('native-null-assertions') | 
|  | ? options['native-null-assertions'] as bool | 
|  | : soundNullSafety; | 
|  | var jsInteropNonNullAsserts = options['interop-null-assertions'] as bool; | 
|  | var weakNullSafetyErrors = options['weak-null-safety-errors'] as bool; | 
|  | var ddcModules = options['ddc-modules'] as bool; | 
|  | var canaryFeatures = options['canary'] as bool; | 
|  | var sourceFiles = options.rest.map(p.canonicalize); | 
|  | var entryPoint = sourceFiles.last; | 
|  | var libRoot = p.dirname(entryPoint); | 
|  | var basename = p.basenameWithoutExtension(entryPoint); | 
|  | var libname = pathToLibName(entryPoint); | 
|  |  | 
|  | // This is used in the DDC module system and usually corresponds to the | 
|  | // entrypoint's path. | 
|  | var appname = p.relative(p.withoutExtension(entryPoint)); | 
|  |  | 
|  | // This is used in the DDC module system for multiapp workflows and is | 
|  | // stubbed in ddb. | 
|  | var uuid = '00000000-0000-0000-0000-000000000000'; | 
|  |  | 
|  | // By default (no `-d`), we use the `dartdevc` binary on the user's path to | 
|  | // compute the SDK we use for execution.  I.e., we assume that `dart` is | 
|  | // under `$DART_SDK/bin/dart` and use that to find `dartdevc` and related | 
|  | // artifacts.  In this mode, this script can run against any installed SDK. | 
|  | // If you want to run against a freshly built SDK, that must be first on | 
|  | // your path. | 
|  | var dartBinary = Platform.resolvedExecutable; | 
|  | var dartSdk = p.dirname(p.dirname(dartBinary)); | 
|  |  | 
|  | // In debug mode (`-d`), we run from the `pkg/dev_compiler` sources.  We | 
|  | // determine the location via this actual script (i.e., `-d` assumes | 
|  | // this script remains under to `tool` sub-directory). | 
|  | var toolPath = | 
|  | Platform.script.normalizePath().toFilePath(windows: Platform.isWindows); | 
|  | var ddcPath = p.dirname(p.dirname(toolPath)); | 
|  | var dartCheckoutPath = p.dirname(p.dirname(ddcPath)); | 
|  |  | 
|  | /// Runs the [command] with [args] in [environment]. | 
|  | /// | 
|  | /// Will echo the commands to the console before running them when running in | 
|  | /// `verbose` mode. | 
|  | Future<Process> startProcess(String name, String command, List<String> args, | 
|  | [Map<String, String> environment = const {}]) { | 
|  | if (verbose) { | 
|  | print('Running $name:\n$command ${args.join(' ')}\n'); | 
|  | if (environment.isNotEmpty) { | 
|  | var environmentVariables = | 
|  | environment.entries.map((e) => '${e.key}: ${e.value}').join('\n'); | 
|  | print('With Environment:\n$environmentVariables\n'); | 
|  | } | 
|  | } | 
|  | return Process.start(command, args, | 
|  | mode: ProcessStartMode.inheritStdio, environment: environment); | 
|  | } | 
|  |  | 
|  | Future<void> runDdc(List<String> ddcArgs) async { | 
|  | var observe = | 
|  | options.wasParsed('vm-service-port') || options['observe'] as bool; | 
|  | var vmServicePort = options.wasParsed('vm-service-port') | 
|  | ? '=${options['vm-service-port']}' | 
|  | : ''; | 
|  | var vmOptions = options['compile-vm-options'] as String?; | 
|  | var args = <String>[ | 
|  | ...?vmOptions?.split(' '), | 
|  | if (debug) ...[ | 
|  | if (observe) ...[ | 
|  | '--enable-vm-service$vmServicePort', | 
|  | '--pause-isolates-on-start', | 
|  | ], | 
|  | '--enable-asserts', | 
|  | // Use unbuilt script.  This only works from a source checkout. | 
|  | p.join(ddcPath, 'bin', 'dartdevc.dart'), | 
|  | ] else | 
|  | // Use built snapshot. | 
|  | p.join(dartSdk, 'bin', 'snapshots', 'dartdevc.dart.snapshot'), | 
|  | ...ddcArgs, | 
|  | ]; | 
|  | var process = await startProcess('DDC', dartBinary, args); | 
|  | if (await process.exitCode != 0) exit(await process.exitCode); | 
|  | } | 
|  |  | 
|  | String mod; | 
|  | var chrome = false; | 
|  | var node = false; | 
|  | var d8 = false; | 
|  | var runtime = options['runtime'] as String?; | 
|  | switch (runtime) { | 
|  | case 'node': | 
|  | // TODO(nshahan): Cleanup after the ddc module format is used everywhere. | 
|  | if (ddcModules) { | 
|  | throw ('The combination of `--runtime=$runtime` and `--ddc-modules` ' | 
|  | 'is not supported at this time.'); | 
|  | } | 
|  | node = true; | 
|  | mod = 'common'; | 
|  | break; | 
|  | case 'd8': | 
|  | d8 = true; | 
|  | mod = 'ddc'; | 
|  | break; | 
|  | case 'chrome': | 
|  | chrome = true; | 
|  | // TODO(nshahan): Cleanup after the ddc module format is used everywhere. | 
|  | mod = ddcModules ? 'ddc' : 'amd'; | 
|  | break; | 
|  | default: | 
|  | throw Exception('Unexpected runtime: $runtime'); | 
|  | } | 
|  |  | 
|  | var sdkRoot = p.dirname(p.dirname(ddcPath)); | 
|  | var buildDir = resolveBuildDir(sdkRoot, arch); | 
|  | var requirePath = p.join(sdkRoot, 'third_party', 'requirejs'); | 
|  | var sdkOutlineDill = p.join(buildDir, | 
|  | soundNullSafety ? 'ddc_outline.dill' : 'ddc_outline_unsound.dill'); | 
|  | var compileModeDir = [ | 
|  | canaryFeatures ? 'canary' : 'stable', | 
|  | soundNullSafety ? '' : '_unsound', | 
|  | ].join(); | 
|  | var sdkJsPath = | 
|  | p.join(buildDir, 'gen', 'utils', 'ddc', compileModeDir, 'sdk', mod); | 
|  | var preamblesDir = p.join( | 
|  | sdkRoot, 'sdk', 'lib', '_internal', 'js_runtime', 'lib', 'preambles'); | 
|  |  | 
|  | // Print an initial empty line to separate the invocation from the output. | 
|  | if (verbose) { | 
|  | print(''); | 
|  | } | 
|  | var outputs = <String>[]; | 
|  | if (compile) { | 
|  | var ddcArgs = [ | 
|  | if (summarizeText) '--summarize-text', | 
|  | '--modules=$mod', | 
|  | '--dart-sdk-summary=$sdkOutlineDill', | 
|  | for (var summary in summaries) '--summary=$summary', | 
|  | for (var experiment in experiments) '--enable-experiment=$experiment', | 
|  | if (soundNullSafety) '--sound-null-safety' else '--no-sound-null-safety', | 
|  | if (options['packages'] != null) '--packages=${options['packages']}', | 
|  | if (emitDebugSymbols) '--emit-debug-symbols', | 
|  | if (canaryFeatures) '--canary', | 
|  | // Provide predictable library URIs for all libraries when using the | 
|  | // new ddc module format. | 
|  | if (canaryFeatures) '--multi-root-scheme=ddb', | 
|  | if (canaryFeatures) '--multi-root=/', | 
|  | ]; | 
|  | var summaryFiles = []; | 
|  | for (var sourceFile in sourceFiles) { | 
|  | var out = p.setExtension(sourceFile, '.js'); | 
|  | var requestArgs = [ | 
|  | for (var summary in summaryFiles) '--summary=$summary', | 
|  | '-o', | 
|  | out, | 
|  | if (canaryFeatures) 'ddb:$sourceFile' else sourceFile, | 
|  | ]; | 
|  | await runDdc([...ddcArgs, ...requestArgs]); | 
|  | outputs.add(out); | 
|  | var summaryFile = p.setExtension(out, '.dill'); | 
|  | var libname = canaryFeatures | 
|  | ? 'ddb:$sourceFile' | 
|  | : js_names.pathToJSIdentifier(p.basenameWithoutExtension(sourceFile)); | 
|  | summaryFiles.add('$summaryFile=$libname'); | 
|  | } | 
|  | } | 
|  |  | 
|  | if (run) { | 
|  | var ddcModuleSdkOptions = canaryFeatures | 
|  | ? '''let sdkOptions = { | 
|  | weakNullSafetyWarnings: !($weakNullSafetyErrors || $soundNullSafety), | 
|  | weakNullSafetyErrors: $weakNullSafetyErrors, | 
|  | nonNullAsserts: $nonNullAsserts, | 
|  | nativeNonNullAsserts: $nativeNonNullAsserts, | 
|  | jsInteropNonNullAsserts: $jsInteropNonNullAsserts, | 
|  | };''' | 
|  | : ''' | 
|  | let sdk = dart_library.import("dart_sdk", "$appname"); | 
|  | sdk.dart.weakNullSafetyWarnings(!($weakNullSafetyErrors || $soundNullSafety)); | 
|  | sdk.dart.weakNullSafetyErrors($weakNullSafetyErrors); | 
|  | sdk.dart.nonNullAsserts($nonNullAsserts); | 
|  | sdk.dart.nativeNonNullAsserts($nativeNonNullAsserts); | 
|  | sdk.dart.jsInteropNonNullAsserts($jsInteropNonNullAsserts); | 
|  | '''; | 
|  | var ddcModuleRunMain = canaryFeatures | 
|  | ? 'dartDevEmbedder.runMain("ddb:$entryPoint", sdkOptions);' | 
|  | : 'dart_library.start(' | 
|  | '"$appname", "$uuid", "$basename", "$libname", false);'; | 
|  | if (chrome) { | 
|  | String chromeBinary; | 
|  | if (binary != null) { | 
|  | chromeBinary = binary; | 
|  | } else if (Platform.isWindows) { | 
|  | chromeBinary = | 
|  | 'C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe'; | 
|  | } else if (Platform.isMacOS) { | 
|  | chromeBinary = | 
|  | '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome'; | 
|  | } else { | 
|  | // Assume Linux | 
|  | chromeBinary = 'google-chrome'; | 
|  | } | 
|  | var amdModulePaths = [ | 
|  | for (var output in outputs) | 
|  | '"${pathToLibName(output)}": "${p.withoutExtension(output)}"' | 
|  | ].join(',\n        '); | 
|  |  | 
|  | // Seal the native JavaScript Object prototype to avoid pollution before | 
|  | // loading the Dart SDK module. | 
|  | var amdModulesHtml = ''' | 
|  | <script src="$preamblesDir/seal_native_object.js"></script> | 
|  | <script src='$requirePath/require.js'></script> | 
|  | <script> | 
|  | require.config({ | 
|  | paths: { | 
|  | 'dart_sdk': '$sdkJsPath/dart_sdk', | 
|  | $amdModulePaths | 
|  | }, | 
|  | waitSeconds: 15 | 
|  | }); | 
|  | require(['dart_sdk', '$libname'], | 
|  | function(sdk, app) { | 
|  | 'use strict'; | 
|  |  | 
|  | sdk.dart.weakNullSafetyWarnings( | 
|  | !($weakNullSafetyErrors || $soundNullSafety)); | 
|  | sdk.dart.weakNullSafetyErrors($weakNullSafetyErrors); | 
|  | sdk.dart.nonNullAsserts($nonNullAsserts); | 
|  | sdk.dart.nativeNonNullAsserts($nativeNonNullAsserts); | 
|  | sdk.dart.jsInteropNonNullAsserts($jsInteropNonNullAsserts); | 
|  | sdk._debugger.registerDevtoolsFormatter(); | 
|  | app.$libname.main([]); | 
|  | }); | 
|  | </script> | 
|  | '''; | 
|  | var ddcModuleScriptTags = [ | 
|  | for (var output in outputs) '<script src="$output"></script>' | 
|  | ].join('\n'); | 
|  | var ddcModulesHtml = ''' | 
|  | <script src="$preamblesDir/seal_native_object.js"></script> | 
|  | <script src="$ddcPath/lib/js/ddc/ddc_module_loader.js"></script> | 
|  | <script src="$sdkJsPath/dart_sdk.js"></script> | 
|  | $ddcModuleScriptTags | 
|  | <script> | 
|  | $ddcModuleSdkOptions | 
|  | $ddcModuleRunMain | 
|  | </script> | 
|  | '''; | 
|  | var htmlFile = p.setExtension(entryPoint, '.html'); | 
|  | File(htmlFile) | 
|  | .writeAsStringSync(ddcModules ? ddcModulesHtml : amdModulesHtml); | 
|  | var tmp = p.join(Directory.systemTemp.path, 'ddc'); | 
|  |  | 
|  | var process = await startProcess('Chrome', chromeBinary, [ | 
|  | '--auto-open-devtools-for-tabs', | 
|  | '--allow-file-access-from-files', | 
|  | '--remote-debugging-port=$port', | 
|  | '--user-data-dir=$tmp', | 
|  | htmlFile | 
|  | ]); | 
|  | if (await process.exitCode != 0) exit(await process.exitCode); | 
|  | } else if (node) { | 
|  | var nodePath = '$sdkJsPath:$libRoot'; | 
|  | var runjs = ''' | 
|  | // Seal the native JavaScript Object prototype to avoid pollution before | 
|  | // loading the Dart SDK module. | 
|  | delete Object.prototype.__proto__; | 
|  | Object.seal(Object.prototype); | 
|  |  | 
|  | let source_maps; | 
|  | try { | 
|  | source_maps = require('source-map-support'); | 
|  | source_maps.install(); | 
|  | } catch(e) { | 
|  | } | 
|  | let sdk = require(\"dart_sdk\"); | 
|  | // Create a self reference for JS interop tests that set fields on self. | 
|  | sdk.dart.global.self = sdk.dart.global; | 
|  | let main = require(\"./$basename\").$libname.main; | 
|  | try { | 
|  | sdk.dart.weakNullSafetyWarnings( | 
|  | !($weakNullSafetyErrors || $soundNullSafety)); | 
|  | sdk.dart.weakNullSafetyErrors($weakNullSafetyErrors); | 
|  | sdk.dart.nonNullAsserts($nonNullAsserts); | 
|  | sdk.dart.nativeNonNullAsserts($nativeNonNullAsserts); | 
|  | sdk.dart.jsInteropNonNullAsserts($jsInteropNonNullAsserts); | 
|  | sdk._isolate_helper.startRootIsolate(main, []); | 
|  | } catch(e) { | 
|  | if (!source_maps) { | 
|  | console.log('For Dart source maps: npm install source-map-support'); | 
|  | } | 
|  | sdk.core.print(sdk.dart.stackTrace(e)); | 
|  | process.exit(1); | 
|  | } | 
|  | '''; | 
|  | var nodeFile = p.setExtension(entryPoint, '.run.js'); | 
|  | File(nodeFile).writeAsStringSync(runjs); | 
|  | var nodeBinary = binary ?? 'node'; | 
|  | var process = await startProcess('Node', nodeBinary, | 
|  | ['--inspect=localhost:$port', nodeFile], {'NODE_PATH': nodePath}); | 
|  | if (await process.exitCode != 0) exit(await process.exitCode); | 
|  | } else if (d8) { | 
|  | var ddcModuleScriptTags = | 
|  | [for (var output in outputs) 'load("$output");'].join('\n'); | 
|  | var ddcModuleAssignGlobalSelf = canaryFeatures | 
|  | ? ''' | 
|  | let dart = dartDevEmbedder.importLibrary("dart:_runtime"); | 
|  | dart.global.self = dart.global;''' | 
|  | : 'sdk.dart.global.self = sdk.dart.global;'; | 
|  | var runjs = ''' | 
|  | load("$ddcPath/lib/js/ddc/ddc_module_loader.js"); | 
|  | load("$sdkJsPath/dart_sdk.js"); | 
|  | $ddcModuleScriptTags | 
|  |  | 
|  | $ddcModuleSdkOptions | 
|  | // Create a self reference for JS interop tests that set fields on self. | 
|  | $ddcModuleAssignGlobalSelf | 
|  |  | 
|  | // Invoke main through the d8 preamble to ensure the code is running | 
|  | // within the fake event loop. | 
|  | self.dartMainRunner(function () { | 
|  | $ddcModuleRunMain | 
|  | }); | 
|  | '''; | 
|  | var d8File = p.setExtension(entryPoint, '.d8.js'); | 
|  | File(d8File).writeAsStringSync(runjs); | 
|  | var d8Binary = binary ?? p.join(dartCheckoutPath, _d8executable); | 
|  | var process = await startProcess('D8', d8Binary, [ | 
|  | p.join(preamblesDir, 'seal_native_object.js'), | 
|  | p.join(preamblesDir, 'd8.js'), | 
|  | d8File | 
|  | ]); | 
|  | if (await process.exitCode != 0) exit(await process.exitCode); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | /// Converts a path to the expected default library name DDC will use. | 
|  | String pathToLibName(String path) => | 
|  | js_names.pathToJSIdentifier(p.withoutExtension( | 
|  | p.isWithin(p.current, path) ? p.relative(path) : p.absolute(path))); | 
|  |  | 
|  | String get _d8executable { | 
|  | final arch = Abi.current().toString().split('_')[1]; | 
|  | if (Platform.isWindows) { | 
|  | return p.join('third_party', 'd8', 'windows', arch, 'd8.exe'); | 
|  | } else if (Platform.isLinux) { | 
|  | return p.join('third_party', 'd8', 'linux', arch, 'd8'); | 
|  | } else if (Platform.isMacOS) { | 
|  | return p.join('third_party', 'd8', 'macos', arch, 'd8'); | 
|  | } | 
|  | throw UnsupportedError('Unsupported platform.'); | 
|  | } | 
|  |  | 
|  | /// Maps supported unames to supported architectures. | 
|  | final _resolvedUnames = { | 
|  | 'arm64': 'arm64', | 
|  | 'x86_64': 'x64', | 
|  | 'x64': 'x64', | 
|  | }; | 
|  |  | 
|  | /// Returns the location of the Dart SDK's build directory. | 
|  | String resolveBuildDir(String sdkRoot, String? architecture) { | 
|  | String platformString; | 
|  | String archString; | 
|  | if (Platform.isMacOS) { | 
|  | platformString = 'xcodebuild'; | 
|  | var resolvedArchitecture = architecture; | 
|  | if (architecture == null) { | 
|  | var result = Process.runSync('uname', ['-m']).stdout as String; | 
|  | final uname = result.trim(); | 
|  | resolvedArchitecture = _resolvedUnames[uname] ?? uname; | 
|  | } | 
|  | if (resolvedArchitecture == 'x64') { | 
|  | archString = 'ReleaseX64'; | 
|  | } else if (resolvedArchitecture == 'arm64') { | 
|  | archString = 'ReleaseARM64'; | 
|  | } else { | 
|  | throw UnsupportedError( | 
|  | 'DDB does not currently support the architecture $architecture ' | 
|  | 'on MacOS.'); | 
|  | } | 
|  | } else if (Platform.isLinux || Platform.isWindows) { | 
|  | platformString = 'out'; | 
|  | if (architecture != null && architecture != 'x64') { | 
|  | throw UnsupportedError( | 
|  | 'DDB does not currently support the architecture $architecture ' | 
|  | 'on Windows or Linux.'); | 
|  | } | 
|  | archString = 'ReleaseX64'; | 
|  | } else { | 
|  | throw UnsupportedError('Unsupported platform.'); | 
|  | } | 
|  | return p.join(sdkRoot, platformString, archString); | 
|  | } |