- 图形学
- 图像处理
【免费下载链接】skia
Skia is a complete 2D graphic library for drawing Text, Geometries, and Images.
本篇技术指南以 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 testRecipe 体系的核心要素包括:
- 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),负责"准备变量":
- 读取 property
buildername,通过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):
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。
- 持久化 gclient 缓存默认指向
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且不含Flutter | android.compile_fn | android.copy_build_products |
含Chromebook | chromebook.compile_fn | chromebook.copy_build_products |
含EMCC且含PathKit | pathkit.compile_fn | pathkit.copy_build_products |
含EMCC(其余) | canvaskit.compile_fn | canvaskit.copy_build_products |
含CMake | cmake.compile_fn | cmake.copy_build_products |
含Docker | docker.compile_fn | docker.copy_build_products |
| 其他(默认) | default.compile_fn | default.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/full | recipe_modules/build/examples/full.py | 调用 build API 编译并拷贝产物 |
| builder_name_schema:examples/full | recipe_modules/builder_name_schema/examples/full.py | Builder 名称编解码往返 |
| checkout:examples/full | recipe_modules/checkout/examples/full.py | bot_update / git 两种签出 |
| docker:examples/full | recipe_modules/docker/examples/full.py | Docker 容器内运行脚本 |
| doxygen:examples/full | recipe_modules/doxygen/examples/full.py | 文档生成 |
| env:examples/full | recipe_modules/env/examples/full.py | 环境变量注入 |
| flavor:examples/full | recipe_modules/flavor/examples/full.py | 设备抽象操作,含test_exceptions(full.py#L17)异常路径测试 |
| git:examples/full | recipe_modules/git/examples/full.py | Git 环境 |
| gold_upload:examples/full | recipe_modules/gold_upload/examples/full.py | Gold 上传 |
| gsutil:examples/full | recipe_modules/gsutil/examples/full.py | GCS 拷贝 |
| infra:examples/full | recipe_modules/infra/examples/full.py | Go 环境 |
| run:examples/full | recipe_modules/run/examples/full.py | 步骤执行,含myfunc演示run_once |
| vars:examples/full | recipe_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 首行注释,实际工作流如下:
训练(train):修改了任何 recipe 或 recipe_module 后,运行
$ ./infra/bots/recipes.py test train它会重新生成 infra/bots/README.recipes.md(即本文主题文档)以及各
.expected期望文件,使 API 文档与实现保持同步。测试(test):运行
$ ./infra/bots/recipes.py test执行全部模拟测试,比对步骤输出与期望文件。
本地运行单个 Recipe:使用 infra/bots/run_recipe.py 配合 property 参数(如
buildername、repository、revision、patch_ref等)在本地回放某个 Recipe,适合调试新任务编排。生成任务 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.
相关推荐
Skia Recipes 自动化测试体系:Swarming 任务中的 Recipe 本地运行与模拟测试训练指南
Skia Recipes 自动化测试体系:Swarming 任务中的 Recipe 本地运行与模拟测试训练指南 Skia 的持续集成(CI)自动化测试全部由一套
图形学Skia Recipe Modules 开发指南:理解 Skia 自动化测试的模块化 Recipe 体系
Skia Recipe Modules 开发指南:理解 Skia 自动化测试的模块化 Recipe 体系 导读 本文聚焦于 Skia 仓库中 infra/bot
图形学Skia 自动化测试的 Recipe 体系详解:模块 API 参考与 CI 实战指南
Skia 自动化测试的 Recipe 体系详解:模块 API 参考与 CI 实战指南 导读 infra/bots/README.recipes.md 是 Ski
图形学
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考