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