Flutter 前端编译器编译流程分析

521 阅读6分钟

1. 前端编译器和后端编译器的区别

编译流程粗略分为词法分析、语法分析、类型检查、中间代码生成、代码优化、目标代码生成、目标代码优化。中间代码生成及之前阶段都属于前端编译器的工作,前端和后端相互独立。

2. Flutter 前端编译器(flutter_frontend_server) 源码

github.com/flutter/eng… 入口方法:/bin/starter.dart main函数

3. Flutter 前端编译参数

dart --disable-dart-dev
flutter/bin/cache/artifacts/engine/darwin-x64/frontend_server.dart.snapshot
--sdk-root flutter/bin/cache/artifacts/engine/common/flutter_patched_sdk/
--target=flutter -Ddart.developer.causal_async_stacks=true
-Ddart.vm.profile=false
-Ddart.vm.product=false
--bytecode-options=source-positions,...
--enable-asserts
--track-widget-creation
--no-link-platform 
--packages example/.packages
--output-dill example/.dart_tool/flutter_build/046a7caff7f8f88ac9d8ca5634391d78/app.dill
--depfile example/.dart_tool/flutter_build/046a7caff7f8f88ac9d8ca5634391d78/kernel_snapshot.d
package:example/main.dart

4. 源码分析

starter.dart

void main(List<String> args) async {
  调用/lib/server.dart文件中的starter方法开始执行前端编译,如果返回码不为0,退出Dart虚拟机,抛出编译错误  
  final int exitCode = await starter(args);
  if (exitCode != 0) {
    exit(exitCode);
  }
}

server.dart

Future<int> starter(
  List<String> args, {
  frontend.CompilerInterface compiler,
  Stream<List<int>> input,
  StringSink output,
  frontend.ProgramTransformer transformer,
}) async {
  //解析编译参数,解析流程参考: 《ArgParser源码分析》
  ArgResults options = frontend.argParser.parse(args);
  //创建_FlutterFrontendCompiler对象,用于对Dart代码进行编译
  compiler ??= _FlutterFrontendCompiler(...);
  //rest[0] = 'example/main.dart',即项目的入口文件
  if (options.rest.isNotEmpty) {
    //调用_FlutterFrontendCompiler对象的compile方法
    return await compiler.compile(options.rest[0], options) ? 0 : 254;
  }
}

//_FlutterFrontendCompiler类结构(_FlutterFrontendCompiler只是_FrontendCompiler的代理)
//其中_FrontendCompiler位于:frontend_server包下的frontend_server.dart文件
class _FlutterFrontendCompiler implements frontend.CompilerInterface {
    
  final frontend.CompilerInterface _compiler;

  //_FlutterFrontendCompile构造方法创建了一个FrontendCompiler对象
  _FlutterFrontendCompiler(): _compiler = frontend.FrontendCompiler(...);

  //将CompilerInterface接口中的方法都转发给 _compiler对象处理
  @override
  Future<bool> compile(String filename, ArgResults options,{IncrementalCompiler generator}) async {
    return _compiler.compile(filename, options, generator: generator);
  }
  
  ... 
}

frontend_server.dart#FrontendCompiler

class FrontendCompiler implements CompilerInterface {
    
