☰
Skia CI Recipes 体系完全解读:从 Recipe 模块到自动化编译、测试与性能任务
2026/9/25 4:16:53 网站建设 项目流程
  • 图形学
  • 图像处理

【免费下载链接】skia

Skia is a complete 2D graphic library for drawing Text, Geometries, and Images.

项目地址:https://gitcode.com/gh_mirrors/skia1/skia
点击查看免费下载

本篇技术指南以 infra/bots/README.recipes.md 为核心骨架,系统讲解 Skia 开源仓库中基于 Chromium LUCI recipes 框架构建的持续集成(CI)自动化体系:13 个 Recipe 模块(build、checkout、docker、flavor、run、vars 等)如何被 16 个正式 Recipe(compile、test、perf、housekeeper 等)编排成一次次的 Swarming 任务。读完本文,你将理解 Skia 构建机器人(Builder)从拉取代码、编译产物到上传测试/性能结果的完整调用链,掌握每个模块核心 API 的签名、参数与底层实现,并知道如何阅读、运行与验证这套 Recipe 体系。

Recipes 在 Skia 基础设施中的定位

在深入 README.recipes.md 之前,有必要先明确它服务的上层框架。根据 infra/bots/README.md 的说明,Skia 的持续集成体系由以下几层构成:

  • Task(任务):通过 Swarming 在机器池中运行的最小自包含单元,任务之间可以串联(例如先编译测试二进制、再运行它们);
  • Job(作业):相关任务的集合,用于圈定 DAG 的某一段,例如作为 Try Job 的入口;
  • Recipes(配方):在 Swarming 任务内部执行具体工作的框架,这正是本文的主题;
  • Isolate 文件:决定 Swarming 任务触发时向机器人传输仓库的哪些部分;
  • Assets(资产):版本化的基础设施制品(NDK、SDK、sysroot 等),配套有重建/上传/下载脚本,见 infra/bots/assets/。

任务 DAG 的定义集中在tasks.json,该文件永不手工编辑,而是由 infra/bots/gen_tasks.go 依据 infra/bots/cfg.json 与 infra/bots/jobs.json 生成。任何改动这些输入后都需要重新生成:

$ go run infra/bots/gen_tasks.go # 重新生成 tasks.json $ go run infra/bots/gen_tasks.go --test # 一致性校验模式 # 等价形式: $ make -C infra/bots train $ make -C infra/bots test

Recipe 体系的核心要素包括:

  • infra/bots/recipes.py:用于运行和测试 recipes 的入口脚本;
  • recipes:每种任务的入口点,例如编译或运行测试;
  • recipe_modules:被 recipes 共享的模块;
  • .recipe_deps:recipes 和模块可能依赖其他仓库(如 depot_tools、recipe_engine)的模块,recipes.py会自动同步这些依赖。

本文的关联文档 infra/bots/README.recipes.md 正是这套体系的自描述文档:其首行注释AUTOGENERATED BY './recipes.py test train'表明,它是通过 recipes 框架的训练(train)机制自动生成的 API 索引,内容覆盖全部模块的 DEPS 依赖、类与方法签名,以及所有 Recipe 及其内部函数。

Recipe 模块(Recipe Modules)总览

README.recipes.md 索引了 13 个 Recipe 模块,它们构成 Skia CI 的"积木库"。按职责可划分为四类:

类别模块职责
环境与变量vars、env、infra、git解析 Builder 名称、准备环境变量、定位 Go 工具链、配置 Git
代码获取checkout、builder_name_schema通过 bot_update 或纯 git 拉取代码;Builder 命名编解码
构建与执行build、docker、run、flavor多平台编译、容器化构建、步骤执行与重试、设备抽象层
结果上报gold_upload、gsutil、doxygen上传到 Gold 像素比对、GCS 存储、文档站点

下面按此分类深入每个模块的源码实现。

环境与变量类:vars、env、infra、git

vars:一切变量的源头

