Writing Bazel rules: data and runfiles

Bazel has a neat feature that can simplify a lot of work with tests and executables: the ability to make data files available at run-time using data attributes. You may have seen these in rules like this:Bazel 有一个巧妙的功能,可以简化测试和可执行文件的大量工作:使用数据属性在运行时使数据文件可用。您可能已经在这样的规则中看到过这些:

cc_library(name = "server_lib",srcs = ["server.cc"],data = ["private.key"],
)

When a file is listed in a data attribute (or something that behaves like a data attribute), Bazel makes that file available at run-time to executables started with bazel run. This is useful for all kinds of things such as plugins, configuration files, certificates and keys, and resources.

In this article, we’ll add data attributes to the go_library and go_binary rules in rules_go_simple, the set of rules we’ve been working on. We’ll be working on the v3 branch. This won’t take long: we only need to add a few lines of code for each rule.

当文件在数据属性(或行为类似于数据属性的东西)中列出时,Bazel 会在运行时将该文件提供给使用 bazel run 启动的可执行文件。这对于各种事物都很有用,例如插件、配置文件、证书和密钥以及资源。

在本文中,我们将向 rules_go_simple 中的 go_library 和 go_binary 规则添加数据属性,这是我们一直在研究的规则集。我们将在 v3 分支上工作。这不会花很长时间:我们只需要为每个规则添加几行代码。

Data and runfiles

We can start by adding a data attribute to our rules. Here’s the new declaration for go_library. The attribute in go_binary is similar.

go_library = rule(implementation = _go_library_impl,attrs = {"srcs": attr.label_list(allow_files = [".go"],doc = "Source files to compile",),"deps": attr.label_list(providers = [GoLibraryInfo],doc = "Direct dependencies of the library",),"data": attr.label_list(allow_files = True,doc = "Data files available to binaries using this library",),"importpath": attr.string(mandatory = True,doc = "Name by which the library may be imported",),"_stdlib": attr.label(default = "//internal:stdlib",providers = [GoStdLibInfo],doc = "Hidden dependency on the Go standard library",),},doc = "Compiles a Go archive from Go sources and dependencies",
)

Bazel tracks files that should be made available at run-time using runfiles objects. You can create new runfiles objects with ctx.runfiles. In order to actually make files available, you need to put one of these in the runfiles field in the DefaultInfo provider returned by your rule. Recall that DefaultInfo is used to list the output files and executables produced by a rule.

Bazel 使用 runfiles 对象跟踪应在运行时提供的文件。您可以使用 ctx.runfiles 创建新的 runfiles 对象。为了真正使文件可用,您需要将其中一个文件放入规则返回的 DefaultInfo 提供程序中的 runfiles 字段中。回想一下,DefaultInfo 用于列出规则生成的输出文件和可执行文件。
Here’s how we create the DefaultInfo provider for go_library. Again, go_binary is similar.

return [DefaultInfo(files = depset([archive]),runfiles = ctx.runfiles(collect_data = True),),...
]

The expression ctx.runfiles(collect_data = True) gathers the files listed in the data attribute and the runfiles returned by rules in the deps and srcs attributes. That means any library can have data files, and they will be available to tests and binaries run with bazel run that link that library. There are a few different ways to call ctx.runfiles. If you set collect_data = True, as we did above, Bazel will collect data runfiles from dependencies in the srcs, deps, and data attributes. If you set collect_default = True, Bazel will collect default runfiles from the same dependencies. I have no idea what the distinction is between data and default runfiles, but when you construct DefaultInfo, you can set the data_runfiles or default_runfiles fields explicitly. If you just set runfiles, your files will be treated as both data and default.

What if you want to build the list of files explicitly? This is useful if you want to collect files from non-standard attributes, or if you create files within your rule. ctx.runfiles accepts a files argument, which is a simple list of files. You can access runfiles from your dependencies with an expression like dep[DefaultInfo].data_runfiles, where dep is a Target. You can combine runfiles objects using runfiles.merge, which returns a new runfiles object. So we could have implemented go_library like this:表达式 ctx.runfiles(collect_data = True) 收集 data 属性中列出的文件以及 deps 和 srcs 属性中的规则返回的运行文件。这意味着任何库都可以有数据文件,并且它们将可用于使用 bazel run 运行的链接该库的测试和二进制文件。有几种不同的方法可以调用 ctx.runfiles。如果设置 collect_data = True(如上所述),Bazel 将从 srcs、deps 和 data 属性中的依赖项中收集数据运行文件。如果设置 collect_default = True,Bazel 将从相同的依赖项中收集默认运行文件。我不知道数据和默认运行文件之间的区别是什么,但是当您构造 DefaultInfo 时,您可以明确设置 data_runfiles 或 default_runfiles 字段。如果您只设置运行文件,您的文件将被视为数据和默认文件。