    @override
    Future<bool> compile(String entryPoint,ArgResults options,
     {IncrementalCompiler generator}) async {
      //从ArgResults中读取参数
      _options = options;
      ...
      //获取sdk-root目录
      final Uri sdkRoot = _ensureFolderPath(options['sdk-root']);
      //平台特性dill文件,里面包含了预编译的framework dart代码,包括类似core、service等库
      final String platformKernelDill = options['platform'] ?? 'platform_strong.dill';
      //获取.package文件的路径,用来索引三方package位置
      final String packagesOption = _options['packages'];
      ...
      //将上面获取到的参数,拼装成一个CompileOptions对象
      final CompilerOptions compilerOptions = CompilerOptions()
        ..sdkRoot = sdkRoot
        ..fileSystem = _fileSystem
        ..packagesFileUri =
            packagesOption != null ? resolveInputUri(packagesOption) : null
          //将平台特性dill文件uri赋值给sdkSummary对象,dart编译器会优化处理, 后面会说明
        ..sdkSummary = sdkRoot.resolve(platformKernelDill)
        ..verbose = options['verbose']
        ..embedSourceText = options['embed-source-text']
        ..experimentalFlags = parseExperimentalFlags(
            parseExperimentalArguments(options['enable-experiment']),
            onError: (msg) => errors.add(msg))
        ..nnbdMode = (nullSafety == true) ? NnbdMode.Strong : NnbdMode.Weak
        ..onDiagnostic = _onDiagnostic;
        
      ...
      //处理增量编译
      if (options['incremental']) {
        ...
      } else {
        ...
        //调用compileToKernel将dart代码进行编译,生成Dart AST 语法树,
        //并保存在Component对象中,下一节着重分析
        results = await _runWithPrintRedirection(() => compileToKernel(
            _mainSource, compilerOptions,
            includePlatform: options['link-platform'],
            aot: options['aot'],
            useGlobalTypeFlowAnalysis: options['tfa'],
            environmentDefines: environmentDefines,
            enableAsserts: options['enable-asserts'],
            useProtobufTreeShaker: options['protobuf-tree-shaker'],
            useProtobufTreeShakerV2: options['protobuf-tree-shaker-v2'],
            minimalKernel: options['minimal-kernel'],
            treeShakeWriteOnlyFields: options['tree-shake-write-only-fields'],
            fromDillFile: options['from-dill']));
      }
      if (results.component != null) {
        //将生成的Component对象保存在app.dill文件中
        await writeDillFile(results, _kernelBinaryFilename,
            filterExternal: importDill != null || options['minimal-kernel'],
            incrementalSerializer: incrementalSerializer);
        ...
        //统计此次编译有哪些文件
        final String depfile = options['depfile'];
        if (depfile != null) {
          await writeDepfile(compilerOptions.fileSystem, results.compiledSources,
              _kernelBinaryFilename, depfile);
        }
        _kernelBinaryFilename = _kernelBinaryFilenameIncremental;
      } else {
        _outputStream.writeln(boundaryKey);
      }
      results = null; // Fix leak: Probably variation of http://dartbug.com/36983.
      return errors.isEmpty;
    }
} 

compileToKernel

Future<KernelCompilationResults> compileToKernel(
     Uri source, CompilerOptions options,
     {bool includePlatform: false,
     bool aot: false,
     bool useGlobalTypeFlowAnalysis: false,
     Map<String, String> environmentDefines,
     bool enableAsserts: true,
     bool genBytecode: false,
     BytecodeOptions bytecodeOptions,
    bool dropAST: false,
    bool useProtobufTreeShaker: false,
    bool useProtobufTreeShakerV2: false,
    bool minimalKernel: false,
    bool treeShakeWriteOnlyFields: false,
    String fromDillFile: null}) async {
    ...
      CompilerResult compilerResult;
      if (fromDillFile != null) {
        //如果提供了初始化文件,直接读取
        //首次编译不走此方法,不分析
        compilerResult =
            await loadKernel(options.fileSystem, resolveInputUri(fromDillFile));
      } else {
        //调用kernelForProgram编译Dart代码,生成Component对象,下一节着重分析 
        compilerResult = await kernelForProgram(source, options);
      }
      ...
      if ((aot || minimalKernel) && component != null) {
        // 对生成的Component对象,执行Transform处理,类似AGP中的Transform 
        await runGlobalTransformations(
            options.target,
            component,
            useGlobalTypeFlowAnalysis,
            enableAsserts,
            useProtobufTreeShaker,
            useProtobufTreeShakerV2,
            errorDetector,
            minimalKernel: minimalKernel,
            treeShakeWriteOnlyFields: treeShakeWriteOnlyFields);
            ...
      }
     if (genBytecode && !errorDetector.hasCompilationErrors && component != null) {
          ...
         await runWithFrontEndCompilerContext(source, options, component, () {
                  //根据Component中的AST信息,生成字节码数据,见此代码区域的下一个方法
                  generateBytecode(component,
                                  libraries: libraries,
                                  hierarchy: compilerResult.classHierarchy,
                                  coreTypes: compilerResult.coreTypes,
                                  options: bytecodeOptions);
                                });
          }
      }
      //返回结果
      return new KernelCompilationResults(
          component,
          loadedLibraries,
          compilerResult?.classHierarchy,
          compilerResult?.coreTypes,
          compiledSources);
}

