in pkg/compiler/lib/src/dart2js.dart [100:1072]
Future<api.CompilationResult> compile(List<String> argv,
{fe.InitializedCompilerState kernelInitializedCompilerState}) {
Stopwatch wallclock = Stopwatch()..start();
stackTraceFilePrefix = '${Uri.base}';
Uri entryUri;
Uri inputDillUri;
Uri librariesSpecificationUri = Uri.base.resolve('lib/libraries.json');
bool outputSpecified = false;
Uri out;
Uri sourceMapOut;
Uri writeModularAnalysisUri;
Uri readDataUri;
Uri writeDataUri;
Uri readClosedWorldUri;
Uri writeClosedWorldUri;
Uri readCodegenUri;
Uri writeCodegenUri;
int codegenShard;
int codegenShards;
List<String> bazelPaths;
List<Uri> multiRoots;
String multiRootScheme = 'org-dartlang-app';
Uri packageConfig = null;
List<String> options = <String>[];
bool wantHelp = false;
bool wantVersion = false;
bool trustTypeAnnotations = false;
bool checkedMode = false;
bool strongMode = true;
List<String> hints = <String>[];
bool verbose;
bool throwOnError;
int throwOnErrorCount;
bool showWarnings;
bool showHints;
bool enableColors;
int optimizationLevel = null;
Uri platformBinaries;
Map<String, String> environment = Map<String, String>();
ReadStrategy readStrategy = ReadStrategy.fromDart;
WriteStrategy writeStrategy = WriteStrategy.toJs;
FeatureOptions features = FeatureOptions();
String invoker;
void passThrough(String argument) => options.add(argument);
void ignoreOption(String argument) {}
if (BUILD_ID != null) {
passThrough("--build-id=$BUILD_ID");
}
Uri extractResolvedFileUri(String argument) {
return Uri.base.resolve(extractPath(argument, isDirectory: false));
}
void setEntryUri(String argument) {
entryUri = extractResolvedFileUri(argument);
}
void setInputDillUri(String argument) {
inputDillUri = extractResolvedFileUri(argument);
}
void setLibrarySpecificationUri(String argument) {
librariesSpecificationUri = extractResolvedFileUri(argument);
}
void setPackageConfig(String argument) {
packageConfig = extractResolvedFileUri(argument);
}
void setOutput(Iterator<String> arguments) {
outputSpecified = true;
String path;
if (arguments.current == '-o') {
if (!arguments.moveNext()) {
helpAndFail('Error: Missing file after -o option.');
}
path = arguments.current;
} else {
path = extractParameter(arguments.current);
}
out = Uri.base.resolve(fe.nativeToUriPath(path));
}
void setOptimizationLevel(String argument) {
int value = int.tryParse(extractParameter(argument));
if (value == null || value < 0 || value > 4) {
helpAndFail("Error: Unsupported optimization level '$argument', "
"supported levels are: 0, 1, 2, 3, 4");
return;
}
if (optimizationLevel != null) {
print("Optimization level '$argument' ignored "
"due to preceding '-O$optimizationLevel'");
return;
}
optimizationLevel = value;
}
void setOutputType(String argument) {
if (argument == '--output-type=dart' ||
argument == '--output-type=dart-multi') {
helpAndFail(
"--output-type=dart is no longer supported. It was deprecated "
"since Dart 1.11 and removed in Dart 1.19.");
}
}
setStrip(String argument) {
helpAndFail("Option '--force-strip' is not in use now that"
"--output-type=dart is no longer supported.");
}
void setBazelPaths(String argument) {
String paths = extractParameter(argument);
bazelPaths = <String>[]..addAll(paths.split(','));
}
void setMultiRoots(String argument) {
String paths = extractParameter(argument);
multiRoots ??= <Uri>[];
multiRoots.addAll(paths.split(',').map(fe.nativeToUri));
}
void setMultiRootScheme(String argument) {
multiRootScheme = extractParameter(argument);
}
String getDepsOutput(Iterable<Uri> sourceFiles) {
var filenames = sourceFiles.map((uri) => '$uri').toList();
filenames.sort();
return filenames.join("\n");
}
void setAllowNativeExtensions(String argument) {
helpAndFail("Option '${Flags.allowNativeExtensions}' is not supported.");
}
void setVerbose(_) {
verbose = true;
passThrough('--verbose');
}
void setTrustTypeAnnotations(String argument) {
trustTypeAnnotations = true;
}
void setCheckedMode(String argument) {
checkedMode = true;
passThrough(argument);
}
void addInEnvironment(Iterator<String> arguments) {
final isDefine = arguments.current.startsWith('--define');
String argument;
if (arguments.current == '--define') {
arguments.moveNext();
argument = arguments.current;
} else {
argument = arguments.current.substring(isDefine ? '--define='.length : 2);
}
// Allow for ' ' or '=' after --define
int eqIndex = argument.indexOf('=');
if (eqIndex <= 0) {
helpAndFail('Invalid value for --define: $argument');
return;
}
String name = argument.substring(0, eqIndex);
String value = argument.substring(eqIndex + 1);
environment[name] = value;
}
void setCategories(String argument) {
List<String> categories = extractParameter(argument).split(',');
bool isServerMode = categories.length == 1 && categories.single == "Server";
if (isServerMode) {
hints.add("The --categories flag is deprecated and will be deleted in a "
"future release, please use '${Flags.serverMode}' instead of "
"'--categories=Server'.");
passThrough(Flags.serverMode);
} else {
hints.add(
"The --categories flag is deprecated, see the usage for details.");
}
}
void setPlatformBinaries(String argument) {
platformBinaries =
Uri.base.resolve(extractPath(argument, isDirectory: true));
}
void setUriList(String flag, String argument) {
String list = extractParameter(argument);
String uriList = list.splitMapJoin(',',
onMatch: (_) => ',', onNonMatch: (p) => '${fe.nativeToUri(p)}');
options.add('${flag}=${uriList}');
}
void setModularAnalysisInputs(String argument) {
setUriList(Flags.readModularAnalysis, argument);
}
void setWriteModularAnalysis(String argument) {
if (writeStrategy == WriteStrategy.toClosedWorld) {
fail("Cannot use ${Flags.writeModularAnalysis} "
"and write serialized closed world simultaneously.");
}
if (writeStrategy == WriteStrategy.toData) {
fail("Cannot use ${Flags.writeModularAnalysis} "
"and write serialized global data simultaneously.");
}
if (writeStrategy == WriteStrategy.toCodegen) {
fail("Cannot use ${Flags.writeModularAnalysis} "
"and write serialized codegen simultaneously.");
}
if (writeStrategy == WriteStrategy.toKernel) {
fail("Cannot use ${Flags.writeModularAnalysis} "
"and run the CFE simultaneously.");
}
if (argument != Flags.writeModularAnalysis) {
writeModularAnalysisUri =
fe.nativeToUri(extractPath(argument, isDirectory: false));
}
writeStrategy = WriteStrategy.toModularAnalysis;
}
void setReadData(String argument) {
if (argument != Flags.readData) {
readDataUri = fe.nativeToUri(extractPath(argument, isDirectory: false));
}
if (readStrategy == ReadStrategy.fromDart) {
readStrategy = ReadStrategy.fromData;
} else if (readStrategy == ReadStrategy.fromClosedWorld) {
readStrategy = ReadStrategy.fromDataAndClosedWorld;
} else if (readStrategy == ReadStrategy.fromCodegen) {
readStrategy = ReadStrategy.fromCodegenAndData;
} else if (readStrategy == ReadStrategy.fromCodegenAndClosedWorld) {
readStrategy = ReadStrategy.fromCodegenAndClosedWorldAndData;
}
}
void setReadClosedWorld(String argument) {
if (argument != Flags.readClosedWorld) {
readClosedWorldUri =
fe.nativeToUri(extractPath(argument, isDirectory: false));
}
if (readStrategy == ReadStrategy.fromDart) {
readStrategy = ReadStrategy.fromClosedWorld;
} else if (readStrategy == ReadStrategy.fromData) {
readStrategy = ReadStrategy.fromDataAndClosedWorld;
} else if (readStrategy == ReadStrategy.fromCodegen) {
readStrategy = ReadStrategy.fromCodegenAndClosedWorld;
} else if (readStrategy == ReadStrategy.fromCodegenAndData) {
readStrategy = ReadStrategy.fromCodegenAndClosedWorldAndData;
}
}
void setDillDependencies(String argument) {
setUriList(Flags.dillDependencies, argument);
}
void setCfeOnly(String argument) {
if (writeStrategy == WriteStrategy.toModularAnalysis) {
fail("Cannot use ${Flags.cfeOnly} "
"and write serialized modular analysis simultaneously.");
}
if (writeStrategy == WriteStrategy.toClosedWorld) {
fail("Cannot use ${Flags.cfeOnly} "
"and write serialized closed world simultaneously.");
}
if (writeStrategy == WriteStrategy.toData) {
fail("Cannot use ${Flags.cfeOnly} "
"and write serialized data simultaneously.");
}
if (writeStrategy == WriteStrategy.toCodegen) {
fail("Cannot use ${Flags.cfeOnly} "
"and write serialized codegen simultaneously.");
}
writeStrategy = WriteStrategy.toKernel;
}
void setReadCodegen(String argument) {
if (argument != Flags.readCodegen) {
readCodegenUri =
fe.nativeToUri(extractPath(argument, isDirectory: false));
}
if (readStrategy == ReadStrategy.fromDart) {
readStrategy = ReadStrategy.fromCodegen;
} else if (readStrategy == ReadStrategy.fromClosedWorld) {
readStrategy = ReadStrategy.fromCodegenAndClosedWorld;
} else if (readStrategy == ReadStrategy.fromData) {
readStrategy = ReadStrategy.fromCodegenAndData;
} else if (readStrategy == ReadStrategy.fromDataAndClosedWorld) {
readStrategy = ReadStrategy.fromCodegenAndClosedWorldAndData;
}
}
void setWriteData(String argument) {
if (writeStrategy == WriteStrategy.toKernel) {
fail("Cannot use ${Flags.cfeOnly} "
"and write serialized data simultaneously.");
}
if (writeStrategy == WriteStrategy.toClosedWorld) {
fail("Cannot write closed world and data simultaneously.");
}
if (writeStrategy == WriteStrategy.toCodegen) {
fail("Cannot write serialized data and codegen simultaneously.");
}
if (argument != Flags.writeData) {
writeDataUri = fe.nativeToUri(extractPath(argument, isDirectory: false));
}
writeStrategy = WriteStrategy.toData;
}
void setWriteClosedWorld(String argument) {
if (writeStrategy == WriteStrategy.toKernel) {
fail("Cannot use ${Flags.cfeOnly} "
"and write serialized data simultaneously.");
}
if (writeStrategy == WriteStrategy.toData) {
fail("Cannot write both closed world and data");
}
if (writeStrategy == WriteStrategy.toCodegen) {
fail("Cannot write serialized data and codegen simultaneously.");
}
if (argument != Flags.writeClosedWorld) {
writeClosedWorldUri =
fe.nativeToUri(extractPath(argument, isDirectory: false));
}
writeStrategy = WriteStrategy.toClosedWorld;
}
void setWriteCodegen(String argument) {
if (writeStrategy == WriteStrategy.toKernel) {
fail("Cannot use ${Flags.cfeOnly} "
"and write serialized codegen simultaneously.");
}
if (writeStrategy == WriteStrategy.toClosedWorld) {
fail("Cannot write closed world and codegen simultaneously.");
}
if (writeStrategy == WriteStrategy.toData) {
fail("Cannot write serialized data and codegen data simultaneously.");
}
if (argument != Flags.writeCodegen) {
writeCodegenUri =
fe.nativeToUri(extractPath(argument, isDirectory: false));
}
writeStrategy = WriteStrategy.toCodegen;
}
void setCodegenShard(String argument) {
codegenShard = int.parse(extractParameter(argument));
}
void setCodegenShards(String argument) {
codegenShards = int.parse(extractParameter(argument));
}
void setDumpInfo(String argument) {
passThrough(Flags.dumpInfo);
if (argument == Flags.dumpInfo || argument == "${Flags.dumpInfo}=json") {
return;
}
if (argument == "${Flags.dumpInfo}=binary") {
passThrough(argument);
return;
}
helpAndFail("Error: Unsupported dump-info format '$argument', "
"supported formats are: json or binary");
}
String nullSafetyMode = null;
void setNullSafetyMode(String argument) {
if (nullSafetyMode != null && nullSafetyMode != argument) {
helpAndFail("Error: cannot specify both $nullSafetyMode and $argument.");
}
nullSafetyMode = argument;
passThrough(argument);
}
void setInvoker(String argument) {
invoker = extractParameter(argument);
}
void handleThrowOnError(String argument) {
throwOnError = true;
String parameter = extractParameter(argument, isOptionalArgument: true);
if (parameter != null) {
var count = int.parse(parameter);
throwOnErrorCount = count;
}
}
void handleShortOptions(String argument) {
var shortOptions = argument.substring(1).split("");
for (var shortOption in shortOptions) {
switch (shortOption) {
case 'v':
setVerbose(null);
break;
case 'h':
case '?':
wantHelp = true;
break;
case 'c':
setCheckedMode(Flags.enableCheckedMode);
break;
case 'm':
passThrough(Flags.minify);
break;
default:
throw 'Internal error: "$shortOption" did not match';
}
}
}
List<String> arguments = <String>[];
List<OptionHandler> handlers = <OptionHandler>[
OptionHandler('${Flags.entryUri}=.+', setEntryUri),
OptionHandler('${Flags.inputDill}=.+', setInputDillUri),
OptionHandler('-[chvm?]+', handleShortOptions),
OptionHandler('--throw-on-error(?:=[0-9]+)?', handleThrowOnError),
OptionHandler(Flags.suppressWarnings, (String argument) {
showWarnings = false;
passThrough(argument);
}),
OptionHandler(Flags.fatalWarnings, passThrough),
OptionHandler(Flags.suppressHints, (String argument) {
showHints = false;
passThrough(argument);
}),
// TODO(sigmund): remove entirely after Dart 1.20
OptionHandler(
'--output-type=dart|--output-type=dart-multi|--output-type=js',
setOutputType),
OptionHandler('--use-kernel', ignoreOption),
OptionHandler(Flags.platformBinaries, setPlatformBinaries),
OptionHandler(Flags.noFrequencyBasedMinification, passThrough),
OptionHandler(Flags.verbose, setVerbose),
OptionHandler(Flags.progress, passThrough),
OptionHandler(Flags.reportMetrics, passThrough),
OptionHandler(Flags.reportAllMetrics, passThrough),
OptionHandler(Flags.version, (_) => wantVersion = true),
OptionHandler('--library-root=.+', ignoreOption),
OptionHandler('--libraries-spec=.+', setLibrarySpecificationUri),
OptionHandler('${Flags.dillDependencies}=.+', setDillDependencies),
OptionHandler('${Flags.readModularAnalysis}=.+', setModularAnalysisInputs),
OptionHandler(
'${Flags.writeModularAnalysis}|${Flags.writeModularAnalysis}=.+',
setWriteModularAnalysis),
OptionHandler('${Flags.readData}|${Flags.readData}=.+', setReadData),
OptionHandler('${Flags.writeData}|${Flags.writeData}=.+', setWriteData),
OptionHandler(Flags.noClosedWorldInData, ignoreOption),
OptionHandler('${Flags.readClosedWorld}|${Flags.readClosedWorld}=.+',
setReadClosedWorld),
OptionHandler('${Flags.writeClosedWorld}|${Flags.writeClosedWorld}=.+',
setWriteClosedWorld),
OptionHandler(
'${Flags.readCodegen}|${Flags.readCodegen}=.+', setReadCodegen),
OptionHandler(
'${Flags.writeCodegen}|${Flags.writeCodegen}=.+', setWriteCodegen),
OptionHandler('${Flags.codegenShard}=.+', setCodegenShard),
OptionHandler('${Flags.codegenShards}=.+', setCodegenShards),
OptionHandler(Flags.cfeOnly, setCfeOnly),
OptionHandler(Flags.debugGlobalInference, passThrough),
OptionHandler('--out=.+|-o.*', setOutput, multipleArguments: true),
OptionHandler('-O.*', setOptimizationLevel),
OptionHandler(Flags.allowMockCompilation, ignoreOption),
OptionHandler(Flags.fastStartup, ignoreOption),
OptionHandler(Flags.genericMethodSyntax, ignoreOption),
OptionHandler(Flags.initializingFormalAccess, ignoreOption),
OptionHandler(Flags.minify, passThrough),
OptionHandler(Flags.noMinify, passThrough),
OptionHandler(Flags.omitLateNames, passThrough),
OptionHandler(Flags.noOmitLateNames, passThrough),
OptionHandler(Flags.preserveUris, ignoreOption),
OptionHandler(Flags.printLegacyStars, passThrough),
OptionHandler('--force-strip=.*', setStrip),
OptionHandler(Flags.disableDiagnosticColors, (_) {
enableColors = false;
}),
OptionHandler(Flags.enableDiagnosticColors, (_) {
enableColors = true;
}),
OptionHandler('--enable[_-]checked[_-]mode|--checked',
(_) => setCheckedMode(Flags.enableCheckedMode)),
OptionHandler(Flags.enableAsserts, passThrough),
OptionHandler(Flags.enableNullAssertions, passThrough),
OptionHandler(Flags.nativeNullAssertions, passThrough),
OptionHandler(Flags.noNativeNullAssertions, passThrough),
OptionHandler(Flags.trustTypeAnnotations, setTrustTypeAnnotations),
OptionHandler(Flags.trustPrimitives, passThrough),
OptionHandler(Flags.trustJSInteropTypeAnnotations, ignoreOption),
OptionHandler(r'--help|/\?|/h', (_) => wantHelp = true),
OptionHandler('--packages=.+', setPackageConfig),
OptionHandler(Flags.noSourceMaps, passThrough),
OptionHandler(Option.resolutionInput, ignoreOption),
OptionHandler(Option.bazelPaths, setBazelPaths),
OptionHandler(Option.multiRoots, setMultiRoots),
OptionHandler(Option.multiRootScheme, setMultiRootScheme),
OptionHandler(Flags.resolveOnly, ignoreOption),
OptionHandler(Flags.disableNativeLiveTypeAnalysis, passThrough),
OptionHandler('--categories=.*', setCategories),
OptionHandler(Flags.serverMode, passThrough),
OptionHandler(Flags.disableInlining, passThrough),
OptionHandler(Flags.disableProgramSplit, passThrough),
OptionHandler(Flags.stopAfterProgramSplit, passThrough),
OptionHandler(Flags.disableTypeInference, passThrough),
OptionHandler(Flags.useTrivialAbstractValueDomain, passThrough),
OptionHandler(Flags.experimentalWrapped, passThrough),
OptionHandler(Flags.experimentalPowersets, passThrough),
OptionHandler(Flags.disableRtiOptimization, passThrough),
OptionHandler(Flags.terse, passThrough),
OptionHandler('--deferred-map=.+', passThrough),
OptionHandler('${Flags.writeProgramSplit}=.+', passThrough),
OptionHandler('${Flags.readProgramSplit}=.+', passThrough),
OptionHandler('${Flags.dumpInfo}|${Flags.dumpInfo}=.+', setDumpInfo),
OptionHandler('--disallow-unsafe-eval', ignoreOption),
OptionHandler(Option.showPackageWarnings, passThrough),
OptionHandler(Option.enableLanguageExperiments, passThrough),
OptionHandler('--enable-experimental-mirrors', ignoreOption),
OptionHandler(Flags.enableAssertMessage, passThrough),
OptionHandler('--strong', ignoreOption),
OptionHandler(Flags.previewDart2, ignoreOption),
OptionHandler(Flags.omitImplicitChecks, passThrough),
OptionHandler(Flags.omitAsCasts, passThrough),
OptionHandler(Flags.laxRuntimeTypeToString, passThrough),
OptionHandler(Flags.benchmarkingProduction, passThrough),
OptionHandler(Flags.benchmarkingExperiment, passThrough),
OptionHandler(Flags.soundNullSafety, setNullSafetyMode),
OptionHandler(Flags.noSoundNullSafety, setNullSafetyMode),
OptionHandler(Flags.dumpUnusedLibraries, passThrough),
// TODO(floitsch): remove conditional directives flag.
// We don't provide the info-message yet, since we haven't publicly
// launched the feature yet.
OptionHandler(Flags.conditionalDirectives, ignoreOption),
OptionHandler('--enable-async', ignoreOption),
OptionHandler('--enable-null-aware-operators', ignoreOption),
OptionHandler('--enable-enum', ignoreOption),
OptionHandler(Flags.allowNativeExtensions, setAllowNativeExtensions),
OptionHandler(Flags.generateCodeWithCompileTimeErrors, ignoreOption),
OptionHandler(Flags.useMultiSourceInfo, passThrough),
OptionHandler(Flags.useNewSourceInfo, passThrough),
OptionHandler(Flags.useOldRti, passThrough),
OptionHandler(Flags.useSimpleLoadIds, passThrough),
OptionHandler(Flags.testMode, passThrough),
OptionHandler('${Flags.dumpSsa}=.+', passThrough),
OptionHandler('${Flags.cfeInvocationModes}=.+', passThrough),
OptionHandler('${Flags.invoker}=.+', setInvoker),
OptionHandler('${Flags.verbosity}=.+', passThrough),
// Experimental features.
// We don't provide documentation for these yet.
// TODO(29574): provide documentation when this feature is supported.
// TODO(29574): provide a warning/hint/error, when profile-based data is
// used without `--fast-startup`.
OptionHandler(Flags.experimentalTrackAllocations, passThrough),
OptionHandler(Flags.experimentLocalNames, ignoreOption),
OptionHandler(Flags.experimentStartupFunctions, passThrough),
OptionHandler(Flags.experimentToBoolean, passThrough),
OptionHandler(Flags.experimentUnreachableMethodsThrow, passThrough),
OptionHandler(Flags.experimentCallInstrumentation, passThrough),
OptionHandler(Flags.experimentNewRti, ignoreOption),
OptionHandler('${Flags.mergeFragmentsThreshold}=.+', passThrough),
// Wire up feature flags.
OptionHandler(Flags.canary, passThrough),
OptionHandler(Flags.noShipping, passThrough),
// Shipped features.
for (var feature in features.shipped)
OptionHandler('--${feature.flag}', passThrough),
for (var feature in features.shipped)
OptionHandler('--no-${feature.flag}', passThrough),
// Shipping features.
for (var feature in features.shipping)
OptionHandler('--${feature.flag}', passThrough),
for (var feature in features.shipping)
OptionHandler('--no-${feature.flag}', passThrough),
// Canary features.
for (var feature in features.canary)
OptionHandler('--${feature.flag}', passThrough),
for (var feature in features.canary)
OptionHandler('--no-${feature.flag}', passThrough),
// The following three options must come last.
OptionHandler('-D.+=.*|--define=.+=.*|--define', addInEnvironment,
multipleArguments: true),
OptionHandler('-.*', (String argument) {
helpAndFail("Unknown option '$argument'.");
}),
OptionHandler('.*', (String argument) {
arguments.add(fe.nativeToUriPath(argument));
})
];
parseCommandLine(handlers, argv);
if (invoker == null) {
warning("The 'dart2js' entrypoint script is deprecated, "
"please use 'dart compile js' instead.");
} else if (verbose != null) {
print("Compiler invoked from: '$invoker'");
}
// TODO(johnniwinther): Measure time for reading files.
SourceFileProvider inputProvider;
if (bazelPaths != null) {
if (multiRoots != null) {
helpAndFail(
'The options --bazel-root and --multi-root cannot be supplied '
'together, please choose one or the other.');
}
inputProvider = BazelInputProvider(bazelPaths);
} else if (multiRoots != null) {
inputProvider = MultiRootInputProvider(multiRootScheme, multiRoots);
} else {
inputProvider = CompilerSourceFileProvider();
}
diagnosticHandler = FormattingDiagnosticHandler(inputProvider);
if (verbose != null) {
diagnosticHandler.verbose = verbose;
}
if (throwOnError != null) {
diagnosticHandler.throwOnError = throwOnError;
}
if (throwOnErrorCount != null) {
diagnosticHandler.throwOnErrorCount = throwOnErrorCount;
}
if (showWarnings != null) {
diagnosticHandler.showWarnings = showWarnings;
}
if (showHints != null) {
diagnosticHandler.showHints = showHints;
}
if (enableColors != null) {
diagnosticHandler.enableColors = enableColors;
}
if (checkedMode && strongMode) {
checkedMode = false;
hints.add("Option '${Flags.enableCheckedMode}' is not needed in Dart 2.0. "
"To enable assertions use '${Flags.enableAsserts}' instead.");
}
if (trustTypeAnnotations && strongMode) {
hints.add("Option '${Flags.trustTypeAnnotations}' is not available "
"in Dart 2.0. Try using '${Flags.omitImplicitChecks}' instead.");
}
for (String hint in hints) {
diagnosticHandler.info(hint, api.Diagnostic.HINT);
}
if (wantHelp || wantVersion) {
helpAndExit(wantHelp, wantVersion, diagnosticHandler.verbose);
}
if (arguments.isEmpty && entryUri == null && inputDillUri == null) {
helpAndFail('No Dart file specified.');
}
if (arguments.length > 1) {
var extra = arguments.sublist(1);
helpAndFail('Extra arguments: ${extra.join(" ")}');
}
if (trustTypeAnnotations && checkedMode) {
helpAndFail("Option '${Flags.trustTypeAnnotations}' may not be used in "
"checked mode.");
}
if (arguments.isNotEmpty) {
String sourceOrDill = arguments[0];
Uri file = Uri.base.resolve(fe.nativeToUriPath(sourceOrDill));
if (sourceOrDill.endsWith('.dart')) {
entryUri = file;
} else {
assert(sourceOrDill.endsWith('.dill'));
inputDillUri = file;
}
}
// Make [scriptName] a relative path..
String scriptName =
fe.relativizeUri(Uri.base, inputDillUri ?? entryUri, Platform.isWindows);
switch (writeStrategy) {
case WriteStrategy.toJs:
out ??= Uri.base.resolve('out.js');
break;
case WriteStrategy.toKernel:
out ??= Uri.base.resolve('out.dill');
options.add(Flags.cfeOnly);
if (readStrategy == ReadStrategy.fromClosedWorld) {
fail("Cannot use ${Flags.cfeOnly} "
"and read serialized closed world simultaneously.");
} else if (readStrategy == ReadStrategy.fromData) {
fail("Cannot use ${Flags.cfeOnly} "
"and read serialized data simultaneously.");
} else if (readStrategy == ReadStrategy.fromCodegen) {
fail("Cannot use ${Flags.cfeOnly} "
"and read serialized codegen simultaneously.");
}
break;
case WriteStrategy.toModularAnalysis:
writeModularAnalysisUri ??= Uri.base.resolve('$out.mdata');
options.add('${Flags.writeModularAnalysis}=${writeModularAnalysisUri}');
out ??= Uri.base.resolve('out.dill');
break;
case WriteStrategy.toClosedWorld:
out ??= Uri.base.resolve('out.dill');
writeClosedWorldUri ??= Uri.base.resolve('$out.world');
options.add('${Flags.writeClosedWorld}=${writeClosedWorldUri}');
if (readStrategy == ReadStrategy.fromClosedWorld) {
fail("Cannot read and write serialized data simultaneously.");
} else if (readStrategy == ReadStrategy.fromData) {
fail("Cannot read from both closed world and data");
} else if (readStrategy == ReadStrategy.fromCodegen) {
fail("Cannot read serialized codegen and "
"write serialized data simultaneously.");
}
break;
case WriteStrategy.toData:
out ??= Uri.base.resolve('out.dill');
writeDataUri ??= Uri.base.resolve('$out.data');
options.add('${Flags.writeData}=${writeDataUri}');
if (readStrategy == ReadStrategy.fromData) {
fail("Cannot read and write serialized data simultaneously.");
} else if (readStrategy == ReadStrategy.fromCodegen) {
fail("Cannot read serialized codegen and "
"write serialized data simultaneously.");
}
break;
case WriteStrategy.toCodegen:
// TODO(johnniwinther): Avoid the need for an [out] value in this case or
// use [out] to pass [writeCodegenUri].
out ??= Uri.base.resolve('out');
writeCodegenUri ??= Uri.base.resolve('$out.code');
options.add('${Flags.writeCodegen}=${writeCodegenUri}');
if (readStrategy == ReadStrategy.fromCodegen) {
fail("Cannot read and write serialized codegen simultaneously.");
}
if (readStrategy != ReadStrategy.fromDataAndClosedWorld) {
fail("Can only write serialized codegen from serialized data.");
}
if (codegenShards == null) {
fail("Cannot write serialized codegen without setting "
"${Flags.codegenShards}.");
} else if (codegenShards <= 0) {
fail("${Flags.codegenShards} must be a positive integer.");
}
if (codegenShard == null) {
fail("Cannot write serialized codegen without setting "
"${Flags.codegenShard}.");
} else if (codegenShard < 0 || codegenShard >= codegenShards) {
fail("${Flags.codegenShard} must be between 0 and "
"${Flags.codegenShards}.");
}
options.add('${Flags.codegenShard}=$codegenShard');
options.add('${Flags.codegenShards}=$codegenShards');
break;
}
switch (readStrategy) {
case ReadStrategy.fromDart:
break;
case ReadStrategy.fromClosedWorld:
readClosedWorldUri ??= Uri.base.resolve('$scriptName.world');
options.add('${Flags.readClosedWorld}=${readClosedWorldUri}');
break;
case ReadStrategy.fromData:
fail("Must read from closed world and data.");
break;
case ReadStrategy.fromDataAndClosedWorld:
readClosedWorldUri ??= Uri.base.resolve('$scriptName.world');
options.add('${Flags.readClosedWorld}=${readClosedWorldUri}');
readDataUri ??= Uri.base.resolve('$scriptName.data');
options.add('${Flags.readData}=${readDataUri}');
break;
case ReadStrategy.fromCodegen:
case ReadStrategy.fromCodegenAndData:
case ReadStrategy.fromCodegenAndClosedWorld:
fail("Must read from closed world, data, and codegen");
break;
case ReadStrategy.fromCodegenAndClosedWorldAndData:
readClosedWorldUri ??= Uri.base.resolve('$scriptName.world');
options.add('${Flags.readClosedWorld}=${readClosedWorldUri}');
readDataUri ??= Uri.base.resolve('$scriptName.data');
options.add('${Flags.readData}=${readDataUri}');
readCodegenUri ??= Uri.base.resolve('$scriptName.code');
options.add('${Flags.readCodegen}=${readCodegenUri}');
if (codegenShards == null) {
fail("Cannot write serialized codegen without setting "
"${Flags.codegenShards}.");
} else if (codegenShards <= 0) {
fail("${Flags.codegenShards} must be a positive integer.");
}
options.add('${Flags.codegenShards}=$codegenShards');
break;
}
options.add('--out=$out');
if (writeStrategy == WriteStrategy.toJs) {
sourceMapOut = Uri.parse('$out.map');
options.add('--source-map=${sourceMapOut}');
}
RandomAccessFileOutputProvider outputProvider =
RandomAccessFileOutputProvider(out, sourceMapOut,
onInfo: diagnosticHandler.info, onFailure: fail);
api.CompilationResult compilationDone(api.CompilationResult result) {
if (!result.isSuccess) {
fail('Compilation failed.');
}
writeString(
Uri.parse('$out.deps'), getDepsOutput(inputProvider.getSourceUris()));
String input = scriptName;
int inputSize;
String processName;
String inputName;
int outputSize;
int primaryOutputSize;
String outputName;
String summary;
switch (readStrategy) {
case ReadStrategy.fromDart:
inputName = inputDillUri != null ? 'kernel bytes' : 'characters Dart';
inputSize = inputProvider.dartCharactersRead;
summary = 'Dart file $input ';
break;
case ReadStrategy.fromClosedWorld:
inputName = 'bytes data';
inputSize = inputProvider.dartCharactersRead;
String dataInput =
fe.relativizeUri(Uri.base, readClosedWorldUri, Platform.isWindows);
summary = 'Data files $input and $dataInput ';
break;
case ReadStrategy.fromData:
fail("Must read from closed world and data.");
break;
case ReadStrategy.fromDataAndClosedWorld:
inputName = 'bytes data';
inputSize = inputProvider.dartCharactersRead;
String worldInput =
fe.relativizeUri(Uri.base, readClosedWorldUri, Platform.isWindows);
String dataInput =
fe.relativizeUri(Uri.base, readDataUri, Platform.isWindows);
summary = 'Data files $input, $worldInput, and $dataInput ';
break;
case ReadStrategy.fromCodegen:
case ReadStrategy.fromCodegenAndData:
case ReadStrategy.fromCodegenAndClosedWorld:
fail("Must read from closed world, data, and codegen");
break;
case ReadStrategy.fromCodegenAndClosedWorldAndData:
inputName = 'bytes data';
inputSize = inputProvider.dartCharactersRead;
String worldInput =
fe.relativizeUri(Uri.base, readClosedWorldUri, Platform.isWindows);
String dataInput =
fe.relativizeUri(Uri.base, readDataUri, Platform.isWindows);
String codeInput =
fe.relativizeUri(Uri.base, readCodegenUri, Platform.isWindows);
summary = 'Data files $input, $worldInput, $dataInput and '
'${codeInput}[0-${codegenShards - 1}] ';
break;
}
switch (writeStrategy) {
case WriteStrategy.toJs:
processName = 'Compiled';
outputName = 'characters JavaScript';
outputSize = outputProvider.totalCharactersWrittenJavaScript;
primaryOutputSize = outputProvider.totalCharactersWrittenPrimary;
String output = fe.relativizeUri(Uri.base, out, Platform.isWindows);
summary += 'compiled to JavaScript: ${output}';
break;
case WriteStrategy.toKernel:
processName = 'Compiled';
outputName = 'kernel bytes';
outputSize = outputProvider.totalDataWritten;
String output = fe.relativizeUri(Uri.base, out, Platform.isWindows);
summary += 'compiled to dill: ${output}.';
break;
case WriteStrategy.toModularAnalysis:
processName = 'Serialized';
outputName = 'bytes data';
outputSize = outputProvider.totalDataWritten;
String output = fe.relativizeUri(Uri.base, out, Platform.isWindows);
String dataOutput = fe.relativizeUri(
Uri.base, writeModularAnalysisUri, Platform.isWindows);
summary += 'serialized to dill and data: ${output} and ${dataOutput}.';
break;
case WriteStrategy.toClosedWorld:
processName = 'Serialized';
outputName = 'bytes data';
outputSize = outputProvider.totalDataWritten;
String output = fe.relativizeUri(Uri.base, out, Platform.isWindows);
String dataOutput =
fe.relativizeUri(Uri.base, writeClosedWorldUri, Platform.isWindows);
summary += 'serialized to dill and data: ${output} and ${dataOutput}.';
break;
case WriteStrategy.toData:
processName = 'Serialized';
outputName = 'bytes data';
outputSize = outputProvider.totalDataWritten;
String output = fe.relativizeUri(Uri.base, out, Platform.isWindows);
String dataOutput =
fe.relativizeUri(Uri.base, writeDataUri, Platform.isWindows);
summary += 'serialized to dill and data: ${output} and ${dataOutput}.';
break;
case WriteStrategy.toCodegen:
processName = 'Serialized';
outputName = 'bytes data';
outputSize = outputProvider.totalDataWritten;
String codeOutput =
fe.relativizeUri(Uri.base, writeCodegenUri, Platform.isWindows);
summary += 'serialized to codegen data: '
'${codeOutput}${codegenShard}.';
break;
}
print('$processName '
'${_formatCharacterCount(inputSize)} $inputName to '
'${_formatCharacterCount(outputSize)} $outputName in '
'${_formatDurationAsSeconds(wallclock.elapsed)} seconds');
if (primaryOutputSize != null) {
diagnosticHandler
.info('${_formatCharacterCount(primaryOutputSize)} $outputName '
'in ${fe.relativizeUri(Uri.base, out, Platform.isWindows)}');
}
if (writeStrategy == WriteStrategy.toJs) {
if (outputSpecified || diagnosticHandler.verbose) {
print(summary);
if (diagnosticHandler.verbose) {
var files = outputProvider.allOutputFiles;
int jsCount = files.where((f) => f.endsWith('.js')).length;
print('Emitted file $jsCount JavaScript files.');
}
}
} else {
print(summary);
}
return result;
}
diagnosticHandler.autoReadFileUri = true;
CompilerOptions compilerOptions = CompilerOptions.parse(options,
featureOptions: features,
librariesSpecificationUri: librariesSpecificationUri,
platformBinaries: platformBinaries,
onError: (String message) => fail(message),
onWarning: (String message) => print(message))
..entryUri = entryUri
..inputDillUri = inputDillUri
..packageConfig = packageConfig
..environment = environment
..kernelInitializedCompilerState = kernelInitializedCompilerState
..optimizationLevel = optimizationLevel;
return compileFunc(
compilerOptions, inputProvider, diagnosticHandler, outputProvider)
.then(compilationDone);
}