OLD | NEW |
1 #!/usr/bin/env dart | 1 #!/usr/bin/env dart |
2 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 2 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file |
3 // for details. All rights reserved. Use of this source code is governed by a | 3 // for details. All rights reserved. Use of this source code is governed by a |
4 // BSD-style license that can be found in the LICENSE file. | 4 // BSD-style license that can be found in the LICENSE file. |
5 | 5 |
6 import 'dart:async'; | 6 import 'dart:async'; |
7 import 'dart:io'; | 7 import 'dart:io'; |
8 | 8 |
9 import 'batch_util.dart'; | 9 import 'batch_util.dart'; |
10 import 'util.dart'; | 10 import 'util.dart'; |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
61 ..addOption('embedder-entry-points-manifest', | 61 ..addOption('embedder-entry-points-manifest', |
62 allowMultiple: true, | 62 allowMultiple: true, |
63 help: 'A path to a file describing entrypoints ' | 63 help: 'A path to a file describing entrypoints ' |
64 '(lines of the form `<library>,<class>,<member>`).') | 64 '(lines of the form `<library>,<class>,<member>`).') |
65 ..addFlag('verbose', | 65 ..addFlag('verbose', |
66 abbr: 'v', | 66 abbr: 'v', |
67 negatable: false, | 67 negatable: false, |
68 help: 'Print internal warnings and diagnostics to stderr.') | 68 help: 'Print internal warnings and diagnostics to stderr.') |
69 ..addFlag('print-metrics', | 69 ..addFlag('print-metrics', |
70 negatable: false, help: 'Print performance metrics.') | 70 negatable: false, help: 'Print performance metrics.') |
71 ..addOption('write-dependencies', | |
72 help: 'Write all the .dart that were loaded to the given file.') | |
73 ..addFlag('verify-ir', help: 'Perform slow internal correctness checks.') | 71 ..addFlag('verify-ir', help: 'Perform slow internal correctness checks.') |
74 ..addFlag('tolerant', | 72 ..addFlag('tolerant', |
75 help: 'Generate kernel even if there are compile-time errors.', | 73 help: 'Generate kernel even if there are compile-time errors.', |
76 defaultsTo: false) | 74 defaultsTo: false) |
77 ..addOption('D', | 75 ..addOption('D', |
78 abbr: 'D', | 76 abbr: 'D', |
79 allowMultiple: true, | 77 allowMultiple: true, |
80 help: 'Define an environment variable.', | 78 help: 'Define an environment variable.', |
81 hide: true) | 79 hide: true) |
82 ..addFlag('show-external', | 80 ..addFlag('show-external', |
83 help: 'When printing a library as text, also print its dependencies\n' | 81 help: 'When printing a library as text, also print its dependencies\n' |
84 'on external libraries.') | 82 'on external libraries.') |
85 ..addFlag('show-offsets', | 83 ..addFlag('show-offsets', |
86 help: 'When printing a library as text, also print node offsets') | 84 help: 'When printing a library as text, also print node offsets') |
| 85 ..addFlag('include-sdk', |
| 86 help: 'Include the SDK in the output. Implied by --link.') |
87 ..addFlag('tree-shake', | 87 ..addFlag('tree-shake', |
88 defaultsTo: false, help: 'Enable tree-shaking if the target supports it'); | 88 defaultsTo: false, help: 'Enable tree-shaking if the target supports it'); |
89 | 89 |
90 String getUsage() => """ | 90 String getUsage() => """ |
91 Usage: dartk [options] FILE | 91 Usage: dartk [options] FILE |
92 | 92 |
93 Convert .dart or .dill files to kernel's IR and print out its textual | 93 Convert .dart or .dill files to kernel's IR and print out its textual |
94 or binary form. | 94 or binary form. |
95 | 95 |
96 Examples: | 96 Examples: |
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
267 } | 267 } |
268 var applicationRoot = new ApplicationRoot(applicationRootOption); | 268 var applicationRoot = new ApplicationRoot(applicationRootOption); |
269 | 269 |
270 // Set up logging. | 270 // Set up logging. |
271 if (options['verbose']) { | 271 if (options['verbose']) { |
272 log.onRecord.listen((LogRecord rec) { | 272 log.onRecord.listen((LogRecord rec) { |
273 stderr.writeln(rec.message); | 273 stderr.writeln(rec.message); |
274 }); | 274 }); |
275 } | 275 } |
276 | 276 |
277 if (options.rest.length != 1) { | 277 bool includeSdk = options['include-sdk']; |
278 return fail('Exactly one FILE should be given.'); | 278 |
| 279 List<String> inputFiles = options.rest; |
| 280 if (inputFiles.length < 1 && !includeSdk) { |
| 281 return fail('At least one file should be given.'); |
279 } | 282 } |
280 | 283 |
281 String file = options.rest.single; | 284 bool hasBinaryInput = false; |
282 checkIsFile(file, option: 'Input file'); | 285 bool hasDartInput = includeSdk; |
283 file = new File(file).absolute.path; | 286 for (String file in inputFiles) { |
284 Uri fileUri = new Uri(scheme: 'file', path: file); | 287 checkIsFile(file, option: 'Input file'); |
| 288 if (file.endsWith('.dill')) { |
| 289 hasBinaryInput = true; |
| 290 } else if (file.endsWith('.dart')) { |
| 291 hasDartInput = true; |
| 292 } else { |
| 293 fail('Unrecognized file extension: $file'); |
| 294 } |
| 295 } |
| 296 |
| 297 if (hasBinaryInput && hasDartInput) { |
| 298 fail('Mixed binary and dart input is not currently supported'); |
| 299 } |
285 | 300 |
286 String format = options['format'] ?? defaultFormat(); | 301 String format = options['format'] ?? defaultFormat(); |
287 String outputFile = options['out'] ?? defaultOutput(); | 302 String outputFile = options['out'] ?? defaultOutput(); |
288 | 303 |
289 List<String> urlMapping = options['url-mapping'] as List<String>; | 304 List<String> urlMapping = options['url-mapping'] as List<String>; |
290 var customUriMappings = parseCustomUriMappings(urlMapping); | 305 var customUriMappings = parseCustomUriMappings(urlMapping); |
291 | 306 |
292 List<String> embedderEntryPointManifests = | 307 List<String> embedderEntryPointManifests = |
293 options['embedder-entry-points-manifest'] as List<String>; | 308 options['embedder-entry-points-manifest'] as List<String>; |
294 List<ProgramRoot> programRoots = | 309 List<ProgramRoot> programRoots = |
295 parseProgramRoots(embedderEntryPointManifests); | 310 parseProgramRoots(embedderEntryPointManifests); |
296 | 311 |
297 var repository = new Repository(); | 312 var program = new Program(); |
298 | |
299 Program program; | |
300 | 313 |
301 var watch = new Stopwatch()..start(); | 314 var watch = new Stopwatch()..start(); |
302 List<String> loadedFiles; | |
303 Function getLoadedFiles; | |
304 List errors = const []; | 315 List errors = const []; |
305 TargetFlags targetFlags = new TargetFlags( | 316 TargetFlags targetFlags = new TargetFlags( |
306 strongMode: options['strong'], | 317 strongMode: options['strong'], |
307 treeShake: options['tree-shake'], | 318 treeShake: options['tree-shake'], |
308 programRoots: programRoots); | 319 programRoots: programRoots); |
309 Target target = getTarget(options['target'], targetFlags); | 320 Target target = getTarget(options['target'], targetFlags); |
310 | 321 |
311 var declaredVariables = <String, String>{}; | 322 var declaredVariables = <String, String>{}; |
312 declaredVariables.addAll(target.extraDeclaredVariables); | 323 declaredVariables.addAll(target.extraDeclaredVariables); |
313 for (String define in options['D']) { | 324 for (String define in options['D']) { |
314 int separator = define.indexOf('='); | 325 int separator = define.indexOf('='); |
315 if (separator == -1) { | 326 if (separator == -1) { |
316 fail('Invalid define: -D$define. Format is -D<name>=<value>'); | 327 fail('Invalid define: -D$define. Format is -D<name>=<value>'); |
317 } | 328 } |
318 String name = define.substring(0, separator); | 329 String name = define.substring(0, separator); |
319 String value = define.substring(separator + 1); | 330 String value = define.substring(separator + 1); |
320 declaredVariables[name] = value; | 331 declaredVariables[name] = value; |
321 } | 332 } |
322 | 333 |
323 if (file.endsWith('.dill')) { | 334 DartLoader loader; |
324 program = loadProgramFromBinary(file, repository); | 335 if (hasDartInput) { |
325 getLoadedFiles = () => [file]; | 336 String packageDiscoveryPath = |
326 } else { | 337 batchModeState.isBatchMode || inputFiles.isEmpty |
327 DartOptions dartOptions = new DartOptions( | 338 ? null |
328 strongMode: target.strongMode, | 339 : inputFiles.first; |
329 strongModeSdk: target.strongModeSdk, | 340 loader = await batchModeState.batch.getLoader( |
330 sdk: options['sdk'], | 341 program, |
331 packagePath: packagePath, | 342 new DartOptions( |
332 customUriMappings: customUriMappings, | 343 strongMode: target.strongMode, |
333 declaredVariables: declaredVariables, | 344 strongModeSdk: target.strongModeSdk, |
334 applicationRoot: applicationRoot); | 345 sdk: options['sdk'], |
335 String packageDiscoveryPath = batchModeState.isBatchMode ? null : file; | 346 packagePath: packagePath, |
336 DartLoader loader = await batchModeState.batch.getLoader( | 347 customUriMappings: customUriMappings, |
337 repository, dartOptions, | 348 declaredVariables: declaredVariables, |
| 349 applicationRoot: applicationRoot), |
338 packageDiscoveryPath: packageDiscoveryPath); | 350 packageDiscoveryPath: packageDiscoveryPath); |
339 if (options['link']) { | 351 if (includeSdk) { |
340 program = loader.loadProgram(fileUri, target: target); | 352 for (var uri in batchModeState.batch.dartSdk.uris) { |
341 } else { | 353 loader.loadLibrary(Uri.parse(uri)); |
342 var library = loader.loadLibrary(fileUri); | |
343 loader.loadSdkInterface(program, target); | |
344 assert(library == | |
345 repository.getLibraryReference(applicationRoot.relativeUri(fileUri))); | |
346 program = new Program(repository.libraries); | |
347 } | |
348 errors = loader.errors; | |
349 if (errors.isNotEmpty) { | |
350 const int errorLimit = 100; | |
351 stderr.writeln(errors.take(errorLimit).join('\n')); | |
352 if (errors.length > errorLimit) { | |
353 stderr | |
354 .writeln('[error] ${errors.length - errorLimit} errors not shown'); | |
355 } | 354 } |
356 } | 355 } |
357 getLoadedFiles = () => loadedFiles ??= loader.getLoadedFileNames(); | 356 loader.loadSdkInterface(program, target); |
| 357 } |
| 358 |
| 359 for (String file in inputFiles) { |
| 360 Uri fileUri = Uri.base.resolve(file); |
| 361 |
| 362 if (file.endsWith('.dill')) { |
| 363 loadProgramFromBinary(file, program); |
| 364 } else { |
| 365 if (options['link']) { |
| 366 loader.loadProgram(fileUri, target: target); |
| 367 } else { |
| 368 var library = loader.loadLibrary(fileUri); |
| 369 program.mainMethod ??= library.procedures |
| 370 .firstWhere((p) => p.name.name == 'main', orElse: () => null); |
| 371 } |
| 372 errors = loader.errors; |
| 373 if (errors.isNotEmpty) { |
| 374 const int errorLimit = 100; |
| 375 stderr.writeln(errors.take(errorLimit).join('\n')); |
| 376 if (errors.length > errorLimit) { |
| 377 stderr.writeln( |
| 378 '[error] ${errors.length - errorLimit} errors not shown'); |
| 379 } |
| 380 } |
| 381 } |
358 } | 382 } |
359 | 383 |
360 bool canContinueCompilation = errors.isEmpty || options['tolerant']; | 384 bool canContinueCompilation = errors.isEmpty || options['tolerant']; |
361 | 385 |
362 int loadTime = watch.elapsedMilliseconds; | 386 int loadTime = watch.elapsedMilliseconds; |
363 if (shouldReportMetrics) { | 387 if (shouldReportMetrics) { |
364 print('loader.time = $loadTime ms'); | 388 print('loader.time = $loadTime ms'); |
365 } | 389 } |
366 | 390 |
367 void runVerifier() { | 391 void runVerifier() { |
368 if (options['verify-ir']) { | 392 if (options['verify-ir']) { |
369 verifyProgram(program); | 393 verifyProgram(program); |
370 } | 394 } |
371 } | 395 } |
372 | 396 |
373 if (canContinueCompilation) { | 397 if (canContinueCompilation) { |
374 runVerifier(); | 398 runVerifier(); |
375 } | 399 } |
376 | 400 |
377 String outputDependencies = options['write-dependencies']; | 401 if (options['link'] && program.mainMethodName == null) { |
378 if (outputDependencies != null) { | 402 fail('[error] The program has no main method.'); |
379 new File(outputDependencies).writeAsStringSync(getLoadedFiles().join('\n')); | |
380 } | 403 } |
381 | 404 |
382 // Apply target-specific transformations. | 405 // Apply target-specific transformations. |
383 if (target != null && canContinueCompilation) { | 406 if (target != null && canContinueCompilation) { |
384 target.performModularTransformations(program); | 407 target.performModularTransformations(program); |
385 runVerifier(); | 408 runVerifier(); |
386 if (options['link']) { | 409 if (options['link']) { |
387 target.performGlobalTransformations(program); | 410 target.performGlobalTransformations(program); |
388 runVerifier(); | 411 runVerifier(); |
389 } | 412 } |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
421 int flushTime = watch.elapsedMilliseconds - time; | 444 int flushTime = watch.elapsedMilliseconds - time; |
422 print('writer.flush_time = $flushTime ms'); | 445 print('writer.flush_time = $flushTime ms'); |
423 } | 446 } |
424 | 447 |
425 if (options['tolerant']) { | 448 if (options['tolerant']) { |
426 return CompilerOutcome.Ok; | 449 return CompilerOutcome.Ok; |
427 } | 450 } |
428 | 451 |
429 return errors.length > 0 ? CompilerOutcome.Fail : CompilerOutcome.Ok; | 452 return errors.length > 0 ? CompilerOutcome.Fail : CompilerOutcome.Ok; |
430 } | 453 } |
OLD | NEW |