void generateBytecode(ast.Component component, {
      BytecodeOptions options,
      List<Library> libraries,
      CoreTypes coreTypes,
      ClassHierarchy hierarchy,
}) {
    ...
    //创建BytecodeGenerator对象,处理每一个Library数据(Library: 可以理解为每个dart文件对应一个library对象)
   final bytecodeGenerator = new BytecodeGenerator(
          component, coreTypes, hierarchy, typeEnvironment, options);
      for (library in libraries) {
        bytecodeGenerator.visitLibrary(library);
      }
  });
}

BytecodeGenerator

class BytecodeGenerator extends RecursiveVisitor<Null> {
    
    //开始访问文件
    @override
    visitLibrary(Library node) {
       ...
       //处理文件中的每个方法
       visitList(node.procedures, this);
       //处理文件中的每个字段
      visitList(node.fields, this);
      ...
    }
    
    @override
    visitClass(Class node) {
      //处理每个类中构造方法
      visitList(node.constructors, this);
      //处理每个类中的方法
      visitList(node.procedures, this);
      //处理每个类中的字段
      visitList(node.fields, this);
      ...
     }
    
    @override
    defaultMember(Member node) {
        ...
        //asm代表BytecodeAssembler,将对应的Opcode值放入的asm类中的buffer中
        asm.emitPushNull();
        //把asm.buff数据放入到Component中
        end(node, hasCode);
    }
}

KernelForProgram

Future<CompilerResult> kernelForProgram(
    Uri source, CompilerOptions options) async {
  return (await kernelForProgramInternal(source, options));
}

Future<CompilerResult> kernelForProgramInternal(
    Uri source, CompilerOptions options,
    {bool retainDataForTesting: false, bool requireMain: true}) async {
  ProcessedOptions pOptions =
      new ProcessedOptions(options: options, inputs: [source]);
  return await CompilerContext.runWithOptions(pOptions, (context) async {
    //调用 generateKernelInternal方法生成Component对象,下一节分析
    CompilerResult result = await generateKernelInternal(
        includeHierarchyAndCoreTypes: true,
        retainDataForTesting: retainDataForTesting);
    Component component = result?.component;
    if (component == null) return null;

    if (requireMain && component.mainMethod == null) {
      context.options.report(
          messageMissingMain.withLocation(source, -1, noLength),
          Severity.error);
      return null;
    }
    return result;
  });
}

generateKernelInternal