vars模块的 SkiaVarsApi 是几乎所有 Recipe 依赖链的起点。其核心方法是setup()(vars/api.py#L18),负责"准备变量":

  • 读取 propertybuildername,通过builder_name_schema.DictForBuilderName()将其解析为结构化字典builder_cfg;
  • 依据builder_cfg['role']决定构建配置:housekeeper角色固定使用Release,其余默认Debug(对应模块常量CONFIG_DEBUG/CONFIG_RELEASE),Windows x86_64 会追加_x64后缀;
  • 解析extra_config得到extra_tokens(以SK开头的整段大写 token,否则按下划线拆分);
  • 根据patch_issue/patch_set/patch_ref等 property 判定is_trybot,从而让下游区分 Try 构建与 CI 构建;
  • 建立workdir、build_dir、cache_dir、swarming_out_dir、tmp_dir等关键目录,并在default_env中注入CHROME_HEADLESS=1与 depot_tools 路径。

vars还提供只读属性is_linux(vars/api.py#L87,通过 Builder 名称中是否含Ubuntu/Debian/Housekeeper判定)、swarming_bot_id与swarming_task_id(vars/api.py#L95、vars/api.py#L106),后者通过执行资源脚本get_env_var.py读取 Swarming 注入的环境变量。

该模块的 DEPS 依赖(vars/init.py#L7)覆盖bot_update、context、json、path、properties、raw_io、step等 recipe_engine 通用模块,以及本仓库的builder_name_schema。

env:环境变量作用域

env是最轻量的模块,仅依赖recipe_engine/context。其 EnvApi 常被其他模块用于with self.m.env(...)临时注入环境变量,例如docker模块运行容器时设置DOCKER_CONFIG。它的示例 Recipe 是 env/examples/full.py。

infra:Go 工具链定位

infra模块(InfraApi)用于 CI 中运行 Go 程序(如生成 tasks.json、执行 gen_tasks 相关工具)。四个只读属性负责组装 Go 环境:

  • goroot(infra/api.py#L15):Go 安装根目录;
  • go_bin(infra/api.py#L46):go可执行文件路径;
  • gopath(infra/api.py#L60):GOPATH 路径;
  • go_env(infra/api.py#L50):完整的 Go 环境变量字典。

这些属性被 infra.py 等 Recipe 用于在git_init后执行 Go 任务。其示例 Recipe 为 infra/examples/full.py。

git:把 Git 加入 PATH

git模块的 GitApi 只有一个env()属性(git/api.py#L10):将 Git 加入 PATH。其文档字符串明确要求:需要infra/git与infra/tools/git两个 CIPD 包按相对路径git安装。DEPS 仅含recipe_engine/path与env。这解释了为什么checkout模块在拉代码前要调用assert_git_is_from_cipd()——保证 CI 使用的是 CIPD 分发的受控 Git 版本。

代码获取类:builder_name_schema 与 checkout

builder_name_schema:Builder 命名的编解码器

Skia 的 Builder 名称不是随意字符串,而是遵循builder_name_schema模块定义的规范(见 builder_name_schema/builder_name_schema.py,模块 api.py 中暴露了BUILDER_NAME_SCHEMA、BUILDER_NAME_SEP与五类角色常量:BUILDER_ROLE_BUILD、BUILDER_ROLE_HOUSEKEEPER、BUILDER_ROLE_INFRA、BUILDER_ROLE_PERF、BUILDER_ROLE_TEST)。模块 API 提供两个对称方法:

  • MakeBuilderName(**kwargs)(api.py#L29):由结构化字段生成规范名称;
  • DictForBuilderName(*args, **kwargs)(api.py#L32):把 Builder 名称解析回字典。

vars.setup()正是通过DictForBuilderName把buildernameproperty 变成builder_cfg,再推导出role、configuration、extra_tokens等下游变量——因此它是整条依赖链的"第一块积木"。

checkout:获取代码的两种方式

checkout模块提供两种拉取策略(CheckoutApi):

  1. bot_update(checkout_root, gclient_cache=None, skip_patch=False, override_revision=None)(checkout/api.py#L39):默认策略,走depot_tools的 gclient + bot_update 流程。源码细节包括:
    • 持久化 gclient 缓存默认指向vars.cache_dir.join('git');
    • 以repositoryproperty 作为主 solution,got_revision_mapping记录到got_revision;
    • 若存在patch_ref且未skip_patch,则构造patch_refs并始终patch=True(注释说明是为避免步骤名出现误导性的 "(without patch)"),同时download_topics=True以拉取同一 Gerrit topic 的所有改动;
    • 返回got_revisionproperty。
  2. git(checkout_root)(checkout/api.py#L26):无 DEPS 的纯 git 拉取,先断言 Git 来自 CIPD,再git checkout到指定revision;若为 trybot,则fetchpatch_ref、checkout FETCH_HEAD并rebase到目标 revision。

辅助成员包括default_checkout_root属性(checkout/api.py#L15,即cache_dir/work,持久化缓存签出目录)与assert_git_is_from_cipd()(checkout/api.py#L20,执行资源脚本assert_git_cipd.py,失败即中止)。其 DEPS(checkout/init.py#L7)包含了bot_update、gclient、git、tryserver等 depot_tools 模块。

构建与执行类:build、docker、run、flavor

build:按 Builder 分发编译策略

build模块文档描述为 "Build Skia for various platforms"。其 BuildApi 的构造函数根据 Builder 名称关键字分发编译实现(build/api.py#L21-L45):

Builder 名称特征编译实现产物拷贝实现
含Android且不含Flutterandroid.compile_fnandroid.copy_build_products
含Chromebookchromebook.compile_fnchromebook.copy_build_products
含EMCC且含PathKitpathkit.compile_fnpathkit.copy_build_products
含EMCC(其余)canvaskit.compile_fncanvaskit.copy_build_products
含CMakecmake.compile_fncmake.copy_build_products
含Dockerdocker.compile_fndocker.copy_build_products
其他(默认)default.compile_fndefault.copy_build_products

对应子模块文件位于 build/ 目录(android.py、canvaskit.py、chromebook.py、cmake.py、default.py、docker.py、pathkit.py)。公开方法有两个:

  • __call__(checkout_root, out_dir)(build/api.py#L47):"Compile the code",调用分发得到的compile_fn;
  • copy_build_products(out_dir, dst)(build/api.py#L51):"Copy selected build products to dst",调用分发得到的copy_fn。

该模块的 DEPS(build/init.py#L7)同时依赖 depot_tools 的gclient、recipe_engine 的context/file/path/step,以及本仓库的docker、env、infra、run、vars——可以看出它是编译类 Recipe(compile、sync_and_compile)的核心。

docker:容器化构建的胶水层

docker模块(DockerApi)让 Recipe 在 Docker 容器内运行脚本,服务于perf_pathkit、test_canvaskit、test_lottie_web、test_pathkit等 Web/WASM 相关 Recipe。两个挂载常量MOUNT_SRC = '/SRC'、MOUNT_OUT = '/OUT',对应方法mount_src()与mount_out()(docker/api.py#L24、docker/api.py#L27)。

核心方法是run(...)(docker/api.py#L32),签名参数含义:

参数说明
name步骤名
docker_image使用的镜像
src_dir/out_dir源码与输出目录(宿主侧)
script容器内要执行的脚本(默认要求位于start_dir)
args/docker_args传给脚本 / 附加给docker run的参数
copies需预先拷入的{src, dst}文件列表
recursive_read需要递归chmod a+r的目录
attempts失败重试次数
match_directory_structure为 True 时保持目录结构挂载,否则分别挂到/SRC、/OUT

实现细节:运行前先以get_uid_gid.py取得 uid/gid,对out_dir显式chmod 777、对src_dir非递归chmod 755、对脚本chmod 0755,并处理copies拷贝与recursive_read;随后构造命令docker run --shm-size=2gb --rm --user <uid:gid> --mount type=bind,...并设置DOCKER_CONFIG=/home/chrome-bot/.docker,最后通过run.with_retry按attempts重试。该模块的 DEPS(docker/init.py#L8)为file、path、raw_io、step、env、run。

run:步骤执行的统一出口

run模块(SkiaStepApi)是所有 Recipe 执行命令的统一封装,DEPS 为file、path、properties、step、env、vars。核心方法:

  • __call__(steptype, name, abort_on_failure=True, fail_build_on_failure=True, **kwargs)(run/api.py#L69):在vars.default_env环境下执行步骤;失败时若fail_build_on_failure=True则记录到_failed列表但不一定中止("keep going but mark the build status failed"),abort_on_failure=True才立即抛出。对应的check_failure()(run/api.py#L25)在阶段末尾统一抛出StepFailure,列出所有失败步骤。
  • with_retry(steptype, name, attempts, between_attempts_fn=None, ...)(run/api.py#L81):带重试的执行,重试步骤名追加 "(attempt N)",成功后回滚之前记录的失败(del self._failed[-attempt:]),between_attempts_fn可在重试间隙执行清理。
  • run_once(fn, *args, **kwargs)(run/api.py#L35):按函数名去重,保证某操作在整个 Recipe 生命周期只执行一次(如只做一次的清理)。
  • asset_version(asset_name, skia_dir, test_data=None)(run/api.py#L54):读取infra/bots/assets/<asset_name>/VERSION文件内容,测试时可用 propertytest_<asset_name>_version或默认值TEST_DEFAULT_ASSET_VERSION = '42'覆盖。flavor.install()正是靠它获取 skimage/skp/lottie-samples/svg/text_blob_traces 的版本号。
  • 便捷函数:readfile(filename)、writefile(filename, contents)(run/api.py#L40、run/api.py#L45)、rmtree(path)(run/api.py#L50),以及只读属性failed_steps(run/api.py#L31)。
flavor:跨设备抽象层

flavor模块是 Skia CI 中最能体现多平台支持力度的模块。其文档说明:模块方法定义高层操作,每种 flavor 对应一个DefaultFlavor子类,可按平台覆盖——例如AndroidFlavor会重写主机与 Android 设备间的文件拷贝以及step(通过 ADB 执行命令)。支持的平台由 flavor/api.py#L38-L51 的判定函数给出:is_android、is_chromebook、is_ios、is_valgrind,分别看extra_tokens或builder_cfg['os']中的关键字。

SkiaFlavorApi 的方法族:

  • get_flavor(vars_api, app_name)(flavor/api.py#L55):按 Builder 返回对应的 flavor 工具对象(ChromebookFlavor、AndroidFlavor、iOSFlavor、ValgrindFlavor或DefaultFlavor),对应子模块在 flavor/ 下(android.py、chromebook.py、default.py、ios.py、valgrind.py)。
  • setup(app_name)(flavor/api.py#L68):初始化 flavor 对象,暴露device_dirs/host_dirs。
  • step(name, cmd, **kwargs)(flavor/api.py#L74)与device_path_join(*args)(flavor/api.py#L77):设备上执行命令与拼接路径。
  • 文件传输族:copy_directory_contents_to_device/copy_directory_contents_to_host/copy_file_to_device(flavor/api.py#L80-L86)、create_clean_host_dir/create_clean_device_dir(flavor/api.py#L89、flavor/api.py#L92)、read_file_on_device/remove_file_on_device(flavor/api.py#L95、flavor/api.py#L98)。
  • install(skps=False, images=False, lotties=False, svgs=False, resources=False, texttraces=False)(flavor/api.py#L101):按需把测试资产(SKP 回放文件、测试图片、Lottie 动画、SVG、文本轨迹、resources 目录)安装到设备。每个资产通过版本文件(SKP_VERSION、SK_IMAGE_VERSION、LOTTIE_VERSION、SVG_VERSION、TEXTTRACES_VERSION,见 flavor/api.py#L30-L34)与设备端已装版本比对,仅当版本不一致时才重新拷贝(_copy_dir逻辑,flavor/api.py#L125-L144),设备端无版本文件则视为VERSION_NONE = -1。
  • cleanup_steps()(flavor/api.py#L122):委托给 flavor 对象的清理步骤(如 Android 的 ADB 清理)。

其 DEPS(flavor/init.py#L7)覆盖context、file、json、path、platform、raw_io、step及本仓库env、run、vars。test、perf、perf_skottietrace等 Recipe 的 DEPS 都依赖它。

结果上报类:gold_upload、gsutil、doxygen

gold_upload:像素比对结果上报

gold_upload模块(GoldUploadApi)用于把测试生成的图像上传到 Skia Gold(像素差异比对服务)。唯一公开方法upload()(gold_upload/api.py#L12)注释明确:"Attempt to upload files to Gold",且前置条件是vars与flavor模块已完成 setup。其 DEPS(gold_upload/init.py#L7)包含context、file、json、platform、properties、step、time以及本仓库的flavor、gsutil、run、vars——其中gsutil用于实际把数据写入 GCS。

gsutil:GCS 上传/下载封装

gsutil模块(GSUtilApi)封装 Google Cloud Storage 操作,其注释指出:假定 PATH 上存在gsutil可执行文件,且主要用于 Linux/Mac(上传到 GCS 仅在这两类宿主上进行)。两个方法:

  • __call__(step_name, *args)(gsutil/api.py#L11):以给定参数运行 gsutil;
  • cp(name, src, dst, extra_gsutil_args=None, extra_args=None, multithread=False)(gsutil/api.py#L20):上传或下载文件。参数含义:name用于步骤名;src/dst为本地绝对路径或gs://...路径;extra_gsutil_args追加在cp命令之前;extra_args追加在cp之后(例如-Z表示上传后用 gzip 压缩、下载前解压);multithread=True时使用gsutil -m并发拷贝(如gsutil -m cp foo* gs://bar/dir)。失败会自动重试多次。

该模块被gold_upload、upload_dm_results等用于把产物送抵 GCS。

doxygen:API 文档生成与发布

doxygen模块(DoxygenApi)只有一个方法generate_and_upload(skia_dir)(doxygen/api.py#L10),用于生成 Doxygen 文档并上传。它被housekeeperRecipe 调用,DEPS 仅context、step、run,非常轻量。

Recipes:CI 任务入口全景

README.recipes.md 索引了 29 个 Recipe 条目(16 个正式 Recipe + 13 个examples/full示例 Recipe)。每个 Recipe 以RunSteps(api)为入口,配合若干辅助函数。按职能分组如下。

编译类:compile、sync_and_compile

  • compile:核心编译 Recipe,RunSteps(compile.py#L26)内部按流程调用checkout、build与run/vars;DEPS(compile.py#L11)包含context、file、json、path、platform、properties、step及build、checkout、run、vars。
  • sync_and_compile:在 compile 基础上增加depot_tools/gitiles依赖(sync_and_compile.py#L10),适用于需要同步特定 Git 引用后再编译的场景;RunSteps位于 sync_and_compile.py#L27。

测试类:test、test_canvaskit、test_lottie_web、test_pathkit

  • test:运行 DM(Skia 的测试驱动程序)的 Recipe。RunSteps(test.py#L136)与test_steps(test.py#L30,注释 "Run the DM test")共同完成:安装 flavor 资产、执行 DM、必要时上传 Gold。DEPS 包含env、flavor、gold_upload、run、vars等(test.py#L13)。
  • test_canvaskit/test_lottie_web/test_pathkit:Web/WASM 测试三件套,RunSteps分别在 test_canvaskit.py#L28、test_lottie_web.py#L29、test_pathkit.py#L29。三者 DEPS 结构一致(test_canvaskit.py#L9、test_lottie_web.py#L9、test_pathkit.py#L9):file、path、properties、step加checkout、docker、env、flavor、gold_upload、infra、run、vars——即"先 checkout,再在 Docker 容器中构建/测试,结果上 Gold"的流水线。

性能类:perf、perf_pathkit、perf_skottietrace、perf_skottiewasm_lottieweb

  • perf:运行 Skia 基准测试(nanobench)的 Recipe。perf_steps(perf.py#L31,注释 "Run Skia benchmarks")与RunSteps(perf.py#L104)配合执行。DEPS 最重(perf.py#L15):file、json、path、platform、properties、raw_io、step、time加env、flavor、run、vars。
  • perf_pathkit:PathKit(WASM 路径工具库)性能测试,RunSteps(perf_pathkit.py#L27),DEPS 含docker、infra(perf_pathkit.py#L9)。
  • perf_skottietrace:对 Lottie 文件开启 tracing 运行 DM 并解析输出。其perf_steps(perf_skottietrace.py#L37)负责执行,get_trace_match(lottie_filename, is_android)(perf_skottietrace.py#L147)返回匹配指定 Lottie 文件的 DM 正则,parse_trace(trace_json, lottie_filename, api)(perf_skottietrace.py#L162)解析 trace JSON。文档对返回结构给出了明确示例:
{ 'frame_max_us': 100, 'frame_min_us': 90, 'frame_avg_us': 95, }

其中单帧时间 = seek 时间 + render 时间,且首次 seek 被忽略(因为那是构造调用)。RunSteps位于 perf_skottietrace.py#L191,DEPS 见 perf_skottietrace.py#L17。

  • perf_skottiewasm_lottieweb:Skottie WASM 与 Lottie Web 渲染器的性能对比测试。RunSteps(perf_skottiewasm_lottieweb.py#L85)与parse_trace(trace_json, lottie_filename, api, renderer)(perf_skottiewasm_lottieweb.py#L206)同样产出frame_max_us/frame_min_us/frame_avg_us结构,DEPS 见 perf_skottiewasm_lottieweb.py#L14。

上传类:upload_buildstats_results、upload_dm_results、upload_nano_results

  • upload_dm_results:把 DM 测试结果上传,RunSteps(upload_dm_results.py#L29)依赖gsutil完成 GCS 传输(upload_dm_results.py#L13)。
  • upload_nano_results:上传 nanobench 性能结果,RunSteps(upload_nano_results.py#L21)。
  • upload_buildstats_results:上传构建体积统计结果,RunSteps(upload_buildstats_results.py#L21)。

其他:housekeeper、infra、compute_buildstats

  • housekeeper:日常维护任务(Doxygen 文档生成等),RunSteps(housekeeper.py#L24)依赖checkout、doxygen、run、vars(housekeeper.py#L13)。
  • infra:基础设施维护任务,RunSteps(infra.py#L28)在git_init(repo_root, env)(infra.py#L20)初始化仓库后运行 Go 工具,DEPS 为infra、vars及context、path、properties、step(infra.py#L10)。
  • compute_buildstats:计算并汇报构建体积。内部函数族(compute_buildstats.py#L30-L265)针对不同产物形态分析:analyze_web_file(compute_buildstats.py#L139)、analyze_cpp_lib(compute_buildstats.py#L166)、analyze_flutter_lib(compute_buildstats.py#L194)、analyze_wasm_file(compute_buildstats.py#L233),以及keys_and_props(compute_buildstats.py#L115)与make_treemap(compute_buildstats.py#L265)。配套的分析脚本位于 infra/bots/buildstats/(buildstats_cpp.py、buildstats_web.py、buildstats_wasm.py、buildstats_flutter.py、make_treemap.py)。

examples/full:每个模块的活文档

README.recipes.md 为每个 Recipe 模块都收录了一个examples/full示例 Recipe,它们是阅读模块 API 的最佳"活文档":

示例 Recipe位置演示内容
build:examples/fullrecipe_modules/build/examples/full.py调用 build API 编译并拷贝产物
builder_name_schema:examples/fullrecipe_modules/builder_name_schema/examples/full.pyBuilder 名称编解码往返
checkout:examples/fullrecipe_modules/checkout/examples/full.pybot_update / git 两种签出
docker:examples/fullrecipe_modules/docker/examples/full.pyDocker 容器内运行脚本
doxygen:examples/fullrecipe_modules/doxygen/examples/full.py文档生成
env:examples/fullrecipe_modules/env/examples/full.py环境变量注入
flavor:examples/fullrecipe_modules/flavor/examples/full.py设备抽象操作,含test_exceptions(full.py#L17)异常路径测试
git:examples/fullrecipe_modules/git/examples/full.pyGit 环境
gold_upload:examples/fullrecipe_modules/gold_upload/examples/full.pyGold 上传
gsutil:examples/fullrecipe_modules/gsutil/examples/full.pyGCS 拷贝
infra:examples/fullrecipe_modules/infra/examples/full.pyGo 环境
run:examples/fullrecipe_modules/run/examples/full.py步骤执行,含myfunc演示run_once
vars:examples/fullrecipe_modules/vars/examples/full.py变量初始化

这些示例与各 Recipe 的.expected/*.json期望文件(如 recipes/test.expected/)共同构成 recipes 的可测试性:recipes 框架的模拟(simulation)测试机制会执行示例 Recipe、产出步骤日志并与期望 JSON 比对,保证任何对模块或 Recipe 的改动都不会静默破坏 CI 流程。

如何运行与验证这套 Recipe 体系

结合 infra/bots/README.md 与 README.recipes.md 首行注释,实际工作流如下:

  1. 训练(train):修改了任何 recipe 或 recipe_module 后,运行

    $ ./infra/bots/recipes.py test train

    它会重新生成 infra/bots/README.recipes.md(即本文主题文档)以及各.expected期望文件,使 API 文档与实现保持同步。

  2. 测试(test):运行

    $ ./infra/bots/recipes.py test

    执行全部模拟测试,比对步骤输出与期望文件。

  3. 本地运行单个 Recipe:使用 infra/bots/run_recipe.py 配合 property 参数(如buildername、repository、revision、patch_ref等)在本地回放某个 Recipe,适合调试新任务编排。

  4. 生成任务 DAG:改动 infra/bots/jobs.json、infra/bots/cfg.json 或 assets 后,运行go run infra/bots/gen_tasks.go(或make -C infra/bots train)重新生成tasks.json,并可用--test做一致性校验。

结语

从 infra/bots/README.recipes.md 这张自动生成的"地图"出发,可以完整还原 Skia CI 的运转逻辑:vars解析 Builder 名称并准备环境 →checkout拉取代码 →build按平台分发编译 →flavor把产物与测试资产部署到设备 →test/perf运行 DM 与 nanobench →gold_upload/gsutil把图像、性能与体积数据送往 Gold/GCS;Web 相关任务则通过docker模块在容器中完成。这套模块化、可模拟测试的设计,使得 Skia 在多平台(Android、Chromebook、iOS、Linux、Windows、WASM)上的海量构建与测试任务能够在一个统一框架下稳定演进。对于想要阅读或扩展 Skia CI 的开发者,建议按"README.recipes.md 索引 → 对应api.py实现 → 对应examples/full.py→.expected期望文件"的顺序研读,即可快速上手。

  • 图形学
  • 图像处理

【免费下载链接】skia

Skia is a complete 2D graphic library for drawing Text, Geometries, and Images.

项目地址:https://gitcode.com/gh_mirrors/skia1/skia
点击查看免费下载
上一篇:RxBinding源码中的设计模式:观察者模式的最佳实践
下一篇:3分钟掌握Mermaid Live Editor:免费实时图表编辑器的完整指南

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询