@@ -76,7 +76,7 @@ Future<CompilerResult> _compile(List<String> args,
7676 var argParser = ArgParser (allowTrailingOptions: true )
7777 ..addFlag ('help' ,
7878 abbr: 'h' , help: 'Display this message.' , negatable: false )
79- ..addOption ('out' , abbr: 'o' , help: 'Output file (required).' )
79+ ..addMultiOption ('out' , abbr: 'o' , help: 'Output file (required).' )
8080 ..addOption ('packages' , help: 'The package spec file to use.' )
8181 // TODO(jmesserly): is this still useful for us, or can we remove it now?
8282 ..addFlag ('summarize-text' ,
@@ -95,6 +95,8 @@ Future<CompilerResult> _compile(List<String> args,
9595 help: 'The directories to search when encountering uris with the '
9696 'specified multi-root scheme.' ,
9797 defaultsTo: [Uri .base .path])
98+ ..addOption ('multi-root-output-path' ,
99+ help: 'Path to set multi-root files relative to.' , hide: true )
98100 ..addOption ('dart-sdk' ,
99101 help: '(unsupported with --kernel) path to the Dart SDK.' , hide: true )
100102 ..addFlag ('compile-sdk' ,
@@ -113,12 +115,15 @@ Future<CompilerResult> _compile(List<String> args,
113115 return CompilerResult (64 );
114116 }
115117
116- var output = argResults['out' ] as String ;
117- if (output == null ) {
118+ var outPaths = argResults['out' ] as List <String >;
119+ var moduleFormats = parseModuleFormatOption (argResults);
120+ if (outPaths.isEmpty) {
118121 print ('Please specify the output file location. For example:\n '
119- ' -o PATH/TO/OUTPUT_FILE.js'
120- '' );
121- print (_usageMessage (argParser));
122+ ' -o PATH/TO/OUTPUT_FILE.js' );
123+ return CompilerResult (64 );
124+ } else if (outPaths.length != moduleFormats.length) {
125+ print ('Number of output files (${outPaths .length }) must match '
126+ 'number of module formats (${moduleFormats .length }).' );
122127 return CompilerResult (64 );
123128 }
124129
@@ -136,8 +141,17 @@ Future<CompilerResult> _compile(List<String> args,
136141 var multiRootPaths = (argResults['multi-root' ] as Iterable <String >)
137142 .map (Uri .base .resolve)
138143 .toList ();
139- var multiRootOutputPath = _longestPrefixingPath (
140- sourcePathToUri (p.absolute (output)), multiRootPaths);
144+ var multiRootOutputPath = argResults['multi-root-output-path' ] as String ;
145+ if (multiRootOutputPath == null ) {
146+ if (outPaths.length > 1 ) {
147+ print (
148+ 'If multiple output files (found ${outPaths .length }) are specified, '
149+ 'then --multi-root-output-path must be explicitly provided.' );
150+ return CompilerResult (64 );
151+ }
152+ multiRootOutputPath = _longestPrefixingPath (
153+ sourcePathToUri (p.absolute (outPaths.first)), multiRootPaths);
154+ }
141155
142156 var fileSystem = MultiRootFileSystem (
143157 multiRootScheme, multiRootPaths, fe.StandardFileSystem .instance);
@@ -314,12 +328,15 @@ Future<CompilerResult> _compile(List<String> args,
314328 return CompilerResult (1 , kernelState: compilerState);
315329 }
316330
317- var file = File (output);
318- await file.parent.create (recursive: true );
319-
320331 // Output files can be written in parallel, so collect the futures.
321332 var outFiles = < Future > [];
322333 if (argResults['summarize' ] as bool ) {
334+ if (outPaths.length > 1 ) {
335+ print (
336+ 'If multiple output files (found ${outPaths .length }) are specified, '
337+ 'the --summarize option is not supported.' );
338+ return CompilerResult (64 );
339+ }
323340 // TODO(jmesserly): CFE mutates the Kernel tree, so we can't save the dill
324341 // file if we successfully reused a cached library. If compiler state is
325342 // unchanged, it means we used the cache.
@@ -329,16 +346,22 @@ Future<CompilerResult> _compile(List<String> args,
329346 if (identical (compilerState, oldCompilerState)) {
330347 component.unbindCanonicalNames ();
331348 }
332- var sink = File (p.withoutExtension (output ) + '.dill' ).openWrite ();
349+ var sink = File (p.withoutExtension (outPaths.first ) + '.dill' ).openWrite ();
333350 // TODO(jmesserly): this appears to save external libraries.
334351 // Do we need to run them through an outlining step so they can be saved?
335352 kernel.BinaryPrinter (sink).writeComponentFile (component);
336353 outFiles.add (sink.flush ().then ((_) => sink.close ()));
337354 }
338355 if (argResults['summarize-text' ] as bool ) {
356+ if (outPaths.length > 1 ) {
357+ print (
358+ 'If multiple output files (found ${outPaths .length }) are specified, '
359+ 'the --summarize-text option is not supported.' );
360+ return CompilerResult (64 );
361+ }
339362 StringBuffer sb = StringBuffer ();
340363 kernel.Printer (sb, showExternal: false ).writeComponentFile (component);
341- outFiles.add (File (output + '.txt' ).writeAsString (sb.toString ()));
364+ outFiles.add (File (outPaths.first + '.txt' ).writeAsString (sb.toString ()));
342365 }
343366 if (hierarchy == null ) {
344367 var target = compilerState.options.target as DevCompilerTarget ;
@@ -351,24 +374,28 @@ Future<CompilerResult> _compile(List<String> args,
351374 var jsModule = compiler.emitModule (
352375 component, result.inputSummaries, inputSummaries, summaryModules);
353376
354- // TODO(jmesserly): support for multiple output formats?
355- //
356377 // Also the old Analyzer backend had some code to make debugging better when
357378 // --single-out-file is used, but that option does not appear to be used by
358379 // any of our build systems.
359- var jsCode = jsProgramToCode (jsModule, options.moduleFormats.first,
360- buildSourceMap: options.sourceMap,
361- inlineSourceMap: options.inlineSourceMap,
362- jsUrl: p.toUri (output).toString (),
363- mapUrl: p.toUri (output + '.map' ).toString (),
364- bazelMapping: options.bazelMapping,
365- customScheme: multiRootScheme,
366- multiRootOutputPath: multiRootOutputPath);
367-
368- outFiles.add (file.writeAsString (jsCode.code));
369- if (jsCode.sourceMap != null ) {
370- outFiles.add (
371- File (output + '.map' ).writeAsString (json.encode (jsCode.sourceMap)));
380+ for (var i = 0 ; i < outPaths.length; ++ i) {
381+ var output = outPaths[i];
382+ var moduleFormat = moduleFormats[i];
383+ var file = File (output);
384+ await file.parent.create (recursive: true );
385+ var jsCode = jsProgramToCode (jsModule, moduleFormat,
386+ buildSourceMap: options.sourceMap,
387+ inlineSourceMap: options.inlineSourceMap,
388+ jsUrl: p.toUri (output).toString (),
389+ mapUrl: p.toUri (output + '.map' ).toString (),
390+ bazelMapping: options.bazelMapping,
391+ customScheme: multiRootScheme,
392+ multiRootOutputPath: multiRootOutputPath);
393+
394+ outFiles.add (file.writeAsString (jsCode.code));
395+ if (jsCode.sourceMap != null ) {
396+ outFiles.add (
397+ File (output + '.map' ).writeAsString (json.encode (jsCode.sourceMap)));
398+ }
372399 }
373400
374401 await Future .wait (outFiles);
0 commit comments