Future<CompilerResult> generateKernelInternal(
    {bool buildSummary: false,
    bool buildComponent: true,
    bool truncateSummary: false,
    bool includeOffsets: true,
    bool retainDataForTesting: false,
    bool includeHierarchyAndCoreTypes: false}) async {
  return withCrashReporting<CompilerResult>(() async {
      //获取UriTranslator对象(UriTranslator包含MapPackages对象),主要用于处理包目录。 
    UriTranslator uriTranslator = await options.getUriTranslator();
    //创建DillTarget对象,用来处理平台特定Dill文件
    DillTarget dillTarget =
        new DillTarget(options.ticker, uriTranslator, options.target);
    //对平台特定文件:platform_strong.dill文件进行解析,生成Component对象:sdkSummary
    Component sdkSummary = await options.loadSdkSummary(null);
    //剔除sdkSummary中external库,并将剩余Library加入到dillTarget.loader中
    CanonicalName nameRoot = sdkSummary?.root ?? new CanonicalName.root();
    if (sdkSummary != null) {
      Set<Uri> excluded = externalLibs(sdkSummary);
      //appendLibraries,见下一节
      dillTarget.loader.appendLibraries(sdkSummary,
          filter: (uri) => !excluded.contains(uri));
    }
    //标记dillTarget及Loader.libraries状态,见下一节
    await dillTarget.buildOutlines();
    //创建KernelTarget,用来解析dart源代码
    KernelTarget kernelTarget =
        new KernelTarget(fs, false, dillTarget, uriTranslator);
    sourceLoader = kernelTarget.loader;
    //设置源代码入口文件,如package:example/main.dart,见下一节
    kernelTarget.setEntryPoints(options.inputs);
    //对源码生成Component对象,构建AST大体结构,见下一节
    Component summaryComponent =
        await kernelTarget.buildOutlines(nameRoot: nameRoot);
    Component component;
    if (buildComponent) {
      //处理AST细节,比如MethodBody之类的 ,见下一节
      component = await kernelTarget.buildComponent(verify: options.verify);
      if (options.debugDump) {
        printComponentText(component,
            libraryFilter: kernelTarget.isSourceLibrary);
      }
      options.ticker.logMs("Generated component");
    }
    //将Component对象包装在CompilerResult中,并返回
    return new InternalCompilerResult(
        summary: summary,
        component: component,
        classHierarchy:
            includeHierarchyAndCoreTypes ? kernelTarget.loader.hierarchy : null,
        coreTypes:
            includeHierarchyAndCoreTypes ? kernelTarget.loader.coreTypes : null,
        deps: new List<Uri>.from(CompilerContext.current.dependencies),
        kernelTargetForTesting: retainDataForTesting ? kernelTarget : null);
  }, () => sourceLoader?.currentUriForCrashReporting ?? options.inputs.first);
}

此方法重点方法:

  • DillTarget.loader.appendLibraries()
  • DillTarget.buildOutlines()
  • KernelTarget.setEntryPoints()
  • KernelTarget.buildOutlines()
  • KernelTarget.buildComponent()

DillTarget.loader.appendLibraries()

List<DillLibraryBuilder> appendLibraries(Component component,
    {bool filter(Uri uri), int byteCount: 0}) {
  List<Library> componentLibraries = component.libraries;
  List<Uri> requestedLibraries = <Uri>[];
  DillTarget target = this.target;
  for (int i = 0; i < componentLibraries.length; i++) {
    Library library = componentLibraries[i];
    Uri uri = library.importUri;
    //找到非external类型的library
    if (filter == null || filter(library.importUri)) {
      //将library存入到全局变量libraries中  
      libraries.add(library);
      //将library以 library.importUri: DillLibraryBuild(library) 的形式
      //存入到DillTarget.libraryBuilders的Map类型变量中
      target.addLibrary(library);
      //存在临时变量
      requestedLibraries.add(uri);
    }
  }
  List<DillLibraryBuilder> result = <DillLibraryBuilder>[];
  for (int i = 0; i < requestedLibraries.length; i++) {
    //将DillTarget.libraryBuilders的数据,转存到
    //Loader.builders和Loader.unParsedLibraries中
    //Loader.builder: <Uri,LibraryBuilder>
    //Loader.unParsedLibraries: List<LibraryBuilder>
    result.add(read(requestedLibraries[i], -1));
  }
  target.uriToSource.addAll(component.uriToSource);
  this.byteCount += byteCount;
  return result;
}

DillTarget.buildOutlines()

