美文网首页
Flutter engine runtime mode 研究

Flutter engine runtime mode 研究

作者: 三三At你 | 来源:发表于2019-10-30 20:02 被阅读0次

    本文主要对比Flutter编辑engine中两种runtime mode(debug release)的区别
    首先使用gn构建两种模式的engine

    ./flutter/tools/gn --runtime-mode=debug --ios --ios-cpu=arm64
    ./flutter/tools/gn --runtime-mode=release --ios --ios-cpu=arm64
    

    两个命令背后的真实动作

    //debug
    gn gen --check --ide=xcode out/ios_debug_arm --args=skia_enable_pdf=false enable_lto=true full_dart_sdk=false use_clang_static_analyzer=false flutter_enable_skshaper=false skia_use_expat=false enable_bitcode=false skia_use_fontconfig=false skia_use_dng_sdk=false skia_enable_flutter_defines=true use_goma=false dart_custom_version_for_pub="flutter" embedder_for_target=false is_official_build=true android_full_debug=false is_clang=true skia_use_sfntly=false dart_target_arch="arm" skia_gl_standard="gles" skia_use_wuffs=true flutter_use_fontconfig=false dart_component_kind="static_library" flutter_runtime_mode="debug" goma_dir="None" target_os="ios" skia_use_x11=false enable_coverage=false target_cpu="arm" dart_runtime_mode="develop" dart_lib_export_symbols=false is_debug=false use_ios_simulator=false
    
    ninja -C out/ios_debug_arm -t compdb cc cxx objc objcxx asm 
    
    //release
    gn gen --check --ide=xcode out/ios_release_arm --args=skia_enable_pdf=false enable_lto=true full_dart_sdk=false use_clang_static_analyzer=false flutter_enable_skshaper=false skia_use_expat=false enable_bitcode=false skia_use_fontconfig=false skia_use_dng_sdk=false skia_enable_flutter_defines=true use_goma=false dart_custom_version_for_pub="flutter" embedder_for_target=false is_official_build=true android_full_debug=false is_clang=true skia_use_sfntly=false dart_target_arch="arm" skia_gl_standard="gles" skia_use_wuffs=true flutter_use_fontconfig=false dart_component_kind="static_library" flutter_runtime_mode="release" goma_dir="None" target_os="ios" skia_use_x11=false enable_coverage=false target_cpu="arm" dart_runtime_mode="release" dart_lib_export_symbols=false is_debug=false use_ios_simulator=false 
    
    ninja -C out/ios_release_arm -t compdb cc cxx objc objcxx asm
    

    可以看出两条命令的不同之处在于
    //release
    flutter_runtime_mode="release"
    dart_runtime_mode="release"
    //debug
    flutter_runtime_mode="debug"
    dart_runtime_mode="develop"

    接下来分析compile_commands.json
    忽略掉ios_debug ios_release
    忽略掉-DFLUTTER_RUNTIME_MODE=1 -DFLUTTER_RUNTIME_MODE=3
    忽略掉-DPRODUCT

    剩下的不同之处
    debug编译test_font.test_font_data.o.d 时多了个-DEMBED_TEST_FONT_DATA=1
    release独有

    {
        "directory": "/Users/kila/Desktop/Workspace/engine/src/out/ios_release",
        "command": "../../buildtools/mac-x64/clang/bin/clang++ -MD -MF obj/third_party/dart/runtime/bin/dart.observatory_assets_empty.o.d -DNO_TCMALLOC -DMEMORY_TOOL_REPLACES_ALLOCATOR -DMEMORY_SANITIZER_INITIAL_SIZE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D_FORTIFY_SOURCE=2 -D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS -D_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS -DNDEBUG -DNVALGRIND -DDYNAMIC_ANNOTATIONS_ENABLED=0 -DTARGET_ARCH_ARM64 -DNDEBUG -DTARGET_OS_MACOS -DTARGET_OS_MACOS_IOS -DPRODUCT -I../../third_party/dart/runtime -I../../third_party -I../.. -Igen -I../../third_party/dart/runtime/include -I../../third_party/dart/runtime -I../../third_party/dart/runtime/include -I../../third_party/boringssl/src/include -I../../third_party/zlib -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS13.1.sdk -miphoneos-version-min=8.0 -flto -fno-strict-aliasing -arch arm64 -fcolor-diagnostics -Wall -Wextra -Wendif-labels -Werror -Wno-missing-field-initializers -Wno-unused-parameter -Wunguarded-availability -fvisibility=hidden -stdlib=libc++ -Wheader-hygiene -Wstring-conversion -Wthread-safety -Os -fno-ident -fdata-sections -ffunction-sections -g2 -Werror -Wall -Wextra -Wno-unused-parameter -Wno-unused-private-field -Wnon-virtual-dtor -Wvla -Wno-conversion-null -Woverloaded-virtual -Wno-comments -g3 -ggdb3 -fno-rtti -fno-exceptions -Wimplicit-fallthrough -O3 -fvisibility-inlines-hidden -std=c++17 -fno-rtti -fno-exceptions  -c ../../third_party/dart/runtime/bin/observatory_assets_empty.cc -o obj/third_party/dart/runtime/bin/dart.observatory_assets_empty.o",
        "file": "../../third_party/dart/runtime/bin/observatory_assets_empty.cc"
    },
    {
        "directory": "/Users/kila/Desktop/Workspace/engine/src/out/ios_release",
        "command": "../../buildtools/mac-x64/clang/bin/clang++ -MD -MF obj/third_party/dart/runtime/bin/dart_precompiled_runtime.observatory_assets_empty.o.d -DNO_TCMALLOC -DMEMORY_TOOL_REPLACES_ALLOCATOR -DMEMORY_SANITIZER_INITIAL_SIZE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D_FORTIFY_SOURCE=2 -D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS -D_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS -DNDEBUG -DNVALGRIND -DDYNAMIC_ANNOTATIONS_ENABLED=0 -DTARGET_ARCH_ARM64 -DNDEBUG -DTARGET_OS_MACOS -DTARGET_OS_MACOS_IOS -DPRODUCT -DDART_PRECOMPILED_RUNTIME -DEXCLUDE_CFE_AND_KERNEL_PLATFORM -I../../third_party/dart/runtime -I../../third_party -I../.. -Igen -I../../third_party/dart/runtime/include -I../../third_party/dart/runtime -I../../third_party/dart/runtime/include -I../../third_party/boringssl/src/include -I../../third_party/zlib -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS13.1.sdk -miphoneos-version-min=8.0 -flto -fno-strict-aliasing -arch arm64 -fcolor-diagnostics -Wall -Wextra -Wendif-labels -Werror -Wno-missing-field-initializers -Wno-unused-parameter -Wunguarded-availability -fvisibility=hidden -stdlib=libc++ -Wheader-hygiene -Wstring-conversion -Wthread-safety -Os -fno-ident -fdata-sections -ffunction-sections -g2 -Werror -Wall -Wextra -Wno-unused-parameter -Wno-unused-private-field -Wnon-virtual-dtor -Wvla -Wno-conversion-null -Woverloaded-virtual -Wno-comments -g3 -ggdb3 -fno-rtti -fno-exceptions -Wimplicit-fallthrough -O3 -fvisibility-inlines-hidden -std=c++17 -fno-rtti -fno-exceptions  -c ../../third_party/dart/runtime/bin/observatory_assets_empty.cc -o obj/third_party/dart/runtime/bin/dart_precompiled_runtime.observatory_assets_empty.o",
        "file": "../../third_party/dart/runtime/bin/observatory_assets_empty.cc"
    },
    

    debug独有

    {
        "directory": "/Users/kila/Desktop/Workspace/engine/src/out/ios_debug",
        "command": "../../buildtools/mac-x64/clang/bin/clang++ -MD -MF obj/out/ios_debug/gen/third_party/dart/runtime/observatory/embedded_observatory_archive.embedded_archive_observatory.o.d -DNO_TCMALLOC -DMEMORY_TOOL_REPLACES_ALLOCATOR -DMEMORY_SANITIZER_INITIAL_SIZE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D_FORTIFY_SOURCE=2 -D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS -D_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS -DNDEBUG -DNVALGRIND -DDYNAMIC_ANNOTATIONS_ENABLED=0 -I../.. -Igen -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS13.1.sdk -miphoneos-version-min=8.0 -flto -fno-strict-aliasing -arch arm64 -fcolor-diagnostics -Wall -Wextra -Wendif-labels -Werror -Wno-missing-field-initializers -Wno-unused-parameter -Wunguarded-availability -fvisibility=hidden -stdlib=libc++ -Wheader-hygiene -Wstring-conversion -Wthread-safety -Os -fno-ident -fdata-sections -ffunction-sections -g2 -fvisibility-inlines-hidden -std=c++17 -fno-rtti -fno-exceptions  -c gen/third_party/dart/runtime/observatory/embedded_archive_observatory.cc -o obj/out/ios_debug/gen/third_party/dart/runtime/observatory/embedded_observatory_archive.embedded_archive_observatory.o",
        "file": "gen/third_party/dart/runtime/observatory/embedded_archive_observatory.cc"
    },
    {
        "directory": "/Users/kila/Desktop/Workspace/engine/src/out/ios_debug",
        "command": "../../buildtools/mac-x64/clang/bin/clang++ -MD -MF obj/out/ios_debug/gen/third_party/dart/runtime/observatory/standalone_observatory_archive.standalone_archive_observatory.o.d -DNO_TCMALLOC -DMEMORY_TOOL_REPLACES_ALLOCATOR -DMEMORY_SANITIZER_INITIAL_SIZE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D_FORTIFY_SOURCE=2 -D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS -D_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS -DNDEBUG -DNVALGRIND -DDYNAMIC_ANNOTATIONS_ENABLED=0 -I../.. -Igen -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS13.1.sdk -miphoneos-version-min=8.0 -flto -fno-strict-aliasing -arch arm64 -fcolor-diagnostics -Wall -Wextra -Wendif-labels -Werror -Wno-missing-field-initializers -Wno-unused-parameter -Wunguarded-availability -fvisibility=hidden -stdlib=libc++ -Wheader-hygiene -Wstring-conversion -Wthread-safety -Os -fno-ident -fdata-sections -ffunction-sections -g2 -fvisibility-inlines-hidden -std=c++17 -fno-rtti -fno-exceptions  -c gen/third_party/dart/runtime/observatory/standalone_archive_observatory.cc -o obj/out/ios_debug/gen/third_party/dart/runtime/observatory/standalone_observatory_archive.standalone_archive_observatory.o",
        "file": "gen/third_party/dart/runtime/observatory/standalone_archive_observatory.cc"
    },
    

    dart_runtime_mode 涉及的模块

    third_party/dart/runtime/vm/BUILD.gn

    is_product_flag = dart_runtime_mode == "release"
    allow_causal_async_stacks = !is_product_flag
    args += [
          "-Ddart.vm.product=$is_product_flag",
          "-Ddart.developer.causal_async_stacks=$allow_causal_async_stacks",
          "-Ddart.isVM=true",
    ]
    

    third_party/dart/runtime/runtime_args.gni

      # TODO(rmacnak): dart_runtime_mode no longer selects whether libdart is build
      # for JIT or AOT, since libdart waw split into libdart_jit and
      # libdart_precompiled_runtime. We should remove this flag and just set
      # dart_debug/dart_product.
      dart_runtime_mode = "develop"
    

    third_party/dart/runtime/BUILD.gn

    # Adds PRODUCT define if Flutter has specified "release" for dart_runtime_mode
    config("dart_maybe_product_config") {
      defines = []
    
      if (dart_runtime_mode != "develop" && dart_runtime_mode != "profile" &&
          dart_runtime_mode != "release") {
        print("Invalid |dart_runtime_mode|")
        assert(false)
      }
    
      if (dart_runtime_mode == "release") {
        if (dart_debug) {
          print("Debug and release mode are mutually exclusive.")
        }
        assert(!dart_debug)
        defines += [ "PRODUCT" ]
      }
    }
    

    third_party/dart/runtime/bin/BUILD.gn

    dart_executable("dart") {
      extra_deps = [
        "..:libdart_jit",
        "../platform:libdart_platform_jit",
        ":dart_snapshot_cc",
      ]
      if (dart_runtime_mode != "release") {
        extra_deps += [ "../observatory:standalone_observatory_archive" ]
      }
      extra_sources = [
        "builtin.cc",
        "dfe.cc",
        "dfe.h",
        "gzip.cc",
        "gzip.h",
        "loader.cc",
        "loader.h",
        "main.cc",
      ]
      if (dart_runtime_mode == "release") {
        extra_sources += [ "observatory_assets_empty.cc" ]
      }
      if (!exclude_kernel_service) {
        extra_deps += [ ":dart_kernel_platform_cc" ]
      }
    }
    
    dart_executable("dart_precompiled_runtime") {
      extra_configs = [ "..:dart_precompiled_runtime_config" ]
      extra_deps = [
        "..:libdart_precompiled_runtime",
        "../platform:libdart_platform_precompiled_runtime",
      ]
      if (dart_runtime_mode != "release") {
        extra_deps += [ "../observatory:standalone_observatory_archive" ]
      }
      extra_sources = [
        "builtin.cc",
        "gzip.cc",
        "gzip.h",
        "loader.cc",
        "loader.h",
        "main.cc",
        "snapshot_empty.cc",
      ]
      if (dart_runtime_mode == "release") {
        extra_sources += [ "observatory_assets_empty.cc" ]
      }
    }
    
    

    flutter_runtime_mode涉及模块

    flutter/common/config.gni

    declare_args() {
      # The runtime mode ("debug", "profile", or "release")
      flutter_runtime_mode = "debug"
    
      # Whether to use the Skia text shaper module
      flutter_enable_skshaper = false
    
      # A copy of the enable_bitcode flag from build/toolchain/clang.gni.
      # This needs to be mirrored here because build/toolchain/clang.gni does
      # not exist in the Fuchsia source tree.
      flutter_enable_bitcode = false
    }
    feature_defines_list = [
      "FLUTTER_RUNTIME_MODE_DEBUG=1",
      "FLUTTER_RUNTIME_MODE_PROFILE=2",
      "FLUTTER_RUNTIME_MODE_RELEASE=3",
    ]
    
    if (flutter_runtime_mode == "debug") {
      feature_defines_list += [ "FLUTTER_RUNTIME_MODE=1" ]
    } else if (flutter_runtime_mode == "profile") {
      feature_defines_list += [ "FLUTTER_RUNTIME_MODE=2" ]
    } else if (flutter_runtime_mode == "release") {
      feature_defines_list += [ "FLUTTER_RUNTIME_MODE=3" ]
    } else {
      feature_defines_list += [ "FLUTTER_RUNTIME_MODE=0" ]
    }
    

    flutter/flow/raster_cache.cc

    void RasterCache::TraceStatsToTimeline() const {
    #if FLUTTER_RUNTIME_MODE != FLUTTER_RUNTIME_MODE_RELEASE
    
      size_t layer_cache_count = 0;
      size_t layer_cache_bytes = 0;
      size_t picture_cache_count = 0;
      size_t picture_cache_bytes = 0;
    
      for (const auto& item : layer_cache_) {
        const auto dimensions = item.second.image.image_dimensions();
        layer_cache_count++;
        layer_cache_bytes += dimensions.width() * dimensions.height() * 4;
      }
    
      for (const auto& item : picture_cache_) {
        const auto dimensions = item.second.image.image_dimensions();
        picture_cache_count++;
        picture_cache_bytes += dimensions.width() * dimensions.height() * 4;
      }
    
      FML_TRACE_COUNTER("flutter", "RasterCache",
                        reinterpret_cast<int64_t>(this),             //
                        "LayerCount", layer_cache_count,             //
                        "LayerMBytes", layer_cache_bytes * 1e-6,     //
                        "PictureCount", picture_cache_count,         //
                        "PictureMBytes", picture_cache_bytes * 1e-6  //
      );
    
    #endif  // FLUTTER_RUNTIME_MODE != FLUTTER_RUNTIME_MODE_RELEASE
    }
    

    flutter/lib/snapshot/BUILD.gn

    if (is_debug && flutter_runtime_mode != "profile" &&
          flutter_runtime_mode != "release") {
        args += [ "--enable_asserts" ]
      }
    

    flutter/runtime/BUILD.gn(需要改动)

    source_set("test_font") {
      sources = [
        "test_font_data.cc",
        "test_font_data.h",
      ]
      deps = [
        "//third_party/skia",
      ]
      public_configs = [ "$flutter_root:config" ]
      defines = []
      if (flutter_runtime_mode == "debug" || current_toolchain == host_toolchain) {
        # Though the test font data is small, we dont want to add to the binary size
        # on the device (in profile and release modes). We only add the same on the
        # host test shells and the debug device shell.
        defines += [ "EMBED_TEST_FONT_DATA=1" ]
      }
    }
    # Picks the libdart implementation based on the Flutter runtime mode.
    group("libdart") {
      public_deps = []
    
      if (!(is_fuchsia && using_fuchsia_sdk)) {
        if (flutter_runtime_mode == "profile" ||
            flutter_runtime_mode == "release") {
          public_deps +=
              [ "//third_party/dart/runtime:libdart_precompiled_runtime" ]
        } else {
          public_deps += [
            "$flutter_root/lib/snapshot",
            "//third_party/dart/runtime:libdart_jit",
          ]
        }
      }
    }
    

    flutter/runtime/dart_snapshot.cc

    #define DART_SNAPSHOT_STATIC_LINK \
      (OS_WIN || (OS_ANDROID && FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG))
    #if !DART_SNAPSHOT_STATIC_LINK
    
    static std::unique_ptr<const fml::Mapping> GetFileMapping(
        const std::string& path,
        bool executable) {
      if (executable) {
        return fml::FileMapping::CreateReadExecute(path);
      } else {
        return fml::FileMapping::CreateReadOnly(path);
      }
    }
    
    // The first party embedders don't yet use the stable embedder API and depend on
    // the engine figuring out the locations of the various heap and instructions
    // buffers. Consequently, the engine had baked in opinions about where these
    // buffers would reside and how they would be packaged (examples, in an external
    // dylib, in the same dylib, at a path, at a path relative to and FD, etc..). As
    // the needs of the platforms changed, the lack of an API meant that the engine
    // had to be patched to look for new fields in the settings object. This grew
    // untenable and with the addition of the new Fuchsia embedder and the generic C
    // embedder API, embedders could specify the mapping directly. Once everyone
    // moves to the embedder API, this method can effectively be reduced to just
    // invoking the embedder_mapping_callback directly.
    static std::shared_ptr<const fml::Mapping> SearchMapping(
        MappingCallback embedder_mapping_callback,
        const std::string& file_path,
        const std::vector<std::string>& native_library_path,
        const char* native_library_symbol_name,
        bool is_executable) {
      // Ask the embedder. There is no fallback as we expect the embedders (via
      // their embedding APIs) to just specify the mappings directly.
      if (embedder_mapping_callback) {
        return embedder_mapping_callback();
      }
    
      // Attempt to open file at path specified.
      if (file_path.size() > 0) {
        if (auto file_mapping = GetFileMapping(file_path, is_executable)) {
          return file_mapping;
        }
      }
    
      // Look in application specified native library if specified.
      for (const std::string& path : native_library_path) {
        auto native_library = fml::NativeLibrary::Create(path.c_str());
        auto symbol_mapping = std::make_unique<const fml::SymbolMapping>(
            native_library, native_library_symbol_name);
        if (symbol_mapping->GetMapping() != nullptr) {
          return symbol_mapping;
        }
      }
    
      // Look inside the currently loaded process.
      {
        auto loaded_process = fml::NativeLibrary::CreateForCurrentProcess();
        auto symbol_mapping = std::make_unique<const fml::SymbolMapping>(
            loaded_process, native_library_symbol_name);
        if (symbol_mapping->GetMapping() != nullptr) {
          return symbol_mapping;
        }
      }
    
      return nullptr;
    }
    
    #endif  // !DART_SNAPSHOT_STATIC_LINK
    
    static std::shared_ptr<const fml::Mapping> ResolveVMData(
        const Settings& settings) {
    #if DART_SNAPSHOT_STATIC_LINK
      return std::make_unique<fml::NonOwnedMapping>(kDartVmSnapshotData, 0);
    #else   // DART_SNAPSHOT_STATIC_LINK
      return SearchMapping(
          settings.vm_snapshot_data,          // embedder_mapping_callback
          settings.vm_snapshot_data_path,     // file_path
          settings.application_library_path,  // native_library_path
          DartSnapshot::kVMDataSymbol,        // native_library_symbol_name
          false                               // is_executable
      );
    #endif  // DART_SNAPSHOT_STATIC_LINK
    }
    static std::shared_ptr<const fml::Mapping> ResolveVMInstructions(
        const Settings& settings) {
    #if DART_SNAPSHOT_STATIC_LINK
      return std::make_unique<fml::NonOwnedMapping>(kDartVmSnapshotInstructions, 0);
    #else   // DART_SNAPSHOT_STATIC_LINK
      return SearchMapping(
          settings.vm_snapshot_instr,           // embedder_mapping_callback
          settings.vm_snapshot_instr_path,      // file_path
          settings.application_library_path,    // native_library_path
          DartSnapshot::kVMInstructionsSymbol,  // native_library_symbol_name
          true                                  // is_executable
      );
    #endif  // DART_SNAPSHOT_STATIC_LINK
    }
    
    static std::shared_ptr<const fml::Mapping> ResolveIsolateData(
        const Settings& settings) {
    #if DART_SNAPSHOT_STATIC_LINK
      return std::make_unique<fml::NonOwnedMapping>(kDartIsolateSnapshotData, 0);
    #else   // DART_SNAPSHOT_STATIC_LINK
      return SearchMapping(
          settings.isolate_snapshot_data,       // embedder_mapping_callback
          settings.isolate_snapshot_data_path,  // file_path
          settings.application_library_path,    // native_library_path
          DartSnapshot::kIsolateDataSymbol,     // native_library_symbol_name
          false                                 // is_executable
      );
    #endif  // DART_SNAPSHOT_STATIC_LINK
    }
    
    static std::shared_ptr<const fml::Mapping> ResolveIsolateInstructions(
        const Settings& settings) {
    #if DART_SNAPSHOT_STATIC_LINK
      return std::make_unique<fml::NonOwnedMapping>(
          kDartIsolateSnapshotInstructions, 0);
    #else   // DART_SNAPSHOT_STATIC_LINK
      return SearchMapping(
          settings.isolate_snapshot_instr,           // embedder_mapping_callback
          settings.isolate_snapshot_instr_path,      // file_path
          settings.application_library_path,         // native_library_path
          DartSnapshot::kIsolateInstructionsSymbol,  // native_library_symbol_name
          true                                       // is_executable
      );
    #endif  // DART_SNAPSHOT_STATIC_LINK
    }
    

    flutter/runtime/dart_vm.cc

    namespace dart {
    namespace observatory {
    
    #if !OS_FUCHSIA && (FLUTTER_RUNTIME_MODE != FLUTTER_RUNTIME_MODE_RELEASE)
    
    // These two symbols are defined in |observatory_archive.cc| which is generated
    // by the |//third_party/dart/runtime/observatory:archive_observatory| rule.
    // Both of these symbols will be part of the data segment and therefore are read
    // only.
    extern unsigned int observatory_assets_archive_len;
    extern const uint8_t* observatory_assets_archive;
    
    #endif  // !OS_FUCHSIA && (FLUTTER_RUNTIME_MODE !=
            // FLUTTER_RUNTIME_MODE_RELEASE)
    
    }  // namespace observatory
    }  // namespace dart
    
    Dart_Handle GetVMServiceAssetsArchiveCallback() {
    #if (FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_RELEASE)
      return nullptr;
    #elif OS_FUCHSIA
      fml::UniqueFD fd = fml::OpenFile("pkg/data/observatory.tar", false,
                                       fml::FilePermission::kRead);
      fml::FileMapping mapping(fd, {fml::FileMapping::Protection::kRead});
      if (mapping.GetSize() == 0 || mapping.GetMapping() == nullptr) {
        FML_LOG(ERROR) << "Fail to load Observatory archive";
        return nullptr;
      }
      return tonic::DartConverter<tonic::Uint8List>::ToDart(mapping.GetMapping(),
                                                            mapping.GetSize());
    #else
      return tonic::DartConverter<tonic::Uint8List>::ToDart(
          ::dart::observatory::observatory_assets_archive,
          ::dart::observatory::observatory_assets_archive_len);
    #endif
    }
    
    #if (FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG)
    #if !OS_IOS || TARGET_OS_SIMULATOR
      // Debug mode uses the JIT, disable code page write protection to avoid
      // memory page protection changes before and after every compilation.
      PushBackAll(&args, kDartWriteProtectCodeArgs,
                  fml::size(kDartWriteProtectCodeArgs));
    #else
      EnsureDebuggedIOS(settings_);
    #if TARGET_CPU_ARM
      // Tell Dart in JIT mode to not use integer division on armv7
      // Ideally, this would be detected at runtime by Dart.
      // TODO(dnfield): Remove this code
      // https://github.com/dart-lang/sdk/issues/24743
      PushBackAll(&args, kDartDisableIntegerDivisionArgs,
                  fml::size(kDartDisableIntegerDivisionArgs));
    #endif  // TARGET_CPU_ARM
    #endif  // !OS_IOS || TARGET_OS_SIMULATOR
    #endif  // (FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG)
    

    flutter/runtime/ptrace_ios.cc

    #if OS_IOS && (FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG)
    
    // These headers should only be needed in debug mode.
    #include <sys/sysctl.h>
    #include <sys/types.h>
    
    #define PT_TRACE_ME 0
    #define PT_SIGEXC 12
    extern "C" int ptrace(int request, pid_t pid, caddr_t addr, int data);
    
    static bool DebuggedIOS(const flutter::Settings& vm_settings) {
      // Only the Flutter CLI passes "--enable-checked-mode". Therefore, if the flag
      // is present, we have been launched by "ios-deploy" via "debugserver".
      //
      // We choose this flag because it is always passed to launch debug builds.
      if (vm_settings.enable_checked_mode) {
        return true;
      }
    
      // Use "sysctl()" to check if we're currently being debugged (e.g. by Xcode).
      // We could also check "getppid() != 1" (launchd), but this is more direct.
      const pid_t self = getpid();
      int mib[5] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, self, 0};
    
      auto proc = std::make_unique<struct kinfo_proc>();
      size_t proc_size = sizeof(struct kinfo_proc);
      if (sysctl(mib, 4, proc.get(), &proc_size, nullptr, 0) < 0) {
        FML_LOG(ERROR) << "Could not execute sysctl() to get current process info: "
                       << strerror(errno);
        return false;
      }
    
      return proc->kp_proc.p_flag & P_TRACED;
    }
    
    void EnsureDebuggedIOS(const flutter::Settings& vm_settings) {
      if (DebuggedIOS(vm_settings)) {
        return;
      }
    
      if (ptrace(PT_TRACE_ME, 0, nullptr, 0) == -1) {
        FML_LOG(ERROR) << "Could not call ptrace(PT_TRACE_ME): " << strerror(errno);
        // No use trying PT_SIGEXC -- it's only needed if PT_TRACE_ME succeeds.
        return;
      }
      if (ptrace(PT_SIGEXC, 0, nullptr, 0) == -1) {
        FML_LOG(ERROR) << "Could not call ptrace(PT_SIGEXC): " << strerror(errno);
      }
    
      // The previous operation causes this process to not be reaped after it
      // terminates (even if PT_SIGEXC fails). Issue a warning to the console every
      // (approximiately) maxproc/10 leaks. See the links above for an explanation
      // of this issue.
      size_t maxproc = 0;
      size_t maxproc_size = sizeof(size_t);
      const int sysctl_result =
          sysctlbyname("kern.maxproc", &maxproc, &maxproc_size, nullptr, 0);
      if (sysctl_result < 0) {
        FML_LOG(ERROR)
            << "Could not execute sysctl() to determine process count limit: "
            << strerror(errno);
      }
    
      const char* warning =
          "Launching a debug-mode app from the home screen may cause problems.\n"
          "Please compile a profile-/release-build, launch your app via \"flutter "
          "run\", or see https://github.com/flutter/flutter/wiki/"
          "PID-leak-in-iOS-debug-builds-launched-from-home-screen for details.";
    
      if (vm_settings.verbose_logging  // used for testing and also informative
          || sysctl_result < 0         // could not determine maximum process count
          || maxproc / 10 == 0         // avoid division (%) by 0
          || getpid() % (maxproc / 10) == 0)  // warning every ~maxproc/10 leaks
      {
        FML_LOG(ERROR) << warning;
      }
    }
    
    #endif  // OS_IOS && (FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG)
    

    ptrace_ios.h

    #if OS_IOS && (FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG)
    
    // Ensure that the current process is or was ptrace()-d at some point in its
    // life. Can only be used within debug builds for iOS.
    void EnsureDebuggedIOS(const flutter::Settings& vm_settings);
    
    #endif
    

    flutter/shell/common/shell_unittests.cc

    TEST_F(ShellTest, BlacklistedDartVMFlag) {
      // Run this test in a thread-safe manner, otherwise gtest will complain.
      ::testing::FLAGS_gtest_death_test_style = "threadsafe";
    
      const std::vector<fml::CommandLine::Option> options = {
          fml::CommandLine::Option("dart-flags", "--verify_after_gc")};
      fml::CommandLine command_line("", options, std::vector<std::string>());
    
    #if FLUTTER_RUNTIME_MODE != FLUTTER_RUNTIME_MODE_RELEASE
      // Upon encountering a non-whitelisted Dart flag the process terminates.
      const char* expected =
          "Encountered blacklisted Dart VM flag: --verify_after_gc";
      ASSERT_DEATH(flutter::SettingsFromCommandLine(command_line), expected);
    #else
      flutter::Settings settings = flutter::SettingsFromCommandLine(command_line);
      EXPECT_EQ(settings.dart_flags.size(), 0u);
    #endif
    }
    
    TEST_F(ShellTest, WhitelistedDartVMFlag) {
      const std::vector<fml::CommandLine::Option> options = {
          fml::CommandLine::Option("dart-flags",
                                   "--max_profile_depth 1,--random_seed 42")};
      fml::CommandLine command_line("", options, std::vector<std::string>());
      flutter::Settings settings = flutter::SettingsFromCommandLine(command_line);
    
    #if FLUTTER_RUNTIME_MODE != FLUTTER_RUNTIME_MODE_RELEASE
      EXPECT_EQ(settings.dart_flags.size(), 2u);
      EXPECT_EQ(settings.dart_flags[0], "--max_profile_depth 1");
      EXPECT_EQ(settings.dart_flags[1], "--random_seed 42");
    #else
      EXPECT_EQ(settings.dart_flags.size(), 0u);
    #endif
    }
    #if FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_RELEASE
    TEST_F(ShellTest, ReportTimingsIsCalledLaterInReleaseMode) {
    #else
    TEST_F(ShellTest, ReportTimingsIsCalledSoonerInNonReleaseMode) {
    #endif
      fml::TimePoint start = fml::TimePoint::Now();
      auto settings = CreateSettingsForFixture();
      std::unique_ptr<Shell> shell = CreateShell(settings);
    
      // Create the surface needed by rasterizer
      PlatformViewNotifyCreated(shell.get());
    
      auto configuration = RunConfiguration::InferFromSettings(settings);
      ASSERT_TRUE(configuration.IsValid());
      configuration.SetEntrypoint("reportTimingsMain");
    
      // Wait for 2 reports: the first one is the immediate callback of the first
      // frame; the second one will exercise the batching logic.
      fml::CountDownLatch reportLatch(2);
      std::vector<int64_t> timestamps;
      auto nativeTimingCallback = [&reportLatch,
                                   &timestamps](Dart_NativeArguments args) {
        Dart_Handle exception = nullptr;
        timestamps = tonic::DartConverter<std::vector<int64_t>>::FromArguments(
            args, 0, exception);
        reportLatch.CountDown();
      };
      AddNativeCallback("NativeReportTimingsCallback",
                        CREATE_NATIVE_ENTRY(nativeTimingCallback));
      RunEngine(shell.get(), std::move(configuration));
    
      PumpOneFrame(shell.get());
      PumpOneFrame(shell.get());
    
      reportLatch.Wait();
      shell.reset();
    
      fml::TimePoint finish = fml::TimePoint::Now();
      fml::TimeDelta ellapsed = finish - start;
    
    #if FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_RELEASE
      // Our batch time is 1000ms. Hopefully the 800ms limit is relaxed enough to
      // make it not too flaky.
      ASSERT_TRUE(ellapsed >= fml::TimeDelta::FromMilliseconds(800));
    #else
      // Our batch time is 100ms. Hopefully the 500ms limit is relaxed enough to
      // make it not too flaky.
      ASSERT_TRUE(ellapsed <= fml::TimeDelta::FromMilliseconds(500));
    #endif
    }
    
    

    flutter/shell/common/shell.cc

      // In tests using iPhone 6S with profile mode, sending a batch of 1 frame or a
      // batch of 100 frames have roughly the same cost of less than 0.1ms. Sending
      // a batch of 500 frames costs about 0.2ms. The 1 second threshold usually
      // kicks in before we reaching the following 100 frames threshold. The 100
      // threshold here is mainly for unit tests (so we don't have to write a
      // 1-second unit test), and make sure that our vector won't grow too big with
      // future 120fps, 240fps, or 1000fps displays.
      //
      // In the profile/debug mode, the timings are used by development tools which
      // require a latency of no more than 100ms. Hence we lower that 1-second
      // threshold to 100ms because performance overhead isn't that critical in
      // those cases.
      if (!first_frame_rasterized_ || UnreportedFramesCount() >= 100) {
        first_frame_rasterized_ = true;
        ReportTimings();
      } else if (!frame_timings_report_scheduled_) {
    #if FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_RELEASE
        constexpr int kBatchTimeInMilliseconds = 1000;
    #else
        constexpr int kBatchTimeInMilliseconds = 100;
    #endif
    

    flutter/shell/common/switches.cc

    #if FLUTTER_RUNTIME_MODE != FLUTTER_RUNTIME_MODE_RELEASE
    
    // List of common and safe VM flags to allow to be passed directly to the VM.
    // clang-format off
    static const std::string gDartFlagsWhitelist[] = {
        "--max_profile_depth",
        "--profile_period",
        "--random_seed",
        "--enable_mirrors",
    };
    // clang-format on
    
    #endif
    
    #if FLUTTER_RUNTIME_MODE != FLUTTER_RUNTIME_MODE_RELEASE
    
    static bool IsWhitelistedDartVMFlag(const std::string& flag) {
      for (uint32_t i = 0; i < fml::size(gDartFlagsWhitelist); ++i) {
        const std::string& allowed = gDartFlagsWhitelist[i];
        // Check that the prefix of the flag matches one of the whitelisted flags.
        // We don't need to worry about cases like "--safe --sneaky_dangerous" as
        // the VM will discard these as a single unrecognized flag.
        if (std::equal(allowed.begin(), allowed.end(), flag.begin())) {
          return true;
        }
      }
      return false;
    }
    
    #endif
    
    #if FLUTTER_RUNTIME_MODE != FLUTTER_RUNTIME_MODE_RELEASE
      command_line.GetOptionValue(FlagForSwitch(Switch::LogTag), &settings.log_tag);
      std::string all_dart_flags;
      if (command_line.GetOptionValue(FlagForSwitch(Switch::DartFlags),
                                      &all_dart_flags)) {
        std::stringstream stream(all_dart_flags);
        std::string flag;
    
        // Assume that individual flags are comma separated.
        while (std::getline(stream, flag, ',')) {
          if (!IsWhitelistedDartVMFlag(flag)) {
            FML_LOG(FATAL) << "Encountered blacklisted Dart VM flag: " << flag;
          }
          settings.dart_flags.push_back(flag);
        }
      }
    
      settings.trace_skia =
          command_line.HasOption(FlagForSwitch(Switch::TraceSkia));
      settings.trace_systrace =
          command_line.HasOption(FlagForSwitch(Switch::TraceSystrace));
    #endif
    
    

    flutter/shell/platform/darwin/ios/framework/Source/FlutterBinaryMessengerRelay.h

    #if FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG
    FLUTTER_EXPORT
    #endif
    @interface FlutterBinaryMessengerRelay : NSObject <FlutterBinaryMessenger>
    @property(nonatomic, assign) NSObject<FlutterBinaryMessenger>* parent;
    - (instancetype)initWithParent:(NSObject<FlutterBinaryMessenger>*)parent;
    @end
    

    flutter/shell/platform/darwin/ios/framework/Source/FlutterDartProject.mm可能需要改动

    extern "C" {
    #if FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG
    // Used for debugging dart:* sources.
    extern const uint8_t kPlatformStrongDill[];
    extern const intptr_t kPlatformStrongDillSize;
    #endif
    }
    #if FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG
      // There are no ownership concerns here as all mappings are owned by the
      // embedder and not the engine.
      auto make_mapping_callback = [](const uint8_t* mapping, size_t size) {
        return [mapping, size]() { return std::make_unique<fml::NonOwnedMapping>(mapping, size); };
      };
    
      settings.dart_library_sources_kernel =
          make_mapping_callback(kPlatformStrongDill, kPlatformStrongDillSize);
    #endif  // FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG
    
    

    flutter/shell/platform/darwin/ios/framework/Source/FlutterObservatoryPublisher.mm

    #if FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_RELEASE || \
        FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DYNAMIC_RELEASE
    
    @implementation FlutterObservatoryPublisher {
    }
    
    #else
    
    @interface FlutterObservatoryPublisher () <NSNetServiceDelegate>
    @end
    
    @implementation FlutterObservatoryPublisher {
      fml::scoped_nsobject<NSURL> _url;
    #if TARGET_IPHONE_SIMULATOR
      DNSServiceRef _dnsServiceRef;
    #else   // TARGET_IPHONE_SIMULATOR
      fml::scoped_nsobject<NSNetService> _netService;
    #endif  // TARGET_IPHONE_SIMULATOR
    
      flutter::DartServiceIsolate::CallbackHandle _callbackHandle;
      std::unique_ptr<fml::WeakPtrFactory<FlutterObservatoryPublisher>> _weakFactory;
    }
    
    - (NSURL*)url {
      return _url.get();
    }
    
    - (instancetype)init {
      self = [super init];
      NSAssert(self, @"Super must not return null on init.");
    
      _weakFactory = std::make_unique<fml::WeakPtrFactory<FlutterObservatoryPublisher>>(self);
    
      fml::MessageLoop::EnsureInitializedForCurrentThread();
    
      _callbackHandle = flutter::DartServiceIsolate::AddServerStatusCallback(
          [weak = _weakFactory->GetWeakPtr(),
           runner = fml::MessageLoop::GetCurrent().GetTaskRunner()](const std::string& uri) {
            runner->PostTask([weak, uri]() {
              if (weak) {
                [weak.get() publishServiceProtocolPort:std::move(uri)];
              }
            });
          });
    
      return self;
    }
    
    - (void)stopService {
    #if TARGET_IPHONE_SIMULATOR
      if (_dnsServiceRef) {
        DNSServiceRefDeallocate(_dnsServiceRef);
        _dnsServiceRef = NULL;
      }
    #else   // TARGET_IPHONE_SIMULATOR
      [_netService.get() stop];
    #endif  // TARGET_IPHONE_SIMULATOR
    }
    
    - (void)dealloc {
      [self stopService];
    
      flutter::DartServiceIsolate::RemoveServerStatusCallback(std::move(_callbackHandle));
      [super dealloc];
    }
    
    - (void)publishServiceProtocolPort:(std::string)uri {
      [self stopService];
      if (uri.empty()) {
        return;
      }
      // uri comes in as something like 'http://127.0.0.1:XXXXX/' where XXXXX is the port
      // number.
      _url.reset([[NSURL alloc] initWithString:[NSString stringWithUTF8String:uri.c_str()]]);
    
      NSString* serviceName =
          [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleIdentifier"];
    
      // Check to see if there's an authentication code. If there is, we'll provide
      // it as a txt record so flutter tools can establish a connection.
      auto path = std::string{[[_url path] UTF8String]};
      if (!path.empty()) {
        // Remove leading "/"
        path = path.substr(1);
      }
      NSData* pathData = [[[NSData alloc] initWithBytes:path.c_str() length:path.length()] autorelease];
      NSDictionary* txtDict = @{
        @"authCode" : pathData,
      };
      NSData* txtData = [NSNetService dataFromTXTRecordDictionary:txtDict];
    
    #if TARGET_IPHONE_SIMULATOR
      DNSServiceFlags flags = kDNSServiceFlagsDefault;
      uint32_t interfaceIndex = if_nametoindex("lo0");
      const char* registrationType = "_dartobservatory._tcp";
      const char* domain = "local.";  // default domain
      uint16_t port = [[_url port] intValue];
    
      int err = DNSServiceRegister(&_dnsServiceRef, flags, interfaceIndex, [serviceName UTF8String],
                                   registrationType, domain, NULL, htons(port), txtData.length,
                                   txtData.bytes, registrationCallback, NULL);
    
      if (err != 0) {
        FML_LOG(ERROR) << "Failed to register observatory port with mDNS.";
      } else {
        DNSServiceSetDispatchQueue(_dnsServiceRef, dispatch_get_main_queue());
      }
    #else   // TARGET_IPHONE_SIMULATOR
      NSNetService* netServiceTmp = [[NSNetService alloc] initWithDomain:@"local."
                                                                    type:@"_dartobservatory._tcp."
                                                                    name:serviceName
                                                                    port:[[_url port] intValue]];
      [netServiceTmp setTXTRecordData:txtData];
      _netService.reset(netServiceTmp);
      [_netService.get() setDelegate:self];
      [_netService.get() publish];
    #endif  // TARGET_IPHONE_SIMULATOR
    }
    
    - (void)netServiceDidPublish:(NSNetService*)sender {
      FML_DLOG(INFO) << "FlutterObservatoryPublisher is ready!";
    }
    
    - (void)netService:(NSNetService*)sender didNotPublish:(NSDictionary*)errorDict {
      FML_LOG(ERROR) << "Could not register as server for FlutterObservatoryPublisher. Check your "
                        "network settings and relaunch the application.";
    }
    
    #if TARGET_IPHONE_SIMULATOR
    static void DNSSD_API registrationCallback(DNSServiceRef sdRef,
                                               DNSServiceFlags flags,
                                               DNSServiceErrorType errorCode,
                                               const char* name,
                                               const char* regType,
                                               const char* domain,
                                               void* context) {
      if (errorCode == kDNSServiceErr_NoError) {
        FML_DLOG(INFO) << "FlutterObservatoryPublisher is ready!";
      } else {
        FML_LOG(ERROR) << "Could not register as server for FlutterObservatoryPublisher. Check your "
                          "network settings and relaunch the application.";
      }
    }
    #endif  // TARGET_IPHONE_SIMULATOR
    
    #endif  // FLUTTER_RUNTIME_MODE != FLUTTER_RUNTIME_MODE_RELEASE && FLUTTER_RUNTIME_MODE !=
            // FLUTTER_RUNTIME_MODE_DYNAMIC_RELEASE
    

    flutter/shell/platform/darwin/ios/framework/Source/FlutterPluginAppLifeCycleDelegate.mm

    - (void)handleDidEnterBackground:(NSNotification*)notification {
      UIApplication* application = [UIApplication sharedApplication];
    #if FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG
      // The following keeps the Flutter session alive when the device screen locks
      // in debug mode. It allows continued use of features like hot reload and
      // taking screenshots once the device unlocks again.
      //
      // Note the name is not an identifier and multiple instances can exist.
      _debugBackgroundTask = [application
          beginBackgroundTaskWithName:@"Flutter debug task"
                    expirationHandler:^{
                      [application endBackgroundTask:_debugBackgroundTask];
                      FML_LOG(WARNING)
                          << "\nThe OS has terminated the Flutter debug connection for being "
                             "inactive in the background for too long.\n\n"
                             "There are no errors with your Flutter application.\n\n"
                             "To reconnect, launch your application again via 'flutter run'";
                    }];
    #endif  // FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG
      for (NSObject<FlutterApplicationLifeCycleDelegate>* delegate in _delegates) {
        if (!delegate) {
          continue;
        }
        if ([delegate respondsToSelector:@selector(applicationDidEnterBackground:)]) {
          [delegate applicationDidEnterBackground:application];
        }
      }
    }
    
    - (void)handleWillEnterForeground:(NSNotification*)notification {
      UIApplication* application = [UIApplication sharedApplication];
    #if FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG
      [application endBackgroundTask:_debugBackgroundTask];
    #endif  // FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG
      for (NSObject<FlutterApplicationLifeCycleDelegate>* delegate in _delegates) {
        if (!delegate) {
          continue;
        }
        if ([delegate respondsToSelector:@selector(applicationWillEnterForeground:)]) {
          [delegate applicationWillEnterForeground:application];
        }
      }
    }
    
    

    flutter/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm

    - (void)viewDidLayoutSubviews {
      CGSize viewSize = self.view.bounds.size;
      CGFloat scale = [UIScreen mainScreen].scale;
    
      // First time since creation that the dimensions of its view is known.
      bool firstViewBoundsUpdate = !_viewportMetrics.physical_width;
      _viewportMetrics.device_pixel_ratio = scale;
      _viewportMetrics.physical_width = viewSize.width * scale;
      _viewportMetrics.physical_height = viewSize.height * scale;
    
      [self updateViewportPadding];
      [self updateViewportMetrics];
    
      // This must run after updateViewportMetrics so that the surface creation tasks are queued after
      // the viewport metrics update tasks.
      if (firstViewBoundsUpdate) {
        [self surfaceUpdated:YES];
    
        flutter::Shell& shell = [_engine.get() shell];
        fml::TimeDelta waitTime =
    #if FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG
            fml::TimeDelta::FromMilliseconds(200);
    #else
            fml::TimeDelta::FromMilliseconds(100);
    #endif
        if (shell.WaitForFirstFrame(waitTime).code() == fml::StatusCode::kDeadlineExceeded) {
          FML_LOG(INFO) << "Timeout waiting for the first frame to render.  This may happen in "
                        << "unoptimized builds.  If this is a release build, you should load a less "
                        << "complex frame to avoid the timeout.";
        }
      }
    }
    

    flutter/shell/platform/embedder/embedder.cc可能需要改动

    extern "C" {
    #if FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG
    // Used for debugging dart:* sources.
    extern const uint8_t kPlatformStrongDill[];
    extern const intptr_t kPlatformStrongDillSize;
    #endif  // FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG
    }
    
    #if !OS_FUCHSIA && (FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG)
      settings.dart_library_sources_kernel =
          make_mapping_callback(kPlatformStrongDill, kPlatformStrongDillSize);
    #endif  // !OS_FUCHSIA && (FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG)
    
    

    flutter/testing/testing.gni

        is_aot_test =
        flutter_runtime_mode == "profile" || flutter_runtime_mode == "release"
        if (is_aot_test) {
          deps += [ "$flutter_root/lib/snapshot:strong_platform" ]
        }
        if (flutter_runtime_mode == "release") {
          args += [ "-Ddart.vm.product=true" ]
        }
    
        if (is_aot_test) {
          args += [
            "--aot",
    
            # type flow analysis
            "--tfa",
          ]
        }
    
    snapshot_deps = [ ":$dart_snapshot_kernel_target_name" ]
    
      if (is_aot_test) {
        dart_snapshot_aot_target_name = "dart_snapshot_aot_$target_name"
        dart_snapshot_aot(dart_snapshot_aot_target_name) {
          dart_kernel = dart_snapshot_kernel_path
          deps = [
            ":$dart_snapshot_kernel_target_name",
          ]
        }
        snapshot_deps += [ ":$dart_snapshot_aot_target_name" ]
      }
    

    文件对比报告
    https://gist.github.com/Kila2/5e6b59947309a44154e9c904a18e92e4

    相关文章

      网友评论

          本文标题:Flutter engine runtime mode 研究

          本文链接:https://www.haomeiwen.com/subject/wuvovctx.html