cc_binary(name, deps, srcs, data, additional_linker_inputs, args, aspect_hints, compatible_with, conlyopts, copts, cxxopts, defines, deprecation, dynamic_deps, env, exec_compatible_with, exec_group_compatible_with, exec_properties, features, hdrs_check, includes, licenses, link_extra_lib, linkopts, linkshared, linkstatic, local_defines, malloc, module_interfaces, nocopts, output_licenses, package_metadata, reexport_deps, restricted_to, stamp, tags, target_compatible_with, testonly, toolchains, visibility, win_def_file)

它会生成一个可执行的二进制文件。


目标的 name 应与作为应用主要入口点的源文件的名称相同(不含扩展名)。例如,如果您的入口点位于 main.cc 中,则您的名称应为 main

隐式输出目标

  • name .stripped (仅在明确请求时构建):二进制文件的精简版本。在二进制文件上运行 strip -g 以移除调试符号。可以使用 --stripopt=-foo 在命令行中提供其他剥离选项。
  • name .dwp (仅在明确请求时构建):如果启用了 Fission :适合用于调试远程部署的二进制文件的调试信息软件包文件。否则:一个空文件。
  • 用于创建库目标的 C 和 C++ 文件列表。 这些是 C/C++ 源文件和头文件,可以是未生成的(常规源代码),也可以是生成的。

    所有 .cc .c .cpp 文件都将被编译。这些可能是生成的文件:如果某个命名文件位于其他规则的 outs 中,则此 cc_library 将自动依赖于该其他规则。

    纯汇编器文件(.s、.asm)不会经过预处理,通常使用汇编器构建。预处理后的汇编文件 (.S) 经过预处理,通常使用 C/C++ 编译器构建。

    .h 文件不会被编译,但可供此规则中的来源包含。 .cc .h 文件可以直接包含这些 srcs 中列出的标头,也可以包含相应规则的 hdrs 中列出的标头,还可以包含 deps 实参中列出的任何规则的标头。

    所有 #include d 文件都必须在此规则或所引用规则的 hdrs 属性中提及,或者如果它们对此库是私有的,则应列在 srcs 中。 cc_library 如需更详细的说明,请参阅 “标头包含检查”

    .so .lo .a 文件是预编译的文件。如果您的库使用我们没有源代码的第三方代码,则可能将这些权限标记为 srcs

    如果 srcs 属性包含其他规则的标签, cc_library 将使用该规则的输出文件作为要编译的源文件。这对于一次性生成源代码非常有用(如果需要经常使用,最好实现一个 Starlark 规则类并使用 cc_common API) 允许的 srcs 文件类型:

  • C 和 C++ 源文件: .c .cc .cpp .cxx .c++ .C
  • C 和 C++ 头文件: .h .hh .hpp .hxx .inc .inl .H
  • 带有 C 预处理器的汇编器: .S
  • 归档: .a .pic.a
  • “始终链接”库: .lo .pic.lo
  • 共享库(已添加版本信息或未添加版本信息): .so .so. version
  • 对象文件: .o .pic.o
  • ... 以及生成这些文件的任何规则(例如 cc_embed_data )。 根据 gcc 惯例,不同的扩展名表示不同的编程语言。

    如果 data 是生成文件的名称,则此 cc_library 规则会自动依赖于生成规则。

    如果 data 是规则名称,则此 cc_library 规则会自动依赖于该规则,并且该规则的 outs 会自动添加到此 cc_library 的数据文件中。

    您的 C++ 代码可以按如下方式访问这些数据文件:

    const std::string path = devtools_build::GetDataDependencyFilepath( "my/test/data/file"); 仅提供给 C++ 链接器命令的依赖项。 deps 在概念上是为编译和链接依赖项而设计的,而 additional_linker_inputs 专门用于链接依赖项,并表示仅在链接时需要的依赖项(例如,在 linkopts 中引用的文件)。

    例如,此处可以提供已编译的 Windows .res 文件,以便将其嵌入到二进制目标中。 将这些选项添加到 C/C++ 编译命令中。受 “创建变量” 替换和 Bourne shell 令牌化 的影响。 此属性中的每个字符串都会按指定顺序添加到 COPTS 中,然后再编译二进制目标。这些标志仅对编译此目标有效,对其依赖项无效,因此请注意其他位置包含的头文件。 所有路径都应相对于工作区,而不是相对于当前软件包。 此属性不应在 third_party 之外使用。 如果软件包声明了 feature no_copts_tokenization ,则 Bourne shell 令牌化仅适用于由单个“Make”变量组成的字符串。

    要添加到编译行的包含目录的列表。 需进行 “创建变量” 替换。 每个字符串前面都会附加软件包路径,并通过“include_paths”CROSSTOOL 功能传递给 C++ 工具链以进行扩展。在具有典型功能定义的 POSIX 系统上运行的工具链将生成 -isystem path_to_package/include_entry 。此属性仅应用于不符合 Google 编写 #include 语句的样式的第三方库。与 COPTS 不同,这些标志会添加到相应规则以及依赖于该规则的每个规则中。(注意:不是它所依赖的规则!)请务必谨慎操作,因为这可能会产生深远的影响。如果不确定,请改为向 COPTS 添加“-I”标志。 添加的 include 路径将包含生成的文件以及源代码树中的文件。

    如需启用此属性,请在规则中添加 linkshared=True 。默认情况下,此选项处于关闭状态。 此标志的存在意味着链接时使用 -shared 标志链接到 gcc ,并且生成的共享库适合加载到 Java 程序等中。不过,出于构建目的,它永远不会关联到依赖的二进制文件中,因为假定使用 cc_binary 规则构建的共享库仅由其他程序手动加载,因此不应将其视为 cc_library 规则的替代项。为了实现可伸缩性,我们建议完全避免使用此方法,而只需让 java_library 依赖于 cc_library 规则即可。

    如果您同时指定 linkopts=['-static'] linkshared=True ,则会获得一个完全自包含的单元。如果您同时指定 linkstatic=True linkshared=True ,则会获得一个主要自包含的单元。

    布尔值;默认值为 True

    对于 cc_binary cc_test :以静态模式关联二进制文件。对于 cc_library.link_static :请参阅下文。

    默认情况下,此选项对 cc_binary 处于开启状态,对其他设备处于关闭状态。

    如果已启用且这是二进制文件或测试,此选项会告知 build 工具尽可能链接用户库的 .a 而不是 .so 。libc 等系统库(但 包括 C/C++ 运行时库,请参阅下文)仍会动态链接,没有静态库的库也是如此。因此,生成的可执行文件仍将是动态链接的,因此只能说是 大部分 静态。

    实际上,关联可执行文件有三种不同的方式:
  • 具有 fully_static_link 功能的 STATIC,其中所有内容都以静态方式链接;例如“ gcc -static foo.o libbar.a libbaz.a -lm ”。
    通过在 features 属性中指定 fully_static_link 来启用此模式。
  • STATIC:所有用户库都以静态方式关联(如果提供静态版本),但系统库(C/C++ 运行时库除外)以动态方式关联,例如“ gcc foo.o libfoo.a libbaz.a -lm ”。
    通过指定 linkstatic=True 启用此模式。
  • DYNAMIC:所有库都动态链接(如果存在动态版本),例如“ gcc foo.o libfoo.so libbaz.so -lm ”。
    通过指定 linkstatic=False 启用此模式。
  • 如果 linkstatic 属性或 features 中的 fully_static_link //third_party 之外使用,请在规则附近添加注释以说明原因。 如果 linkstatic 属性用于 cc_library() 规则,则具有不同的含义。对于 C++ 库, linkstatic=True 表示只允许静态链接,因此不会生成 .so 。linkstatic=False 不会阻止创建静态库。该属性旨在控制动态库的创建。

    在生产环境中,使用 linkstatic=False 构建的代码应该非常少。 如果值为 linkstatic=False ,则构建工具将在 *.runfiles 区域中创建指向所依赖的共享库的符号链接。

    替换对 malloc 的默认依赖项。 默认情况下,C++ 二进制文件会链接到 //tools/cpp:malloc ,这是一个空库,因此二进制文件最终会使用 libc malloc。 此标签必须引用 cc_library 。如果编译是针对非 C++ 规则的,此选项不会产生任何影响。如果指定了 linkshared=True ,系统会忽略此属性的值。 stamp = 1 :始终将 build 信息标记到二进制文件中,即使在 --nostamp build 中也是如此。 应避免使用此设置 ,因为它可能会终止二进制文件和依赖于它的任何下游操作的远程缓存。 stamp = 0 :始终将 build 信息替换为常量值。这可实现良好的 build 结果缓存。 stamp = -1 :构建信息的嵌入由 --[no]stamp 标志控制。

    除非已加戳记的二进制文件发生依赖项更改,否则 不会 重新构建。

    cc_import(name, deps, data, hdrs, alwayslink, aspect_hints, compatible_with, deprecation, exec_compatible_with, exec_group_compatible_with, exec_properties, features, includes, interface_library, linkopts, objects, package_metadata, pic_objects, pic_static_library, restricted_to, shared_library, static_library, strip_include_prefix, system_provided, tags, target_compatible_with, testonly, toolchains, visibility)
    cc_import 规则允许用户导入预编译的 C/C++ 库。

    以下是典型使用场景:
    1. 关联静态库 cc_import( name = "mylib", hdrs = ["mylib.h"], static_library = "libmylib.a", # If alwayslink is turned on, # libmylib.a will be forcely linked into any binary that depends on it. # alwayslink = True, 2. 关联共享库 (Unix) cc_import( name = "mylib", hdrs = ["mylib.h"], shared_library = "libmylib.so", 3. 将共享库与接口库相关联

    在 Unix 上: cc_import( name = "mylib", hdrs = ["mylib.h"], # libmylib.ifso is an interface library for libmylib.so which will be passed to linker interface_library = "libmylib.ifso", # libmylib.so will be available for runtime shared_library = "libmylib.so",

    在 Windows 上: cc_import( name = "mylib", hdrs = ["mylib.h"], # mylib.lib is an import library for mylib.dll which will be passed to linker interface_library = "mylib.lib", # mylib.dll will be available for runtime shared_library = "mylib.dll", 4. 将共享库与 system_provided=True 相关联

    在 Unix 上: cc_import( name = "mylib", hdrs = ["mylib.h"], interface_library = "libmylib.ifso", # Or we can also use libmylib.so as its own interface library # libmylib.so is provided by system environment, for example it can be found in LD_LIBRARY_PATH. # This indicates that Bazel is not responsible for making libmylib.so available. system_provided = True,

    在 Windows 上: cc_import( name = "mylib", hdrs = ["mylib.h"], # mylib.lib is an import library for mylib.dll which will be passed to linker interface_library = "mylib.lib", # mylib.dll is provided by system environment, for example it can be found in PATH. # This indicates that Bazel is not responsible for making mylib.dll available. system_provided = True, 5. 关联到静态库或共享库

    在 Unix 上: cc_import( name = "mylib", hdrs = ["mylib.h"], static_library = "libmylib.a", shared_library = "libmylib.so",

    在 Windows 上: cc_import( name = "mylib", hdrs = ["mylib.h"], static_library = "libmylib.lib", # A normal static library interface_library = "mylib.lib", # An import library for mylib.dll shared_library = "mylib.dll",

    在 Unix 和 Windows 上,其余部分相同: # first will link to libmylib.a (or libmylib.lib) cc_binary( name = "first", srcs = ["first.cc"], deps = [":mylib"], linkstatic = True, # default value # second will link to libmylib.so (or libmylib.lib) cc_binary( name = "second", srcs = ["second.cc"], deps = [":mylib"], linkstatic = False, cc_import 支持 include 属性。例如: cc_import( name = "curl_lib", hdrs = glob(["vendor/curl/include/curl/*.h"]), includes = ["vendor/curl/include"], shared_library = "vendor/curl/lib/.libs/libcurl.dylib",

    布尔值;默认值为 False

    如果值为 1,则任何依赖于(直接或间接)此 C++ 预编译库的二进制文件都将链接到静态库中归档的所有对象文件,即使某些对象文件不包含二进制文件引用的符号也是如此。如果您的代码未被二进制文件中的代码显式调用,例如,如果您的代码注册为接收由某个服务提供的回调,则此方法非常有用。

    如果 alwayslink 在 Windows 上无法与 VS 2017 搭配使用,这是由于 已知问题 所致,请将 VS 2017 升级到最新版本。

    要添加到编译行的包含目录的列表。 需进行 “创建变量” 替换。 每个字符串前面都会附加软件包路径,并通过“include_paths”CROSSTOOL 功能传递给 C++ 工具链以进行扩展。在具有典型功能定义的 POSIX 系统上运行的工具链将生成 -isystem path_to_package/include_entry 。此属性仅应用于不符合 Google 编写 #include 语句的样式的第三方库。与 COPTS 不同,这些标志会添加到相应规则以及依赖于该规则的每个规则中。(注意:不是它所依赖的规则!)请务必谨慎操作,因为这可能会产生深远的影响。如果不确定,请改为向 COPTS 添加“-I”标志。 默认的 include 路径不包含生成的文件。如果您需要 #include 生成的头文件,请在 srcs 中列出该文件。

    cc_library(name, deps, srcs, data, hdrs, additional_compiler_inputs, additional_linker_inputs, alwayslink, aspect_hints, compatible_with, conlyopts, copts, cxxopts, defines, deprecation, exec_compatible_with, exec_group_compatible_with, exec_properties, features, hdrs_check, implementation_deps, include_prefix, includes, licenses, linkopts, linkstamp, linkstatic, local_defines, module_interfaces, package_metadata, restricted_to, strip_include_prefix, tags, target_compatible_with, testonly, textual_hdrs, toolchains, visibility, win_def_file)

    对于 C++ 编译的库,请使用 cc_library() 。 结果可以是 .so .lo .a ,具体取决于需要什么。 如果您构建的某个内容通过静态链接依赖于 cc_library ,则所依赖的库规则的输出是 .a 文件。如果您指定 alwayslink=True ,则会获得 .lo 文件。

    共享库的实际输出文件名是 lib foo .so ,其中 foo 是规则的名称。其他类型的库分别以 .lo .a 结尾。如果您需要特定的共享库名称(例如,为了定义 Python 模块),请使用 genrule 将库复制到所需的名称。

    标头包含情况检查

    构建中使用的所有头文件都必须在 cc_* 规则的 hdrs srcs 中声明。 这是强制执行的。 对于 cc_library 规则, hdrs 中的头文件构成库的公共接口,可以直接从库本身的 hdrs srcs 中的文件以及 cc_* 规则(在其 deps 中列出该库)的 hdrs srcs 中的文件进行包含。 srcs 中的头文件只能直接从库本身的 hdrs srcs 中的文件包含。在决定是将标头放入 hdrs 还是 srcs 时,您应考虑是否希望此库的消费者能够直接包含该标头。这与编程语言中 public private 可见性之间的选择大致相同。

    cc_binary cc_test 规则没有导出的接口,因此也没有 hdrs 属性。属于二进制文件或测试的所有标头都应直接列在 srcs 中。

    为了说明这些规则,请看以下示例。 cc_binary( name = "foo", srcs = [ "foo.cc", "foo.h", deps = [":bar"], cc_library( name = "bar", srcs = [ "bar.cc", "bar-impl.h", hdrs = ["bar.h"], deps = [":baz"], cc_library( name = "baz", srcs = [ "baz.cc", "baz-impl.h", hdrs = ["baz.h"], 下表列出了此示例中允许的直接包含项。 例如, foo.cc 可以直接包含 foo.h bar.h ,但不包含 baz.h

    包含文件允许的包含项 foo.hbar.h foo.ccfoo.h bar.h bar.hbar-impl.h baz.h bar-impl.hbar.h baz.h bar.ccbar.h bar-impl.h baz.h baz.hbaz-impl.h baz-impl.hbaz.h baz.ccbaz.h baz-impl.h 纳入检查规则仅适用于 直接 纳入。在上面的示例中, foo.cc 可以包含 bar.h ,而 bar.h 可以包含 baz.h baz.h 又可以包含 baz-impl.h 。从技术上讲, .cc 文件的编译可能会以传递方式包含传递 deps 闭包中任何 cc_library 内的 hdrs srcs 中的任何头文件。在这种情况下,编译器在编译 foo.cc 时可能会读取 baz.h baz-impl.h ,但 foo.cc 不得包含 #include "baz.h" 。如需允许这样做,必须将 baz 添加到 foo deps 中。

    Bazel 依赖于工具链支持来强制执行包含检查规则。 工具链必须支持 layering_check 功能,并且必须明确请求该功能,例如通过 --features=layering_check 命令行标志或 package 函数的 features 参数。Bazel 提供的工具链仅支持在 Unix 和 macOS 上使用 clang 实现此功能。

    我们使用 alwayslink 标志强制链接器链接此代码,即使主二进制代码未引用它也是如此。 cc_library( name = "ast_inspector_lib", srcs = ["ast_inspector_lib.cc"], hdrs = ["ast_inspector_lib.h"], visibility = ["//visibility:public"], deps = ["//third_party/llvm/llvm/tools/clang:frontend"], # alwayslink as we want to be able to call things in this library at # debug time, even if they aren't used anywhere in the code. alwayslink = True,

    以下示例来自 third_party/python2_4_3/BUILD 。 部分代码使用了 dl 库(用于加载另一个动态库),因此此规则指定了 -ldl 链接选项来链接 dl 库。

    cc_library( name = "python2_4_3", linkopts = [ "-ldl", "-lutil", deps = ["//third_party/expat"],

    以下示例来自 third_party/kde/BUILD 。 我们在代码库中保留预构建的 .so 文件。 头文件位于名为 include 的子目录中。

    cc_library( name = "kde", srcs = [ "lib/libDCOP.so", "lib/libkdesu.so", "lib/libkhtml.so", "lib/libkparts.so", ...more .so files... , includes = ["include"], deps = ["//third_party/X11"],

    以下示例来自 third_party/gles/BUILD 。 第三方代码通常需要一些 defines linkopts 。 cc_library( name = "gles", srcs = [ "GLES/egl.h", "GLES/gl.h", "ddx.c", "egl.c", defines = [ "USE_FLOAT", "__GL_FLOAT", "__GL_COMMON", linkopts = ["-ldl"], # uses dlopen(), dl library deps = [ "es", "//third_party/X11",

    这些应该是 C++ 库规则的名称。 当您构建链接此规则的库的二进制文件时,您还将链接 deps 中的库。

    尽管名称为“deps”,但此库并非所有客户端都属于此处。运行时数据依赖项属于 data 。 由其他规则生成的源文件应放在 srcs 中。

    如需链接预编译的第三方库,请改为将该库的名称添加到 srcs 中。

    如需依赖某个内容,但不将其链接到此库,请改为将该内容的名称添加到 data 中。

    用于创建库目标的 C 和 C++ 文件列表。 这些是 C/C++ 源文件和头文件,可以是未生成的(常规源代码),也可以是生成的。

    所有 .cc .c .cpp 文件都将被编译。这些可能是生成的文件:如果某个命名文件位于其他规则的 outs 中,则此 cc_library 将自动依赖于该其他规则。

    纯汇编器文件(.s、.asm)不会经过预处理,通常使用汇编器构建。预处理后的汇编文件 (.S) 经过预处理,通常使用 C/C++ 编译器构建。

    .h 文件不会被编译,但可供此规则中的来源包含。 .cc .h 文件可以直接包含这些 srcs 中列出的标头,也可以包含相应规则的 hdrs 中列出的标头,还可以包含 deps 实参中列出的任何规则的标头。

    所有 #include d 文件都必须在此规则或所引用规则的 hdrs 属性中提及,或者如果它们对此库是私有的,则应列在 srcs 中。 cc_library 如需更详细的说明,请参阅 “标头包含检查”

    .so .lo .a 文件是预编译的文件。如果您的库使用我们没有源代码的第三方代码,则可能将这些权限标记为 srcs

    如果 srcs 属性包含其他规则的标签, cc_library 将使用该规则的输出文件作为要编译的源文件。这对于一次性生成源代码非常有用(如果需要经常使用,最好实现一个 Starlark 规则类并使用 cc_common API) 允许的 srcs 文件类型:

  • C 和 C++ 源文件: .c .cc .cpp .cxx .c++ .C
  • C 和 C++ 头文件: .h .hh .hpp .hxx .inc .inl .H
  • 带有 C 预处理器的汇编器: .S
  • 归档: .a .pic.a
  • “始终链接”库: .lo .pic.lo
  • 共享库(已添加版本信息或未添加版本信息): .so .so. version
  • 对象文件: .o .pic.o
  • ... 以及生成这些文件的任何规则(例如 cc_embed_data )。 根据 gcc 惯例,不同的扩展名表示不同的编程语言。

    如果 data 是生成文件的名称,则此 cc_library 规则会自动依赖于生成规则。

    如果 data 是规则名称,则此 cc_library 规则会自动依赖于该规则,并且该规则的 outs 会自动添加到此 cc_library 的数据文件中。

    您的 C++ 代码可以按如下方式访问这些数据文件:

    const std::string path = devtools_build::GetDataDependencyFilepath( "my/test/data/file");

    标签 列表;默认值为 []

    此库发布的头文件列表,供依赖规则中的来源直接包含。

    强烈建议在此位置声明描述库接口的头文件。这些标头将可供此规则或相关规则中的来源包含。 不打算由相应库的客户端包含的标头应列在 srcs 属性中,即使它们包含在已发布的标头中也是如此。如需了解更详细的说明,请参阅 “标头包含检查”

    允许使用的 headers 文件类型: .hh .hpp .hxx 。 仅提供给 C++ 链接器命令的依赖项。 deps 在概念上是为编译和链接依赖项而设计的,而 additional_linker_inputs 专门用于链接依赖项,并表示仅在链接时需要的依赖项(例如,在 linkopts 中引用的文件)。

    例如,此处可以提供已编译的 Windows .res 文件,以便将其嵌入到二进制目标中。

    布尔值;默认值为 False

    如果值为 1,则任何直接或间接依赖于此 C++ 库的二进制文件都会链接到 srcs 中列出的文件的所有目标文件,即使其中一些文件不包含二进制文件引用的符号也是如此。如果您的代码未被二进制文件中的代码显式调用,例如,如果您的代码注册为接收由某个服务提供的回调,则此方法非常有用。

    如果 alwayslink 在 Windows 上无法与 VS 2017 搭配使用,这是由于 已知问题 所致,请将 VS 2017 升级到最新版本。

    将这些选项添加到 C/C++ 编译命令中。受 “创建变量” 替换和 Bourne shell 令牌化 的影响。 此属性中的每个字符串都会按指定顺序添加到 COPTS 中,然后再编译二进制目标。这些标志仅对编译此目标有效,对其依赖项无效,因此请注意其他位置包含的头文件。 所有路径都应相对于工作区,而不是相对于当前软件包。 此属性不应在 third_party 之外使用。 如果软件包声明了 feature no_copts_tokenization ,则 Bourne shell 令牌化仅适用于由单个“Make”变量组成的字符串。

    设置后,此规则的 hdrs 属性中的标头可通过以下方式访问:将此属性的值附加到其相对于代码库的路径前面。

    系统会先移除 strip_include_prefix 属性中的前缀,然后再添加此属性。

    此属性仅在 third_party 下合法。 要添加到编译行的包含目录的列表。 需进行 “创建变量” 替换。 每个字符串前面都会附加软件包路径,并通过“include_paths”CROSSTOOL 功能传递给 C++ 工具链以进行扩展。在具有典型功能定义的 POSIX 系统上运行的工具链将生成 -isystem path_to_package/include_entry 。此属性仅应用于不符合 Google 编写 #include 语句的样式的第三方库。与 COPTS 不同,这些标志会添加到相应规则以及依赖于该规则的每个规则中。(注意:不是它所依赖的规则!)请务必谨慎操作,因为这可能会产生深远的影响。如果不确定,请改为向 COPTS 添加“-I”标志。 添加的 include 路径将包含生成的文件以及源代码树中的文件。

    字符串列表;默认值为 []

    请参阅 cc_binary.linkopts linkopts 属性还会应用于通过 deps 属性(或通过其他类似属性: cc_binary malloc 属性)直接或间接依赖于此库的任何目标。依赖项 linkopts 的优先级高于被依赖项 linkopts(即,依赖项 linkopts 会显示在命令行中更靠后的位置)。在 --linkopt 中指定的 linkopts 优先于规则 linkopts。

    请注意, linkopts 属性仅在创建 .so 文件或可执行文件时适用,而在创建 .a .lo 文件时则不适用。 因此,如果设置了 linkstatic=True 属性, linkopts 属性对创建此库没有影响,仅对依赖于此库的其他目标有影响。

    另请务必注意,不支持“-Wl,-soname”或“-Xlinker -soname”选项,并且绝不应在此属性中指定这些选项。

    cc_library 规则生成的 .so 文件不会链接到它们所依赖的库。如果您尝试创建要在主代码库外部使用的共享库(例如,手动与 dlopen() LD_PRELOAD 搭配使用),最好使用带有 linkshared=True 属性的 cc_binary 规则。请参阅 cc_binary.linkshared

    布尔值;默认值为 False

    对于 cc_binary cc_test :以静态模式关联二进制文件。对于 cc_library.link_static :请参阅下文。

    默认情况下,此选项对 cc_binary 处于开启状态,对其他设备处于关闭状态。

    如果已启用且这是二进制文件或测试,此选项会告知 build 工具尽可能链接用户库的 .a 而不是 .so 。libc 等系统库(但 包括 C/C++ 运行时库,请参阅下文)仍会动态链接,没有静态库的库也是如此。因此,生成的可执行文件仍将是动态链接的,因此只能说是 大部分 静态。

    实际上,关联可执行文件有三种不同的方式:
  • 具有 fully_static_link 功能的 STATIC,其中所有内容都以静态方式链接;例如“ gcc -static foo.o libbar.a libbaz.a -lm ”。
    通过在 features 属性中指定 fully_static_link 来启用此模式。
  • STATIC:所有用户库都以静态方式关联(如果提供静态版本),但系统库(C/C++ 运行时库除外)以动态方式关联,例如“ gcc foo.o libfoo.a libbaz.a -lm ”。
    通过指定 linkstatic=True 启用此模式。
  • DYNAMIC:所有库都动态链接(如果存在动态版本),例如“ gcc foo.o libfoo.so libbaz.so -lm ”。
    通过指定 linkstatic=False 启用此模式。
  • 如果 linkstatic 属性或 features 中的 fully_static_link //third_party 之外使用,请在规则附近添加注释以说明原因。 如果 linkstatic 属性用于 cc_library() 规则,则具有不同的含义。对于 C++ 库, linkstatic=True 表示只允许静态链接,因此不会生成 .so 。linkstatic=False 不会阻止创建静态库。该属性旨在控制动态库的创建。

    在生产环境中,使用 linkstatic=False 构建的代码应该非常少。 如果值为 linkstatic=False ,则构建工具将在 *.runfiles 区域中创建指向所依赖的共享库的符号链接。

    cc_shared_library(name, deps, additional_linker_inputs, aspect_hints, compatible_with, deprecation, dynamic_deps, exec_compatible_with, exec_group_compatible_with, exec_properties, exports_filter, features, package_metadata, restricted_to, roots, shared_lib_name, static_deps, tags, target_compatible_with, testonly, toolchains, user_link_flags, visibility, win_def_file)

    它会生成一个共享库。

    cc_shared_library( name = "foo_shared", deps = [ ":foo", dynamic_deps = [ ":bar_shared", additional_linker_inputs = [ ":foo.lds", user_link_flags = [ "-Wl,--version-script=$(location :foo.lds)", cc_library( name = "foo", srcs = ["foo.cc"], hdrs = ["foo.h"], deps = [ ":bar", ":baz", cc_shared_library( name = "bar_shared", shared_lib_name = "bar.so", deps = [":bar"], cc_library( name = "bar", srcs = ["bar.cc"], hdrs = ["bar.h"], cc_library( name = "baz", srcs = ["baz.cc"], hdrs = ["baz.h"],

    在示例中, foo_shared 静态链接 foo baz ,后者是传递依赖项。它不链接 bar ,因为 dynamic_dep bar_shared 已经动态提供了该链接。

    foo_shared 使用链接器脚本 *.lds 文件来控制应导出哪些符号。 cc_shared_library 规则逻辑不控制导出哪些符号,它仅使用假定导出的内容,以便在分析阶段发现两个共享库导出相同目标时给出错误。

    cc_shared_library 的每个直接依赖项都被假定为已导出。因此,Bazel 在分析期间会假定 foo foo_shared 导出。 baz 不会被 foo_shared 假定为已导出。 exports_filter 匹配的每个目标也被假定为已导出。

    示例中的每个 cc_library 最多只能出现在一个 cc_shared_library 中。如果我们还想将 baz 链接到 bar_shared 中,则需要向 baz 添加 tags = ["LINKABLE_MORE_THAN_ONCE"]

    由于存在 shared_lib_name 属性, bar_shared 生成的文件将命名为 bar.so ,而不是 Linux 上的默认名称 libbar.so

    Two shared libraries in dependencies export the same symbols.

    当您创建具有两个不同 cc_shared_library 依赖项(导出同一目标)的目标时,就会发生这种情况。如需解决此问题,您需要阻止在某个 cc_shared_library 依赖项中导出库。

    当您创建具有两个不同 cc_shared_library 依赖项的新 cc_shared_library 时,如果这两个依赖项静态链接到同一目标,就会发生这种情况。与导出错误类似。

    一种解决方法是停止将该库链接到某个 cc_shared_library 依赖项中。与此同时,仍链接该库的模块需要导出该库,以便未链接该库的模块能够继续看到这些符号。另一种方法是提取导出目标的第三方库。第三种方法是使用 LINKABLE_MORE_THAN_ONCE 标记有问题的 cc_library ,但这种修复方法应该很少使用,并且您必须确保 cc_library 确实可以安全地链接多次。

    '//foo:foo' is already linked statically in '//bar:bar' but not exported`

    这意味着, deps 的传递闭包中的某个库无需通过某个 cc_shared_library 依赖项即可访问,但已链接到 dynamic_deps 中的另一个 cc_shared_library ,并且未导出。

    解决方案是从 cc_shared_library 依赖项中导出它,或者提取导出它的第三方 cc_shared_library

    Do not place libraries which only contain a precompiled dynamic library in deps.

    如果您有预编译的动态库,则无需将其静态链接到您当前正在创建的 cc_shared_library 目标中,也无法这样做。因此,它不属于 cc_shared_library deps 。如果此预编译的动态库是某个 cc_libraries 的依赖项,则 cc_library 需要直接依赖于它。

    Trying to export a library already exported by a different shared library

    如果您在当前规则中声明要导出某个目标,而该目标已由您的某个动态依赖项导出,则会看到此错误。

    如需修正此问题,请从 deps 中移除目标,仅依赖于动态依赖项中的目标,或确保 exports_filter 不会捕获此目标。

    在分析期间,规则实现会将 deps 中列出的任何目标视为由共享库导出,以便在多个 cc_shared_libraries 导出相同目标时给出错误。规则实现不会负责告知链接器哪些符号应由共享对象导出。用户应通过链接器脚本或源代码中的可见性声明来处理此问题。

    如果同一库静态链接到多个 cc_shared_library 中,该实现也会触发错误。为避免这种情况,您可以向 cc_library.tags 添加 "LINKABLE_MORE_THAN_ONCE" ,也可以将 `cc_library` 列为某个共享库的导出项,以便一个共享库成为另一个共享库的 dynamic_dep

    请注意,此属性实际上并未向这些目标添加依赖关系边,依赖关系边应由 deps 创建。此属性中的条目只是字符串。请注意,在此属性中放置目标时,这会被视为声明共享库从该目标导出符号。 cc_shared_library 逻辑实际上并不处理告知链接器哪些符号应导出。

    允许使用以下语法:

    //foo:__pkg__ ,用于表示 foo/BUILD 中的任何目标

    //foo:__subpackages__ ,以涵盖 foo/BUILD 中的任何目标或 foo/ 下的任何其他软件包(例如 foo/bar/BUILD)

    字符串列表;默认值为 []

    您可能想要传递给链接器的任何其他标志。例如,如需让链接器了解通过 additional_linker_inputs 传递的链接器脚本,您可以使用以下代码: cc_shared_library( name = "foo_shared", additional_linker_inputs = select({ "//src/conditions:linux": [ ":foo.lds", ":additional_script.txt", "//conditions:default": []}), user_link_flags = select({ "//src/conditions:linux": [ "-Wl,-rpath,kittens", "-Wl,--version-script=$(location :foo.lds)", "-Wl,--script=$(location :additional_script.txt)", "//conditions:default": []}),
    cc_static_library(name, deps, aspect_hints, compatible_with, deprecation, exec_compatible_with, exec_group_compatible_with, exec_properties, features, package_metadata, restricted_to, tags, target_compatible_with, testonly, toolchains, visibility)
    根据目标列表及其传递依赖项生成静态库。

    生成的静态库包含 deps 中列出的目标及其传递依赖项的对象文件,并优先考虑 PIC 对象。

    linkdeps

    一个文本文件,其中包含 deps 中列出的目标的传递依赖项的标签,这些依赖项未向静态库贡献任何对象文件,但至少提供了一个静态库、动态库或接口库。生成的静态库可能需要在链接时提供这些库。

    linkopts

    一个文本文件,其中包含 deps 中列出的目标的所有传递依赖项的用户提供的 linkopts

    重复的符号

    默认情况下, cc_static_library 规则会检查生成的静态库是否不包含任何重复符号。如果存在,build 会失败,并显示一条错误消息,其中列出了重复的符号以及包含这些符号的对象文件。

    您可以通过设置 features = ["-symbol_check"] 或通过 --features=-symbol_check 全局停用此检查,也可以按目标或按软件包停用此检查。

    针对 symbol_check 的工具链支持

    随 Bazel 提供的自动配置的 C++ 工具链在所有平台上都支持 symbol_check 功能。自定义工具链可以通过以下两种方式之一添加对它的支持:

  • 实现 ACTION_NAMES.validate_static_library 操作,并通过 symbol_check 功能启用该操作。操作中的工具集会使用两个实参进行调用,即要检查重复符号的静态库和检查通过时必须创建的文件的路径。
  • 启用 symbol_check 功能会添加归档器标志,导致创建静态库的操作因符号重复而失败。
  • cc_test(name, deps, srcs, data, additional_linker_inputs, args, aspect_hints, compatible_with, conlyopts, copts, cxxopts, defines, deprecation, dynamic_deps, env, env_inherit, exec_compatible_with, exec_group_compatible_with, exec_properties, features, flaky, hdrs_check, includes, licenses, link_extra_lib, linkopts, linkshared, linkstatic, local, local_defines, malloc, module_interfaces, nocopts, package_metadata, reexport_deps, restricted_to, shard_count, size, stamp, tags, target_compatible_with, testonly, timeout, toolchains, visibility, win_def_file)
    cc_test() 规则用于编译测试。在此处,测试是某些测试代码的二进制封装容器。

    默认情况下,C++ 测试是动态关联的。
    如需静态关联单元测试,请指定 linkstatic=True 。 最好添加注释,说明您的测试为何需要 linkstatic ;这可能并不明显。

    隐式输出目标

  • name .stripped (仅在明确请求时构建):二进制文件的精简版本。在二进制文件上运行 strip -g 以移除调试符号。可以使用 --stripopt=-foo 在命令行中提供其他剥离选项。
  • name .dwp (仅在明确请求时构建):如果启用了 Fission :适合用于调试远程部署的二进制文件的调试信息软件包文件。否则:一个空文件。
  • 请参阅 cc_binary() 实参,但 stamp 实参默认设置为 0(针对测试),并且 cc_test 具有 所有测试规则 (*_test) 共有的额外属性

    用于创建库目标的 C 和 C++ 文件列表。 这些是 C/C++ 源文件和头文件,可以是未生成的(常规源代码),也可以是生成的。

    所有 .cc .c .cpp 文件都将被编译。这些可能是生成的文件:如果某个命名文件位于其他规则的 outs 中,则此 cc_library 将自动依赖于该其他规则。

    纯汇编器文件(.s、.asm)不会经过预处理,通常使用汇编器构建。预处理后的汇编文件 (.S) 经过预处理,通常使用 C/C++ 编译器构建。

    .h 文件不会被编译,但可供此规则中的来源包含。 .cc .h 文件可以直接包含这些 srcs 中列出的标头,也可以包含相应规则的 hdrs 中列出的标头,还可以包含 deps 实参中列出的任何规则的标头。

    所有 #include d 文件都必须在此规则或所引用规则的 hdrs 属性中提及,或者如果它们对此库是私有的,则应列在 srcs 中。 cc_library 如需更详细的说明,请参阅 “标头包含检查”

    .so .lo .a 文件是预编译的文件。如果您的库使用我们没有源代码的第三方代码,则可能将这些权限标记为 srcs

    如果 srcs 属性包含其他规则的标签, cc_library 将使用该规则的输出文件作为要编译的源文件。这对于一次性生成源代码非常有用(如果需要经常使用,最好实现一个 Starlark 规则类并使用 cc_common API) 允许的 srcs 文件类型:

  • C 和 C++ 源文件: .c .cc .cpp .cxx .c++ .C
  • C 和 C++ 头文件: .h .hh .hpp .hxx .inc .inl .H
  • 带有 C 预处理器的汇编器: .S
  • 归档: .a .pic.a
  • “始终链接”库: .lo .pic.lo
  • 共享库(已添加版本信息或未添加版本信息): .so .so. version
  • 对象文件: .o .pic.o
  • ... 以及生成这些文件的任何规则(例如 cc_embed_data )。 根据 gcc 惯例,不同的扩展名表示不同的编程语言。

    如果 data 是生成文件的名称,则此 cc_library 规则会自动依赖于生成规则。

    如果 data 是规则名称,则此 cc_library 规则会自动依赖于该规则,并且该规则的 outs 会自动添加到此 cc_library 的数据文件中。

    您的 C++ 代码可以按如下方式访问这些数据文件:

    const std::string path = devtools_build::GetDataDependencyFilepath( "my/test/data/file"); 仅提供给 C++ 链接器命令的依赖项。 deps 在概念上是为编译和链接依赖项而设计的,而 additional_linker_inputs 专门用于链接依赖项,并表示仅在链接时需要的依赖项(例如,在 linkopts 中引用的文件)。

    例如,此处可以提供已编译的 Windows .res 文件,以便将其嵌入到二进制目标中。 将这些选项添加到 C/C++ 编译命令中。受 “创建变量” 替换和 Bourne shell 令牌化 的影响。 此属性中的每个字符串都会按指定顺序添加到 COPTS 中,然后再编译二进制目标。这些标志仅对编译此目标有效,对其依赖项无效,因此请注意其他位置包含的头文件。 所有路径都应相对于工作区,而不是相对于当前软件包。 此属性不应在 third_party 之外使用。 如果软件包声明了 feature no_copts_tokenization ,则 Bourne shell 令牌化仅适用于由单个“Make”变量组成的字符串。

    要添加到编译行的包含目录的列表。 需进行 “创建变量” 替换。 每个字符串前面都会附加软件包路径,并通过“include_paths”CROSSTOOL 功能传递给 C++ 工具链以进行扩展。在具有典型功能定义的 POSIX 系统上运行的工具链将生成 -isystem path_to_package/include_entry 。此属性仅应用于不符合 Google 编写 #include 语句的样式的第三方库。与 COPTS 不同,这些标志会添加到相应规则以及依赖于该规则的每个规则中。(注意:不是它所依赖的规则!)请务必谨慎操作,因为这可能会产生深远的影响。如果不确定,请改为向 COPTS 添加“-I”标志。 添加的 include 路径将包含生成的文件以及源代码树中的文件。

    如需启用此属性,请在规则中添加 linkshared=True 。默认情况下,此选项处于关闭状态。 此标志的存在意味着链接时使用 -shared 标志链接到 gcc ,并且生成的共享库适合加载到 Java 程序等中。不过,出于构建目的,它永远不会关联到依赖的二进制文件中,因为假定使用 cc_binary 规则构建的共享库仅由其他程序手动加载,因此不应将其视为 cc_library 规则的替代项。为了实现可伸缩性,我们建议完全避免使用此方法,而只需让 java_library 依赖于 cc_library 规则即可。

    如果您同时指定 linkopts=['-static'] linkshared=True ,则会获得一个完全自包含的单元。如果您同时指定 linkstatic=True linkshared=True ,则会获得一个主要自包含的单元。

    布尔值;默认值为 False

    对于 cc_binary cc_test :以静态模式关联二进制文件。对于 cc_library.link_static :请参阅下文。

    默认情况下,此选项对 cc_binary 处于开启状态,对其他设备处于关闭状态。

    如果已启用且这是二进制文件或测试,此选项会告知 build 工具尽可能链接用户库的 .a 而不是 .so 。libc 等系统库(但 包括 C/C++ 运行时库,请参阅下文)仍会动态链接,没有静态库的库也是如此。因此,生成的可执行文件仍将是动态链接的,因此只能说是 大部分 静态。

    实际上,关联可执行文件有三种不同的方式:
  • 具有 fully_static_link 功能的 STATIC,其中所有内容都以静态方式链接;例如“ gcc -static foo.o libbar.a libbaz.a -lm ”。
    通过在 features 属性中指定 fully_static_link 来启用此模式。
  • STATIC:所有用户库都以静态方式关联(如果提供静态版本),但系统库(C/C++ 运行时库除外)以动态方式关联,例如“ gcc foo.o libfoo.a libbaz.a -lm ”。
    通过指定 linkstatic=True 启用此模式。
  • DYNAMIC:所有库都动态链接(如果存在动态版本),例如“ gcc foo.o libfoo.so libbaz.so -lm ”。
    通过指定 linkstatic=False 启用此模式。
  • 如果 linkstatic 属性或 features 中的 fully_static_link //third_party 之外使用,请在规则附近添加注释以说明原因。 如果 linkstatic 属性用于 cc_library() 规则,则具有不同的含义。对于 C++ 库, linkstatic=True 表示只允许静态链接,因此不会生成 .so 。linkstatic=False 不会阻止创建静态库。该属性旨在控制动态库的创建。

    在生产环境中,使用 linkstatic=False 构建的代码应该非常少。 如果值为 linkstatic=False ,则构建工具将在 *.runfiles 区域中创建指向所依赖的共享库的符号链接。

    替换对 malloc 的默认依赖项。 默认情况下,C++ 二进制文件会链接到 //tools/cpp:malloc ,这是一个空库,因此二进制文件最终会使用 libc malloc。 此标签必须引用 cc_library 。如果编译是针对非 C++ 规则的,此选项不会产生任何影响。如果指定了 linkshared=True ,系统会忽略此属性的值。 stamp = 1 :始终将 build 信息标记到二进制文件中,即使在 --nostamp build 中也是如此。 应避免使用此设置 ,因为它可能会终止二进制文件和依赖于它的任何下游操作的远程缓存。 stamp = 0 :始终将 build 信息替换为常量值。这可实现良好的 build 结果缓存。 stamp = -1 :构建信息的嵌入由 --[no]stamp 标志控制。

    除非已加戳记的二进制文件发生依赖项更改,否则 不会 重新构建。

    cc_toolchain(name, all_files, ar_files, as_files, aspect_hints, compatible_with, compiler_files, compiler_files_without_includes, coverage_files, deprecation, dwp_files, dynamic_runtime_lib, exec_compatible_with, exec_group_compatible_with, exec_properties, exec_transition_for_inputs, features, libc_top, licenses, linker_files, module_map, objcopy_files, output_licenses, package_metadata, restricted_to, static_runtime_lib, strip_files, supports_header_parsing, supports_param_files, tags, target_compatible_with, testonly, toolchain_config, toolchain_identifier, toolchains, visibility)

    表示 C++ 工具链。

    此规则负责: 收集 C++ 操作运行所需的所有制品。这是通过 all_files compiler_files linker_files 等属性或以 _files 结尾的其他属性完成的。这些属性最常见的是包含所有必需文件的 filegroup。 为 C++ 操作生成正确的命令行。这是通过使用 CcToolchainConfigInfo 提供程序(详见下文)完成的。

    标签 ;必需

    所有 cc_toolchain 制品的集合。这些制品将作为输入添加到所有 rules_cc 相关操作中(使用以下属性中更精确的制品集的操作除外)。Bazel 假设 all_files 是所有其他提供制品的属性的超集(例如,链接时间戳编译需要编译文件和链接文件,因此它采用 all_files )。 这就是 cc_toolchain.files 的内容,所有使用 C++ 工具链的 Starlark 规则都会使用它。

    fdo_prefetch_hints(name, aspect_hints, compatible_with, deprecation, exec_compatible_with, exec_group_compatible_with, exec_properties, features, package_metadata, profile, restricted_to, tags, target_compatible_with, testonly, toolchains, visibility)

    表示工作区中的 FDO 预提取提示配置文件。示例:

    fdo_prefetch_hints( name = "hints", profile = "//path/to/hints:profile.afdo",
    fdo_profile(name, aspect_hints, compatible_with, deprecation, exec_compatible_with, exec_group_compatible_with, exec_properties, features, memprof_profile, package_metadata, profile, proto_profile, restricted_to, tags, target_compatible_with, testonly, toolchains, visibility)

    表示工作区中的 FDO 配置文件。 fdo_profile( name = "fdo", profile = "//path/to/fdo:profile.zip",

    memprof_profile(name, aspect_hints, compatible_with, deprecation, exec_compatible_with, exec_group_compatible_with, exec_properties, features, package_metadata, profile, restricted_to, tags, target_compatible_with, testonly, toolchains, visibility)

    表示工作区中的 MEMPROF 配置文件。 memprof_profile( name = "memprof", profile = "//path/to/memprof:profile.afdo",

    标签 ;必需

    MEMPROF 配置文件的标签。配置文件应具有 .profdata 扩展名(对于已编入索引/已符号化的 memprof 配置文件),或者具有 .zip 扩展名(对于包含 memprof.profdata 文件的 ZIP 文件)。 标签还可以指向 fdo_absolute_path_profile 规则。
    propeller_optimize(name, aspect_hints, cc_profile, compatible_with, deprecation, exec_compatible_with, exec_group_compatible_with, exec_properties, features, ld_profile, package_metadata, restricted_to, tags, target_compatible_with, testonly, toolchains, visibility)

    表示工作区中的 Propeller 优化配置文件。 propeller_optimize( name = "layout", cc_profile = "//path:cc_profile.txt", ld_profile = "//path:ld_profile.txt"

    如未另行说明,那么本页面中的内容已根据 知识共享署名 4.0 许可 获得了许可,并且代码示例已根据 Apache 2.0 许可 获得了许可。有关详情,请参阅 Google 开发者网站政策 。Java 是 Oracle 和/或其关联公司的注册商标。

    最后更新时间 (UTC):2025-10-01。

    [[["易于理解","easyToUnderstand","thumb-up"],["解决了我的问题","solvedMyProblem","thumb-up"],["其他","otherUp","thumb-up"]],[["没有我需要的信息","missingTheInformationINeed","thumb-down"],["太复杂/步骤太多","tooComplicatedTooManySteps","thumb-down"],["内容需要更新","outOfDate","thumb-down"],["翻译问题","translationIssue","thumb-down"],["示例/代码问题","samplesCodeIssue","thumb-down"],["其他","otherDown","thumb-down"]],["最后更新时间 (UTC):2025-10-01。"],[],[]]