AspectD 构建流程

13 篇文章 0 订阅

项目构建流程

下面分析一下aspectd是的执行过程是怎样的,我们先看一下aspectd给flutter tools打的git patch上的代码。

主要改了两个类。

一个新添加的aspectd.dart,另一个common.dart是系统原有的类。

我们先看common.dart

可以看到对KernelSnapShot类的build方法做了一些修改。

也就是修改了原来生成dill的流程。

把原来的编译流程抽取出来到buildImpl()方法中。增加了如下判断。

  await buildImpl(environment);
    if (await AspectdHook.isAspectdEnabled()) {
      await AspectdHook().runBuildDillCommand(environment);
    }

这里就是上面所说的,如果不是aspectd的项目,就走普通的构建流程。

static Future<bool> isAspectdEnabled() async {
    final Directory currentDirectory = globals.fs.currentDirectory;
    final Directory aspectdDirectory =
        getAspectdImplDirectory(currentDirectory);
    if (!aspectdDirectory.existsSync()) {
      return false;
    }
    final String aspectdImplPackagesPath = globals.fs.path
        .join(aspectdDirectory.absolute.path, globalPackagesPath);
    final Directory flutterFrontendServerDirectory =
        await getFlutterFrontendServerDirectory(aspectdImplPackagesPath);
    if (!(aspectdDirectory.existsSync() &&
        flutterFrontendServerDirectory.existsSync() &&
        currentDirectory.absolute.path != aspectdDirectory.absolute.path &&
        globals.fs
            .file(globals.fs.path.join(aspectdDirectory.path, 'pubspec.yaml'))
            .existsSync() &&
        globals.fs
            .file(
                globals.fs.path.join(aspectdDirectory.path, globalPackagesPath))
            .existsSync() &&
        globals.fs
            .file(globals.fs.path.join(
                aspectdDirectory.path, 'lib', aspectdImplPackageName + '.dart'))
            .existsSync())) {
      return false;
    }
    return await checkAspectdFlutterFrontendServerSnapshot(
        aspectdImplPackagesPath);
  }

可以看到这里只要有一个条件不满足就会return false:

1.aspectdDirectory是否存在

2.flutterFrontendServerDirectory是否存在

3.当前目录是否包含pubspec,aspectd_impl.dart

等等

然后check aspectd hook过的FrontendServerSnapshot文件是否存在。

如果不存在,则去调用命令行process去生成一个snapshot对象。

 

  static Future<bool> checkAspectdFlutterFrontendServerSnapshot(
      String packagesPath) async {
    final Directory flutterFrontendServerDirectory =
        await getFlutterFrontendServerDirectory(packagesPath);
    final String aspectdFlutterFrontendServerSnapshot = globals.fs.path.join(
        flutterFrontendServerDirectory.absolute.path,
        frontendServerDartSnapshot);
    final String defaultFlutterFrontendServerSnapshot = globals.artifacts
        .getArtifactPath(Artifact.frontendServerSnapshotForEngineDartSdk);
    if (!globals.fs.file(aspectdFlutterFrontendServerSnapshot).existsSync()) {
      final String dartSdkDir = await getDartSdkDependency(
          (await getPackagePathFromConfig(packagesPath, 'aspectd'))
              .absolute
              .path);

      final String frontendServerPackageConfigJsonFile =
          '${flutterFrontendServerDirectory.absolute.path}/package_config.json';
      final String rebasedFrontendServerPackageConfigJsonFile =
          '${flutterFrontendServerDirectory.absolute.path}/rebased_package_config.json';
      String frontendServerPackageConfigJson = globals.fs
          .file(frontendServerPackageConfigJsonFile)
          .readAsStringSync();
      frontendServerPackageConfigJson = frontendServerPackageConfigJson
          .replaceAll('../../../third_party/dart/', dartSdkDir);
      globals.fs
          .file(rebasedFrontendServerPackageConfigJsonFile)
          .writeAsStringSync(frontendServerPackageConfigJson);

      final List<String> commands = <String>[
        globals.artifacts.getArtifactPath(Artifact.engineDartBinary),
        '--deterministic',
        '--packages=$rebasedFrontendServerPackageConfigJsonFile',
        '--snapshot=$aspectdFlutterFrontendServerSnapshot',
        '--snapshot-kind=kernel',
        '${flutterFrontendServerDirectory.absolute.path}/starter.dart'
      ];
      final ProcessResult processResult =
          await globals.processManager.run(commands);
      globals.fs.file(rebasedFrontendServerPackageConfigJsonFile).deleteSync();
      if (processResult.exitCode != 0 ||
          globals.fs.file(aspectdFlutterFrontendServerSnapshot).existsSync() ==
              false) {
        throwToolExit(
            'Aspectd unexpected error: ${processResult.stderr.toString()}');
      }
    }
    if (globals.fs.file(defaultFlutterFrontendServerSnapshot).existsSync()) {
      globals.fs.file(defaultFlutterFrontendServerSnapshot).deleteSync();
    }
    globals.fs
        .file(aspectdFlutterFrontendServerSnapshot)
        .copySync(defaultFlutterFrontendServerSnapshot);
    return true;
  }