如果您想明确构建文件列表怎么办?如果您想要从非标准属性中收集文件,或者在规则中创建文件,这将非常有用。ctx.runfiles 接受文件参数,即一个简单的文件列表。您可以使用类似 dep[DefaultInfo].data_runfiles 的表达式从依赖项中访问运行文件,其中 dep 是目标。您可以使用 runfiles.merge 组合运行文件对象,它会返回一个新的运行文件对象。因此,我们可以像这样实现 go_library:

# Gather runfiles.
runfiles = ctx.runfiles(files = ctx.files.data)
for dep in ctx.attr.deps:runfiles = runfiles.merge(dep[DefaultInfo].data_runfiles)# Return the output file and metadata about the library.
return [DefaultInfo(files = depset([archive]),runfiles = runfiles,),...
]

NOTE: When you have an attribute that is a label or label_list, you can access a list of all the files from all the labels using ctx.files (for example: ctx.files.data). This is almost always more convenient than going through ctx.attr (which gives you a Target or a list of Targets), since each target may have multiple files. If your label has allow_single_file = True set, you can also access the file through ctx.file. And if executable = True, you can access it through ctx.executable.注意:当您的属性是标签或 label_list 时,您可以使用 ctx.files(例如:ctx.files.data)访问所有标签中的所有文件列表。这几乎总是比通过 ctx.attr(它为您提供目标或目标列表)更方便,因为每个目标可能有多个文件。如果您的标签设置了 allow_single_file = True,您也可以通过 ctx.file 访问该文件。如果 executable = True,您可以通过 ctx.executable 访问它。

Testing data and runfiles

We test our new support for runfiles with a simple binary that depends on a library. Both binary and library have data files, and the test verifies they are present.

sh_test(name = "data_test",srcs = ["data_test.sh"],args = ["$(location :list_data_bin)"],data = [":list_data_bin"],
)go_binary(name = "list_data_bin",srcs = ["list_data_bin.go"],deps = [":list_data_lib"],data = ["foo.txt"],
)go_library(name = "list_data_lib",srcs = ["list_data_lib.go"],data = ["bar.txt"],importpath = "rules_go_simple/tests/list_data_lib"
)

You can run this test with bazel test //tests/…

Accessing runfiles, cross-platform

You should use a library to find and open runfiles, especially in tests. When Bazel executes a binary on Unix platforms, it creates a tree of symbolic links to the binary’s runfiles. If your code only ever runs on Unix platforms, you can open a runfile by opening its relative path within the workspace.
您应该使用库来查找和打开运行文件,尤其是在测试中。当 Bazel 在 Unix 平台上执行二进制文件时,它会创建一个指向二进制文件运行文件的符号链接树。如果您的代码只在 Unix 平台上运行,您可以通过在工作区内打开其相对路径来打开运行文件。
This is not generally safe because Bazel handles runfiles differently on Windows. In versions of Windows before about 2019, Windows required you to be an administrator to create symbolic links. Even now in consumer versions of Windows, you need to enable “Developer Mode” to create symbolic links, which requries administrator access. Creating a symbolic link on Windows is also surprisingly slow. To avoid these problems, Bazel uses another strategy: it creates a manifest file that maps logical runfile paths to absolute paths paths for the real files in Bazel’s cache. The manifest is pointed to by the RUNFILES_MANIFEST_FILE environment variable, which is set for tests. Nothing points to the manifest file for binaries run with bazel run, but you should find a file named MANIFEST in the initial working directory of the binary. (Incidentally, you can override this and force symbolic links with the Bazel flag --enable_runfiles).
这通常不安全,因为 Bazel 在 Windows 上处理运行文件的方式不同。在 2019 年之前的 Windows 版本中,Windows 要求您以管理员身份创建符号链接。即使现在在 Windows 的消费者版本中,您也需要启用“开发人员模式”来创建符号链接,这需要管理员访问权限。在 Windows 上创建符号链接也非常慢。为了避免这些问题,Bazel 使用了另一种策略:它创建一个清单文件,将逻辑运行文件路径映射到 Bazel 缓存中实际文件的绝对路径。清单由 RUNFILES_MANIFEST_FILE 环境变量指向,该变量是为测试设置的。对于使用 bazel run 运行的二进制文件,没有任何内容指向清单文件,但您应该在二进制文件的初始工作目录中找到一个名为 MANIFEST 的文件。(顺便说一句,您可以覆盖此文件并使用 Bazel 标志 --enable_runfiles 强制符号链接)。
It is best to use a library if one is available for your language, rather than parsing the manifest file on your own. Bazel’s runfile semantics change over time, as they are changing now with bzlmod, and using a library will keep your code working. Most languages provide such a library:

C++: @bazel_tools//tools/cpp/runfiles
Bash: @bazel_tools//tools/bash/runfiles
Java: @bazel_tools//tools/java/runfiles
Python: @rules_python//python/runfiles
Go: @io_bazel_rules_go//go/runfiles
Rust: @rules_rust//tools/runfiles
如果您的语言有可用的库,最好使用库,而不是自己解析清单文件。Bazel 的运行文件语义会随着时间的推移而发生变化,因为它们现在随着 bzlmod 而发生变化,使用库将使您的代码保持正常运行。大多数语言都提供了这样的库:

C++:@bazel_tools//tools/cpp/runfiles
Bash:@bazel_tools//tools/bash/runfiles
Java:@bazel_tools//tools/java/runfiles
Python:@rules_python//python/runfiles
Go:@io_bazel_rules_go//go/runfiles
Rust:@rules_rust//tools/runfiles

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/47406.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

简单实用的企业舆情安全解决方案

前言:企业舆情安全重要吗?其实很重要,尤其面对负面新闻,主动处理和应对,可以掌握主动权,避免股价下跌等,那么如何做使用简单实用的企业舆情解决方案呢? 背景 好了,提取词…

CSS技巧专栏:一日一例 7 - 纯CSS实现炫光边框按钮特效

CSS技巧专栏:一日一例 7 - 纯CSS实现炫光边框按钮特效 本例效果图 案例分析 相信你可能已经在网络见过类似这样的流光的按钮,在羡慕别人做的按钮这么酷的时候,你有没有扒一下它的源代码的冲动?或者你当时有点冲动,却…

【PostgreSQL】PostgreSQL简史

博主介绍:✌全网粉丝20W,CSDN博客专家、Java领域优质创作者,掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围:SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物…

基于python的百度资讯爬虫的设计与实现

研究背景 随着互联网和信息技术的飞速发展,网络已经成为人们获取信息的主要来源之一。特别是搜索引擎,作为信息检索的核心工具,极大地改变了人们获取信息的方式。其中,百度作为中国最受欢迎的搜索引擎之一,其新闻搜索…

开发扫地机器人系统时无法兼容手机解决方案

在开发扫地机器人系统时,遇到无法兼容手机的问题,可以从以下几个方面寻求解决方案: 一、了解兼容性问题根源 ① 操作系统差异:不同手机可能运行不同的操作系统(如iOS、Android),且即使是同一操…

leetcode简单题27 N.119 杨辉三角II rust描述

// 直接生成杨辉三角当前行 pub fn get_row(row_index: i32) -> Vec<i32> {let mut row vec![1; (row_index 1) as usize];for i in 1..row_index as usize {for j in (1..i).rev() {row[j] row[j] row[j - 1];}}row } // 空间优化的方法 pub fn get_row2(row_ind…

Java中的final关键字详解

Java中的final关键字详解 大家好&#xff0c;我是微赚淘客系统3.0的小编&#xff0c;是个冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01; 1. final关键字的基本用法 在Java中&#xff0c;final关键字可以用来修饰类、方法和变量&#xff0c;具有不同的含义和作用…

【QT】label适应图片(QImage)大小;图片适应label大小

目录 0.简介 1.详细代码 1&#xff09;label适应img大小 2&#xff09;img适应label大小 0.简介 一个小demo &#xff0c;想在QLabel中放一张QImage的图片&#xff0c;我有一张图片叫【bird.jpg】&#xff0c;是提前放在资源文件中的&#xff0c;直接显示在label上后&#…

【机器学习入门】拥抱人工智能,从机器学习开始