@override
Future<Null> buildOutlines() async {
  if (loader.libraries.isNotEmpty) {
    //标记Loader数据状态,如下  
    await loader.buildOutlines();
    loader.finalizeExports();
  }
  //标记DillTarget状态
  isLoaded = true;
}

=========== DillLoader==============
Future<Null> buildOutlines() async {
  ensureCoreLibrary();
  while (unparsedLibraries.isNotEmpty) {
    LibraryBuilder library = unparsedLibraries.removeFirst();
    await buildOutline(library);
  }
}

Future<Null> buildOutline(DillLibraryBuilder builder) async {
  if (builder.library == null) {
    unhandled("null", "builder.library", 0, builder.fileUri);
  }
  builder.markAsReadyToBuild();
}
=========== DillLibraryBuilder ==============
void markAsReadyToBuild() {
  isReadyToBuild = true;
}

KernelTarget.setEntryPoints()

List<Uri> setEntryPoints(List<Uri> entryPoints) {
    ...
    //读取入口文件,根据entryPoint创建SourceLibraryBuilder对象
    //并存在到loader.builders和loader.unParsedLibraries中
    loader.read(entryPoint, -1, accessor: loader.first, fileUri: fileUri);
  }
  return result;
}

KernelTarget.buildOutlines()

@override
Future<Component> buildOutlines({CanonicalName nameRoot}) async {
  if (loader.first == null) return null;
  return withCrashReporting<Component>(() async {
    loader.createTypeInferenceEngine();
    //读取unParsedLibraries数据,构建AST大纲
    await loader.buildOutlines();
    //完善Library子节点相关数据
    loader.coreLibrary.becomeCoreLibrary();
    dynamicType.bind(
        loader.coreLibrary.lookupLocalMember("dynamic", required: true));
    loader.resolveParts();
    loader.computeLibraryScopes();
    setupTopAndBottomTypes();
    loader.resolveTypes();
    loader.computeVariances();
    loader.computeDefaultTypes(dynamicType, bottomType, objectClassBuilder);
    List<SourceClassBuilder> myClasses =
        loader.checkSemantics(objectClassBuilder);
    loader.finishTypeVariables(objectClassBuilder, dynamicType);
    loader.buildComponent();
    installDefaultSupertypes();
    installSyntheticConstructors(myClasses);
    loader.resolveConstructors();
    //创建Component对象
    component =
        link(new List<Library>.from(loader.libraries), nameRoot: nameRoot);
    computeCoreTypes();
    loader.buildClassHierarchy(myClasses, objectClassBuilder);
    loader.computeHierarchy();
    loader.performTopLevelInference(myClasses);
    loader.checkSupertypes(myClasses);
    loader.checkBounds();
    loader.checkOverrides(myClasses);
    loader.checkAbstractMembers(myClasses);
    loader.checkRedirectingFactories(myClasses);
    loader.addNoSuchMethodForwarders(myClasses);
    loader.checkMixins(myClasses);
    loader.buildOutlineExpressions();
    installAllComponentProblems(loader.allComponentProblems);
    loader.allComponentProblems.clear();
    return component;
  }, () => loader?.currentUriForCrashReporting);
}

####KernelTarget.buildComponent()

@override
Future<Component> buildComponent({bool verify: false}) async {
  if (loader.first == null) return null;
  return withCrashReporting<Component>(() async {
    //构建AST细节。先构建大纲,然后在构建细节,主要是为了降低内存的使用
    await loader.buildBodies();
    finishClonedParameters();
    loader.finishDeferredLoadTearoffs();
    loader.finishNoSuchMethodForwarders();
    List<SourceClassBuilder> myClasses = collectMyClasses();
    loader.finishNativeMethods();
    loader.finishPatchMethods();
    finishAllConstructors(myClasses);
    //对Component执行转化,比如 trackWidgetCreation Transformer
    runBuildTransformations();

    if (verify) this.verify();
    installAllComponentProblems(loader.allComponentProblems);
    return component;
  }, () => loader?.currentUriForCrashReporting);
}