最后删除sdk默认目录下的frontendServerSnapshot

回到common.dart中,如果AspectdHook.isAspectdEnabled()是true,

就去走runBuildDillCommand();

Future<void> runBuildDillCommand(Environment environment) async {
    final Directory aspectdDir =
        getAspectdImplDirectory(globals.fs.currentDirectory);
    final Directory previousDirectory = globals.fs.currentDirectory;
    globals.fs.currentDirectory = aspectdDir;

    String relativeDir = environment.outputDir.absolute.path
        .substring(environment.projectDir.absolute.path.length + 1);
    final String outputDir = globals.fs.path.join(aspectdDir.path, relativeDir);

    final String buildDir =
        globals.fs.path.join(aspectdDir.path, '.dart_tool', 'flutter_build');

    final Map<String, String> defines = environment.defines;
    defines[kTargetFile] = globals.fs.path
        .join(aspectdDir.path, 'lib', aspectdImplPackageName + '.dart');

    final Environment auxEnvironment = Environment(
        projectDir: aspectdDir,
        outputDir: globals.fs.directory(outputDir),
        cacheDir: environment.cacheDir,
        flutterRootDir: environment.flutterRootDir,
        fileSystem: environment.fileSystem,
        logger: environment.logger,
        artifacts: environment.artifacts,
        processManager: environment.processManager,
        engineVersion: environment.engineVersion,
        buildDir: globals.fs.directory(buildDir),
        defines: defines,
        inputs: environment.inputs);
    const KernelSnapshot auxKernelSnapshot = KernelSnapshot();
    final CompilerOutput compilerOutput =
        await auxKernelSnapshot.buildImpl(auxEnvironment);

    final String aspectdDill = compilerOutput.outputFilename;
    final File originalDillFile = globals.fs.file(
        globals.fs.path.join(environment.buildDir.absolute.path, 'app.dill'));
    if (originalDillFile.existsSync()) {
      originalDillFile.renameSync(originalDillFile.absolute.path + '.bak');
    }
    globals.fs.file(aspectdDill).copySync(originalDillFile.absolute.path);
    globals.fs.currentDirectory = previousDirectory;
  }

1.把路径切换到aspectd_impl所在的目录,并保存之前的目录

2.在aspectd_impl的.dart_tool/flutter_build目录下生成

然后把生成的app.dill从aspectd_impl目录拷贝到example工程目录。如果原来生成的app.dill已经存在,会先把原来的app.dill重命名为app.dill.bak

最后再切换回最开始的目录。

所以最后参与打包生成的app.dill是由aspectd_impl下构建好拷贝过来的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值