拥抱人工智能&#xff0c;从机器学习开始 目录&#xff1a; 1. 机器学习&#xff1a;一种实现人工智能的方法 2. 机器学习算法&#xff1a;是使计算机具有智能的关键 3. Anaconda&#xff1a;初学Python、入门机器学习的首选 4. 总结 转载链接&#xff1a; 文章-阿里云开发者社…

【LeetCode:试题 16.06. 最小差 + 双指针 + 防止整型溢出】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

ELK企业级日志分析

目 录 一、ELK简介 1.1 elasticsearch简介 1.2 logstash简介 1.3 kibana简介 1.4 ELK的好处 1.5 ELK的工作原理 二、部署ELK 2.1 部署elasticsearch(集群) 2.1.1 修改配置文件 2.1.2 修改系统参数 2.1.2.1 修改systemmd服务管理器 2.1.2.2 性能调优参数 2.1.2.3 …

Python编程工具PyCharm和Jupyter Notebook的使用差异

在编写Python程序时需要用到相应的编程工具&#xff0c;PyCharm和Jupyter Notebook是最常用2款软件。 PyCharm是很强大的综合编程软件&#xff0c;代码提示、代码自动补全、语法检验、文本彩色显示等对于新手来说实在太方便了&#xff0c;但在做数据分析时发现不太方便&#xf…

phpinfo

phpinfo() 是 PHP 中的一个内置函数&#xff0c;用于显示关于 PHP 配置的大量信息&#xff0c;包括已安装的扩展、PHP 版本、服务器信息、环境变量、注册的流封装器和包装器、路径、内存使用情况、上传文件大小限制、脚本运行时间限制等等。这对于调试和优化 PHP 应用程序非常有…

手写实现简单Redis命令客户端功能

RESP协议 Redis 的客户端和服务端之间采取了一种名为 Redis序列化的协议&#xff08;REdis Serialization Protocol&#xff0c;简称RESP&#xff09;&#xff0c;是基于 TCP 的应用层协议 &#xff0c;RESP 底层采用的是 TCP 的连接方式&#xff0c;通过 TCP 进行数据传输&am…

layui前端开发-记录一次弹窗嵌套表格功能的开发

1.碎碎念&#xff1a; 前端是真的难写哇&#xff0c;写的巨烂&#xff0c;毕竟平时很少写前端&#xff0c;很容易忘记。每次写都要抱着官方文档看&#xff0c;特此记录一下layui的使用。 大概就是打开一个弹窗实现一些button然后再渲染一个表格上去。 2.code&#xff1a; <…

基于嵌入式Linux的高性能车载娱乐系统设计与实现 —— 融合Qt、FFmpeg和CAN总线技术

随着汽车智能化的发展&#xff0c;车载娱乐系统已成为现代汽车的标配。本文介绍了一个基于Linux的车载娱乐系统的设计与实现过程。该系统集成了音视频娱乐、导航、车辆信息显示等功能&#xff0c;旨在提供安全、便捷、丰富的驾驶体验。 1. 项目概述 随着汽车智能化的发展&…

240717.学习日志——51单片机C语言版学习总结

课程资料 视频&#xff1a;51单片机入门教程&#xff1a;2020版 书籍&#xff1a;手把手教你学51单片机 开发板&#xff1a;普中51实验版 课程目录 1-1 课程简介 1-2 开发工具介绍及软件安装 1-3 单片机及开发板介绍 2-1 点亮一个LED 2-2 LED闪烁 2-3 LED流水灯 3-1…

postgresql删除用户

背景 **角色与用户**&#xff1a;在 PostgreSQL 中&#xff0c;用户和组的概念是通过“角色”来统一实现的。角色可以有登录权限&#xff08;在这种情况下&#xff0c;它们通常被称为“用户”&#xff09;&#xff0c;也可以没有&#xff08;在这种情况下&#xff0c;它们通常用…

Flutter笔记--WebSocket

Flutter中WebSocket这一块主要用的是插件web_socket_channel&#xff0c;它主要基于 WebSocket 协议&#xff0c;通过该协议实现与服务器之间的双向通信&#xff1b; web_socket_channel 插件的几个主要步骤&#xff1a; 1 连接到WebSocket服务器: 使用 WebSocketChannel.conn…

解决VSCode自动识别文件编码

在VScode 的 设置界面 输入 autoGuess 关键字 &#xff0c;勾选启用即可自动识别&#xff01;&#xff01;&#xff01;