如何进行Bazel中的自定义工具链分析,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。小编讲述 Bazel 自定义工具链的两种方式,Platform
和 Non-Platform
方式。会存在这两种方式的原因是 Bazel 的历史问题。例如,C++
相关规则使用 --cpu
和 --crosstool_top
来设置一个构建目标 CPU
和 C++
工具链,这样就可以实现选择不同的工具链构建 C++
项目。但是这都不能正确地表达出“平台”特征。使用这种方式不可避免地导致出现了笨拙且不准确的构建 APIs。这其中导致了对 Java 工具链基本没有涉及,Java 工具链就发展了他们自己的独立接口 --java_toolchain
。因此非平台方式(Non-Platform)的自定义工具链实现并没有统一的 APIs 来规范不同语言的跨平台构建。而 Bazel 的目标是在大型、混合语言、多平台项目中脱颖而出。这就要求对这些概念有更原则的支持,包括清晰的 APIs,这些 API 绑定而不是分散语言和项目。这就是新平台(platform)和工具链(toolchain) APIs 所实现的内容。如果没有去了解 Platform
和 Non-Platform
方式区别,可能会对上面说的内容有点不理解,这里通俗的来讲下这两者区别。比如我们编译 C++
和 Java
混合的相关项目,这个项目需要在多个平台下可以运行,因此涉及到多个平台下的工具链,而 C++
和 Java
的工具链是不一样的,非平台方式,对于 C++
,我们需要通过 --crosstool_top
来指定工具链集合,--cpu
来指定具体的某设备工具链;对于 Java
,则需要通过 --java_toolchain
、--host_java_toolchain
、--javabase
和 --host_javabase
来构建 Java
相关内容。这样一个 C++
和 Java
的混合项目,需要指定这么多的输入才能够完整编译项目。如果用了平台方式,那就简单了。首先理解平台概念很简单,平台就是一组约束值(constraint_value
)的集合,即比如一个平台可以由 OS
和 CPU
两个约束类型来决定,又或者一个平台可以由 OS
、CPU
和 GLibc_Version
来决定。则我们可以将 C++
相关编译的平台约束绑定平台,将 Java
相关编译的平台约束也绑定平台,这样就可以将混合语言项目统一到一个平台,即一旦确定了某个平台,那么只需要在命令行执行类似如下命令即可编译混合语言项目:目前平台方式构建在 Bazel 中并不完善。这些 APIs 不足以让所有项目都使用平台。Bazel 还必须淘汰旧的 APIs。这不是很容易就完成的任务,因为项目的所有语言、工具链、依赖项和 select()
都必须支持新的 APIs。这需要一个有序的迁移顺序来保持项目正常工作。Bazel 的 C++
相关规则已经支持平台,而 Android 相关规则不支持。你的 C++
项目可能不关心 Android,但其他人可能会。因此,在全球范围内启用所有 C++
平台构建方式是不安全的。已经完整支持平台构建方式的有:未来 Bazel
的目标是实现 $ bazel build //:all
,即一个命令行就可以构建任何项目和目标平台。通过上一章节的介绍,Non-Platform
方式,则是通过各项目性质采用对应的独立构建方式,比如 C++
相关的 --crosstool_top
和 --cpu
。Java
相关的 --java_toolchain
、--host_java_toolchain
、--javabase
和 --host_javabase
。这一节我们仅仅实现 C++
的 Non-Platform
方式构建(当然完整的平台构建方式并未完善,比如 Apple、Android 都还未支持平台构建方式)。在 Bazel 的官方文档中有一个教程已经详细地介绍了如何去配置一个 C++
工具链,具体见 https://docs.bazel.build/versions/master/tutorial/cc-toolchain-config.html ,主要涉及的内置规则有:cc_common
、cc_toolchain
、cc_toolchain_suite
。当然这里可以进一步去做一些工程上的优化:最后--crosstool_top=//toolchains/cpp:{cc_toolchain_suite的名称}
,--cpu={cc_toolchain的名称}
,即可实现交叉编译。整个实现内容这里就不贴出来了。为了简化 $ bazel build
命令,可以将默认配置项写入 .bazelrc
文件中:Bazel 可以在各种硬件、操作系统和系统配置上构建和测试代码,使用许多不同版本的构建工具,比如链接器和编译器。为了帮助管理这种复杂性,Bazel 提出了约束(constraints )和平台(platforms)的概念。约束是构建或生产环境可能不同的维度,比如 CPU 架构、GPU 的存在或缺失,或者系统安装的编译器的版本。如第一章所述,平台是这些约束的指定选择集合,表示在某些环境中可用的特定资源。将环境建模为平台有助于 Bazel 为构建操作自动选择适当的工具链。平台还可以与 config_setting
规则结合使用来编写可配置属性。Bazel 认为平台可以扮演三个角色:注:这里 Host 平台只是平台扮演一个角色的阐述,跟实际编写 Bazel 规则没有关系。toolchain
规则里也只有对执行平台和目标平台的约束设置。Bazel 支持以下针对平台的构建场景:平台的可能选择空间是通过使用构建文件中的 constraint_setting
和 constraint_value
规则定义的。constraint_setting
创建一个新维度,可以说是一个约束值集合,constraint_value
为给定维度(constraint_setting
)创建一个新值;它们一起有效地定义了枚举及其可能的值。简单来说,constraint_setting
和 constraint_value
就是一个单键多值的 map ,例如,下面的构建文件片段为系统的 glibc
版本 香港云主机引入了具有两个可能值的约束。约束及其值可以在工作区中的不同包之间定义。它们通过标签进行引用,并服从通常的可见性控制。如果可见性允许,你就可以通过定义自己的值来扩展现有的约束设置。平台规则 `platform`[1] 引入了一个具有特定约束值选择的新平台。下面创建了一个名为 linux_x86
的平台,描述了在 glibc
版本为 2.25
的 x86_64
体系结构上运行 Linux
操作系统的任何环境。注意,对于一个平台来说,同一个约束设置多个值是错误的,比如 glibc_2_25
和 glibc_2_26
不能同时设置,因为他们都属于 glibc_version
约束。为了保持生态系统的一致性,Bazel 团队维护了一个存储库,其中包含最流行的 CPU 架构和操作系统的约束定义。这些都位于 https://github.com/bazelbuild/platforms
。当然你也可以自己自定义。Bazel 附带以下特殊的平台定义 :@local_config_platform//:host
。会自动检测主机平台的值:表示 Bazel 运行的系统的平台。你可以使用以下命令行标志为构建指定主机和目标平台:在“前言”一章节中,可以知道平台可以实现混合语言项目的构建,而如果对每一种语言实现构建,则需要配置工具链以及实现工具链的平台约束设定。这样就可以将平台与工具链联合在一起了,原理类似依赖注入。工具链是使用 toolchain[2] 规则定义的目标,该规则将工具链实现与工具链类型相关联。工具链类型是使用 tooclhain_type()
规则定义的目标(其实用一个字符串常量也可以替代)。工具链实现是一个目标,它通过列出作为工具链一部分的文件(例如,编译器和标准库)以及使用该工具链所需的代码来表示实际的工具链。工具链实现必须返回 ToolchainInfo
Provider(Provider 可以认为就是一个函数的返回值),ToolchainInfo
存放着工具链相关配置信息,对于存放什么内容没有要求,即你可以定义任何你想要存放的信息。任何定义工具链的人都需要声明一个 toolchain_type
目标,这是一个字符串标识,用来标志工具链类别,以避免在加载了多个语言规则的工作区中出现潜在的冲突。比如 Bazel 官方提供了一个 CPP 的标识:@bazel_tools//tools/cpp:toolchain_type
,而 rules_go
提供了 @io_bazel_rules_go//go:toolchain
用以区分工具链类别。对于 C++
,cc_toolchain
规则即工具链实现,跟 Non-Platform
的工具链目标实现一致。当然你也可以使用任何返回 ToolchainInfo
的规则,而不仅仅是 cc_toolchain
,比如可以通过 platform_common.ToolchainInfo
创建一个 ToolchainInfo
,然后创建自己的工具链实现规则。工具链实现规则可以认为是面向对象中的类,我们可以 New 很多实例出来,这里 New 出来的就是很多不同平台架构或者不同版本的工具链了。完成工具链实例创建,就可以通过 native.toolchain
绑定工具链类型、目标平台、运行平台约束了。用户通过在 WORKSPACE 文件中调用 `register_toolchains`[3] 函数或者在命令行中传递 --extra_toolchains
标志来注册他们想要使用的工具链。最后,当 Bazel 开始构建时,它会检查执行和目标平台的约束条件。然后选择与这些约束兼容的一组合适的工具链。Bazel 将向请求它们的规则提供这些工具链的 ToolchainInfo 对象。如果想了解 Bazel 如何选择或拒绝注册的工具链,可以使用 --toolchain_resolution_debug
标志来调试。Bazel 的 C++
规则使用平台来选择工具链,需要设置 --incompatible_enable_cc_toolchain_resolution
,如果不设置,即使显示的在命令行加上--platforms
也不起作用。同样地,Platform
+ Toolchain
实现平台方式构建,官方文档也提供了一个样例,参见:https://docs.bazel.build/versions/master/toolchains.html 。总的步骤这里总结下:这里同样跟 Non-Platform
方式一样,对于 C++
,我们可以复用工具链的配置和 cc_toolchain
配置部分。工程上可以优化:--incompatible_enable_cc_toolchain_resolution
启动平台方式设置我们也可以将其放入 .bazelrc
全局构建配置文件中,从而省去命令行键入:看完上述内容,你们掌握如何进行Bazel中的自定义工具链分析的方法了吗?如果还想学到更多技能或想了解更多相关内容,欢迎关注开发云行业资讯频道,感谢各位的阅读!
本篇内容主要讲解“JDK15新特性介绍”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“JDK15新特性介绍”吧!TreeMap重新实现压倒性一切的如:putIfAbsent、computeIfAbsent、compu…
免责声明:本站发布的图片视频文字,以转载和分享为主,文章观点不代表本站立场,本站不承担相关法律责任;如果涉及侵权请联系邮箱:360163164@qq.com举报,并提供相关证据,经查实将立刻删除涉嫌侵权内容。