aot.dart 5.43 KB
Newer Older
Ian Hickson's avatar
Ian Hickson committed
1
// Copyright 2014 The Flutter Authors. All rights reserved.
xster's avatar
xster committed
2 3 4 5 6 7 8 9
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'package:meta/meta.dart';

import 'base/common.dart';
import 'base/logger.dart';
import 'build_info.dart';
10
import 'build_system/build_system.dart';
11
import 'build_system/targets/common.dart';
12 13 14
import 'build_system/targets/icon_tree_shaker.dart';
import 'build_system/targets/ios.dart';
import 'cache.dart';
15
import 'globals.dart' as globals;
xster's avatar
xster committed
16
import 'ios/bitcode.dart';
17
import 'project.dart';
xster's avatar
xster committed
18 19 20 21 22 23 24

/// Builds AOT snapshots given a platform, build mode and a path to a Dart
/// library.
class AotBuilder {
  Future<void> build({
    @required TargetPlatform platform,
    @required String outputPath,
25
    @required BuildInfo buildInfo,
xster's avatar
xster committed
26 27 28 29
    @required String mainDartFile,
    bool bitcode = kBitcodeEnabledDefault,
    bool quiet = true,
    Iterable<DarwinArch> iosBuildArchs = defaultIOSArchs,
30
    bool reportTimings = false,
xster's avatar
xster committed
31 32 33 34
  }) async {
    if (platform == null) {
      throwToolExit('No AOT build platform specified');
    }
35 36 37 38
    Target target;
    bool expectSo = false;
    switch (platform) {
      case TargetPlatform.android:
39 40 41
      case TargetPlatform.darwin_x64:
      case TargetPlatform.linux_x64:
      case TargetPlatform.windows_x64:
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
      case TargetPlatform.fuchsia_arm64:
      case TargetPlatform.tester:
      case TargetPlatform.web_javascript:
      case TargetPlatform.android_x86:
        throwToolExit('$platform is not supported in AOT.');
        break;
      case TargetPlatform.fuchsia_x64:
        throwToolExit(
          "To build release for fuchsia, use 'flutter build fuchsia --release'"
        );
        break;
      case TargetPlatform.ios:
        target = buildInfo.isRelease
          ? const AotAssemblyRelease()
          : const AotAssemblyProfile();
        break;
      case TargetPlatform.android_arm:
      case TargetPlatform.android_arm64:
      case TargetPlatform.android_x64:
        expectSo = true;
        target = buildInfo.isRelease
63 64
          ? const AotElfRelease(TargetPlatform.android_arm)
          : const AotElfProfile(TargetPlatform.android_arm);
65 66 67 68
    }

    Status status;
    if (!quiet) {
69
      final String typeName = globals.artifacts.getEngineType(platform, buildInfo.mode);
70
      status = globals.logger.startProgress(
71
        'Building AOT snapshot in ${getFriendlyModeName(buildInfo.mode)} mode ($typeName)...',
72 73 74
      );
    }

75 76 77 78 79 80
    final Environment environment = Environment(
      projectDir: globals.fs.currentDirectory,
      outputDir: globals.fs.directory(outputPath),
      buildDir: FlutterProject.current().dartTool.childDirectory('flutter_build'),
      cacheDir: null,
      flutterRootDir: globals.fs.directory(Cache.flutterRoot),
81 82 83
      engineVersion: globals.artifacts.isLocalEngine
        ? null
        : globals.flutterVersion.engineRevision,
84 85 86 87 88
      defines: <String, String>{
        kTargetFile: mainDartFile ?? globals.fs.path.join('lib', 'main.dart'),
        kBuildMode: getNameForBuildMode(buildInfo.mode),
        kTargetPlatform: getNameForTargetPlatform(platform),
        kIconTreeShakerFlag: buildInfo.treeShakeIcons.toString(),
89
        kDartDefines: buildInfo.dartDefines.join(','),
90 91 92 93 94 95 96
        kBitcodeFlag: bitcode.toString(),
        if (buildInfo?.extraGenSnapshotOptions?.isNotEmpty ?? false)
          kExtraGenSnapshotOptions: buildInfo.extraGenSnapshotOptions.join(','),
        if (buildInfo?.extraFrontEndOptions?.isNotEmpty ?? false)
          kExtraFrontEndOptions: buildInfo.extraFrontEndOptions.join(','),
        if (platform == TargetPlatform.ios)
          kIosArchs: iosBuildArchs.map(getNameForDarwinArch).join(' ')
97 98 99 100 101
      },
      artifacts: globals.artifacts,
      fileSystem: globals.fs,
      logger: globals.logger,
      processManager: globals.processManager,
102
    );
103
    final BuildResult result = await globals.buildSystem.build(target, environment);
104
    status?.stop();
105

106 107 108
    if (!result.success) {
      for (final ExceptionMeasurement measurement in result.exceptions.values) {
        globals.printError(measurement.exception.toString());
109
      }
110
      throwToolExit('The aot build failed.');
111 112
    }

113 114 115 116 117 118
    // This print output is used by the dart team for build benchmarks.
    if (reportTimings) {
      final PerformanceMeasurement kernel = result.performance['kernel_snapshot'];
      PerformanceMeasurement aot;
      if (expectSo) {
        aot = result.performance.values.firstWhere(
119
          (PerformanceMeasurement measurement) => measurement.analyticsName == 'android_aot');
120 121
      } else {
        aot = result.performance.values.firstWhere(
122
          (PerformanceMeasurement measurement) => measurement.analyticsName == 'ios_aot');
123 124 125 126 127
      }
      globals.printStatus('frontend(CompileTime): ${kernel.elapsedMilliseconds} ms.');
      globals.printStatus('snapshot(CompileTime): ${aot.elapsedMilliseconds} ms.');
    }

128 129 130 131 132 133 134 135
    if (expectSo) {
      environment.buildDir.childFile('app.so')
        .copySync(globals.fs.path.join(outputPath, 'app.so'));
    } else {
      globals.fs.directory(globals.fs.path.join(outputPath, 'App.framework'))
        .createSync(recursive: true);
      environment.buildDir.childDirectory('App.framework').childFile('App')
        .copySync(globals.fs.path.join(outputPath, 'App.framework', 'App'));
136 137 138 139 140 141 142 143 144
    }

    final String builtMessage = 'Built to $outputPath${globals.fs.path.separator}.';
    if (quiet) {
      globals.printTrace(builtMessage);
    } else {
      globals.printStatus(builtMessage);
    }
    return;
xster's avatar
xster committed
145 146
  }
}