Squashed 'libs/protobuf/' content from commit fcd3b9a85
git-subtree-dir: libs/protobuf git-subtree-split: fcd3b9a85ef36e46643dc30176cea1a7ad62e02b
This commit is contained in:
469
pkg/BUILD.bazel
Normal file
469
pkg/BUILD.bazel
Normal file
@@ -0,0 +1,469 @@
|
||||
load("@rules_pkg//:pkg.bzl", "pkg_tar", "pkg_zip")
|
||||
load(
|
||||
"@rules_pkg//:mappings.bzl",
|
||||
"pkg_attributes",
|
||||
"pkg_filegroup",
|
||||
"pkg_files",
|
||||
"strip_prefix",
|
||||
)
|
||||
load("//:protobuf_release.bzl", "package_naming")
|
||||
load(":build_systems.bzl", "gen_file_lists")
|
||||
load(":cc_dist_library.bzl", "cc_dist_library")
|
||||
|
||||
package_naming(
|
||||
name = "protobuf_pkg_naming",
|
||||
)
|
||||
|
||||
pkg_files(
|
||||
name = "wkt_protos_files",
|
||||
srcs = [
|
||||
"//:well_known_type_protos",
|
||||
"//src/google/protobuf:descriptor_proto_srcs",
|
||||
],
|
||||
prefix = "include/google/protobuf",
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
pkg_files(
|
||||
name = "compiler_plugin_protos_files",
|
||||
srcs = [
|
||||
"//src/google/protobuf/compiler:compiler_plugin_protos_files",
|
||||
],
|
||||
prefix = "include/google/protobuf/compiler",
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
################################################################################
|
||||
# Generates protoc release artifacts.
|
||||
################################################################################
|
||||
|
||||
genrule(
|
||||
name = "protoc_readme",
|
||||
outs = ["readme.txt"],
|
||||
cmd = """
|
||||
echo "Protocol Buffers - Google's data interchange format
|
||||
Copyright 2008 Google Inc.
|
||||
https://developers.google.com/protocol-buffers/
|
||||
This package contains a precompiled binary version of the protocol buffer
|
||||
compiler (protoc). This binary is intended for users who want to use Protocol
|
||||
Buffers in languages other than C++ but do not want to compile protoc
|
||||
themselves. To install, simply place this binary somewhere in your PATH.
|
||||
If you intend to use the included well known types then don't forget to
|
||||
copy the contents of the 'include' directory somewhere as well, for example
|
||||
into '/usr/local/include/'.
|
||||
Please refer to our official github site for more installation instructions:
|
||||
https://github.com/protocolbuffers/protobuf" > $@
|
||||
""",
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
pkg_files(
|
||||
name = "protoc_files",
|
||||
srcs = ["//:protoc"],
|
||||
attributes = pkg_attributes(mode = "0555"),
|
||||
prefix = "bin/",
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
pkg_zip(
|
||||
name = "protoc_release",
|
||||
srcs = [
|
||||
":compiler_plugin_protos_files",
|
||||
":protoc_files",
|
||||
":protoc_readme",
|
||||
":wkt_protos_files",
|
||||
],
|
||||
package_file_name = "protoc-{version}-{platform}.zip",
|
||||
package_variables = ":protobuf_pkg_naming",
|
||||
)
|
||||
|
||||
################################################################################
|
||||
# Source distribution packaging
|
||||
#
|
||||
# TODO: these will eventually replace autotools for release artifact packaging.
|
||||
################################################################################
|
||||
|
||||
pkg_filegroup(
|
||||
name = "dist_common",
|
||||
srcs = [
|
||||
":dist_files",
|
||||
"//:common_dist_files",
|
||||
"//build_defs:dist_files",
|
||||
"//conformance:all_dist_files",
|
||||
"//src:all_dist_files",
|
||||
"//third_party/utf8_range:dist_files",
|
||||
"@com_google_protobuf_examples//:dist_files",
|
||||
],
|
||||
)
|
||||
|
||||
pkg_filegroup(
|
||||
name = "cpp_srcs",
|
||||
srcs = [
|
||||
":dist_common",
|
||||
"//src:all_dist_files",
|
||||
],
|
||||
)
|
||||
|
||||
pkg_tar(
|
||||
name = "dist_cpp_tar",
|
||||
srcs = [":cpp_srcs"],
|
||||
extension = "tar.gz",
|
||||
package_dir = "protobuf-{version}",
|
||||
package_file_name = "protobuf-cpp-{version}.tar.gz",
|
||||
package_variables = ":protobuf_pkg_naming",
|
||||
)
|
||||
|
||||
pkg_zip(
|
||||
name = "dist_cpp_zip",
|
||||
srcs = [":cpp_srcs"],
|
||||
package_file_name = "protobuf-cpp-{version}.zip",
|
||||
package_variables = ":protobuf_pkg_naming",
|
||||
)
|
||||
|
||||
pkg_filegroup(
|
||||
name = "csharp_srcs",
|
||||
srcs = [
|
||||
":dist_common",
|
||||
"//:csharp_dist_files",
|
||||
"//csharp:dist_files",
|
||||
],
|
||||
)
|
||||
|
||||
pkg_tar(
|
||||
name = "dist_csharp_tar",
|
||||
srcs = [":csharp_srcs"],
|
||||
extension = "tar.gz",
|
||||
package_dir = "protobuf-{version}",
|
||||
package_file_name = "protobuf-csharp-{version}.tar.gz",
|
||||
package_variables = ":protobuf_pkg_naming",
|
||||
)
|
||||
|
||||
pkg_zip(
|
||||
name = "dist_csharp_zip",
|
||||
srcs = [":csharp_srcs"],
|
||||
package_file_name = "protobuf-csharp-{version}.zip",
|
||||
package_variables = ":protobuf_pkg_naming",
|
||||
)
|
||||
|
||||
pkg_filegroup(
|
||||
name = "java_srcs",
|
||||
srcs = [
|
||||
":dist_common",
|
||||
"//java:all_dist_files",
|
||||
],
|
||||
)
|
||||
|
||||
pkg_tar(
|
||||
name = "dist_java_tar",
|
||||
srcs = [":java_srcs"],
|
||||
extension = "tar.gz",
|
||||
package_dir = "protobuf-{version}",
|
||||
package_file_name = "protobuf-java-{version}.tar.gz",
|
||||
package_variables = ":protobuf_pkg_naming",
|
||||
)
|
||||
|
||||
pkg_zip(
|
||||
name = "dist_java_zip",
|
||||
srcs = [":java_srcs"],
|
||||
package_file_name = "protobuf-java-{version}.zip",
|
||||
package_variables = ":protobuf_pkg_naming",
|
||||
)
|
||||
|
||||
pkg_filegroup(
|
||||
name = "objectivec_srcs",
|
||||
srcs = [
|
||||
":dist_common",
|
||||
"//:objectivec_dist_files",
|
||||
"//objectivec:dist_files",
|
||||
],
|
||||
)
|
||||
|
||||
pkg_tar(
|
||||
name = "dist_objectivec_tar",
|
||||
srcs = [":objectivec_srcs"],
|
||||
extension = "tar.gz",
|
||||
package_dir = "protobuf-{version}",
|
||||
package_file_name = "protobuf-objectivec-{version}.tar.gz",
|
||||
package_variables = ":protobuf_pkg_naming",
|
||||
)
|
||||
|
||||
pkg_zip(
|
||||
name = "dist_objectivec_zip",
|
||||
srcs = [":objectivec_srcs"],
|
||||
package_file_name = "protobuf-objectivec-{version}.zip",
|
||||
package_variables = ":protobuf_pkg_naming",
|
||||
)
|
||||
|
||||
pkg_filegroup(
|
||||
name = "php_srcs",
|
||||
srcs = [
|
||||
":dist_common",
|
||||
"//php:dist_files",
|
||||
],
|
||||
)
|
||||
|
||||
pkg_tar(
|
||||
name = "dist_php_tar",
|
||||
srcs = [":php_srcs"],
|
||||
extension = "tar.gz",
|
||||
package_dir = "protobuf-{version}",
|
||||
package_file_name = "protobuf-php-{version}.tar.gz",
|
||||
package_variables = ":protobuf_pkg_naming",
|
||||
)
|
||||
|
||||
pkg_zip(
|
||||
name = "dist_php_zip",
|
||||
srcs = [":php_srcs"],
|
||||
package_file_name = "protobuf-php-{version}.zip",
|
||||
package_variables = ":protobuf_pkg_naming",
|
||||
)
|
||||
|
||||
pkg_filegroup(
|
||||
name = "python_srcs",
|
||||
srcs = [
|
||||
":dist_common",
|
||||
"//python:dist_files",
|
||||
],
|
||||
)
|
||||
|
||||
pkg_tar(
|
||||
name = "dist_python_tar",
|
||||
srcs = [":python_srcs"],
|
||||
extension = "tar.gz",
|
||||
package_dir = "protobuf-{version}",
|
||||
package_file_name = "protobuf-python-{version}.tar.gz",
|
||||
package_variables = ":protobuf_pkg_naming",
|
||||
)
|
||||
|
||||
pkg_zip(
|
||||
name = "dist_python_zip",
|
||||
srcs = [":python_srcs"],
|
||||
package_file_name = "protobuf-python-{version}.zip",
|
||||
package_variables = ":protobuf_pkg_naming",
|
||||
)
|
||||
|
||||
pkg_filegroup(
|
||||
name = "ruby_srcs",
|
||||
srcs = [
|
||||
":dist_common",
|
||||
"//ruby:dist_files",
|
||||
],
|
||||
)
|
||||
|
||||
pkg_tar(
|
||||
name = "dist_ruby_tar",
|
||||
srcs = [":ruby_srcs"],
|
||||
extension = "tar.gz",
|
||||
package_dir = "protobuf-{version}",
|
||||
package_file_name = "protobuf-ruby-{version}.tar.gz",
|
||||
package_variables = ":protobuf_pkg_naming",
|
||||
)
|
||||
|
||||
pkg_zip(
|
||||
name = "dist_ruby_zip",
|
||||
srcs = [":ruby_srcs"],
|
||||
package_file_name = "protobuf-ruby-{version}.zip",
|
||||
package_variables = ":protobuf_pkg_naming",
|
||||
)
|
||||
|
||||
pkg_filegroup(
|
||||
name = "dist_all",
|
||||
srcs = [
|
||||
":cpp_srcs",
|
||||
":csharp_srcs",
|
||||
":java_srcs",
|
||||
":objectivec_srcs",
|
||||
":php_srcs",
|
||||
":python_srcs",
|
||||
":ruby_srcs",
|
||||
],
|
||||
)
|
||||
|
||||
pkg_tar(
|
||||
name = "dist_all_tar",
|
||||
srcs = [":dist_all"],
|
||||
extension = "tar.gz",
|
||||
package_dir = "protobuf-{version}",
|
||||
package_file_name = "protobuf-all-{version}.tar.gz",
|
||||
package_variables = ":protobuf_pkg_naming",
|
||||
)
|
||||
|
||||
pkg_zip(
|
||||
name = "dist_all_zip",
|
||||
srcs = [":dist_all"],
|
||||
package_file_name = "protobuf-all-{version}.zip",
|
||||
package_variables = ":protobuf_pkg_naming",
|
||||
)
|
||||
|
||||
################################################################################
|
||||
# Generated file lists for build systems
|
||||
################################################################################
|
||||
|
||||
gen_file_lists(
|
||||
name = "gen_src_file_lists",
|
||||
testonly = 1,
|
||||
out_stem = "src_file_lists",
|
||||
src_libs = {
|
||||
# {[source rule]: [name in generated file]}
|
||||
# Libraries:
|
||||
":protobuf": "libprotobuf",
|
||||
":protobuf_lite": "libprotobuf_lite",
|
||||
":protoc": "libprotoc",
|
||||
# Protos:
|
||||
"//src/google/protobuf:well_known_type_protos": "wkt_protos",
|
||||
"//src/google/protobuf:descriptor_proto": "descriptor_proto",
|
||||
"//src/google/protobuf/compiler:plugin_proto": "plugin_proto",
|
||||
# Test libraries:
|
||||
":common_test": "common_test",
|
||||
":lite_test_util": "lite_test_util",
|
||||
":test_util": "test_util",
|
||||
# Tests and test-only protos:
|
||||
"//src/google/protobuf:full_test_srcs": "protobuf_test",
|
||||
"//src/google/protobuf:test_proto_srcs": "protobuf_test_protos",
|
||||
"//src/google/protobuf:lite_test_srcs": "protobuf_lite_test",
|
||||
"//src/google/protobuf:lite_test_proto_srcs": "protobuf_lite_test_protos",
|
||||
"//src/google/protobuf/compiler:test_srcs": "compiler_test",
|
||||
"//src/google/protobuf/compiler:test_proto_srcs": "compiler_test_protos",
|
||||
"//src/google/protobuf/compiler:test_plugin_srcs": "test_plugin",
|
||||
"//src/google/protobuf/io:test_srcs": "io_test",
|
||||
"//src/google/protobuf/util:test_srcs": "util_test",
|
||||
"//src/google/protobuf/util:test_proto_srcs": "util_test_protos",
|
||||
"//src/google/protobuf/stubs:test_srcs": "stubs_test",
|
||||
},
|
||||
)
|
||||
|
||||
################################################################################
|
||||
# Protobuf runtime libraries.
|
||||
################################################################################
|
||||
|
||||
cc_dist_library(
|
||||
name = "protobuf_lite",
|
||||
linkopts = select({
|
||||
"//build_defs:config_msvc": [],
|
||||
"//conditions:default": ["-lpthread"],
|
||||
}),
|
||||
tags = ["manual"],
|
||||
deps = [
|
||||
"//src/google/protobuf:arena",
|
||||
"//src/google/protobuf:arena_align",
|
||||
"//src/google/protobuf:arena_allocation_policy",
|
||||
"//src/google/protobuf:arena_cleanup",
|
||||
"//src/google/protobuf:arena_config",
|
||||
"//src/google/protobuf:protobuf_lite",
|
||||
"//src/google/protobuf/io",
|
||||
"//src/google/protobuf/io:io_win32",
|
||||
"//src/google/protobuf/stubs:lite",
|
||||
],
|
||||
)
|
||||
|
||||
cc_dist_library(
|
||||
name = "protobuf",
|
||||
linkopts = select({
|
||||
"//build_defs:config_msvc": [],
|
||||
"//conditions:default": [
|
||||
"-lz",
|
||||
"-lpthread",
|
||||
],
|
||||
}),
|
||||
tags = ["manual"],
|
||||
deps = [
|
||||
"//src/google/protobuf:wkt_cc_proto",
|
||||
"//src/google/protobuf:protobuf_nowkt",
|
||||
"//src/google/protobuf:arena",
|
||||
"//src/google/protobuf:arena_align",
|
||||
"//src/google/protobuf:arena_allocation_policy",
|
||||
"//src/google/protobuf:arena_cleanup",
|
||||
"//src/google/protobuf:arena_config",
|
||||
"//src/google/protobuf:protobuf_lite",
|
||||
"//src/google/protobuf:port_def",
|
||||
"//src/google/protobuf/compiler:importer",
|
||||
"//src/google/protobuf/io",
|
||||
"//src/google/protobuf/io:gzip_stream",
|
||||
"//src/google/protobuf/io:io_win32",
|
||||
"//src/google/protobuf/io:printer",
|
||||
"//src/google/protobuf/io:tokenizer",
|
||||
"//src/google/protobuf/io:zero_copy_sink",
|
||||
"//src/google/protobuf/json",
|
||||
"//src/google/protobuf/json:descriptor_traits",
|
||||
"//src/google/protobuf/json:lexer",
|
||||
"//src/google/protobuf/json:message_path",
|
||||
"//src/google/protobuf/json:parser",
|
||||
"//src/google/protobuf/json:unparser",
|
||||
"//src/google/protobuf/json:untyped_message",
|
||||
"//src/google/protobuf/json:writer",
|
||||
"//src/google/protobuf/json:zero_copy_buffered_stream",
|
||||
"//src/google/protobuf/stubs",
|
||||
"//src/google/protobuf/stubs:lite",
|
||||
"//src/google/protobuf/util:delimited_message_util",
|
||||
"//src/google/protobuf/util:differencer",
|
||||
"//src/google/protobuf/util:field_mask_util",
|
||||
"//src/google/protobuf/util:json_util",
|
||||
"//src/google/protobuf/util:time_util",
|
||||
"//src/google/protobuf/util:type_resolver_util",
|
||||
],
|
||||
)
|
||||
|
||||
cc_dist_library(
|
||||
name = "protoc",
|
||||
tags = ["manual"],
|
||||
deps = [
|
||||
"//src/google/protobuf/compiler:code_generator",
|
||||
"//src/google/protobuf/compiler:command_line_interface",
|
||||
"//src/google/protobuf/compiler/cpp",
|
||||
"//src/google/protobuf/compiler/cpp:names",
|
||||
"//src/google/protobuf/compiler/cpp:names_internal",
|
||||
"//src/google/protobuf/compiler/csharp",
|
||||
"//src/google/protobuf/compiler/csharp:names",
|
||||
"//src/google/protobuf/compiler/java",
|
||||
"//src/google/protobuf/compiler/java:names",
|
||||
"//src/google/protobuf/compiler/java:names_internal",
|
||||
"//src/google/protobuf/compiler/objectivec",
|
||||
"//src/google/protobuf/compiler/objectivec:line_consumer",
|
||||
"//src/google/protobuf/compiler/objectivec:names",
|
||||
"//src/google/protobuf/compiler/objectivec:names_internal",
|
||||
"//src/google/protobuf/compiler/php",
|
||||
"//src/google/protobuf/compiler/php:names",
|
||||
"//src/google/protobuf/compiler/python",
|
||||
"//src/google/protobuf/compiler/ruby",
|
||||
],
|
||||
)
|
||||
|
||||
cc_dist_library(
|
||||
name = "lite_test_util",
|
||||
testonly = 1,
|
||||
tags = ["manual"],
|
||||
deps = ["//src/google/protobuf:lite_test_util"],
|
||||
)
|
||||
|
||||
cc_dist_library(
|
||||
name = "test_util",
|
||||
testonly = 1,
|
||||
tags = ["manual"],
|
||||
deps = [
|
||||
"//src/google/protobuf:test_util",
|
||||
"//src/google/protobuf:test_util2",
|
||||
"//src/google/protobuf/compiler:annotation_test_util",
|
||||
"//src/google/protobuf/compiler/cpp:unittest_lib",
|
||||
],
|
||||
)
|
||||
|
||||
cc_dist_library(
|
||||
name = "common_test",
|
||||
testonly = 1,
|
||||
tags = ["manual"],
|
||||
deps = [
|
||||
"//src/google/protobuf/testing",
|
||||
"//src/google/protobuf/compiler:mock_code_generator",
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
################################################################################
|
||||
# Distribution sources
|
||||
################################################################################
|
||||
|
||||
pkg_files(
|
||||
name = "dist_files",
|
||||
srcs = glob(["*"]),
|
||||
strip_prefix = strip_prefix.from_root(""),
|
||||
)
|
||||
31
pkg/README.md
Normal file
31
pkg/README.md
Normal file
@@ -0,0 +1,31 @@
|
||||
# Protobuf packaging
|
||||
|
||||
This directory contains Bazel rules for building packaging and distribution
|
||||
artifacts.
|
||||
|
||||
*Everything in this directory should be considered internal and subject to
|
||||
change.*
|
||||
|
||||
## Protocol compiler binary packaging
|
||||
|
||||
The protocol compiler is used in binary form in various places. There are rules
|
||||
which package it, along with commonly used `.proto` files, for distribution.
|
||||
|
||||
## Source distribution packaging
|
||||
|
||||
Protobuf releases include source distributions, sliced by target language (C++,
|
||||
Java, etc.). There are rules in this package to define those source archives.
|
||||
These depend upon `pkg_files` rules elsewhere in the repo to get the contents.
|
||||
|
||||
The source distribution files should include the outputs from `autogen.sh`, but
|
||||
this isn't something we can reliably do from Bazel. To produce fully functioning
|
||||
source distributions, run `autogen.sh` before building the archives (this
|
||||
populates the necessary files directly into the source tree).
|
||||
|
||||
## C++ runtime binary distribution
|
||||
|
||||
The `cc_dist_library` rule creates composite libraries from several other
|
||||
`cc_library` targets. Bazel uses a "fine-grained" library model, where each
|
||||
`cc_library` produces its own library artifacts, without transitive
|
||||
dependencies. The `cc_dist_library` rule combines several other libraries
|
||||
together, creating a single library that may be suitable for distribution.
|
||||
327
pkg/build_systems.bzl
Normal file
327
pkg/build_systems.bzl
Normal file
@@ -0,0 +1,327 @@
|
||||
# Starlark utilities for working with other build systems
|
||||
|
||||
load("@rules_pkg//:providers.bzl", "PackageFilegroupInfo", "PackageFilesInfo")
|
||||
load(":cc_dist_library.bzl", "CcFileList")
|
||||
|
||||
################################################################################
|
||||
# Macro to create CMake and Automake source lists.
|
||||
################################################################################
|
||||
|
||||
def gen_file_lists(name, out_stem, **kwargs):
|
||||
gen_cmake_file_lists(
|
||||
name = name + "_cmake",
|
||||
out = out_stem + ".cmake",
|
||||
source_prefix = "${protobuf_SOURCE_DIR}/",
|
||||
**kwargs
|
||||
)
|
||||
native.filegroup(
|
||||
name = name,
|
||||
srcs = [
|
||||
out_stem + ".cmake",
|
||||
],
|
||||
visibility = ["//src:__pkg__"],
|
||||
)
|
||||
|
||||
################################################################################
|
||||
# Aspect that extracts srcs, hdrs, etc.
|
||||
################################################################################
|
||||
|
||||
ProtoFileList = provider(
|
||||
doc = "List of proto files and generated code to be built into a library.",
|
||||
fields = {
|
||||
# Proto files:
|
||||
"proto_srcs": "proto file sources",
|
||||
|
||||
# Generated sources:
|
||||
"hdrs": "header files that are expected to be generated",
|
||||
"srcs": "source files that are expected to be generated",
|
||||
},
|
||||
)
|
||||
|
||||
def _flatten_target_files(targets):
|
||||
files = []
|
||||
for target in targets:
|
||||
for tfile in target.files.to_list():
|
||||
files.append(tfile)
|
||||
return files
|
||||
|
||||
def _file_list_aspect_impl(target, ctx):
|
||||
# We're going to reach directly into the attrs on the traversed rule.
|
||||
rule_attr = ctx.rule.attr
|
||||
providers = []
|
||||
|
||||
# Extract sources from a `proto_library`:
|
||||
if ProtoInfo in target:
|
||||
proto_srcs = []
|
||||
srcs = []
|
||||
hdrs = []
|
||||
for src in _flatten_target_files(rule_attr.srcs):
|
||||
proto_srcs.append(src)
|
||||
srcs.append("%s/%s.pb.cc" % (src.dirname, src.basename))
|
||||
hdrs.append("%s/%s.pb.h" % (src.dirname, src.basename))
|
||||
|
||||
providers.append(ProtoFileList(
|
||||
proto_srcs = proto_srcs,
|
||||
srcs = srcs,
|
||||
hdrs = hdrs,
|
||||
))
|
||||
|
||||
return providers
|
||||
|
||||
file_list_aspect = aspect(
|
||||
doc = """
|
||||
Aspect to provide the list of sources and headers from a rule.
|
||||
|
||||
Output is CcFileList and/or ProtoFileList. Example:
|
||||
|
||||
cc_library(
|
||||
name = "foo",
|
||||
srcs = [
|
||||
"foo.cc",
|
||||
"foo_internal.h",
|
||||
],
|
||||
hdrs = ["foo.h"],
|
||||
textual_hdrs = ["foo_inl.inc"],
|
||||
)
|
||||
# produces:
|
||||
# CcFileList(
|
||||
# hdrs = [File("foo.h")],
|
||||
# textual_hdrs = [File("foo_inl.inc")],
|
||||
# internal_hdrs = [File("foo_internal.h")],
|
||||
# srcs = [File("foo.cc")],
|
||||
# )
|
||||
|
||||
proto_library(
|
||||
name = "bar_proto",
|
||||
srcs = ["bar.proto"],
|
||||
)
|
||||
# produces:
|
||||
# ProtoFileList(
|
||||
# proto_srcs = ["bar.proto"],
|
||||
# # Generated filenames are synthesized:
|
||||
# hdrs = ["bar.pb.h"],
|
||||
# srcs = ["bar.pb.cc"],
|
||||
# )
|
||||
""",
|
||||
implementation = _file_list_aspect_impl,
|
||||
)
|
||||
|
||||
################################################################################
|
||||
# Generic source lists generation
|
||||
#
|
||||
# This factory creates a rule implementation that is parameterized by a
|
||||
# fragment generator function.
|
||||
################################################################################
|
||||
|
||||
def _create_file_list_impl(ctx, fragment_generator):
|
||||
# `fragment_generator` is a function like:
|
||||
# def fn(originating_rule: Label,
|
||||
# varname: str,
|
||||
# source_prefix: str,
|
||||
# path_strings: [str]) -> str
|
||||
#
|
||||
# It returns a string that defines `varname` to `path_strings`, each
|
||||
# prepended with `source_prefix`.
|
||||
#
|
||||
# When dealing with `File` objects, the `short_path` is used to strip
|
||||
# the output prefix for generated files.
|
||||
|
||||
out = ctx.outputs.out
|
||||
|
||||
fragments = []
|
||||
for srcrule, libname in ctx.attr.src_libs.items():
|
||||
if CcFileList in srcrule:
|
||||
cc_file_list = srcrule[CcFileList]
|
||||
|
||||
# Turn depsets of files into sorted lists.
|
||||
srcs = sorted(cc_file_list.srcs.to_list())
|
||||
hdrs = sorted(
|
||||
depset(transitive = [
|
||||
cc_file_list.textual_hdrs,
|
||||
cc_file_list.hdrs,
|
||||
]).to_list(),
|
||||
)
|
||||
|
||||
fragments.extend([
|
||||
fragment_generator(
|
||||
srcrule.label,
|
||||
libname + "_srcs",
|
||||
ctx.attr.source_prefix,
|
||||
[f.short_path for f in srcs],
|
||||
),
|
||||
fragment_generator(
|
||||
srcrule.label,
|
||||
libname + "_hdrs",
|
||||
ctx.attr.source_prefix,
|
||||
[f.short_path for f in hdrs],
|
||||
),
|
||||
])
|
||||
|
||||
if ProtoFileList in srcrule:
|
||||
proto_file_list = srcrule[ProtoFileList]
|
||||
fragments.extend([
|
||||
fragment_generator(
|
||||
srcrule.label,
|
||||
libname + "_proto_srcs",
|
||||
ctx.attr.source_prefix,
|
||||
[f.short_path for f in proto_file_list.proto_srcs],
|
||||
),
|
||||
fragment_generator(
|
||||
srcrule.label,
|
||||
libname + "_srcs",
|
||||
ctx.attr.source_prefix,
|
||||
proto_file_list.srcs,
|
||||
),
|
||||
fragment_generator(
|
||||
srcrule.label,
|
||||
libname + "_hdrs",
|
||||
ctx.attr.source_prefix,
|
||||
proto_file_list.hdrs,
|
||||
),
|
||||
])
|
||||
|
||||
files = {}
|
||||
|
||||
if PackageFilegroupInfo in srcrule:
|
||||
for pkg_files_info, origin in srcrule[PackageFilegroupInfo].pkg_files:
|
||||
# keys are the destination path:
|
||||
files.update(pkg_files_info.dest_src_map)
|
||||
|
||||
if PackageFilesInfo in srcrule:
|
||||
# keys are the destination:
|
||||
files.update(srcrule[PackageFilesInfo].dest_src_map)
|
||||
|
||||
if files == {} and DefaultInfo in srcrule and CcFileList not in srcrule:
|
||||
# This could be an individual file or filegroup.
|
||||
# We explicitly ignore rules with CcInfo, since their
|
||||
# output artifacts are libraries or binaries.
|
||||
files.update(
|
||||
{
|
||||
f.short_path: 1
|
||||
for f in srcrule[DefaultInfo].files.to_list()
|
||||
},
|
||||
)
|
||||
|
||||
if files:
|
||||
fragments.append(
|
||||
fragment_generator(
|
||||
srcrule.label,
|
||||
libname + "_files",
|
||||
ctx.attr.source_prefix,
|
||||
sorted(files.keys()),
|
||||
),
|
||||
)
|
||||
|
||||
ctx.actions.write(
|
||||
output = out,
|
||||
content = (ctx.attr._header % ctx.label) + "\n".join(fragments),
|
||||
)
|
||||
|
||||
return [DefaultInfo(files = depset([out]))]
|
||||
|
||||
# Common rule attrs for rules that use `_create_file_list_impl`:
|
||||
# (note that `_header` is also required)
|
||||
_source_list_common_attrs = {
|
||||
"out": attr.output(
|
||||
doc = (
|
||||
"The generated filename. This should usually have a build " +
|
||||
"system-specific extension, like `out.am` or `out.cmake`."
|
||||
),
|
||||
mandatory = True,
|
||||
),
|
||||
"src_libs": attr.label_keyed_string_dict(
|
||||
doc = (
|
||||
"A dict, {target: libname} of libraries to include. " +
|
||||
"Targets can be C++ rules (like `cc_library` or `cc_test`), " +
|
||||
"`proto_library` rules, files, `filegroup` rules, `pkg_files` " +
|
||||
"rules, or `pkg_filegroup` rules. " +
|
||||
"The libname is a string, and used to construct the variable " +
|
||||
"name in the `out` file holding the target's sources. " +
|
||||
"For generated files, the output root (like `bazel-bin/`) is not " +
|
||||
"included. " +
|
||||
"For `pkg_files` and `pkg_filegroup` rules, the destination path " +
|
||||
"is used."
|
||||
),
|
||||
mandatory = True,
|
||||
providers = [
|
||||
[CcFileList],
|
||||
[DefaultInfo],
|
||||
[PackageFilegroupInfo],
|
||||
[PackageFilesInfo],
|
||||
[ProtoFileList],
|
||||
],
|
||||
aspects = [file_list_aspect],
|
||||
),
|
||||
"source_prefix": attr.string(
|
||||
doc = "String to prepend to each source path.",
|
||||
),
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# CMake source lists generation
|
||||
################################################################################
|
||||
|
||||
def _cmake_var_fragment(owner, varname, prefix, entries):
|
||||
"""Returns a single `set(varname ...)` fragment (CMake syntax).
|
||||
|
||||
Args:
|
||||
owner: Label, the rule that owns these srcs.
|
||||
varname: str, the var name to set.
|
||||
prefix: str, prefix to prepend to each of `entries`.
|
||||
entries: [str], the entries in the list.
|
||||
|
||||
Returns:
|
||||
A string.
|
||||
"""
|
||||
return (
|
||||
"# {owner}\n" +
|
||||
"set({varname}\n" +
|
||||
"{entries}\n" +
|
||||
")\n"
|
||||
).format(
|
||||
owner = owner,
|
||||
varname = varname,
|
||||
entries = "\n".join([" %s%s" % (prefix, f) for f in entries]),
|
||||
)
|
||||
|
||||
def _cmake_file_list_impl(ctx):
|
||||
_create_file_list_impl(ctx, _cmake_var_fragment)
|
||||
|
||||
gen_cmake_file_lists = rule(
|
||||
doc = """
|
||||
Generates a CMake-syntax file with lists of files.
|
||||
|
||||
The generated file defines variables with lists of files from `srcs`. The
|
||||
intent is for these files to be included from a non-generated CMake file
|
||||
which actually defines the libraries based on these lists.
|
||||
|
||||
For C++ rules, the following are generated:
|
||||
{libname}_srcs: contains srcs.
|
||||
{libname}_hdrs: contains hdrs and textual_hdrs.
|
||||
|
||||
For proto_library, the following are generated:
|
||||
{libname}_proto_srcs: contains the srcs from the `proto_library` rule.
|
||||
{libname}_srcs: contains syntesized paths for generated C++ sources.
|
||||
{libname}_hdrs: contains syntesized paths for generated C++ headers.
|
||||
|
||||
""",
|
||||
implementation = _cmake_file_list_impl,
|
||||
attrs = dict(
|
||||
_source_list_common_attrs,
|
||||
_header = attr.string(
|
||||
default = """\
|
||||
# Auto-generated by %s
|
||||
#
|
||||
# This file contains lists of sources based on Bazel rules. It should
|
||||
# be included from a hand-written CMake file that defines targets.
|
||||
#
|
||||
# Changes to this file will be overwritten based on Bazel definitions.
|
||||
|
||||
if(${CMAKE_VERSION} VERSION_GREATER 3.10 OR ${CMAKE_VERSION} VERSION_EQUAL 3.10)
|
||||
include_guard()
|
||||
endif()
|
||||
|
||||
""",
|
||||
),
|
||||
),
|
||||
)
|
||||
400
pkg/cc_dist_library.bzl
Normal file
400
pkg/cc_dist_library.bzl
Normal file
@@ -0,0 +1,400 @@
|
||||
# Rules for distributable C++ libraries
|
||||
|
||||
load("@rules_cc//cc:action_names.bzl", cc_action_names = "ACTION_NAMES")
|
||||
load("@rules_cc//cc:find_cc_toolchain.bzl", "find_cc_toolchain")
|
||||
|
||||
################################################################################
|
||||
# Archive/linking support
|
||||
################################################################################
|
||||
|
||||
def _collect_linker_input_objects(dep_label, cc_info, objs, pic_objs):
|
||||
"""Accumulate .o and .pic.o files into `objs` and `pic_objs`."""
|
||||
link_ctx = cc_info.linking_context
|
||||
if link_ctx == None:
|
||||
return
|
||||
|
||||
linker_inputs = link_ctx.linker_inputs.to_list()
|
||||
for link_input in linker_inputs:
|
||||
if link_input.owner != dep_label:
|
||||
# This is a transitive dep: skip it.
|
||||
continue
|
||||
|
||||
for lib in link_input.libraries:
|
||||
objs.extend(lib.objects or [])
|
||||
pic_objs.extend(lib.pic_objects or [])
|
||||
|
||||
# Creates an action to build the `output_file` static library (archive)
|
||||
# using `object_files`.
|
||||
def _create_archive_action(
|
||||
ctx,
|
||||
feature_configuration,
|
||||
cc_toolchain_info,
|
||||
output_file,
|
||||
object_files):
|
||||
# Based on Bazel's src/main/starlark/builtins_bzl/common/cc/cc_import.bzl:
|
||||
|
||||
# Build the command line and add args for all of the input files:
|
||||
archiver_variables = cc_common.create_link_variables(
|
||||
feature_configuration = feature_configuration,
|
||||
cc_toolchain = cc_toolchain_info,
|
||||
output_file = output_file.path,
|
||||
is_using_linker = False,
|
||||
)
|
||||
command_line = cc_common.get_memory_inefficient_command_line(
|
||||
feature_configuration = feature_configuration,
|
||||
action_name = cc_action_names.cpp_link_static_library,
|
||||
variables = archiver_variables,
|
||||
)
|
||||
args = ctx.actions.args()
|
||||
args.add_all(command_line)
|
||||
args.add_all(object_files)
|
||||
args.use_param_file("@%s", use_always = True)
|
||||
|
||||
archiver_path = cc_common.get_tool_for_action(
|
||||
feature_configuration = feature_configuration,
|
||||
action_name = cc_action_names.cpp_link_static_library,
|
||||
)
|
||||
|
||||
env = cc_common.get_environment_variables(
|
||||
feature_configuration = feature_configuration,
|
||||
action_name = cc_action_names.cpp_link_static_library,
|
||||
variables = archiver_variables,
|
||||
)
|
||||
|
||||
ctx.actions.run(
|
||||
executable = archiver_path,
|
||||
arguments = [args],
|
||||
env = env,
|
||||
inputs = depset(
|
||||
direct = object_files,
|
||||
transitive = [
|
||||
cc_toolchain_info.all_files,
|
||||
],
|
||||
),
|
||||
use_default_shell_env = False,
|
||||
outputs = [output_file],
|
||||
mnemonic = "CppArchiveDist",
|
||||
)
|
||||
|
||||
def _create_dso_link_action(
|
||||
ctx,
|
||||
feature_configuration,
|
||||
cc_toolchain_info,
|
||||
object_files,
|
||||
pic_object_files):
|
||||
compilation_outputs = cc_common.create_compilation_outputs(
|
||||
objects = depset(object_files),
|
||||
pic_objects = depset(pic_object_files),
|
||||
)
|
||||
link_output = cc_common.link(
|
||||
actions = ctx.actions,
|
||||
feature_configuration = feature_configuration,
|
||||
cc_toolchain = cc_toolchain_info,
|
||||
compilation_outputs = compilation_outputs,
|
||||
name = ctx.label.name,
|
||||
output_type = "dynamic_library",
|
||||
user_link_flags = ctx.attr.linkopts,
|
||||
)
|
||||
library_to_link = link_output.library_to_link
|
||||
|
||||
outputs = []
|
||||
|
||||
# Note: library_to_link.dynamic_library and interface_library are often
|
||||
# symlinks in the solib directory. For DefaultInfo, prefer reporting
|
||||
# the resolved artifact paths.
|
||||
if library_to_link.resolved_symlink_dynamic_library != None:
|
||||
outputs.append(library_to_link.resolved_symlink_dynamic_library)
|
||||
elif library_to_link.dynamic_library != None:
|
||||
outputs.append(library_to_link.dynamic_library)
|
||||
|
||||
if library_to_link.resolved_symlink_interface_library != None:
|
||||
outputs.append(library_to_link.resolved_symlink_interface_library)
|
||||
elif library_to_link.interface_library != None:
|
||||
outputs.append(library_to_link.interface_library)
|
||||
|
||||
return outputs
|
||||
|
||||
################################################################################
|
||||
# Source file/header support
|
||||
################################################################################
|
||||
|
||||
CcFileList = provider(
|
||||
doc = "List of files to be built into a library.",
|
||||
fields = {
|
||||
# As a rule of thumb, `hdrs` and `textual_hdrs` are the files that
|
||||
# would be installed along with a prebuilt library.
|
||||
"hdrs": "public header files, including those used by generated code",
|
||||
"textual_hdrs": "files which are included but are not self-contained",
|
||||
|
||||
# The `internal_hdrs` are header files which appear in `srcs`.
|
||||
# These are only used when compiling the library.
|
||||
"internal_hdrs": "internal header files (only used to build .cc files)",
|
||||
"srcs": "source files",
|
||||
},
|
||||
)
|
||||
|
||||
def _flatten_target_files(targets):
|
||||
return depset(transitive = [target.files for target in targets])
|
||||
|
||||
files = []
|
||||
for target in targets:
|
||||
files.extend(target.files.to_list())
|
||||
return files
|
||||
|
||||
def _cc_file_list_aspect_impl(target, ctx):
|
||||
# Extract sources from a `cc_library` (or similar):
|
||||
if CcInfo not in target:
|
||||
return []
|
||||
|
||||
# We're going to reach directly into the attrs on the traversed rule.
|
||||
rule_attr = ctx.rule.attr
|
||||
|
||||
# CcInfo is a proxy for what we expect this rule to look like.
|
||||
# However, some deps may expose `CcInfo` without having `srcs`,
|
||||
# `hdrs`, etc., so we use `getattr` to handle that gracefully.
|
||||
|
||||
internal_hdrs = []
|
||||
srcs = []
|
||||
|
||||
# Filter `srcs` so it only contains source files. Headers will go
|
||||
# into `internal_headers`.
|
||||
for src in _flatten_target_files(getattr(rule_attr, "srcs", [])).to_list():
|
||||
if src.extension.lower() in ["c", "cc", "cpp", "cxx"]:
|
||||
srcs.append(src)
|
||||
else:
|
||||
internal_hdrs.append(src)
|
||||
|
||||
return [CcFileList(
|
||||
hdrs = _flatten_target_files(getattr(rule_attr, "hdrs", depset())),
|
||||
textual_hdrs = _flatten_target_files(getattr(
|
||||
rule_attr,
|
||||
"textual_hdrs",
|
||||
depset(),
|
||||
)),
|
||||
internal_hdrs = depset(internal_hdrs),
|
||||
srcs = depset(srcs),
|
||||
)]
|
||||
|
||||
cc_file_list_aspect = aspect(
|
||||
doc = """
|
||||
Aspect to provide the list of sources and headers from a rule.
|
||||
|
||||
Output is CcFileList. Example:
|
||||
|
||||
cc_library(
|
||||
name = "foo",
|
||||
srcs = [
|
||||
"foo.cc",
|
||||
"foo_internal.h",
|
||||
],
|
||||
hdrs = ["foo.h"],
|
||||
textual_hdrs = ["foo_inl.inc"],
|
||||
)
|
||||
# produces:
|
||||
# CcFileList(
|
||||
# hdrs = depset([File("foo.h")]),
|
||||
# textual_hdrs = depset([File("foo_inl.inc")]),
|
||||
# internal_hdrs = depset([File("foo_internal.h")]),
|
||||
# srcs = depset([File("foo.cc")]),
|
||||
# )
|
||||
""",
|
||||
implementation = _cc_file_list_aspect_impl,
|
||||
)
|
||||
|
||||
################################################################################
|
||||
# Rule impl
|
||||
################################################################################
|
||||
|
||||
def _collect_inputs(deps):
|
||||
"""Collects files from a list of immediate deps.
|
||||
|
||||
This rule collects source files and linker inputs for C++ deps. Only
|
||||
these immediate deps are considered, not transitive deps.
|
||||
|
||||
The return value is a struct with object files (linker inputs),
|
||||
partitioned by PIC and non-pic, and the rules' source and header files:
|
||||
|
||||
struct(
|
||||
objects = ..., # non-PIC object files
|
||||
pic_objects = ..., # PIC objects
|
||||
cc_file_list = ..., # a CcFileList
|
||||
)
|
||||
|
||||
Args:
|
||||
deps: Iterable of immediate deps. These will be treated as the "inputs,"
|
||||
but not the transitive deps.
|
||||
|
||||
Returns:
|
||||
A struct with linker inputs, source files, and header files.
|
||||
"""
|
||||
|
||||
objs = []
|
||||
pic_objs = []
|
||||
|
||||
# The returned CcFileList will contain depsets of the deps' file lists.
|
||||
# These lists hold `depset()`s from each of `deps`.
|
||||
srcs = []
|
||||
hdrs = []
|
||||
internal_hdrs = []
|
||||
textual_hdrs = []
|
||||
|
||||
for dep in deps:
|
||||
if CcInfo in dep:
|
||||
_collect_linker_input_objects(
|
||||
dep.label,
|
||||
dep[CcInfo],
|
||||
objs,
|
||||
pic_objs,
|
||||
)
|
||||
|
||||
if CcFileList in dep:
|
||||
cfl = dep[CcFileList]
|
||||
srcs.append(cfl.srcs)
|
||||
hdrs.append(cfl.hdrs)
|
||||
internal_hdrs.append(cfl.internal_hdrs)
|
||||
textual_hdrs.append(cfl.textual_hdrs)
|
||||
|
||||
return struct(
|
||||
objects = objs,
|
||||
pic_objects = pic_objs,
|
||||
cc_file_list = CcFileList(
|
||||
srcs = depset(transitive = srcs),
|
||||
hdrs = depset(transitive = hdrs),
|
||||
internal_hdrs = depset(transitive = internal_hdrs),
|
||||
textual_hdrs = depset(transitive = textual_hdrs),
|
||||
),
|
||||
)
|
||||
|
||||
# Implementation for cc_dist_library rule.
|
||||
def _cc_dist_library_impl(ctx):
|
||||
cc_toolchain_info = find_cc_toolchain(ctx)
|
||||
|
||||
feature_configuration = cc_common.configure_features(
|
||||
ctx = ctx,
|
||||
cc_toolchain = cc_toolchain_info,
|
||||
)
|
||||
|
||||
inputs = _collect_inputs(ctx.attr.deps)
|
||||
|
||||
# For static libraries, build separately with and without pic.
|
||||
|
||||
stemname = "lib" + ctx.label.name
|
||||
outputs = []
|
||||
|
||||
if len(inputs.objects) > 0:
|
||||
archive_out = ctx.actions.declare_file(stemname + ".a")
|
||||
_create_archive_action(
|
||||
ctx,
|
||||
feature_configuration,
|
||||
cc_toolchain_info,
|
||||
archive_out,
|
||||
inputs.objects,
|
||||
)
|
||||
outputs.append(archive_out)
|
||||
|
||||
if len(inputs.pic_objects) > 0:
|
||||
pic_archive_out = ctx.actions.declare_file(stemname + ".pic.a")
|
||||
_create_archive_action(
|
||||
ctx,
|
||||
feature_configuration,
|
||||
cc_toolchain_info,
|
||||
pic_archive_out,
|
||||
inputs.pic_objects,
|
||||
)
|
||||
outputs.append(pic_archive_out)
|
||||
|
||||
# For dynamic libraries, use the `cc_common.link` command to ensure
|
||||
# everything gets built correctly according to toolchain definitions.
|
||||
outputs.extend(_create_dso_link_action(
|
||||
ctx,
|
||||
feature_configuration,
|
||||
cc_toolchain_info,
|
||||
inputs.objects,
|
||||
inputs.pic_objects,
|
||||
))
|
||||
|
||||
# We could expose the libraries for use from cc rules:
|
||||
#
|
||||
# linking_context = cc_common.create_linking_context(
|
||||
# linker_inputs = depset([
|
||||
# cc_common.create_linker_input(
|
||||
# owner = ctx.label,
|
||||
# libraries = depset([library_to_link]),
|
||||
# ),
|
||||
# ]),
|
||||
# )
|
||||
# cc_info = CcInfo(linking_context = linking_context) # and return this
|
||||
#
|
||||
# However, if the goal is to force a protobuf dependency to use the
|
||||
# DSO, then `cc_import` is a better-supported way to do so.
|
||||
#
|
||||
# If we wanted to expose CcInfo from this rule (and make it usable as a
|
||||
# C++ dependency), then we would probably want to include the static
|
||||
# archive and headers as well. exposing headers would probably require
|
||||
# an additional aspect to extract CcInfos with just the deps' headers.
|
||||
|
||||
return [
|
||||
DefaultInfo(files = depset(outputs)),
|
||||
inputs.cc_file_list,
|
||||
]
|
||||
|
||||
cc_dist_library = rule(
|
||||
implementation = _cc_dist_library_impl,
|
||||
doc = """
|
||||
Create libraries suitable for distribution.
|
||||
|
||||
This rule creates static and dynamic libraries from the libraries listed in
|
||||
'deps'. The resulting libraries are suitable for distributing all of 'deps'
|
||||
in a single logical library, for example, in an installable binary package.
|
||||
Only the targets listed in 'deps' are included in the result (i.e., the
|
||||
output does not include transitive dependencies), allowing precise control
|
||||
over the library boundary.
|
||||
|
||||
The outputs of this rule are a dynamic library and a static library. (If
|
||||
the build produces both PIC and non-PIC object files, then there is also a
|
||||
second static library.) The example below illustrates additional details.
|
||||
|
||||
This rule is different from Bazel's experimental `shared_cc_library` in
|
||||
several ways. First, this rule ignores transitive dependencies, which means
|
||||
that dynamic library dependencies generally need to be specified via
|
||||
'linkopts'. Second, this rule produces a static archive library in addition
|
||||
to the dynamic shared library. Third, this rule is not directly usable as a
|
||||
C++ dependency (although the outputs could be used, e.g., by `cc_import`).
|
||||
|
||||
Example:
|
||||
|
||||
cc_library(name = "a", srcs = ["a.cc"], hdrs = ["a.h"])
|
||||
cc_library(name = "b", srcs = ["b.cc"], hdrs = ["b.h"], deps = [":a"])
|
||||
cc_library(name = "c", srcs = ["c.cc"], hdrs = ["c.h"], deps = [":b"])
|
||||
|
||||
# Creates libdist.so and (typically) libdist.pic.a:
|
||||
# (This may also produce libdist.a if the build produces non-PIC objects.)
|
||||
cc_dist_library(
|
||||
name = "dist",
|
||||
linkopts = ["-la"], # libdist.so dynamically links against liba.so.
|
||||
deps = [":b", ":c"], # Output contains b.o and c.o, but not a.o.
|
||||
)
|
||||
""",
|
||||
attrs = {
|
||||
"deps": attr.label_list(
|
||||
doc = ("The list of libraries to be included in the outputs. " +
|
||||
"Only these targets' compilation outputs will be " +
|
||||
"included (i.e., the transitive dependencies are not " +
|
||||
"included in the output)."),
|
||||
aspects = [cc_file_list_aspect],
|
||||
),
|
||||
"linkopts": attr.string_list(
|
||||
doc = ("Add these flags to the C++ linker command when creating " +
|
||||
"the dynamic library."),
|
||||
),
|
||||
# C++ toolchain before https://github.com/bazelbuild/bazel/issues/7260:
|
||||
"_cc_toolchain": attr.label(
|
||||
default = Label("@rules_cc//cc:current_cc_toolchain"),
|
||||
),
|
||||
},
|
||||
toolchains = [
|
||||
# C++ toolchain after https://github.com/bazelbuild/bazel/issues/7260:
|
||||
"@bazel_tools//tools/cpp:toolchain_type",
|
||||
],
|
||||
fragments = ["cpp"],
|
||||
)
|
||||
Reference in New Issue
Block a user