mirror of https://github.com/bazelbuild/rules_cc
Merge branch 'main' into rules-based-toolchain-example
This commit is contained in:
commit
b82c650543
|
@ -16,7 +16,6 @@ x_defaults:
|
||||||
- "//examples/my_c_archive:all"
|
- "//examples/my_c_archive:all"
|
||||||
- "//examples/my_c_compile:all"
|
- "//examples/my_c_compile:all"
|
||||||
- "//examples/write_cc_toolchain_cpu:all"
|
- "//examples/write_cc_toolchain_cpu:all"
|
||||||
- "//tools/migration:all"
|
|
||||||
- "//tests/..."
|
- "//tests/..."
|
||||||
test_flags:
|
test_flags:
|
||||||
- "--test_timeout=120"
|
- "--test_timeout=120"
|
||||||
|
@ -29,7 +28,6 @@ x_defaults:
|
||||||
- "//examples/my_c_archive:all"
|
- "//examples/my_c_archive:all"
|
||||||
- "//examples/my_c_compile:all"
|
- "//examples/my_c_compile:all"
|
||||||
- "//examples/write_cc_toolchain_cpu:all"
|
- "//examples/write_cc_toolchain_cpu:all"
|
||||||
- "//tools/migration:all"
|
|
||||||
- "//tests/..."
|
- "//tests/..."
|
||||||
|
|
||||||
buildifier:
|
buildifier:
|
||||||
|
|
|
@ -1,6 +1,12 @@
|
||||||
{
|
{
|
||||||
"homepage": "https://github.com/bazelbuild/rules_cc",
|
"homepage": "https://github.com/bazelbuild/rules_cc",
|
||||||
"maintainers": [],
|
"maintainers": [
|
||||||
|
{
|
||||||
|
"email": "ilist@google.com",
|
||||||
|
"github": "comius",
|
||||||
|
"name": "Ivo Ristovski List"
|
||||||
|
}
|
||||||
|
],
|
||||||
"versions": [],
|
"versions": [],
|
||||||
"yanked_versions": {}
|
"yanked_versions": {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,12 @@
|
||||||
matrix:
|
matrix:
|
||||||
platform: ["centos7", "debian10", "macos", "ubuntu2004", "windows"]
|
platform: ["centos7", "debian10", "macos", "ubuntu2004", "windows"]
|
||||||
|
bazel:
|
||||||
|
- 6.x
|
||||||
|
- 7.x
|
||||||
tasks:
|
tasks:
|
||||||
verify_targets:
|
verify_targets:
|
||||||
name: "Verify build targets"
|
name: "Verify build targets"
|
||||||
platform: ${{ platform }}
|
platform: ${{ platform }}
|
||||||
|
bazel: ${{ bazel }}
|
||||||
build_targets:
|
build_targets:
|
||||||
- "@rules_cc//cc/..."
|
- "@rules_cc//cc/..."
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"integrity": "",
|
"integrity": "",
|
||||||
"strip_prefix": "{REPO}-{VERSION}",
|
"strip_prefix": "{REPO}-{VERSION}",
|
||||||
"url": "https://github.com/{OWNER}/{REPO}/archive/refs/tags/{TAG}.tar.gz"
|
"url": "https://github.com/{OWNER}/{REPO}/releases/download/{TAG}/rules_cc-{TAG}.tar.gz"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
module(
|
module(
|
||||||
name = "rules_cc",
|
name = "rules_cc",
|
||||||
version = "0.0.10",
|
version = "0.0.12",
|
||||||
compatibility_level = 1,
|
compatibility_level = 1,
|
||||||
)
|
)
|
||||||
|
|
||||||
bazel_dep(name = "bazel_skylib", version = "1.7.1")
|
bazel_dep(name = "bazel_skylib", version = "1.7.1")
|
||||||
bazel_dep(name = "platforms", version = "0.0.10")
|
bazel_dep(name = "platforms", version = "0.0.10")
|
||||||
bazel_dep(name = "stardoc", version = "0.7.0")
|
|
||||||
|
|
||||||
cc_configure = use_extension("//cc:extensions.bzl", "cc_configure_extension")
|
cc_configure = use_extension("//cc:extensions.bzl", "cc_configure_extension")
|
||||||
use_repo(cc_configure, "local_config_cc", "local_config_cc_toolchains")
|
use_repo(cc_configure, "local_config_cc", "local_config_cc_toolchains")
|
||||||
|
@ -14,3 +13,4 @@ use_repo(cc_configure, "local_config_cc", "local_config_cc_toolchains")
|
||||||
register_toolchains("@local_config_cc_toolchains//:all")
|
register_toolchains("@local_config_cc_toolchains//:all")
|
||||||
|
|
||||||
bazel_dep(name = "rules_testing", version = "0.6.0", dev_dependency = True)
|
bazel_dep(name = "rules_testing", version = "0.6.0", dev_dependency = True)
|
||||||
|
bazel_dep(name = "stardoc", version = "0.7.0", dev_dependency = True)
|
||||||
|
|
67
WORKSPACE
67
WORKSPACE
|
@ -11,34 +11,6 @@ http_archive(
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
http_archive(
|
|
||||||
name = "com_google_googletest",
|
|
||||||
sha256 = "81964fe578e9bd7c94dfdb09c8e4d6e6759e19967e397dbea48d1c10e45d0df2",
|
|
||||||
strip_prefix = "googletest-release-1.12.1",
|
|
||||||
urls = [
|
|
||||||
"https://mirror.bazel.build/github.com/google/googletest/archive/refs/tags/release-1.12.1.tar.gz",
|
|
||||||
"https://github.com/google/googletest/archive/refs/tags/release-1.12.1.tar.gz",
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
http_archive(
|
|
||||||
name = "io_abseil_py",
|
|
||||||
sha256 = "0fb3a4916a157eb48124ef309231cecdfdd96ff54adf1660b39c0d4a9790a2c0",
|
|
||||||
strip_prefix = "abseil-py-1.4.0",
|
|
||||||
urls = [
|
|
||||||
"https://github.com/abseil/abseil-py/archive/refs/tags/v1.4.0.tar.gz",
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
http_archive(
|
|
||||||
name = "io_bazel_rules_go",
|
|
||||||
sha256 = "91585017debb61982f7054c9688857a2ad1fd823fc3f9cb05048b0025c47d023",
|
|
||||||
urls = [
|
|
||||||
"https://mirror.bazel.build/github.com/bazelbuild/rules_go/releases/download/v0.42.0/rules_go-v0.42.0.zip",
|
|
||||||
"https://github.com/bazelbuild/rules_go/releases/download/v0.42.0/rules_go-v0.42.0.zip",
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
http_archive(
|
http_archive(
|
||||||
name = "platforms",
|
name = "platforms",
|
||||||
sha256 = "218efe8ee736d26a3572663b374a253c012b716d8af0c07e842e82f238a0a7ee",
|
sha256 = "218efe8ee736d26a3572663b374a253c012b716d8af0c07e842e82f238a0a7ee",
|
||||||
|
@ -48,49 +20,10 @@ http_archive(
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
http_archive(
|
|
||||||
name = "py_mock",
|
|
||||||
patch_cmds = [
|
|
||||||
"mkdir -p py/mock",
|
|
||||||
"mv mock.py py/mock/__init__.py",
|
|
||||||
"""echo 'licenses(["notice"])' > BUILD""",
|
|
||||||
"touch py/BUILD",
|
|
||||||
"""echo 'py_library(name = "mock", srcs = ["__init__.py"], visibility = ["//visibility:public"],)' > py/mock/BUILD""",
|
|
||||||
],
|
|
||||||
sha256 = "b839dd2d9c117c701430c149956918a423a9863b48b09c90e30a6013e7d2f44f",
|
|
||||||
strip_prefix = "mock-1.0.1",
|
|
||||||
urls = [
|
|
||||||
"https://mirror.bazel.build/pypi.python.org/packages/source/m/mock/mock-1.0.1.tar.gz",
|
|
||||||
"https://pypi.python.org/packages/source/m/mock/mock-1.0.1.tar.gz",
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
http_archive(
|
|
||||||
name = "rules_proto",
|
|
||||||
sha256 = "9a0503631679e9ab4e27d891ea60fee3e86a85654ea2048cae25516171dd260e",
|
|
||||||
strip_prefix = "rules_proto-e51f588e5932966ab9e63e0b0f6de6f740cf04c4",
|
|
||||||
urls = [
|
|
||||||
"https://mirror.bazel.build/github.com/bazelbuild/rules_proto/archive/e51f588e5932966ab9e63e0b0f6de6f740cf04c4.tar.gz",
|
|
||||||
"https://github.com/bazelbuild/rules_proto/archive/e51f588e5932966ab9e63e0b0f6de6f740cf04c4.tar.gz",
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
load("@bazel_skylib//:workspace.bzl", "bazel_skylib_workspace")
|
load("@bazel_skylib//:workspace.bzl", "bazel_skylib_workspace")
|
||||||
|
|
||||||
bazel_skylib_workspace()
|
bazel_skylib_workspace()
|
||||||
|
|
||||||
load("@io_bazel_rules_go//go:deps.bzl", "go_register_toolchains", "go_rules_dependencies")
|
|
||||||
|
|
||||||
go_rules_dependencies()
|
|
||||||
|
|
||||||
go_register_toolchains(version = "1.20.5")
|
|
||||||
|
|
||||||
load("@rules_proto//proto:repositories.bzl", "rules_proto_dependencies", "rules_proto_toolchains")
|
|
||||||
|
|
||||||
rules_proto_dependencies()
|
|
||||||
|
|
||||||
rules_proto_toolchains()
|
|
||||||
|
|
||||||
http_archive(
|
http_archive(
|
||||||
name = "rules_testing",
|
name = "rules_testing",
|
||||||
sha256 = "02c62574631876a4e3b02a1820cb51167bb9cdcdea2381b2fa9d9b8b11c407c4",
|
sha256 = "02c62574631876a4e3b02a1820cb51167bb9cdcdea2381b2fa9d9b8b11c407c4",
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
filegroup(
|
filegroup(
|
||||||
name = "srcs",
|
name = "srcs",
|
||||||
srcs = glob([
|
srcs = glob([
|
||||||
"**/*.bzl",
|
|
||||||
"**/BUILD",
|
"**/BUILD",
|
||||||
]) + [
|
]) + [
|
||||||
"//cc/private/rules_impl:srcs",
|
"//cc/private/rules_impl:srcs",
|
||||||
|
|
|
@ -13,11 +13,6 @@
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
|
load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
|
||||||
load("@bazel_skylib//rules:diff_test.bzl", "diff_test")
|
|
||||||
load("@bazel_skylib//rules:expand_template.bzl", "expand_template")
|
|
||||||
load("@stardoc//stardoc:stardoc.bzl", "stardoc")
|
|
||||||
load("//cc/toolchains/impl:documented_api.bzl", "DOCUMENTED_TOOLCHAIN_RULES")
|
|
||||||
load("//cc/toolchains/impl:markdown_helpers.bzl", "xref_substitutions")
|
|
||||||
|
|
||||||
bzl_library(
|
bzl_library(
|
||||||
name = "toolchain_rules",
|
name = "toolchain_rules",
|
||||||
|
@ -42,35 +37,3 @@ filegroup(
|
||||||
]),
|
]),
|
||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
)
|
)
|
||||||
|
|
||||||
stardoc(
|
|
||||||
name = "toolchain_api",
|
|
||||||
out = "raw_generated_toolchain_api.md",
|
|
||||||
input = "//cc/toolchains/impl:documented_api.bzl",
|
|
||||||
deps = [":toolchain_rules"],
|
|
||||||
)
|
|
||||||
|
|
||||||
expand_template(
|
|
||||||
name = "toolchain_api_md",
|
|
||||||
out = "generated_toolchain_api.md",
|
|
||||||
# Dictionary order 100% matters here!
|
|
||||||
# buildifier: disable=unsorted-dict-items
|
|
||||||
substitutions = {
|
|
||||||
# Strip @rules_cc to prevent instances of @rules_cc@rules_cc//cc.
|
|
||||||
"@rules_cc//cc": "//cc",
|
|
||||||
# In GitHub, we prefer to clarify all the labels that come from
|
|
||||||
# rules_cc.
|
|
||||||
"//cc": "@rules_cc//cc",
|
|
||||||
} | xref_substitutions({
|
|
||||||
"`{}`".format(rule_name): "#{}".format(rule_name)
|
|
||||||
for rule_name in DOCUMENTED_TOOLCHAIN_RULES
|
|
||||||
}),
|
|
||||||
# buildifier: enable=unsorted-dict-items
|
|
||||||
template = ":raw_generated_toolchain_api.md",
|
|
||||||
)
|
|
||||||
|
|
||||||
diff_test(
|
|
||||||
name = "toolchain_api_diff_test",
|
|
||||||
file1 = ":generated_toolchain_api.md",
|
|
||||||
file2 = ":toolchain_api.md",
|
|
||||||
)
|
|
||||||
|
|
|
@ -40,7 +40,7 @@ cc_action_type = rule(
|
||||||
`cc_action_type` rules are used to associate arguments and tools together to
|
`cc_action_type` rules are used to associate arguments and tools together to
|
||||||
perform a specific action. Bazel prescribes a set of known action types that are used to drive
|
perform a specific action. Bazel prescribes a set of known action types that are used to drive
|
||||||
typical C/C++/ObjC actions like compiling, linking, and archiving. The set of well-known action
|
typical C/C++/ObjC actions like compiling, linking, and archiving. The set of well-known action
|
||||||
types can be found in [//cc/toolchains/actions:BUILD](https://github.com/bazelbuild/rules_cc/tree/main/cc/toolchains/actions/BUILD).
|
types can be found in [//third_party/bazel_rules/rules_cc/cc/toolchains/actions:BUILD](https://github.com/bazelbuild/rules_cc/tree/main/cc/toolchains/actions/BUILD).
|
||||||
|
|
||||||
It's possible to create project-specific action types for use in toolchains. Be careful when
|
It's possible to create project-specific action types for use in toolchains. Be careful when
|
||||||
doing this, because every toolchain that encounters the action will need to be configured to
|
doing this, because every toolchain that encounters the action will need to be configured to
|
||||||
|
|
|
@ -235,6 +235,8 @@ cc_action_type_set(
|
||||||
":cpp_compile_actions",
|
":cpp_compile_actions",
|
||||||
":c_compile_actions",
|
":c_compile_actions",
|
||||||
":assembly_actions",
|
":assembly_actions",
|
||||||
|
":objc_compile",
|
||||||
|
":objcpp_compile",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -17,13 +17,14 @@ load("//cc/toolchains:args.bzl", "cc_args")
|
||||||
|
|
||||||
visibility("public")
|
visibility("public")
|
||||||
|
|
||||||
def cc_sysroot(name, sysroot, **kwargs):
|
def cc_sysroot(name, sysroot, args = [], **kwargs):
|
||||||
"""Creates args for a sysroot.
|
"""Creates args for a sysroot.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
name: (str) The name of the target
|
name: (str) The name of the target
|
||||||
sysroot: (bazel_skylib's directory rule) The directory that should be the
|
sysroot: (bazel_skylib's directory rule) The directory that should be the
|
||||||
sysroot.
|
sysroot.
|
||||||
|
args: (List[str]) Extra command-line args to add.
|
||||||
**kwargs: kwargs to pass to cc_args.
|
**kwargs: kwargs to pass to cc_args.
|
||||||
"""
|
"""
|
||||||
cc_args(
|
cc_args(
|
||||||
|
@ -33,7 +34,7 @@ def cc_sysroot(name, sysroot, **kwargs):
|
||||||
Label("//cc/toolchains/actions:c_compile"),
|
Label("//cc/toolchains/actions:c_compile"),
|
||||||
Label("//cc/toolchains/actions:link_actions"),
|
Label("//cc/toolchains/actions:link_actions"),
|
||||||
],
|
],
|
||||||
args = ["--sysroot={sysroot}"],
|
args = ["--sysroot={sysroot}"] + args,
|
||||||
format = {"sysroot": sysroot},
|
format = {"sysroot": sysroot},
|
||||||
**kwargs
|
**kwargs
|
||||||
)
|
)
|
||||||
|
|
|
@ -9,7 +9,7 @@ load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
|
||||||
|
|
||||||
exports_files(
|
exports_files(
|
||||||
["documented_api.bzl"],
|
["documented_api.bzl"],
|
||||||
visibility = ["//cc/toolchains:__subpackages__"],
|
visibility = ["//docs:__pkg__"],
|
||||||
)
|
)
|
||||||
|
|
||||||
bzl_library(
|
bzl_library(
|
||||||
|
|
|
@ -75,7 +75,7 @@ def cc_variable(name, type, **kwargs):
|
||||||
it's not possible to declare custom variables.
|
it's not possible to declare custom variables.
|
||||||
|
|
||||||
For a full list of available variables, see
|
For a full list of available variables, see
|
||||||
[//cc/toolchains/varaibles:BUILD](https://github.com/bazelbuild/rules_cc/tree/main/cc/toolchains/variables/BUILD).
|
[//third_party/bazel_rules/rules_cc/cc/toolchains/varaibles:BUILD](https://github.com/bazelbuild/rules_cc/tree/main/cc/toolchains/variables/BUILD).
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
```
|
```
|
||||||
|
@ -91,7 +91,7 @@ def cc_variable(name, type, **kwargs):
|
||||||
Args:
|
Args:
|
||||||
name: (str) The name of the outer variable, and the rule.
|
name: (str) The name of the outer variable, and the rule.
|
||||||
type: The type of the variable, constructed using `types` factory in
|
type: The type of the variable, constructed using `types` factory in
|
||||||
[//cc/toolchains/impl:variables.bzl](https://github.com/bazelbuild/rules_cc/tree/main/cc/toolchains/impl/variables.bzl).
|
[//third_party/bazel_rules/rules_cc/cc/toolchains/impl:variables.bzl](https://github.com/bazelbuild/rules_cc/tree/main/cc/toolchains/impl/variables.bzl).
|
||||||
**kwargs: [common attributes](https://bazel.build/reference/be/common-definitions#common-attributes) that should be applied to this rule.
|
**kwargs: [common attributes](https://bazel.build/reference/be/common-definitions#common-attributes) that should be applied to this rule.
|
||||||
"""
|
"""
|
||||||
_cc_variable(name = name, type = json.encode(type), **kwargs)
|
_cc_variable(name = name, type = json.encode(type), **kwargs)
|
||||||
|
|
|
@ -102,7 +102,7 @@ This can help work around errors like:
|
||||||
providers = [ToolCapabilityInfo],
|
providers = [ToolCapabilityInfo],
|
||||||
doc = """Declares that a tool is capable of doing something.
|
doc = """Declares that a tool is capable of doing something.
|
||||||
|
|
||||||
For example, `//cc/toolchains/capabilities:supports_pic`.
|
For example, `//third_party/bazel_rules/rules_cc/cc/toolchains/capabilities:supports_pic`.
|
||||||
""",
|
""",
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
|
|
@ -75,7 +75,7 @@ def cc_tool_map(name, tools, **kwargs):
|
||||||
`CXX=/path/to/clang++` environment variables that most build systems use to determine which
|
`CXX=/path/to/clang++` environment variables that most build systems use to determine which
|
||||||
tools to use for a given action. To simplify usage, some actions have been grouped together (for
|
tools to use for a given action. To simplify usage, some actions have been grouped together (for
|
||||||
example,
|
example,
|
||||||
[//cc/toolchains/actions:cpp_compile_actions](https://github.com/bazelbuild/rules_cc/tree/main/cc/toolchains/actions/BUILD)) to
|
[//third_party/bazel_rules/rules_cc/cc/toolchains/actions:cpp_compile_actions](https://github.com/bazelbuild/rules_cc/tree/main/cc/toolchains/actions/BUILD)) to
|
||||||
logically express "all the C++ compile actions".
|
logically express "all the C++ compile actions".
|
||||||
|
|
||||||
In Bazel, there is a little more granularity to the mapping, so the mapping doesn't follow the
|
In Bazel, there is a little more granularity to the mapping, so the mapping doesn't follow the
|
||||||
|
|
|
@ -19,11 +19,6 @@ load("//cc/private/toolchain:windows_cc_configure.bzl", _find_vc_path = "find_vc
|
||||||
|
|
||||||
MSVC_ENVVARS = _MSVC_ENVVARS
|
MSVC_ENVVARS = _MSVC_ENVVARS
|
||||||
|
|
||||||
def find_vc_path(repository_ctx):
|
find_vc_path = _find_vc_path
|
||||||
return _find_vc_path(repository_ctx)
|
setup_vc_env_vars = _setup_vc_env_vars
|
||||||
|
escape_string = _escape_string
|
||||||
def setup_vc_env_vars(repository_ctx):
|
|
||||||
return _setup_vc_env_vars(repository_ctx)
|
|
||||||
|
|
||||||
def escape_string(string):
|
|
||||||
return _escape_string(string)
|
|
||||||
|
|
|
@ -0,0 +1,60 @@
|
||||||
|
# Copyright 2024 The Bazel Authors. All rights reserved.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
load("@bazel_skylib//rules:diff_test.bzl", "diff_test")
|
||||||
|
load("@bazel_skylib//rules:expand_template.bzl", "expand_template")
|
||||||
|
load("@stardoc//stardoc:stardoc.bzl", "stardoc")
|
||||||
|
load("//cc/toolchains/impl:documented_api.bzl", "DOCUMENTED_TOOLCHAIN_RULES")
|
||||||
|
load("//cc/toolchains/impl:markdown_helpers.bzl", "xref_substitutions")
|
||||||
|
|
||||||
|
filegroup(
|
||||||
|
name = "srcs",
|
||||||
|
srcs = glob([
|
||||||
|
"**/*.bzl",
|
||||||
|
"**/BUILD",
|
||||||
|
]),
|
||||||
|
visibility = ["//visibility:public"],
|
||||||
|
)
|
||||||
|
|
||||||
|
stardoc(
|
||||||
|
name = "toolchain_api",
|
||||||
|
out = "raw_generated_toolchain_api.md",
|
||||||
|
input = "//cc/toolchains/impl:documented_api.bzl",
|
||||||
|
deps = ["//cc/toolchains:toolchain_rules"],
|
||||||
|
)
|
||||||
|
|
||||||
|
expand_template(
|
||||||
|
name = "toolchain_api_md",
|
||||||
|
out = "generated_toolchain_api.md",
|
||||||
|
# Dictionary order 100% matters here!
|
||||||
|
# buildifier: disable=unsorted-dict-items
|
||||||
|
substitutions = {
|
||||||
|
# Strip @rules_cc to prevent instances of @rules_cc@rules_cc//cc.
|
||||||
|
"@rules_cc//cc": "//cc",
|
||||||
|
# In GitHub, we prefer to clarify all the labels that come from
|
||||||
|
# rules_cc.
|
||||||
|
"//cc": "@rules_cc//cc",
|
||||||
|
} | xref_substitutions({
|
||||||
|
"`{}`".format(rule_name): "#{}".format(rule_name)
|
||||||
|
for rule_name in DOCUMENTED_TOOLCHAIN_RULES
|
||||||
|
}),
|
||||||
|
# buildifier: enable=unsorted-dict-items
|
||||||
|
template = ":raw_generated_toolchain_api.md",
|
||||||
|
)
|
||||||
|
|
||||||
|
diff_test(
|
||||||
|
name = "toolchain_api_diff_test",
|
||||||
|
file1 = ":generated_toolchain_api.md",
|
||||||
|
file2 = ":toolchain_api.md",
|
||||||
|
)
|
|
@ -1 +0,0 @@
|
||||||
# Intentionally empty, only there to make //third_party a package.
|
|
|
@ -1,30 +0,0 @@
|
||||||
load("@com_google_protobuf//:protobuf.bzl", "py_proto_library")
|
|
||||||
load("@io_bazel_rules_go//proto:def.bzl", "go_proto_library")
|
|
||||||
load("@rules_proto//proto:defs.bzl", "proto_library")
|
|
||||||
|
|
||||||
licenses(["notice"]) # Apache 2.0
|
|
||||||
|
|
||||||
py_proto_library(
|
|
||||||
name = "crosstool_config_py_pb2",
|
|
||||||
srcs = ["crosstool_config.proto"],
|
|
||||||
visibility = [
|
|
||||||
"//tools/migration:__pkg__",
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
proto_library(
|
|
||||||
name = "crosstool_config_pb2",
|
|
||||||
srcs = ["crosstool_config.proto"],
|
|
||||||
visibility = [
|
|
||||||
"//tools/migration:__pkg__",
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
go_proto_library(
|
|
||||||
name = "crosstool_config_go_proto",
|
|
||||||
importpath = "third_party/com/github/bazelbuild/bazel/src/main/protobuf/crosstool_config_go_proto",
|
|
||||||
proto = ":crosstool_config_pb2",
|
|
||||||
visibility = [
|
|
||||||
"//tools/migration:__pkg__",
|
|
||||||
],
|
|
||||||
)
|
|
|
@ -1,548 +0,0 @@
|
||||||
// Copyright 2014 The Bazel Authors. All rights reserved.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
//
|
|
||||||
// File format for Blaze to configure Crosstool releases.
|
|
||||||
|
|
||||||
syntax = "proto2";
|
|
||||||
|
|
||||||
package com.google.devtools.build.lib.view.config.crosstool;
|
|
||||||
|
|
||||||
// option java_api_version = 2; // copybara-comment-this-out-please
|
|
||||||
option java_package = "com.google.devtools.build.lib.view.config.crosstool";
|
|
||||||
|
|
||||||
// A description of a toolchain, which includes all the tools generally expected
|
|
||||||
// to be available for building C/C++ targets, based on the GNU C compiler.
|
|
||||||
//
|
|
||||||
// System and cpu names are two overlapping concepts, which need to be both
|
|
||||||
// supported at this time. The cpu name is the blaze command-line name for the
|
|
||||||
// target system. The most common values are 'k8' and 'piii'. The system name is
|
|
||||||
// a more generic identification of the executable system, based on the names
|
|
||||||
// used by the GNU C compiler.
|
|
||||||
//
|
|
||||||
// Typically, the system name contains an identifier for the cpu (e.g. x86_64 or
|
|
||||||
// alpha), an identifier for the machine (e.g. pc, or unknown), and an
|
|
||||||
// identifier for the operating system (e.g. cygwin or linux-gnu). Typical
|
|
||||||
// examples are 'x86_64-unknown-linux-gnu' and 'i686-unknown-cygwin'.
|
|
||||||
//
|
|
||||||
// The system name is used to determine if a given machine can execute a given
|
|
||||||
// executable. In particular, it is used to check if the compilation products of
|
|
||||||
// a toolchain can run on the host machine.
|
|
||||||
message CToolchain {
|
|
||||||
// A group of correlated flags. Supports parametrization via variable
|
|
||||||
// expansion.
|
|
||||||
//
|
|
||||||
// To expand a variable of list type, flag_group has to be annotated with
|
|
||||||
// `iterate_over` message. Then all nested flags or flag_groups will be
|
|
||||||
// expanded repeatedly for each element of the list.
|
|
||||||
//
|
|
||||||
// For example:
|
|
||||||
// flag_group {
|
|
||||||
// iterate_over: 'include_path'
|
|
||||||
// flag: '-I'
|
|
||||||
// flag: '%{include_path}'
|
|
||||||
// }
|
|
||||||
// ... will get expanded to -I /to/path1 -I /to/path2 ... for each
|
|
||||||
// include_path /to/pathN.
|
|
||||||
//
|
|
||||||
// To expand a variable of structure type, use dot-notation, e.g.:
|
|
||||||
// flag_group {
|
|
||||||
// iterate_over: "libraries_to_link"
|
|
||||||
// flag_group {
|
|
||||||
// iterate_over: "libraries_to_link.libraries"
|
|
||||||
// flag: "-L%{libraries_to_link.libraries.directory}"
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// Flag groups can be nested; if they are, the flag group must only contain
|
|
||||||
// other flag groups (no flags) so the order is unambiguously specified.
|
|
||||||
// In order to expand a variable of nested lists, 'iterate_over' can be used.
|
|
||||||
//
|
|
||||||
// For example:
|
|
||||||
// flag_group {
|
|
||||||
// iterate_over: 'object_files'
|
|
||||||
// flag_group { flag: '--start-lib' }
|
|
||||||
// flag_group {
|
|
||||||
// iterate_over: 'object_files'
|
|
||||||
// flag: '%{object_files}'
|
|
||||||
// }
|
|
||||||
// flag_group { flag: '--end-lib' }
|
|
||||||
// }
|
|
||||||
// ... will get expanded to
|
|
||||||
// --start-lib a1.o a2.o ... --end-lib --start-lib b1.o b2.o .. --end-lib
|
|
||||||
// with %{object_files} being a variable of nested list type
|
|
||||||
// [['a1.o', 'a2.o', ...], ['b1.o', 'b2.o', ...], ...].
|
|
||||||
//
|
|
||||||
// TODO(bazel-team): Write more elaborate documentation and add a link to it.
|
|
||||||
message FlagGroup {
|
|
||||||
repeated string flag = 1;
|
|
||||||
|
|
||||||
repeated FlagGroup flag_group = 2;
|
|
||||||
|
|
||||||
optional string iterate_over = 3;
|
|
||||||
|
|
||||||
repeated string expand_if_all_available = 4;
|
|
||||||
|
|
||||||
repeated string expand_if_none_available = 5;
|
|
||||||
|
|
||||||
optional string expand_if_true = 6;
|
|
||||||
|
|
||||||
optional string expand_if_false = 7;
|
|
||||||
|
|
||||||
optional VariableWithValue expand_if_equal = 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
message VariableWithValue {
|
|
||||||
required string variable = 1;
|
|
||||||
|
|
||||||
required string value = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
// A key/value pair to be added as an environment variable. The value of
|
|
||||||
// this pair is expanded in the same way as is described in FlagGroup.
|
|
||||||
// The key remains an unexpanded string literal.
|
|
||||||
message EnvEntry {
|
|
||||||
required string key = 1;
|
|
||||||
required string value = 2;
|
|
||||||
repeated string expand_if_all_available = 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
// A set of features; used to support logical 'and' when specifying feature
|
|
||||||
// requirements in Feature.
|
|
||||||
message FeatureSet {
|
|
||||||
repeated string feature = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// A set of positive and negative features. This stanza will
|
|
||||||
// evaluate to true when every 'feature' is enabled, and every
|
|
||||||
// 'not_feature' is not enabled.
|
|
||||||
message WithFeatureSet {
|
|
||||||
repeated string feature = 1;
|
|
||||||
repeated string not_feature = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
// A set of flags that are expanded in the command line for specific actions.
|
|
||||||
message FlagSet {
|
|
||||||
// The actions this flag set applies to; each flag set must specify at
|
|
||||||
// least one action.
|
|
||||||
repeated string action = 1;
|
|
||||||
|
|
||||||
// The flags applied via this flag set.
|
|
||||||
repeated FlagGroup flag_group = 2;
|
|
||||||
|
|
||||||
// A list of feature sets defining when this flag set gets applied. The
|
|
||||||
// flag set will be applied when any one of the feature sets evaluate to
|
|
||||||
// true. (That is, when when every 'feature' is enabled, and every
|
|
||||||
// 'not_feature' is not enabled.)
|
|
||||||
//
|
|
||||||
// If 'with_feature' is omitted, the flag set will be applied
|
|
||||||
// unconditionally for every action specified.
|
|
||||||
repeated WithFeatureSet with_feature = 3;
|
|
||||||
|
|
||||||
// Deprecated (https://github.com/bazelbuild/bazel/issues/7008) - use
|
|
||||||
// expand_if_all_available in flag_group
|
|
||||||
//
|
|
||||||
// A list of build variables that this feature set needs, but which are
|
|
||||||
// allowed to not be set. If any of the build variables listed is not
|
|
||||||
// set, the feature set will not be expanded.
|
|
||||||
//
|
|
||||||
// NOTE: Consider alternatives before using this; usually tools should
|
|
||||||
// consistently create the same set of files, even if empty; use this
|
|
||||||
// only for backwards compatibility with already existing behavior in tools
|
|
||||||
// that are currently not worth changing.
|
|
||||||
repeated string expand_if_all_available = 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
// A set of environment variables that are expanded in the command line for
|
|
||||||
// specific actions.
|
|
||||||
message EnvSet {
|
|
||||||
// The actions this env set applies to; each env set must specify at
|
|
||||||
// least one action.
|
|
||||||
repeated string action = 1;
|
|
||||||
|
|
||||||
// The environment variables applied via this env set.
|
|
||||||
repeated EnvEntry env_entry = 2;
|
|
||||||
|
|
||||||
// A list of feature sets defining when this env set gets applied. The
|
|
||||||
// env set will be applied when any one of the feature sets evaluate to
|
|
||||||
// true. (That is, when when every 'feature' is enabled, and every
|
|
||||||
// 'not_feature' is not enabled.)
|
|
||||||
//
|
|
||||||
// If 'with_feature' is omitted, the env set will be applied
|
|
||||||
// unconditionally for every action specified.
|
|
||||||
repeated WithFeatureSet with_feature = 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Contains all flag specifications for one feature.
|
|
||||||
// Next ID: 8
|
|
||||||
message Feature {
|
|
||||||
// The feature's name. Feature names are generally defined by Bazel; it is
|
|
||||||
// possible to introduce a feature without a change to Bazel by adding a
|
|
||||||
// 'feature' section to the toolchain and adding the corresponding string as
|
|
||||||
// feature in the BUILD file.
|
|
||||||
optional string name = 1;
|
|
||||||
|
|
||||||
// If 'true', this feature is enabled unless a rule type explicitly marks it
|
|
||||||
// as unsupported. Such features cannot be turned off from within a BUILD
|
|
||||||
// file or the command line.
|
|
||||||
optional bool enabled = 7;
|
|
||||||
|
|
||||||
// If the given feature is enabled, the flag sets will be applied for the
|
|
||||||
// actions in the modes that they are specified for.
|
|
||||||
repeated FlagSet flag_set = 2;
|
|
||||||
|
|
||||||
// If the given feature is enabled, the env sets will be applied for the
|
|
||||||
// actions in the modes that they are specified for.
|
|
||||||
repeated EnvSet env_set = 6;
|
|
||||||
|
|
||||||
// A list of feature sets defining when this feature is supported by the
|
|
||||||
// toolchain. The feature is supported if any of the feature sets fully
|
|
||||||
// apply, that is, when all features of a feature set are enabled.
|
|
||||||
//
|
|
||||||
// If 'requires' is omitted, the feature is supported independently of which
|
|
||||||
// other features are enabled.
|
|
||||||
//
|
|
||||||
// Use this for example to filter flags depending on the build mode
|
|
||||||
// enabled (opt / fastbuild / dbg).
|
|
||||||
repeated FeatureSet requires = 3;
|
|
||||||
|
|
||||||
// A list of features or action configs that are automatically enabled when
|
|
||||||
// this feature is enabled. If any of the implied features or action configs
|
|
||||||
// cannot be enabled, this feature will (silently) not be enabled either.
|
|
||||||
repeated string implies = 4;
|
|
||||||
|
|
||||||
// A list of names this feature conflicts with.
|
|
||||||
// A feature cannot be enabled if:
|
|
||||||
// - 'provides' contains the name of a different feature or action config
|
|
||||||
// that we want to enable.
|
|
||||||
// - 'provides' contains the same value as a 'provides' in a different
|
|
||||||
// feature or action config that we want to enable.
|
|
||||||
//
|
|
||||||
// Use this in order to ensure that incompatible features cannot be
|
|
||||||
// accidentally activated at the same time, leading to hard to diagnose
|
|
||||||
// compiler errors.
|
|
||||||
repeated string provides = 5;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Describes a tool associated with a crosstool action config.
|
|
||||||
message Tool {
|
|
||||||
// Describes the origin of a path.
|
|
||||||
enum PathOrigin {
|
|
||||||
// Indicates that `tool_path` is relative to the location of the
|
|
||||||
// crosstool. For legacy reasons, absolute paths are als0 allowed here.
|
|
||||||
CROSSTOOL_PACKAGE = 0;
|
|
||||||
|
|
||||||
// Indicates that `tool_path` is an absolute path.
|
|
||||||
// This is enforced by Bazel.
|
|
||||||
FILESYSTEM_ROOT = 1;
|
|
||||||
|
|
||||||
// Indicates that `tool_path` is relative to the current workspace's
|
|
||||||
// exec root.
|
|
||||||
WORKSPACE_ROOT = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Path to the tool, relative to the location of the crosstool.
|
|
||||||
required string tool_path = 1;
|
|
||||||
|
|
||||||
// Origin of `tool_path`.
|
|
||||||
// Optional only for legacy reasons. New crosstools should set this value!
|
|
||||||
optional PathOrigin tool_path_origin = 4 [default = CROSSTOOL_PACKAGE];
|
|
||||||
|
|
||||||
// A list of feature sets defining when this tool is applicable. The tool
|
|
||||||
// will used when any one of the feature sets evaluate to true. (That is,
|
|
||||||
// when when every 'feature' is enabled, and every 'not_feature' is not
|
|
||||||
// enabled.)
|
|
||||||
//
|
|
||||||
// If 'with_feature' is omitted, the tool will apply for any feature
|
|
||||||
// configuration.
|
|
||||||
repeated WithFeatureSet with_feature = 2;
|
|
||||||
|
|
||||||
// Requirements on the execution environment for the execution of this tool,
|
|
||||||
// to be passed as out-of-band "hints" to the execution backend.
|
|
||||||
// Ex. "requires-darwin"
|
|
||||||
repeated string execution_requirement = 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The name for an artifact of a given category of input or output artifacts
|
|
||||||
// to an action.
|
|
||||||
message ArtifactNamePattern {
|
|
||||||
// The category of artifacts that this selection applies to. This field
|
|
||||||
// is compared against a list of categories defined in bazel. Example
|
|
||||||
// categories include "linked_output" or "debug_symbols". An error is thrown
|
|
||||||
// if no category is matched.
|
|
||||||
required string category_name = 1;
|
|
||||||
// The prefix and extension for creating the artifact for this selection.
|
|
||||||
// They are used to create an artifact name based on the target name.
|
|
||||||
required string prefix = 2;
|
|
||||||
required string extension = 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
// An action config corresponds to a blaze action, and allows selection of
|
|
||||||
// a tool based on activated features. Action configs come in two varieties:
|
|
||||||
// automatic (the blaze action will exist whether or not the action config
|
|
||||||
// is activated) and attachable (the blaze action will be added to the
|
|
||||||
// action graph only if the action config is activated).
|
|
||||||
//
|
|
||||||
// Action config activation occurs by the same semantics as features: a
|
|
||||||
// feature can 'require' or 'imply' an action config in the same way that it
|
|
||||||
// would another feature.
|
|
||||||
// Next ID: 9
|
|
||||||
message ActionConfig {
|
|
||||||
// The name other features will use to activate this action config. Can
|
|
||||||
// be the same as action_name.
|
|
||||||
required string config_name = 1;
|
|
||||||
|
|
||||||
// The name of the blaze action that this config applies to, ex. 'c-compile'
|
|
||||||
// or 'c-module-compile'.
|
|
||||||
required string action_name = 2;
|
|
||||||
|
|
||||||
// If 'true', this feature is enabled unless a rule type explicitly marks it
|
|
||||||
// as unsupported. Such action_configs cannot be turned off from within a
|
|
||||||
// BUILD file or the command line.
|
|
||||||
optional bool enabled = 8;
|
|
||||||
|
|
||||||
// The tool applied to the action will be the first Tool with a feature
|
|
||||||
// set that matches the feature configuration. An error will be thrown
|
|
||||||
// if no tool matches a provided feature configuration - for that reason,
|
|
||||||
// it's a good idea to provide a default tool with an empty feature set.
|
|
||||||
repeated Tool tool = 3;
|
|
||||||
|
|
||||||
// If the given action config is enabled, the flag sets will be applied
|
|
||||||
// to the corresponding action.
|
|
||||||
repeated FlagSet flag_set = 4;
|
|
||||||
|
|
||||||
// If the given action config is enabled, the env sets will be applied
|
|
||||||
// to the corresponding action.
|
|
||||||
repeated EnvSet env_set = 5;
|
|
||||||
|
|
||||||
// A list of feature sets defining when this action config
|
|
||||||
// is supported by the toolchain. The action config is supported if any of
|
|
||||||
// the feature sets fully apply, that is, when all features of a
|
|
||||||
// feature set are enabled.
|
|
||||||
//
|
|
||||||
// If 'requires' is omitted, the action config is supported independently
|
|
||||||
// of which other features are enabled.
|
|
||||||
//
|
|
||||||
// Use this for example to filter actions depending on the build
|
|
||||||
// mode enabled (opt / fastbuild / dbg).
|
|
||||||
repeated FeatureSet requires = 6;
|
|
||||||
|
|
||||||
// A list of features or action configs that are automatically enabled when
|
|
||||||
// this action config is enabled. If any of the implied features or action
|
|
||||||
// configs cannot be enabled, this action config will (silently)
|
|
||||||
// not be enabled either.
|
|
||||||
repeated string implies = 7;
|
|
||||||
}
|
|
||||||
|
|
||||||
repeated Feature feature = 50;
|
|
||||||
repeated ActionConfig action_config = 53;
|
|
||||||
repeated ArtifactNamePattern artifact_name_pattern = 54;
|
|
||||||
|
|
||||||
// The unique identifier of the toolchain within the crosstool release. It
|
|
||||||
// must be possible to use this as a directory name in a path.
|
|
||||||
// It has to match the following regex: [a-zA-Z_][\.\- \w]*
|
|
||||||
required string toolchain_identifier = 1;
|
|
||||||
|
|
||||||
// A basic toolchain description.
|
|
||||||
required string host_system_name = 2;
|
|
||||||
required string target_system_name = 3;
|
|
||||||
required string target_cpu = 4;
|
|
||||||
required string target_libc = 5;
|
|
||||||
required string compiler = 6;
|
|
||||||
|
|
||||||
required string abi_version = 7;
|
|
||||||
required string abi_libc_version = 8;
|
|
||||||
|
|
||||||
// Tool locations. Relative paths are resolved relative to the configuration
|
|
||||||
// file directory.
|
|
||||||
// NOTE: DEPRECATED. Prefer specifying an ActionConfig for the action that
|
|
||||||
// needs the tool.
|
|
||||||
// TODO(b/27903698) migrate to ActionConfig.
|
|
||||||
repeated ToolPath tool_path = 9;
|
|
||||||
|
|
||||||
// Feature flags.
|
|
||||||
// TODO(bazel-team): Sink those into 'Feature' instances.
|
|
||||||
// Legacy field, ignored by Bazel.
|
|
||||||
optional bool supports_gold_linker = 10 [default = false];
|
|
||||||
// Legacy field, ignored by Bazel.
|
|
||||||
optional bool supports_thin_archives = 11 [default = false];
|
|
||||||
// Legacy field, use 'supports_start_end_lib' feature instead.
|
|
||||||
optional bool supports_start_end_lib = 28 [default = false];
|
|
||||||
// Legacy field, use 'supports_interface_shared_libraries' instead.
|
|
||||||
optional bool supports_interface_shared_objects = 32 [default = false];
|
|
||||||
// Legacy field, use 'static_link_cpp_runtimes' feature instead.
|
|
||||||
optional bool supports_embedded_runtimes = 40 [default = false];
|
|
||||||
// If specified, Blaze finds statically linked / dynamically linked runtime
|
|
||||||
// libraries in the declared crosstool filegroup. Otherwise, Blaze
|
|
||||||
// looks in "[static|dynamic]-runtime-libs-$TARGET_CPU".
|
|
||||||
// Deprecated, see https://github.com/bazelbuild/bazel/issues/6942
|
|
||||||
optional string static_runtimes_filegroup = 45;
|
|
||||||
// Deprecated, see https://github.com/bazelbuild/bazel/issues/6942
|
|
||||||
optional string dynamic_runtimes_filegroup = 46;
|
|
||||||
// Legacy field, ignored by Bazel.
|
|
||||||
optional bool supports_incremental_linker = 41 [default = false];
|
|
||||||
// Legacy field, ignored by Bazel.
|
|
||||||
optional bool supports_normalizing_ar = 26 [default = false];
|
|
||||||
// Legacy field, use 'per_object_debug_info' feature instead.
|
|
||||||
optional bool supports_fission = 43 [default = false];
|
|
||||||
// Legacy field, ignored by Bazel.
|
|
||||||
optional bool supports_dsym = 51 [default = false];
|
|
||||||
// Legacy field, use 'supports_pic' feature instead
|
|
||||||
optional bool needsPic = 12 [default = false];
|
|
||||||
|
|
||||||
// Compiler flags for C/C++/Asm compilation.
|
|
||||||
repeated string compiler_flag = 13;
|
|
||||||
// Additional compiler flags for C++ compilation.
|
|
||||||
repeated string cxx_flag = 14;
|
|
||||||
// Additional unfiltered compiler flags for C/C++/Asm compilation.
|
|
||||||
// These are not subject to nocopt filtering in cc_* rules.
|
|
||||||
// Note: These flags are *not* applied to objc/objc++ compiles.
|
|
||||||
repeated string unfiltered_cxx_flag = 25;
|
|
||||||
// Linker flags.
|
|
||||||
repeated string linker_flag = 15;
|
|
||||||
// Additional linker flags when linking dynamic libraries.
|
|
||||||
repeated string dynamic_library_linker_flag = 27;
|
|
||||||
// Additional test-only linker flags.
|
|
||||||
repeated string test_only_linker_flag = 49;
|
|
||||||
// Objcopy flags for embedding files into binaries.
|
|
||||||
repeated string objcopy_embed_flag = 16;
|
|
||||||
// Ld flags for embedding files into binaries. This is used by filewrapper
|
|
||||||
// since it calls ld directly and needs to know what -m flag to pass.
|
|
||||||
repeated string ld_embed_flag = 23;
|
|
||||||
// Ar flags for combining object files into archives. If this is not set, it
|
|
||||||
// defaults to "rcsD".
|
|
||||||
// TODO(b/37271982): Remove after blaze with ar action_config release
|
|
||||||
repeated string ar_flag = 47;
|
|
||||||
// Legacy field, ignored by Bazel.
|
|
||||||
repeated string ar_thin_archives_flag = 48;
|
|
||||||
// Legacy field, ignored by Bazel.
|
|
||||||
repeated string gcc_plugin_compiler_flag = 34;
|
|
||||||
|
|
||||||
// Additional compiler and linker flags depending on the compilation mode.
|
|
||||||
repeated CompilationModeFlags compilation_mode_flags = 17;
|
|
||||||
|
|
||||||
// Additional linker flags depending on the linking mode.
|
|
||||||
repeated LinkingModeFlags linking_mode_flags = 18;
|
|
||||||
|
|
||||||
// Legacy field, ignored by Bazel.
|
|
||||||
repeated string gcc_plugin_header_directory = 19;
|
|
||||||
// Legacy field, ignored by Bazel.
|
|
||||||
repeated string mao_plugin_header_directory = 20;
|
|
||||||
|
|
||||||
// Make variables that are made accessible to rules.
|
|
||||||
repeated MakeVariable make_variable = 21;
|
|
||||||
|
|
||||||
// Built-in include directories for C++ compilation. These should be the exact
|
|
||||||
// paths used by the compiler, and are generally relative to the exec root.
|
|
||||||
// The paths used by the compiler can be determined by 'gcc -Wp,-v some.c'.
|
|
||||||
// We currently use the C++ paths also for C compilation, which is safe as
|
|
||||||
// long as there are no name clashes between C++ and C header files.
|
|
||||||
//
|
|
||||||
// Relative paths are resolved relative to the configuration file directory.
|
|
||||||
//
|
|
||||||
// If the compiler has --sysroot support, then these paths should use
|
|
||||||
// %sysroot% rather than the include path, and specify the sysroot attribute
|
|
||||||
// in order to give blaze the information necessary to make the correct
|
|
||||||
// replacements.
|
|
||||||
repeated string cxx_builtin_include_directory = 22;
|
|
||||||
|
|
||||||
// The built-in sysroot. If this attribute is not present, blaze does not
|
|
||||||
// allow using a different sysroot, i.e. through the --grte_top option. Also
|
|
||||||
// see the documentation above.
|
|
||||||
optional string builtin_sysroot = 24;
|
|
||||||
|
|
||||||
// Legacy field, ignored by Bazel.
|
|
||||||
optional string default_python_top = 29;
|
|
||||||
// Legacy field, ignored by Bazel.
|
|
||||||
optional string default_python_version = 30;
|
|
||||||
// Legacy field, ignored by Bazel.
|
|
||||||
optional bool python_preload_swigdeps = 42;
|
|
||||||
|
|
||||||
// The default GRTE to use. This should be a label, and gets the same
|
|
||||||
// treatment from Blaze as the --grte_top option. This setting is only used in
|
|
||||||
// the absence of an explicit --grte_top option. If unset, Blaze will not pass
|
|
||||||
// -sysroot by default. The local part must be 'everything', i.e.,
|
|
||||||
// '//some/label:everything'. There can only be one GRTE library per package,
|
|
||||||
// because the compiler expects the directory as a parameter of the -sysroot
|
|
||||||
// option.
|
|
||||||
// This may only be set to a non-empty value if builtin_sysroot is also set!
|
|
||||||
optional string default_grte_top = 31;
|
|
||||||
|
|
||||||
// Legacy field, ignored by Bazel.
|
|
||||||
repeated string debian_extra_requires = 33;
|
|
||||||
|
|
||||||
// Legacy field, ignored by Bazel. Only there for compatibility with
|
|
||||||
// things internal to Google.
|
|
||||||
optional string cc_target_os = 55;
|
|
||||||
|
|
||||||
// Next free id: 56
|
|
||||||
}
|
|
||||||
|
|
||||||
message ToolPath {
|
|
||||||
required string name = 1;
|
|
||||||
required string path = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum CompilationMode {
|
|
||||||
FASTBUILD = 1;
|
|
||||||
DBG = 2;
|
|
||||||
OPT = 3;
|
|
||||||
// This value is ignored and should not be used in new files.
|
|
||||||
COVERAGE = 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
message CompilationModeFlags {
|
|
||||||
required CompilationMode mode = 1;
|
|
||||||
repeated string compiler_flag = 2;
|
|
||||||
repeated string cxx_flag = 3;
|
|
||||||
// Linker flags that are added when compiling in a certain mode.
|
|
||||||
repeated string linker_flag = 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum LinkingMode {
|
|
||||||
FULLY_STATIC = 1;
|
|
||||||
MOSTLY_STATIC = 2;
|
|
||||||
DYNAMIC = 3;
|
|
||||||
MOSTLY_STATIC_LIBRARIES = 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
message LinkingModeFlags {
|
|
||||||
required LinkingMode mode = 1;
|
|
||||||
repeated string linker_flag = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
message MakeVariable {
|
|
||||||
required string name = 1;
|
|
||||||
required string value = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
message DefaultCpuToolchain {
|
|
||||||
required string cpu = 1;
|
|
||||||
required string toolchain_identifier = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
// An entire crosstool release, containing the version number, and a set of
|
|
||||||
// toolchains.
|
|
||||||
message CrosstoolRelease {
|
|
||||||
// The major and minor version of the crosstool release.
|
|
||||||
required string major_version = 1;
|
|
||||||
required string minor_version = 2;
|
|
||||||
|
|
||||||
// Legacy field, ignored by Bazel.
|
|
||||||
optional string default_target_cpu = 3;
|
|
||||||
// Legacy field, ignored by Bazel.
|
|
||||||
repeated DefaultCpuToolchain default_toolchain = 4;
|
|
||||||
|
|
||||||
// All the toolchains in this release.
|
|
||||||
repeated CToolchain toolchain = 5;
|
|
||||||
}
|
|
|
@ -1,16 +0,0 @@
|
||||||
# Description:
|
|
||||||
# Six provides simple utilities for wrapping over differences between Python 2
|
|
||||||
# and Python 3.
|
|
||||||
|
|
||||||
load("@rules_python//python:defs.bzl", "py_library")
|
|
||||||
|
|
||||||
licenses(["notice"]) # MIT
|
|
||||||
|
|
||||||
exports_files(["LICENSE"])
|
|
||||||
|
|
||||||
py_library(
|
|
||||||
name = "six",
|
|
||||||
srcs = ["six.py"],
|
|
||||||
srcs_version = "PY2AND3",
|
|
||||||
visibility = ["//visibility:public"],
|
|
||||||
)
|
|
|
@ -1,144 +0,0 @@
|
||||||
# Copyright 2018 The Bazel Authors. All rights reserved.
|
|
||||||
#
|
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
# you may not use this file except in compliance with the License.
|
|
||||||
# You may obtain a copy of the License at
|
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
# See the License for the specific language governing permissions and
|
|
||||||
# limitations under the License.
|
|
||||||
|
|
||||||
load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
|
|
||||||
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library", "go_test")
|
|
||||||
load("@rules_python//python:defs.bzl", "py_binary", "py_library", "py_test")
|
|
||||||
|
|
||||||
package(default_visibility = ["//visibility:public"])
|
|
||||||
|
|
||||||
licenses(["notice"])
|
|
||||||
|
|
||||||
py_binary(
|
|
||||||
name = "legacy_fields_migrator",
|
|
||||||
srcs = ["legacy_fields_migrator.py"],
|
|
||||||
python_version = "PY3",
|
|
||||||
deps = [
|
|
||||||
":legacy_fields_migration_lib",
|
|
||||||
"//third_party/com/github/bazelbuild/bazel/src/main/protobuf:crosstool_config_py_pb2",
|
|
||||||
"@io_abseil_py//absl:app",
|
|
||||||
"@io_abseil_py//absl/flags",
|
|
||||||
#internal proto upb dep,
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
py_library(
|
|
||||||
name = "legacy_fields_migration_lib",
|
|
||||||
srcs = ["legacy_fields_migration_lib.py"],
|
|
||||||
deps = [
|
|
||||||
"//third_party/com/github/bazelbuild/bazel/src/main/protobuf:crosstool_config_py_pb2",
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
py_test(
|
|
||||||
name = "legacy_fields_migration_lib_test",
|
|
||||||
srcs = ["legacy_fields_migration_lib_test.py"],
|
|
||||||
python_version = "PY3",
|
|
||||||
deps = [
|
|
||||||
":legacy_fields_migration_lib",
|
|
||||||
"//third_party/com/github/bazelbuild/bazel/src/main/protobuf:crosstool_config_py_pb2",
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
py_binary(
|
|
||||||
name = "crosstool_query",
|
|
||||||
srcs = ["crosstool_query.py"],
|
|
||||||
python_version = "PY3",
|
|
||||||
deps = [
|
|
||||||
"//third_party/com/github/bazelbuild/bazel/src/main/protobuf:crosstool_config_py_pb2",
|
|
||||||
"@io_abseil_py//absl:app",
|
|
||||||
"@io_abseil_py//absl/flags",
|
|
||||||
#internal proto upb dep,
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
py_binary(
|
|
||||||
name = "ctoolchain_comparator",
|
|
||||||
srcs = ["ctoolchain_comparator.py"],
|
|
||||||
python_version = "PY3",
|
|
||||||
deps = [
|
|
||||||
":ctoolchain_comparator_lib",
|
|
||||||
"//third_party/com/github/bazelbuild/bazel/src/main/protobuf:crosstool_config_py_pb2",
|
|
||||||
"@io_abseil_py//absl:app",
|
|
||||||
"@io_abseil_py//absl/flags",
|
|
||||||
#internal proto upb dep,
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
py_library(
|
|
||||||
name = "ctoolchain_comparator_lib",
|
|
||||||
srcs = ["ctoolchain_comparator_lib.py"],
|
|
||||||
deps = [
|
|
||||||
"//third_party/com/github/bazelbuild/bazel/src/main/protobuf:crosstool_config_py_pb2",
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
py_test(
|
|
||||||
name = "ctoolchain_comparator_lib_test",
|
|
||||||
srcs = ["ctoolchain_comparator_lib_test.py"],
|
|
||||||
python_version = "PY3",
|
|
||||||
deps = [
|
|
||||||
":ctoolchain_comparator_lib",
|
|
||||||
"//third_party/com/github/bazelbuild/bazel/src/main/protobuf:crosstool_config_py_pb2",
|
|
||||||
"@py_mock//py/mock",
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
go_binary(
|
|
||||||
name = "convert_crosstool_to_starlark",
|
|
||||||
srcs = ["convert_crosstool_to_starlark.go"],
|
|
||||||
deps = [
|
|
||||||
":crosstooltostarlarklib",
|
|
||||||
"//third_party/com/github/bazelbuild/bazel/src/main/protobuf:crosstool_config_go_proto",
|
|
||||||
"@com_github_golang_protobuf//proto:go_default_library",
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
go_library(
|
|
||||||
name = "crosstooltostarlarklib",
|
|
||||||
srcs = ["crosstool_to_starlark_lib.go"],
|
|
||||||
importpath = "tools/migration/crosstooltostarlarklib",
|
|
||||||
deps = ["//third_party/com/github/bazelbuild/bazel/src/main/protobuf:crosstool_config_go_proto"],
|
|
||||||
)
|
|
||||||
|
|
||||||
go_test(
|
|
||||||
name = "crosstooltostarlarklib_test",
|
|
||||||
size = "small",
|
|
||||||
srcs = ["crosstool_to_starlark_lib_test.go"],
|
|
||||||
embed = [":crosstooltostarlarklib"],
|
|
||||||
deps = [
|
|
||||||
"//third_party/com/github/bazelbuild/bazel/src/main/protobuf:crosstool_config_go_proto",
|
|
||||||
"@com_github_golang_protobuf//proto:go_default_library",
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
filegroup(
|
|
||||||
name = "bazel_osx_p4deps",
|
|
||||||
srcs = [
|
|
||||||
"BUILD",
|
|
||||||
"ctoolchain_compare.bzl",
|
|
||||||
],
|
|
||||||
)
|
|
||||||
|
|
||||||
bzl_library(
|
|
||||||
name = "ctoolchain_compare_bzl",
|
|
||||||
srcs = ["ctoolchain_compare.bzl"],
|
|
||||||
visibility = ["//visibility:private"],
|
|
||||||
)
|
|
||||||
|
|
||||||
bzl_library(
|
|
||||||
name = "cc_toolchain_config_comparator_bzl",
|
|
||||||
srcs = ["cc_toolchain_config_comparator.bzl"],
|
|
||||||
visibility = ["//visibility:private"],
|
|
||||||
)
|
|
|
@ -1,53 +0,0 @@
|
||||||
"""A test rule that compares two C++ toolchain configuration rules in proto format."""
|
|
||||||
|
|
||||||
def _impl(ctx):
|
|
||||||
first_toolchain_config_proto = ctx.actions.declare_file(
|
|
||||||
ctx.label.name + "_first_toolchain_config.proto",
|
|
||||||
)
|
|
||||||
ctx.actions.write(
|
|
||||||
first_toolchain_config_proto,
|
|
||||||
ctx.attr.first[CcToolchainConfigInfo].proto,
|
|
||||||
)
|
|
||||||
|
|
||||||
second_toolchain_config_proto = ctx.actions.declare_file(
|
|
||||||
ctx.label.name + "_second_toolchain_config.proto",
|
|
||||||
)
|
|
||||||
ctx.actions.write(
|
|
||||||
second_toolchain_config_proto,
|
|
||||||
ctx.attr.second[CcToolchainConfigInfo].proto,
|
|
||||||
)
|
|
||||||
|
|
||||||
script = ("%s --before='%s' --after='%s'" % (
|
|
||||||
ctx.executable._comparator.short_path,
|
|
||||||
first_toolchain_config_proto.short_path,
|
|
||||||
second_toolchain_config_proto.short_path,
|
|
||||||
))
|
|
||||||
test_executable = ctx.actions.declare_file(ctx.label.name)
|
|
||||||
ctx.actions.write(test_executable, script, is_executable = True)
|
|
||||||
|
|
||||||
runfiles = ctx.runfiles(files = [first_toolchain_config_proto, second_toolchain_config_proto])
|
|
||||||
runfiles = runfiles.merge(ctx.attr._comparator[DefaultInfo].default_runfiles)
|
|
||||||
|
|
||||||
return DefaultInfo(runfiles = runfiles, executable = test_executable)
|
|
||||||
|
|
||||||
cc_toolchain_config_compare_test = rule(
|
|
||||||
implementation = _impl,
|
|
||||||
attrs = {
|
|
||||||
"first": attr.label(
|
|
||||||
mandatory = True,
|
|
||||||
providers = [CcToolchainConfigInfo],
|
|
||||||
doc = "A C++ toolchain config rule",
|
|
||||||
),
|
|
||||||
"second": attr.label(
|
|
||||||
mandatory = True,
|
|
||||||
providers = [CcToolchainConfigInfo],
|
|
||||||
doc = "A C++ toolchain config rule",
|
|
||||||
),
|
|
||||||
"_comparator": attr.label(
|
|
||||||
default = ":ctoolchain_comparator",
|
|
||||||
executable = True,
|
|
||||||
cfg = "exec",
|
|
||||||
),
|
|
||||||
},
|
|
||||||
test = True,
|
|
||||||
)
|
|
|
@ -1,101 +0,0 @@
|
||||||
/*
|
|
||||||
The convert_crosstool_to_starlark script takes in a CROSSTOOL file and
|
|
||||||
generates a Starlark rule.
|
|
||||||
|
|
||||||
See https://github.com/bazelbuild/bazel/issues/5380
|
|
||||||
|
|
||||||
Example usage:
|
|
||||||
bazel run \
|
|
||||||
@rules_cc//tools/migration:convert_crosstool_to_starlark -- \
|
|
||||||
--crosstool=/path/to/CROSSTOOL \
|
|
||||||
--output_location=/path/to/cc_config.bzl
|
|
||||||
*/
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"flag"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
|
||||||
"os/user"
|
|
||||||
"path"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
// Google internal base/go package, commented out by copybara
|
|
||||||
"log"
|
|
||||||
crosstoolpb "third_party/com/github/bazelbuild/bazel/src/main/protobuf/crosstool_config_go_proto"
|
|
||||||
"github.com/golang/protobuf/proto"
|
|
||||||
|
|
||||||
"tools/migration/crosstooltostarlarklib"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
crosstoolLocation = flag.String(
|
|
||||||
"crosstool", "", "Location of the CROSSTOOL file")
|
|
||||||
outputLocation = flag.String(
|
|
||||||
"output_location", "", "Location of the output .bzl file")
|
|
||||||
)
|
|
||||||
|
|
||||||
func toAbsolutePath(pathString string) (string, error) {
|
|
||||||
usr, err := user.Current()
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
homeDir := usr.HomeDir
|
|
||||||
|
|
||||||
if strings.HasPrefix(pathString, "~") {
|
|
||||||
return path.Join(homeDir, pathString[1:]), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if path.IsAbs(pathString) {
|
|
||||||
return pathString, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
workingDirectory := os.Getenv("BUILD_WORKING_DIRECTORY")
|
|
||||||
return path.Join(workingDirectory, pathString), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
flag.Parse()
|
|
||||||
|
|
||||||
if *crosstoolLocation == "" {
|
|
||||||
log.Fatalf("Missing mandatory argument 'crosstool'")
|
|
||||||
}
|
|
||||||
crosstoolPath, err := toAbsolutePath(*crosstoolLocation)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("Error while resolving CROSSTOOL location:", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if *outputLocation == "" {
|
|
||||||
log.Fatalf("Missing mandatory argument 'output_location'")
|
|
||||||
}
|
|
||||||
outputPath, err := toAbsolutePath(*outputLocation)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("Error resolving output location:", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
in, err := ioutil.ReadFile(crosstoolPath)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("Error reading CROSSTOOL file:", err)
|
|
||||||
}
|
|
||||||
crosstool := &crosstoolpb.CrosstoolRelease{}
|
|
||||||
if err := proto.UnmarshalText(string(in), crosstool); err != nil {
|
|
||||||
log.Fatalf("Failed to parse CROSSTOOL:", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
file, err := os.Create(outputPath)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("Error creating output file:", err)
|
|
||||||
}
|
|
||||||
defer file.Close()
|
|
||||||
|
|
||||||
rule, err := crosstooltostarlarklib.Transform(crosstool)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("Error converting CROSSTOOL to a Starlark rule:", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err := file.WriteString(rule); err != nil {
|
|
||||||
log.Fatalf("Error converting CROSSTOOL to a Starlark rule:", err)
|
|
||||||
}
|
|
||||||
fmt.Println("Success!")
|
|
||||||
}
|
|
|
@ -1,53 +0,0 @@
|
||||||
"""Script to make automated CROSSTOOL refactorings easier.
|
|
||||||
|
|
||||||
This script reads the CROSSTOOL file and allows for querying of its fields.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from absl import app
|
|
||||||
from absl import flags
|
|
||||||
from google.protobuf import text_format
|
|
||||||
from third_party.com.github.bazelbuild.bazel.src.main.protobuf import crosstool_config_pb2
|
|
||||||
|
|
||||||
flags.DEFINE_string("crosstool", None, "CROSSTOOL file path to be queried")
|
|
||||||
flags.DEFINE_string("identifier", None,
|
|
||||||
"Toolchain identifier to specify toolchain.")
|
|
||||||
flags.DEFINE_string("print_field", None, "Field to be printed to stdout.")
|
|
||||||
|
|
||||||
|
|
||||||
def main(unused_argv):
|
|
||||||
crosstool = crosstool_config_pb2.CrosstoolRelease()
|
|
||||||
|
|
||||||
crosstool_filename = flags.FLAGS.crosstool
|
|
||||||
identifier = flags.FLAGS.identifier
|
|
||||||
print_field = flags.FLAGS.print_field
|
|
||||||
|
|
||||||
if not crosstool_filename:
|
|
||||||
raise app.UsageError("ERROR crosstool unspecified")
|
|
||||||
if not identifier:
|
|
||||||
raise app.UsageError("ERROR identifier unspecified")
|
|
||||||
|
|
||||||
if not print_field:
|
|
||||||
raise app.UsageError("ERROR print_field unspecified")
|
|
||||||
|
|
||||||
with open(crosstool_filename, "r") as f:
|
|
||||||
text = f.read()
|
|
||||||
text_format.Merge(text, crosstool)
|
|
||||||
|
|
||||||
toolchain_found = False
|
|
||||||
for toolchain in crosstool.toolchain:
|
|
||||||
if toolchain.toolchain_identifier == identifier:
|
|
||||||
toolchain_found = True
|
|
||||||
if not print_field:
|
|
||||||
continue
|
|
||||||
for field, value in toolchain.ListFields():
|
|
||||||
if print_field == field.name:
|
|
||||||
print value
|
|
||||||
|
|
||||||
if not toolchain_found:
|
|
||||||
print "toolchain_identifier %s not found, valid values are:" % identifier
|
|
||||||
for toolchain in crosstool.toolchain:
|
|
||||||
print " " + toolchain.toolchain_identifier
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
app.run(main)
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,127 +0,0 @@
|
||||||
# Copyright 2018 The Bazel Authors. All rights reserved.
|
|
||||||
#
|
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
# you may not use this file except in compliance with the License.
|
|
||||||
# You may obtain a copy of the License at
|
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
# See the License for the specific language governing permissions and
|
|
||||||
# limitations under the License.
|
|
||||||
r"""A script that compares 2 CToolchains from proto format.
|
|
||||||
|
|
||||||
This script accepts two files in either a CROSSTOOL proto text format or a
|
|
||||||
CToolchain proto text format. It then locates the CToolchains with the given
|
|
||||||
toolchain_identifier and checks if the resulting CToolchain objects in Java
|
|
||||||
are the same.
|
|
||||||
|
|
||||||
Example usage:
|
|
||||||
|
|
||||||
bazel run \
|
|
||||||
@rules_cc//tools/migration:ctoolchain_comparator -- \
|
|
||||||
--before=/path/to/CROSSTOOL1 \
|
|
||||||
--after=/path/to/CROSSTOOL2 \
|
|
||||||
--toolchain_identifier=id
|
|
||||||
"""
|
|
||||||
|
|
||||||
import os
|
|
||||||
from absl import app
|
|
||||||
from absl import flags
|
|
||||||
from google.protobuf import text_format
|
|
||||||
from third_party.com.github.bazelbuild.bazel.src.main.protobuf import crosstool_config_pb2
|
|
||||||
from tools.migration.ctoolchain_comparator_lib import compare_ctoolchains
|
|
||||||
|
|
||||||
flags.DEFINE_string(
|
|
||||||
"before", None,
|
|
||||||
("A text proto file containing the relevant CTooclchain before the change, "
|
|
||||||
"either a CROSSTOOL file or a single CToolchain proto text"))
|
|
||||||
flags.DEFINE_string(
|
|
||||||
"after", None,
|
|
||||||
("A text proto file containing the relevant CToolchain after the change, "
|
|
||||||
"either a CROSSTOOL file or a single CToolchain proto text"))
|
|
||||||
flags.DEFINE_string("toolchain_identifier", None,
|
|
||||||
"The identifier of the CToolchain that is being compared.")
|
|
||||||
flags.mark_flag_as_required("before")
|
|
||||||
flags.mark_flag_as_required("after")
|
|
||||||
|
|
||||||
|
|
||||||
def _to_absolute_path(path):
|
|
||||||
path = os.path.expanduser(path)
|
|
||||||
if os.path.isabs(path):
|
|
||||||
return path
|
|
||||||
else:
|
|
||||||
if "BUILD_WORKING_DIRECTORY" in os.environ:
|
|
||||||
return os.path.join(os.environ["BUILD_WORKING_DIRECTORY"], path)
|
|
||||||
else:
|
|
||||||
return path
|
|
||||||
|
|
||||||
|
|
||||||
def _find_toolchain(crosstool, toolchain_identifier):
|
|
||||||
for toolchain in crosstool.toolchain:
|
|
||||||
if toolchain.toolchain_identifier == toolchain_identifier:
|
|
||||||
return toolchain
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def _read_crosstool_or_ctoolchain_proto(input_file, toolchain_identifier=None):
|
|
||||||
"""Reads a proto file and finds the CToolchain with the given identifier."""
|
|
||||||
with open(input_file, "r") as f:
|
|
||||||
text = f.read()
|
|
||||||
crosstool_release = crosstool_config_pb2.CrosstoolRelease()
|
|
||||||
c_toolchain = crosstool_config_pb2.CToolchain()
|
|
||||||
try:
|
|
||||||
text_format.Merge(text, crosstool_release)
|
|
||||||
if toolchain_identifier is None:
|
|
||||||
print("CROSSTOOL proto needs a 'toolchain_identifier' specified in "
|
|
||||||
"order to be able to select the right toolchain for comparison.")
|
|
||||||
return None
|
|
||||||
toolchain = _find_toolchain(crosstool_release, toolchain_identifier)
|
|
||||||
if toolchain is None:
|
|
||||||
print(("Cannot find a CToolchain with an identifier '%s' in CROSSTOOL "
|
|
||||||
"file") % toolchain_identifier)
|
|
||||||
return None
|
|
||||||
return toolchain
|
|
||||||
except text_format.ParseError as crosstool_error:
|
|
||||||
try:
|
|
||||||
text_format.Merge(text, c_toolchain)
|
|
||||||
if (toolchain_identifier is not None and
|
|
||||||
c_toolchain.toolchain_identifier != toolchain_identifier):
|
|
||||||
print(("Expected CToolchain with identifier '%s', got CToolchain with "
|
|
||||||
"identifier '%s'" % (toolchain_identifier,
|
|
||||||
c_toolchain.toolchain_identifier)))
|
|
||||||
return None
|
|
||||||
return c_toolchain
|
|
||||||
except text_format.ParseError as toolchain_error:
|
|
||||||
print(("Error parsing file '%s':" % input_file)) # pylint: disable=superfluous-parens
|
|
||||||
print("Attempt to parse it as a CROSSTOOL proto:") # pylint: disable=superfluous-parens
|
|
||||||
print(crosstool_error) # pylint: disable=superfluous-parens
|
|
||||||
print("Attempt to parse it as a CToolchain proto:") # pylint: disable=superfluous-parens
|
|
||||||
print(toolchain_error) # pylint: disable=superfluous-parens
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def main(unused_argv):
|
|
||||||
|
|
||||||
before_file = _to_absolute_path(flags.FLAGS.before)
|
|
||||||
after_file = _to_absolute_path(flags.FLAGS.after)
|
|
||||||
toolchain_identifier = flags.FLAGS.toolchain_identifier
|
|
||||||
|
|
||||||
toolchain_before = _read_crosstool_or_ctoolchain_proto(
|
|
||||||
before_file, toolchain_identifier)
|
|
||||||
toolchain_after = _read_crosstool_or_ctoolchain_proto(after_file,
|
|
||||||
toolchain_identifier)
|
|
||||||
|
|
||||||
if not toolchain_before or not toolchain_after:
|
|
||||||
print("There was an error getting the required toolchains.")
|
|
||||||
exit(1)
|
|
||||||
|
|
||||||
found_difference = compare_ctoolchains(toolchain_before, toolchain_after)
|
|
||||||
if found_difference:
|
|
||||||
exit(1)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
app.run(main)
|
|
|
@ -1,523 +0,0 @@
|
||||||
# Copyright 2018 The Bazel Authors. All rights reserved.
|
|
||||||
#
|
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
# you may not use this file except in compliance with the License.
|
|
||||||
# You may obtain a copy of the License at
|
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
# See the License for the specific language governing permissions and
|
|
||||||
# limitations under the License.
|
|
||||||
"""Module providing compare_ctoolchains function.
|
|
||||||
|
|
||||||
compare_ctoolchains takes in two parsed CToolchains and compares them
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
def _print_difference(field_name, before_value, after_value):
|
|
||||||
if not before_value and after_value:
|
|
||||||
print(("Difference in '%s' field:\nValue before change is not set\n"
|
|
||||||
"Value after change is set to '%s'") % (field_name, after_value))
|
|
||||||
elif before_value and not after_value:
|
|
||||||
print(("Difference in '%s' field:\nValue before change is set to '%s'\n"
|
|
||||||
"Value after change is not set") % (field_name, before_value))
|
|
||||||
else:
|
|
||||||
print(("Difference in '%s' field:\nValue before change:\t'%s'\n"
|
|
||||||
"Value after change:\t'%s'\n") % (field_name, before_value,
|
|
||||||
after_value))
|
|
||||||
|
|
||||||
|
|
||||||
def _array_to_string(arr, ordered=False):
|
|
||||||
if not arr:
|
|
||||||
return "[]"
|
|
||||||
elif len(arr) == 1:
|
|
||||||
return "[" + list(arr)[0] + "]"
|
|
||||||
if not ordered:
|
|
||||||
return "[\n\t%s\n]" % "\n\t".join(arr)
|
|
||||||
else:
|
|
||||||
return "[\n\t%s\n]" % "\n\t".join(sorted(list(arr)))
|
|
||||||
|
|
||||||
|
|
||||||
def _check_with_feature_set_equivalence(before, after):
|
|
||||||
before_set = set()
|
|
||||||
after_set = set()
|
|
||||||
for el in before:
|
|
||||||
before_set.add((str(set(el.feature)), str(set(el.not_feature))))
|
|
||||||
for el in after:
|
|
||||||
after_set.add((str(set(el.feature)), str(set(el.not_feature))))
|
|
||||||
return before_set == after_set
|
|
||||||
|
|
||||||
|
|
||||||
def _check_tool_equivalence(before, after):
|
|
||||||
"""Compares two "CToolchain.Tool"s."""
|
|
||||||
if before.tool_path == "NOT_USED":
|
|
||||||
before.tool_path = ""
|
|
||||||
if after.tool_path == "NOT_USED":
|
|
||||||
after.tool_path = ""
|
|
||||||
if before.tool_path != after.tool_path:
|
|
||||||
return False
|
|
||||||
if set(before.execution_requirement) != set(after.execution_requirement):
|
|
||||||
return False
|
|
||||||
if not _check_with_feature_set_equivalence(before.with_feature,
|
|
||||||
after.with_feature):
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
def _check_flag_group_equivalence(before, after):
|
|
||||||
"""Compares two "CToolchain.FlagGroup"s."""
|
|
||||||
if before.flag != after.flag:
|
|
||||||
return False
|
|
||||||
if before.expand_if_true != after.expand_if_true:
|
|
||||||
return False
|
|
||||||
if before.expand_if_false != after.expand_if_false:
|
|
||||||
return False
|
|
||||||
if set(before.expand_if_all_available) != set(after.expand_if_all_available):
|
|
||||||
return False
|
|
||||||
if set(before.expand_if_none_available) != set(
|
|
||||||
after.expand_if_none_available):
|
|
||||||
return False
|
|
||||||
if before.iterate_over != after.iterate_over:
|
|
||||||
return False
|
|
||||||
if before.expand_if_equal != after.expand_if_equal:
|
|
||||||
return False
|
|
||||||
if len(before.flag_group) != len(after.flag_group):
|
|
||||||
return False
|
|
||||||
for (flag_group_before, flag_group_after) in zip(before.flag_group,
|
|
||||||
after.flag_group):
|
|
||||||
if not _check_flag_group_equivalence(flag_group_before, flag_group_after):
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
def _check_flag_set_equivalence(before, after, in_action_config=False):
|
|
||||||
"""Compares two "CToolchain.FlagSet"s."""
|
|
||||||
# ActionConfigs in proto format do not have a 'FlagSet.action' field set.
|
|
||||||
# Instead, when construction the Java ActionConfig object, we set the
|
|
||||||
# flag_set.action field to the action name. This currently causes the
|
|
||||||
# CcToolchainConfigInfo.proto to generate a CToolchain.ActionConfig that still
|
|
||||||
# has the action name in the FlagSet.action field, therefore we don't compare
|
|
||||||
# the FlagSet.action field when comparing flag_sets that belong to an
|
|
||||||
# ActionConfig.
|
|
||||||
if not in_action_config and set(before.action) != set(after.action):
|
|
||||||
return False
|
|
||||||
if not _check_with_feature_set_equivalence(before.with_feature,
|
|
||||||
after.with_feature):
|
|
||||||
return False
|
|
||||||
if len(before.flag_group) != len(after.flag_group):
|
|
||||||
return False
|
|
||||||
for (flag_group_before, flag_group_after) in zip(before.flag_group,
|
|
||||||
after.flag_group):
|
|
||||||
if not _check_flag_group_equivalence(flag_group_before, flag_group_after):
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
def _check_action_config_equivalence(before, after):
|
|
||||||
"""Compares two "CToolchain.ActionConfig"s."""
|
|
||||||
if before.config_name != after.config_name:
|
|
||||||
return False
|
|
||||||
if before.action_name != after.action_name:
|
|
||||||
return False
|
|
||||||
if before.enabled != after.enabled:
|
|
||||||
return False
|
|
||||||
if len(before.tool) != len(after.tool):
|
|
||||||
return False
|
|
||||||
for (tool_before, tool_after) in zip(before.tool, after.tool):
|
|
||||||
if not _check_tool_equivalence(tool_before, tool_after):
|
|
||||||
return False
|
|
||||||
if before.implies != after.implies:
|
|
||||||
return False
|
|
||||||
if len(before.flag_set) != len(after.flag_set):
|
|
||||||
return False
|
|
||||||
for (flag_set_before, flag_set_after) in zip(before.flag_set, after.flag_set):
|
|
||||||
if not _check_flag_set_equivalence(flag_set_before, flag_set_after, True):
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
def _check_env_set_equivalence(before, after):
|
|
||||||
"""Compares two "CToolchain.EnvSet"s."""
|
|
||||||
if set(before.action) != set(after.action):
|
|
||||||
return False
|
|
||||||
if not _check_with_feature_set_equivalence(before.with_feature,
|
|
||||||
after.with_feature):
|
|
||||||
return False
|
|
||||||
if before.env_entry != after.env_entry:
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
def _check_feature_equivalence(before, after):
|
|
||||||
"""Compares two "CToolchain.Feature"s."""
|
|
||||||
if before.name != after.name:
|
|
||||||
return False
|
|
||||||
if before.enabled != after.enabled:
|
|
||||||
return False
|
|
||||||
if len(before.flag_set) != len(after.flag_set):
|
|
||||||
return False
|
|
||||||
for (flag_set_before, flag_set_after) in zip(before.flag_set, after.flag_set):
|
|
||||||
if not _check_flag_set_equivalence(flag_set_before, flag_set_after):
|
|
||||||
return False
|
|
||||||
if len(before.env_set) != len(after.env_set):
|
|
||||||
return False
|
|
||||||
for (env_set_before, env_set_after) in zip(before.env_set, after.env_set):
|
|
||||||
if not _check_env_set_equivalence(env_set_before, env_set_after):
|
|
||||||
return False
|
|
||||||
if len(before.requires) != len(after.requires):
|
|
||||||
return False
|
|
||||||
for (requires_before, requires_after) in zip(before.requires, after.requires):
|
|
||||||
if set(requires_before.feature) != set(requires_after.feature):
|
|
||||||
return False
|
|
||||||
if before.implies != after.implies:
|
|
||||||
return False
|
|
||||||
if before.provides != after.provides:
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
def _compare_features(features_before, features_after):
|
|
||||||
"""Compares two "CToolchain.FlagFeature" lists."""
|
|
||||||
feature_name_to_feature_before = {}
|
|
||||||
feature_name_to_feature_after = {}
|
|
||||||
for feature in features_before:
|
|
||||||
feature_name_to_feature_before[feature.name] = feature
|
|
||||||
for feature in features_after:
|
|
||||||
feature_name_to_feature_after[feature.name] = feature
|
|
||||||
|
|
||||||
feature_names_before = set(feature_name_to_feature_before.keys())
|
|
||||||
feature_names_after = set(feature_name_to_feature_after.keys())
|
|
||||||
|
|
||||||
before_after_diff = feature_names_before - feature_names_after
|
|
||||||
after_before_diff = feature_names_after - feature_names_before
|
|
||||||
|
|
||||||
diff_string = "Difference in 'feature' field:"
|
|
||||||
found_difference = False
|
|
||||||
if before_after_diff:
|
|
||||||
if not found_difference:
|
|
||||||
print(diff_string) # pylint: disable=superfluous-parens
|
|
||||||
found_difference = True
|
|
||||||
print(("* List before change contains entries for the following features "
|
|
||||||
"that the list after the change doesn't:\n%s") % _array_to_string(
|
|
||||||
before_after_diff, ordered=True))
|
|
||||||
if after_before_diff:
|
|
||||||
if not found_difference:
|
|
||||||
print(diff_string) # pylint: disable=superfluous-parens
|
|
||||||
found_difference = True
|
|
||||||
print(("* List after change contains entries for the following features "
|
|
||||||
"that the list before the change doesn't:\n%s") % _array_to_string(
|
|
||||||
after_before_diff, ordered=True))
|
|
||||||
|
|
||||||
names_before = [feature.name for feature in features_before]
|
|
||||||
names_after = [feature.name for feature in features_after]
|
|
||||||
if names_before != names_after:
|
|
||||||
if not found_difference:
|
|
||||||
print(diff_string) # pylint: disable=superfluous-parens
|
|
||||||
found_difference = True
|
|
||||||
print(("Features not in right order:\n"
|
|
||||||
"* List of features before change:\t%s"
|
|
||||||
"* List of features before change:\t%s") %
|
|
||||||
(_array_to_string(names_before), _array_to_string(names_after)))
|
|
||||||
for name in feature_name_to_feature_before:
|
|
||||||
feature_before = feature_name_to_feature_before[name]
|
|
||||||
feature_after = feature_name_to_feature_after.get(name, None)
|
|
||||||
if feature_after and not _check_feature_equivalence(feature_before,
|
|
||||||
feature_after):
|
|
||||||
if not found_difference:
|
|
||||||
print(diff_string) # pylint: disable=superfluous-parens
|
|
||||||
found_difference = True
|
|
||||||
print(("* Feature '%s' differs before and after the change:\n"
|
|
||||||
"Value before change:\n%s\n"
|
|
||||||
"Value after change:\n%s") % (name, str(feature_before),
|
|
||||||
str(feature_after)))
|
|
||||||
if found_difference:
|
|
||||||
print("") # pylint: disable=superfluous-parens
|
|
||||||
return found_difference
|
|
||||||
|
|
||||||
|
|
||||||
def _compare_action_configs(action_configs_before, action_configs_after):
|
|
||||||
"""Compares two "CToolchain.ActionConfig" lists."""
|
|
||||||
action_name_to_action_before = {}
|
|
||||||
action_name_to_action_after = {}
|
|
||||||
for action_config in action_configs_before:
|
|
||||||
action_name_to_action_before[action_config.config_name] = action_config
|
|
||||||
for action_config in action_configs_after:
|
|
||||||
action_name_to_action_after[action_config.config_name] = action_config
|
|
||||||
|
|
||||||
config_names_before = set(action_name_to_action_before.keys())
|
|
||||||
config_names_after = set(action_name_to_action_after.keys())
|
|
||||||
|
|
||||||
before_after_diff = config_names_before - config_names_after
|
|
||||||
after_before_diff = config_names_after - config_names_before
|
|
||||||
|
|
||||||
diff_string = "Difference in 'action_config' field:"
|
|
||||||
found_difference = False
|
|
||||||
if before_after_diff:
|
|
||||||
if not found_difference:
|
|
||||||
print(diff_string) # pylint: disable=superfluous-parens
|
|
||||||
found_difference = True
|
|
||||||
print(("* List before change contains entries for the following "
|
|
||||||
"action_configs that the list after the change doesn't:\n%s") %
|
|
||||||
_array_to_string(before_after_diff, ordered=True))
|
|
||||||
if after_before_diff:
|
|
||||||
if not found_difference:
|
|
||||||
print(diff_string) # pylint: disable=superfluous-parens
|
|
||||||
found_difference = True
|
|
||||||
print(("* List after change contains entries for the following "
|
|
||||||
"action_configs that the list before the change doesn't:\n%s") %
|
|
||||||
_array_to_string(after_before_diff, ordered=True))
|
|
||||||
|
|
||||||
names_before = [config.config_name for config in action_configs_before]
|
|
||||||
names_after = [config.config_name for config in action_configs_after]
|
|
||||||
if names_before != names_after:
|
|
||||||
if not found_difference:
|
|
||||||
print(diff_string) # pylint: disable=superfluous-parens
|
|
||||||
found_difference = True
|
|
||||||
print(("Action configs not in right order:\n"
|
|
||||||
"* List of action configs before change:\t%s"
|
|
||||||
"* List of action_configs before change:\t%s") %
|
|
||||||
(_array_to_string(names_before), _array_to_string(names_after)))
|
|
||||||
for name in config_names_before:
|
|
||||||
action_config_before = action_name_to_action_before[name]
|
|
||||||
action_config_after = action_name_to_action_after.get(name, None)
|
|
||||||
if action_config_after and not _check_action_config_equivalence(
|
|
||||||
action_config_before, action_config_after):
|
|
||||||
if not found_difference:
|
|
||||||
print(diff_string) # pylint: disable=superfluous-parens
|
|
||||||
found_difference = True
|
|
||||||
print(("* Action config '%s' differs before and after the change:\n"
|
|
||||||
"Value before change:\n%s\n"
|
|
||||||
"Value after change:\n%s") % (name, str(action_config_before),
|
|
||||||
str(action_config_after)))
|
|
||||||
if found_difference:
|
|
||||||
print("") # pylint: disable=superfluous-parens
|
|
||||||
return found_difference
|
|
||||||
|
|
||||||
|
|
||||||
def _compare_tool_paths(tool_paths_before, tool_paths_after):
|
|
||||||
"""Compares two "CToolchain.ToolPath" lists."""
|
|
||||||
tool_to_path_before = {}
|
|
||||||
tool_to_path_after = {}
|
|
||||||
for tool_path in tool_paths_before:
|
|
||||||
tool_to_path_before[tool_path.name] = (
|
|
||||||
tool_path.path if tool_path.path != "NOT_USED" else "")
|
|
||||||
for tool_path in tool_paths_after:
|
|
||||||
tool_to_path_after[tool_path.name] = (
|
|
||||||
tool_path.path if tool_path.path != "NOT_USED" else "")
|
|
||||||
|
|
||||||
tool_names_before = set(tool_to_path_before.keys())
|
|
||||||
tool_names_after = set(tool_to_path_after.keys())
|
|
||||||
|
|
||||||
before_after_diff = tool_names_before - tool_names_after
|
|
||||||
after_before_diff = tool_names_after - tool_names_before
|
|
||||||
|
|
||||||
diff_string = "Difference in 'tool_path' field:"
|
|
||||||
found_difference = False
|
|
||||||
if before_after_diff:
|
|
||||||
if not found_difference:
|
|
||||||
print(diff_string) # pylint: disable=superfluous-parens
|
|
||||||
found_difference = True
|
|
||||||
print(("* List before change contains entries for the following tools "
|
|
||||||
"that the list after the change doesn't:\n%s") % _array_to_string(
|
|
||||||
before_after_diff, ordered=True))
|
|
||||||
if after_before_diff:
|
|
||||||
if not found_difference:
|
|
||||||
print(diff_string) # pylint: disable=superfluous-parens
|
|
||||||
found_difference = True
|
|
||||||
print(("* List after change contains entries for the following tools that "
|
|
||||||
"the list before the change doesn't:\n%s") % _array_to_string(
|
|
||||||
after_before_diff, ordered=True))
|
|
||||||
|
|
||||||
for tool in tool_to_path_before:
|
|
||||||
path_before = tool_to_path_before[tool]
|
|
||||||
path_after = tool_to_path_after.get(tool, None)
|
|
||||||
if path_after and path_after != path_before:
|
|
||||||
if not found_difference:
|
|
||||||
print(diff_string) # pylint: disable=superfluous-parens
|
|
||||||
found_difference = True
|
|
||||||
print(("* Path for tool '%s' differs before and after the change:\n"
|
|
||||||
"Value before change:\t'%s'\n"
|
|
||||||
"Value after change:\t'%s'") % (tool, path_before, path_after))
|
|
||||||
if found_difference:
|
|
||||||
print("") # pylint: disable=superfluous-parens
|
|
||||||
return found_difference
|
|
||||||
|
|
||||||
|
|
||||||
def _compare_make_variables(make_variables_before, make_variables_after):
|
|
||||||
"""Compares two "CToolchain.MakeVariable" lists."""
|
|
||||||
name_to_variable_before = {}
|
|
||||||
name_to_variable_after = {}
|
|
||||||
for variable in make_variables_before:
|
|
||||||
name_to_variable_before[variable.name] = variable.value
|
|
||||||
for variable in make_variables_after:
|
|
||||||
name_to_variable_after[variable.name] = variable.value
|
|
||||||
|
|
||||||
variable_names_before = set(name_to_variable_before.keys())
|
|
||||||
variable_names_after = set(name_to_variable_after.keys())
|
|
||||||
|
|
||||||
before_after_diff = variable_names_before - variable_names_after
|
|
||||||
after_before_diff = variable_names_after - variable_names_before
|
|
||||||
|
|
||||||
diff_string = "Difference in 'make_variable' field:"
|
|
||||||
found_difference = False
|
|
||||||
if before_after_diff:
|
|
||||||
if not found_difference:
|
|
||||||
print(diff_string) # pylint: disable=superfluous-parens
|
|
||||||
found_difference = True
|
|
||||||
print(("* List before change contains entries for the following variables "
|
|
||||||
"that the list after the change doesn't:\n%s") % _array_to_string(
|
|
||||||
before_after_diff, ordered=True))
|
|
||||||
if after_before_diff:
|
|
||||||
if not found_difference:
|
|
||||||
print(diff_string) # pylint: disable=superfluous-parens
|
|
||||||
found_difference = True
|
|
||||||
print(("* List after change contains entries for the following variables "
|
|
||||||
"that the list before the change doesn't:\n%s") % _array_to_string(
|
|
||||||
after_before_diff, ordered=True))
|
|
||||||
|
|
||||||
for variable in name_to_variable_before:
|
|
||||||
value_before = name_to_variable_before[variable]
|
|
||||||
value_after = name_to_variable_after.get(variable, None)
|
|
||||||
if value_after and value_after != value_before:
|
|
||||||
if not found_difference:
|
|
||||||
print(diff_string) # pylint: disable=superfluous-parens
|
|
||||||
found_difference = True
|
|
||||||
print(
|
|
||||||
("* Value for variable '%s' differs before and after the change:\n"
|
|
||||||
"Value before change:\t'%s'\n"
|
|
||||||
"Value after change:\t'%s'") % (variable, value_before, value_after))
|
|
||||||
if found_difference:
|
|
||||||
print("") # pylint: disable=superfluous-parens
|
|
||||||
return found_difference
|
|
||||||
|
|
||||||
|
|
||||||
def _compare_cxx_builtin_include_directories(directories_before,
|
|
||||||
directories_after):
|
|
||||||
if directories_before != directories_after:
|
|
||||||
print(("Difference in 'cxx_builtin_include_directory' field:\n"
|
|
||||||
"List of elements before change:\n%s\n"
|
|
||||||
"List of elements after change:\n%s\n") %
|
|
||||||
(_array_to_string(directories_before),
|
|
||||||
_array_to_string(directories_after)))
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
def _compare_artifact_name_patterns(artifact_name_patterns_before,
|
|
||||||
artifact_name_patterns_after):
|
|
||||||
"""Compares two "CToolchain.ArtifactNamePattern" lists."""
|
|
||||||
category_to_values_before = {}
|
|
||||||
category_to_values_after = {}
|
|
||||||
for name_pattern in artifact_name_patterns_before:
|
|
||||||
category_to_values_before[name_pattern.category_name] = (
|
|
||||||
name_pattern.prefix, name_pattern.extension)
|
|
||||||
for name_pattern in artifact_name_patterns_after:
|
|
||||||
category_to_values_after[name_pattern.category_name] = (
|
|
||||||
name_pattern.prefix, name_pattern.extension)
|
|
||||||
|
|
||||||
category_names_before = set(category_to_values_before.keys())
|
|
||||||
category_names_after = set(category_to_values_after.keys())
|
|
||||||
|
|
||||||
before_after_diff = category_names_before - category_names_after
|
|
||||||
after_before_diff = category_names_after - category_names_before
|
|
||||||
|
|
||||||
diff_string = "Difference in 'artifact_name_pattern' field:"
|
|
||||||
found_difference = False
|
|
||||||
if before_after_diff:
|
|
||||||
if not found_difference:
|
|
||||||
print(diff_string) # pylint: disable=superfluous-parens
|
|
||||||
found_difference = True
|
|
||||||
print(("* List before change contains entries for the following categories "
|
|
||||||
"that the list after the change doesn't:\n%s") % _array_to_string(
|
|
||||||
before_after_diff, ordered=True))
|
|
||||||
if after_before_diff:
|
|
||||||
if not found_difference:
|
|
||||||
print(diff_string) # pylint: disable=superfluous-parens
|
|
||||||
found_difference = True
|
|
||||||
print(("* List after change contains entries for the following categories "
|
|
||||||
"that the list before the change doesn't:\n%s") % _array_to_string(
|
|
||||||
after_before_diff, ordered=True))
|
|
||||||
|
|
||||||
for category in category_to_values_before:
|
|
||||||
value_before = category_to_values_before[category]
|
|
||||||
value_after = category_to_values_after.get(category, None)
|
|
||||||
if value_after and value_after != value_before:
|
|
||||||
if not found_difference:
|
|
||||||
print(diff_string) # pylint: disable=superfluous-parens
|
|
||||||
found_difference = True
|
|
||||||
print(("* Value for category '%s' differs before and after the change:\n"
|
|
||||||
"Value before change:\tprefix:'%s'\textension:'%s'\n"
|
|
||||||
"Value after change:\tprefix:'%s'\textension:'%s'") %
|
|
||||||
(category, value_before[0], value_before[1], value_after[0],
|
|
||||||
value_after[1]))
|
|
||||||
if found_difference:
|
|
||||||
print("") # pylint: disable=superfluous-parens
|
|
||||||
return found_difference
|
|
||||||
|
|
||||||
|
|
||||||
def compare_ctoolchains(toolchain_before, toolchain_after):
|
|
||||||
"""Compares two CToolchains."""
|
|
||||||
found_difference = False
|
|
||||||
if (toolchain_before.toolchain_identifier !=
|
|
||||||
toolchain_after.toolchain_identifier):
|
|
||||||
_print_difference("toolchain_identifier",
|
|
||||||
toolchain_before.toolchain_identifier,
|
|
||||||
toolchain_after.toolchain_identifier)
|
|
||||||
if toolchain_before.host_system_name != toolchain_after.host_system_name:
|
|
||||||
_print_difference("host_system_name", toolchain_before.host_system_name,
|
|
||||||
toolchain_after.host_system_name)
|
|
||||||
found_difference = True
|
|
||||||
if toolchain_before.target_system_name != toolchain_after.target_system_name:
|
|
||||||
_print_difference("target_system_name", toolchain_before.target_system_name,
|
|
||||||
toolchain_after.target_system_name)
|
|
||||||
found_difference = True
|
|
||||||
if toolchain_before.target_cpu != toolchain_after.target_cpu:
|
|
||||||
_print_difference("target_cpu", toolchain_before.target_cpu,
|
|
||||||
toolchain_after.target_cpu)
|
|
||||||
found_difference = True
|
|
||||||
if toolchain_before.target_libc != toolchain_after.target_libc:
|
|
||||||
_print_difference("target_libc", toolchain_before.target_libc,
|
|
||||||
toolchain_after.target_libc)
|
|
||||||
found_difference = True
|
|
||||||
if toolchain_before.compiler != toolchain_after.compiler:
|
|
||||||
_print_difference("compiler", toolchain_before.compiler,
|
|
||||||
toolchain_after.compiler)
|
|
||||||
found_difference = True
|
|
||||||
if toolchain_before.abi_version != toolchain_after.abi_version:
|
|
||||||
_print_difference("abi_version", toolchain_before.abi_version,
|
|
||||||
toolchain_after.abi_version)
|
|
||||||
found_difference = True
|
|
||||||
if toolchain_before.abi_libc_version != toolchain_after.abi_libc_version:
|
|
||||||
_print_difference("abi_libc_version", toolchain_before.abi_libc_version,
|
|
||||||
toolchain_after.abi_libc_version)
|
|
||||||
found_difference = True
|
|
||||||
if toolchain_before.cc_target_os != toolchain_after.cc_target_os:
|
|
||||||
_print_difference("cc_target_os", toolchain_before.cc_target_os,
|
|
||||||
toolchain_after.cc_target_os)
|
|
||||||
found_difference = True
|
|
||||||
if toolchain_before.builtin_sysroot != toolchain_after.builtin_sysroot:
|
|
||||||
_print_difference("builtin_sysroot", toolchain_before.builtin_sysroot,
|
|
||||||
toolchain_after.builtin_sysroot)
|
|
||||||
found_difference = True
|
|
||||||
found_difference = _compare_features(
|
|
||||||
toolchain_before.feature, toolchain_after.feature) or found_difference
|
|
||||||
found_difference = _compare_action_configs(
|
|
||||||
toolchain_before.action_config,
|
|
||||||
toolchain_after.action_config) or found_difference
|
|
||||||
found_difference = _compare_tool_paths(
|
|
||||||
toolchain_before.tool_path, toolchain_after.tool_path) or found_difference
|
|
||||||
found_difference = _compare_cxx_builtin_include_directories(
|
|
||||||
toolchain_before.cxx_builtin_include_directory,
|
|
||||||
toolchain_after.cxx_builtin_include_directory) or found_difference
|
|
||||||
found_difference = _compare_make_variables(
|
|
||||||
toolchain_before.make_variable,
|
|
||||||
toolchain_after.make_variable) or found_difference
|
|
||||||
found_difference = _compare_artifact_name_patterns(
|
|
||||||
toolchain_before.artifact_name_pattern,
|
|
||||||
toolchain_after.artifact_name_pattern) or found_difference
|
|
||||||
if not found_difference:
|
|
||||||
print("No difference") # pylint: disable=superfluous-parens
|
|
||||||
return found_difference
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,49 +0,0 @@
|
||||||
"""A test rule that compares two CToolchains in proto format."""
|
|
||||||
|
|
||||||
def _impl(ctx):
|
|
||||||
toolchain_config_proto = ctx.actions.declare_file(ctx.label.name + "_toolchain_config.proto")
|
|
||||||
ctx.actions.write(
|
|
||||||
toolchain_config_proto,
|
|
||||||
ctx.attr.toolchain_config[CcToolchainConfigInfo].proto,
|
|
||||||
)
|
|
||||||
|
|
||||||
script = ("%s --before='%s' --after='%s' --toolchain_identifier='%s'" % (
|
|
||||||
ctx.executable._comparator.short_path,
|
|
||||||
ctx.file.crosstool.short_path,
|
|
||||||
toolchain_config_proto.short_path,
|
|
||||||
ctx.attr.toolchain_identifier,
|
|
||||||
))
|
|
||||||
test_executable = ctx.actions.declare_file(ctx.label.name)
|
|
||||||
ctx.actions.write(test_executable, script, is_executable = True)
|
|
||||||
|
|
||||||
runfiles = ctx.runfiles(files = [toolchain_config_proto, ctx.file.crosstool])
|
|
||||||
runfiles = runfiles.merge(ctx.attr._comparator[DefaultInfo].default_runfiles)
|
|
||||||
|
|
||||||
return DefaultInfo(runfiles = runfiles, executable = test_executable)
|
|
||||||
|
|
||||||
cc_toolchains_compare_test = rule(
|
|
||||||
implementation = _impl,
|
|
||||||
attrs = {
|
|
||||||
"crosstool": attr.label(
|
|
||||||
mandatory = True,
|
|
||||||
allow_single_file = True,
|
|
||||||
doc = "Location of the CROSSTOOL file",
|
|
||||||
),
|
|
||||||
"toolchain_config": attr.label(
|
|
||||||
mandatory = True,
|
|
||||||
providers = [CcToolchainConfigInfo],
|
|
||||||
doc = ("Starlark rule that replaces the CROSSTOOL file functionality " +
|
|
||||||
"for the CToolchain with the given identifier"),
|
|
||||||
),
|
|
||||||
"toolchain_identifier": attr.string(
|
|
||||||
mandatory = True,
|
|
||||||
doc = "identifier of the CToolchain that is being compared",
|
|
||||||
),
|
|
||||||
"_comparator": attr.label(
|
|
||||||
default = ":ctoolchain_comparator",
|
|
||||||
executable = True,
|
|
||||||
cfg = "exec",
|
|
||||||
),
|
|
||||||
},
|
|
||||||
test = True,
|
|
||||||
)
|
|
|
@ -1,564 +0,0 @@
|
||||||
"""Module providing migrate_legacy_fields function.
|
|
||||||
|
|
||||||
migrate_legacy_fields takes parsed CROSSTOOL proto and migrates it (inplace) to
|
|
||||||
use only the features.
|
|
||||||
|
|
||||||
Tracking issue: https://github.com/bazelbuild/bazel/issues/5187
|
|
||||||
|
|
||||||
Since C++ rules team is working on migrating CROSSTOOL from text proto into
|
|
||||||
Starlark, we advise CROSSTOOL owners to wait for the CROSSTOOL -> Starlark
|
|
||||||
migrator before they invest too much time into fixing their pipeline. Tracking
|
|
||||||
issue for the Starlark effort is
|
|
||||||
https://github.com/bazelbuild/bazel/issues/5380.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from third_party.com.github.bazelbuild.bazel.src.main.protobuf import crosstool_config_pb2
|
|
||||||
|
|
||||||
ALL_CC_COMPILE_ACTIONS = [
|
|
||||||
"assemble", "preprocess-assemble", "linkstamp-compile", "c-compile",
|
|
||||||
"c++-compile", "c++-header-parsing", "c++-module-compile",
|
|
||||||
"c++-module-codegen", "lto-backend", "clif-match"
|
|
||||||
]
|
|
||||||
|
|
||||||
ALL_OBJC_COMPILE_ACTIONS = [
|
|
||||||
"objc-compile", "objc++-compile"
|
|
||||||
]
|
|
||||||
|
|
||||||
ALL_CXX_COMPILE_ACTIONS = [
|
|
||||||
action for action in ALL_CC_COMPILE_ACTIONS
|
|
||||||
if action not in ["c-compile", "preprocess-assemble", "assemble"]
|
|
||||||
]
|
|
||||||
|
|
||||||
ALL_CC_LINK_ACTIONS = [
|
|
||||||
"c++-link-executable", "c++-link-dynamic-library",
|
|
||||||
"c++-link-nodeps-dynamic-library"
|
|
||||||
]
|
|
||||||
|
|
||||||
ALL_OBJC_LINK_ACTIONS = [
|
|
||||||
"objc-executable", "objc++-executable",
|
|
||||||
]
|
|
||||||
|
|
||||||
DYNAMIC_LIBRARY_LINK_ACTIONS = [
|
|
||||||
"c++-link-dynamic-library", "c++-link-nodeps-dynamic-library"
|
|
||||||
]
|
|
||||||
|
|
||||||
NODEPS_DYNAMIC_LIBRARY_LINK_ACTIONS = ["c++-link-nodeps-dynamic-library"]
|
|
||||||
|
|
||||||
TRANSITIVE_DYNAMIC_LIBRARY_LINK_ACTIONS = ["c++-link-dynamic-library"]
|
|
||||||
|
|
||||||
TRANSITIVE_LINK_ACTIONS = ["c++-link-executable", "c++-link-dynamic-library"]
|
|
||||||
|
|
||||||
CC_LINK_EXECUTABLE = ["c++-link-executable"]
|
|
||||||
|
|
||||||
|
|
||||||
def compile_actions(toolchain):
|
|
||||||
"""Returns compile actions for cc or objc rules."""
|
|
||||||
if _is_objc_toolchain(toolchain):
|
|
||||||
return ALL_CC_COMPILE_ACTIONS + ALL_OBJC_COMPILE_ACTIONS
|
|
||||||
else:
|
|
||||||
return ALL_CC_COMPILE_ACTIONS
|
|
||||||
|
|
||||||
def link_actions(toolchain):
|
|
||||||
"""Returns link actions for cc or objc rules."""
|
|
||||||
if _is_objc_toolchain(toolchain):
|
|
||||||
return ALL_CC_LINK_ACTIONS + ALL_OBJC_LINK_ACTIONS
|
|
||||||
else:
|
|
||||||
return ALL_CC_LINK_ACTIONS
|
|
||||||
|
|
||||||
|
|
||||||
def executable_link_actions(toolchain):
|
|
||||||
"""Returns transitive link actions for cc or objc rules."""
|
|
||||||
if _is_objc_toolchain(toolchain):
|
|
||||||
return CC_LINK_EXECUTABLE + ALL_OBJC_LINK_ACTIONS
|
|
||||||
else:
|
|
||||||
return CC_LINK_EXECUTABLE
|
|
||||||
|
|
||||||
|
|
||||||
def _is_objc_toolchain(toolchain):
|
|
||||||
return any(ac.action_name == "objc-compile" for ac in toolchain.action_config)
|
|
||||||
|
|
||||||
# Map converting from LinkingMode to corresponding feature name
|
|
||||||
LINKING_MODE_TO_FEATURE_NAME = {
|
|
||||||
"FULLY_STATIC": "fully_static_link",
|
|
||||||
"MOSTLY_STATIC": "static_linking_mode",
|
|
||||||
"DYNAMIC": "dynamic_linking_mode",
|
|
||||||
"MOSTLY_STATIC_LIBRARIES": "static_linking_mode_nodeps_library",
|
|
||||||
}
|
|
||||||
|
|
||||||
def migrate_legacy_fields(crosstool):
|
|
||||||
"""Migrates parsed crosstool (inplace) to not use legacy fields."""
|
|
||||||
crosstool.ClearField("default_toolchain")
|
|
||||||
for toolchain in crosstool.toolchain:
|
|
||||||
_ = [_migrate_expand_if_all_available(f) for f in toolchain.feature]
|
|
||||||
_ = [_migrate_expand_if_all_available(ac) for ac in toolchain.action_config]
|
|
||||||
_ = [_migrate_repeated_expands(f) for f in toolchain.feature]
|
|
||||||
_ = [_migrate_repeated_expands(ac) for ac in toolchain.action_config]
|
|
||||||
|
|
||||||
if (toolchain.dynamic_library_linker_flag or
|
|
||||||
_contains_dynamic_flags(toolchain)) and not _get_feature(
|
|
||||||
toolchain, "supports_dynamic_linker"):
|
|
||||||
feature = toolchain.feature.add()
|
|
||||||
feature.name = "supports_dynamic_linker"
|
|
||||||
feature.enabled = True
|
|
||||||
|
|
||||||
if toolchain.supports_start_end_lib and not _get_feature(
|
|
||||||
toolchain, "supports_start_end_lib"):
|
|
||||||
feature = toolchain.feature.add()
|
|
||||||
feature.name = "supports_start_end_lib"
|
|
||||||
feature.enabled = True
|
|
||||||
|
|
||||||
if toolchain.supports_interface_shared_objects and not _get_feature(
|
|
||||||
toolchain, "supports_interface_shared_libraries"):
|
|
||||||
feature = toolchain.feature.add()
|
|
||||||
feature.name = "supports_interface_shared_libraries"
|
|
||||||
feature.enabled = True
|
|
||||||
|
|
||||||
if toolchain.supports_embedded_runtimes and not _get_feature(
|
|
||||||
toolchain, "static_link_cpp_runtimes"):
|
|
||||||
feature = toolchain.feature.add()
|
|
||||||
feature.name = "static_link_cpp_runtimes"
|
|
||||||
feature.enabled = True
|
|
||||||
|
|
||||||
if toolchain.needsPic and not _get_feature(toolchain, "supports_pic"):
|
|
||||||
feature = toolchain.feature.add()
|
|
||||||
feature.name = "supports_pic"
|
|
||||||
feature.enabled = True
|
|
||||||
|
|
||||||
if toolchain.supports_fission and not _get_feature(
|
|
||||||
toolchain, "per_object_debug_info"):
|
|
||||||
# feature {
|
|
||||||
# name: "per_object_debug_info"
|
|
||||||
# enabled: true
|
|
||||||
# flag_set {
|
|
||||||
# action: "assemble"
|
|
||||||
# action: "preprocess-assemble"
|
|
||||||
# action: "c-compile"
|
|
||||||
# action: "c++-compile"
|
|
||||||
# action: "c++-module-codegen"
|
|
||||||
# action: "lto-backend"
|
|
||||||
# flag_group {
|
|
||||||
# expand_if_all_available: 'is_using_fission'",
|
|
||||||
# flag: "-gsplit-dwarf"
|
|
||||||
# }
|
|
||||||
# }
|
|
||||||
# }
|
|
||||||
feature = toolchain.feature.add()
|
|
||||||
feature.name = "per_object_debug_info"
|
|
||||||
feature.enabled = True
|
|
||||||
flag_set = feature.flag_set.add()
|
|
||||||
flag_set.action[:] = [
|
|
||||||
"c-compile", "c++-compile", "c++-module-codegen", "assemble",
|
|
||||||
"preprocess-assemble", "lto-backend"
|
|
||||||
]
|
|
||||||
flag_group = flag_set.flag_group.add()
|
|
||||||
flag_group.expand_if_all_available[:] = ["is_using_fission"]
|
|
||||||
flag_group.flag[:] = ["-gsplit-dwarf"]
|
|
||||||
|
|
||||||
if toolchain.objcopy_embed_flag and not _get_feature(
|
|
||||||
toolchain, "objcopy_embed_flags"):
|
|
||||||
feature = toolchain.feature.add()
|
|
||||||
feature.name = "objcopy_embed_flags"
|
|
||||||
feature.enabled = True
|
|
||||||
flag_set = feature.flag_set.add()
|
|
||||||
flag_set.action[:] = ["objcopy_embed_data"]
|
|
||||||
flag_group = flag_set.flag_group.add()
|
|
||||||
flag_group.flag[:] = toolchain.objcopy_embed_flag
|
|
||||||
|
|
||||||
action_config = toolchain.action_config.add()
|
|
||||||
action_config.action_name = "objcopy_embed_data"
|
|
||||||
action_config.config_name = "objcopy_embed_data"
|
|
||||||
action_config.enabled = True
|
|
||||||
tool = action_config.tool.add()
|
|
||||||
tool.tool_path = _find_tool_path(toolchain, "objcopy")
|
|
||||||
|
|
||||||
if toolchain.ld_embed_flag and not _get_feature(
|
|
||||||
toolchain, "ld_embed_flags"):
|
|
||||||
feature = toolchain.feature.add()
|
|
||||||
feature.name = "ld_embed_flags"
|
|
||||||
feature.enabled = True
|
|
||||||
flag_set = feature.flag_set.add()
|
|
||||||
flag_set.action[:] = ["ld_embed_data"]
|
|
||||||
flag_group = flag_set.flag_group.add()
|
|
||||||
flag_group.flag[:] = toolchain.ld_embed_flag
|
|
||||||
|
|
||||||
action_config = toolchain.action_config.add()
|
|
||||||
action_config.action_name = "ld_embed_data"
|
|
||||||
action_config.config_name = "ld_embed_data"
|
|
||||||
action_config.enabled = True
|
|
||||||
tool = action_config.tool.add()
|
|
||||||
tool.tool_path = _find_tool_path(toolchain, "ld")
|
|
||||||
|
|
||||||
|
|
||||||
# Create default_link_flags feature for linker_flag
|
|
||||||
flag_sets = _extract_legacy_link_flag_sets_for(toolchain)
|
|
||||||
if flag_sets:
|
|
||||||
if _get_feature(toolchain, "default_link_flags"):
|
|
||||||
continue
|
|
||||||
if _get_feature(toolchain, "legacy_link_flags"):
|
|
||||||
for f in toolchain.feature:
|
|
||||||
if f.name == "legacy_link_flags":
|
|
||||||
f.ClearField("flag_set")
|
|
||||||
feature = f
|
|
||||||
_rename_feature_in_toolchain(toolchain, "legacy_link_flags",
|
|
||||||
"default_link_flags")
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
feature = _prepend_feature(toolchain)
|
|
||||||
feature.name = "default_link_flags"
|
|
||||||
feature.enabled = True
|
|
||||||
_add_flag_sets(feature, flag_sets)
|
|
||||||
|
|
||||||
# Create default_compile_flags feature for compiler_flag, cxx_flag
|
|
||||||
flag_sets = _extract_legacy_compile_flag_sets_for(toolchain)
|
|
||||||
if flag_sets and not _get_feature(toolchain, "default_compile_flags"):
|
|
||||||
if _get_feature(toolchain, "legacy_compile_flags"):
|
|
||||||
for f in toolchain.feature:
|
|
||||||
if f.name == "legacy_compile_flags":
|
|
||||||
f.ClearField("flag_set")
|
|
||||||
feature = f
|
|
||||||
_rename_feature_in_toolchain(toolchain, "legacy_compile_flags",
|
|
||||||
"default_compile_flags")
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
feature = _prepend_feature(toolchain)
|
|
||||||
feature.enabled = True
|
|
||||||
feature.name = "default_compile_flags"
|
|
||||||
_add_flag_sets(feature, flag_sets)
|
|
||||||
|
|
||||||
# Unfiltered cxx flags have to have their own special feature.
|
|
||||||
# "unfiltered_compile_flags" is a well-known (by Bazel) feature name that is
|
|
||||||
# excluded from nocopts filtering.
|
|
||||||
if toolchain.unfiltered_cxx_flag:
|
|
||||||
# If there already is a feature named unfiltered_compile_flags, the
|
|
||||||
# crosstool is already migrated for unfiltered_compile_flags
|
|
||||||
if _get_feature(toolchain, "unfiltered_compile_flags"):
|
|
||||||
for f in toolchain.feature:
|
|
||||||
if f.name == "unfiltered_compile_flags":
|
|
||||||
for flag_set in f.flag_set:
|
|
||||||
for flag_group in flag_set.flag_group:
|
|
||||||
if flag_group.iterate_over == "unfiltered_compile_flags":
|
|
||||||
flag_group.ClearField("iterate_over")
|
|
||||||
flag_group.ClearField("expand_if_all_available")
|
|
||||||
flag_group.ClearField("flag")
|
|
||||||
flag_group.flag[:] = toolchain.unfiltered_cxx_flag
|
|
||||||
else:
|
|
||||||
if not _get_feature(toolchain, "user_compile_flags"):
|
|
||||||
feature = toolchain.feature.add()
|
|
||||||
feature.name = "user_compile_flags"
|
|
||||||
feature.enabled = True
|
|
||||||
flag_set = feature.flag_set.add()
|
|
||||||
flag_set.action[:] = compile_actions(toolchain)
|
|
||||||
flag_group = flag_set.flag_group.add()
|
|
||||||
flag_group.expand_if_all_available[:] = ["user_compile_flags"]
|
|
||||||
flag_group.iterate_over = "user_compile_flags"
|
|
||||||
flag_group.flag[:] = ["%{user_compile_flags}"]
|
|
||||||
|
|
||||||
if not _get_feature(toolchain, "sysroot"):
|
|
||||||
sysroot_actions = compile_actions(toolchain) + link_actions(toolchain)
|
|
||||||
sysroot_actions.remove("assemble")
|
|
||||||
feature = toolchain.feature.add()
|
|
||||||
feature.name = "sysroot"
|
|
||||||
feature.enabled = True
|
|
||||||
flag_set = feature.flag_set.add()
|
|
||||||
flag_set.action[:] = sysroot_actions
|
|
||||||
flag_group = flag_set.flag_group.add()
|
|
||||||
flag_group.expand_if_all_available[:] = ["sysroot"]
|
|
||||||
flag_group.flag[:] = ["--sysroot=%{sysroot}"]
|
|
||||||
|
|
||||||
feature = toolchain.feature.add()
|
|
||||||
feature.name = "unfiltered_compile_flags"
|
|
||||||
feature.enabled = True
|
|
||||||
flag_set = feature.flag_set.add()
|
|
||||||
flag_set.action[:] = compile_actions(toolchain)
|
|
||||||
flag_group = flag_set.flag_group.add()
|
|
||||||
flag_group.flag[:] = toolchain.unfiltered_cxx_flag
|
|
||||||
|
|
||||||
# clear fields
|
|
||||||
toolchain.ClearField("debian_extra_requires")
|
|
||||||
toolchain.ClearField("gcc_plugin_compiler_flag")
|
|
||||||
toolchain.ClearField("ar_flag")
|
|
||||||
toolchain.ClearField("ar_thin_archives_flag")
|
|
||||||
toolchain.ClearField("gcc_plugin_header_directory")
|
|
||||||
toolchain.ClearField("mao_plugin_header_directory")
|
|
||||||
toolchain.ClearField("supports_normalizing_ar")
|
|
||||||
toolchain.ClearField("supports_thin_archives")
|
|
||||||
toolchain.ClearField("supports_incremental_linker")
|
|
||||||
toolchain.ClearField("supports_dsym")
|
|
||||||
toolchain.ClearField("supports_gold_linker")
|
|
||||||
toolchain.ClearField("default_python_top")
|
|
||||||
toolchain.ClearField("default_python_version")
|
|
||||||
toolchain.ClearField("python_preload_swigdeps")
|
|
||||||
toolchain.ClearField("needsPic")
|
|
||||||
toolchain.ClearField("compilation_mode_flags")
|
|
||||||
toolchain.ClearField("linking_mode_flags")
|
|
||||||
toolchain.ClearField("unfiltered_cxx_flag")
|
|
||||||
toolchain.ClearField("ld_embed_flag")
|
|
||||||
toolchain.ClearField("objcopy_embed_flag")
|
|
||||||
toolchain.ClearField("supports_start_end_lib")
|
|
||||||
toolchain.ClearField("supports_interface_shared_objects")
|
|
||||||
toolchain.ClearField("supports_fission")
|
|
||||||
toolchain.ClearField("supports_embedded_runtimes")
|
|
||||||
toolchain.ClearField("compiler_flag")
|
|
||||||
toolchain.ClearField("cxx_flag")
|
|
||||||
toolchain.ClearField("linker_flag")
|
|
||||||
toolchain.ClearField("dynamic_library_linker_flag")
|
|
||||||
toolchain.ClearField("static_runtimes_filegroup")
|
|
||||||
toolchain.ClearField("dynamic_runtimes_filegroup")
|
|
||||||
|
|
||||||
# Enable features that were previously enabled by Bazel
|
|
||||||
default_features = [
|
|
||||||
"dependency_file", "random_seed", "module_maps", "module_map_home_cwd",
|
|
||||||
"header_module_compile", "include_paths", "pic", "preprocessor_define"
|
|
||||||
]
|
|
||||||
for feature_name in default_features:
|
|
||||||
feature = _get_feature(toolchain, feature_name)
|
|
||||||
if feature:
|
|
||||||
feature.enabled = True
|
|
||||||
|
|
||||||
|
|
||||||
def _find_tool_path(toolchain, tool_name):
|
|
||||||
"""Returns the tool path of the tool with the given name."""
|
|
||||||
for tool in toolchain.tool_path:
|
|
||||||
if tool.name == tool_name:
|
|
||||||
return tool.path
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def _add_flag_sets(feature, flag_sets):
|
|
||||||
"""Add flag sets into a feature."""
|
|
||||||
for flag_set in flag_sets:
|
|
||||||
with_feature = flag_set[0]
|
|
||||||
actions = flag_set[1]
|
|
||||||
flags = flag_set[2]
|
|
||||||
expand_if_all_available = flag_set[3]
|
|
||||||
not_feature = None
|
|
||||||
if len(flag_set) >= 5:
|
|
||||||
not_feature = flag_set[4]
|
|
||||||
flag_set = feature.flag_set.add()
|
|
||||||
if with_feature is not None:
|
|
||||||
flag_set.with_feature.add().feature[:] = [with_feature]
|
|
||||||
if not_feature is not None:
|
|
||||||
flag_set.with_feature.add().not_feature[:] = [not_feature]
|
|
||||||
flag_set.action[:] = actions
|
|
||||||
flag_group = flag_set.flag_group.add()
|
|
||||||
flag_group.expand_if_all_available[:] = expand_if_all_available
|
|
||||||
flag_group.flag[:] = flags
|
|
||||||
return feature
|
|
||||||
|
|
||||||
|
|
||||||
def _extract_legacy_compile_flag_sets_for(toolchain):
|
|
||||||
"""Get flag sets for default_compile_flags feature."""
|
|
||||||
result = []
|
|
||||||
if toolchain.compiler_flag:
|
|
||||||
result.append(
|
|
||||||
[None, compile_actions(toolchain), toolchain.compiler_flag, []])
|
|
||||||
|
|
||||||
# Migrate compiler_flag from compilation_mode_flags
|
|
||||||
for cmf in toolchain.compilation_mode_flags:
|
|
||||||
mode = crosstool_config_pb2.CompilationMode.Name(cmf.mode).lower()
|
|
||||||
# coverage mode has been a noop since a while
|
|
||||||
if mode == "coverage":
|
|
||||||
continue
|
|
||||||
|
|
||||||
if (cmf.compiler_flag or
|
|
||||||
cmf.cxx_flag) and not _get_feature(toolchain, mode):
|
|
||||||
feature = toolchain.feature.add()
|
|
||||||
feature.name = mode
|
|
||||||
|
|
||||||
if cmf.compiler_flag:
|
|
||||||
result.append([mode, compile_actions(toolchain), cmf.compiler_flag, []])
|
|
||||||
|
|
||||||
if toolchain.cxx_flag:
|
|
||||||
result.append([None, ALL_CXX_COMPILE_ACTIONS, toolchain.cxx_flag, []])
|
|
||||||
|
|
||||||
# Migrate compiler_flag/cxx_flag from compilation_mode_flags
|
|
||||||
for cmf in toolchain.compilation_mode_flags:
|
|
||||||
mode = crosstool_config_pb2.CompilationMode.Name(cmf.mode).lower()
|
|
||||||
# coverage mode has been a noop since a while
|
|
||||||
if mode == "coverage":
|
|
||||||
continue
|
|
||||||
|
|
||||||
if cmf.cxx_flag:
|
|
||||||
result.append([mode, ALL_CXX_COMPILE_ACTIONS, cmf.cxx_flag, []])
|
|
||||||
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
def _extract_legacy_link_flag_sets_for(toolchain):
|
|
||||||
"""Get flag sets for default_link_flags feature."""
|
|
||||||
result = []
|
|
||||||
|
|
||||||
# Migrate linker_flag
|
|
||||||
if toolchain.linker_flag:
|
|
||||||
result.append([None, link_actions(toolchain), toolchain.linker_flag, []])
|
|
||||||
|
|
||||||
# Migrate linker_flags from compilation_mode_flags
|
|
||||||
for cmf in toolchain.compilation_mode_flags:
|
|
||||||
mode = crosstool_config_pb2.CompilationMode.Name(cmf.mode).lower()
|
|
||||||
# coverage mode has beed a noop since a while
|
|
||||||
if mode == "coverage":
|
|
||||||
continue
|
|
||||||
|
|
||||||
if cmf.linker_flag and not _get_feature(toolchain, mode):
|
|
||||||
feature = toolchain.feature.add()
|
|
||||||
feature.name = mode
|
|
||||||
|
|
||||||
if cmf.linker_flag:
|
|
||||||
result.append([mode, link_actions(toolchain), cmf.linker_flag, []])
|
|
||||||
|
|
||||||
# Migrate linker_flags from linking_mode_flags
|
|
||||||
for lmf in toolchain.linking_mode_flags:
|
|
||||||
mode = crosstool_config_pb2.LinkingMode.Name(lmf.mode)
|
|
||||||
feature_name = LINKING_MODE_TO_FEATURE_NAME.get(mode)
|
|
||||||
# if the feature is already there, we don't migrate, lmf is not used
|
|
||||||
if _get_feature(toolchain, feature_name):
|
|
||||||
continue
|
|
||||||
|
|
||||||
if lmf.linker_flag:
|
|
||||||
feature = toolchain.feature.add()
|
|
||||||
feature.name = feature_name
|
|
||||||
if mode == "DYNAMIC":
|
|
||||||
result.append(
|
|
||||||
[None, NODEPS_DYNAMIC_LIBRARY_LINK_ACTIONS, lmf.linker_flag, []])
|
|
||||||
result.append([
|
|
||||||
None,
|
|
||||||
TRANSITIVE_DYNAMIC_LIBRARY_LINK_ACTIONS,
|
|
||||||
lmf.linker_flag,
|
|
||||||
[],
|
|
||||||
"static_link_cpp_runtimes",
|
|
||||||
])
|
|
||||||
result.append([
|
|
||||||
feature_name,
|
|
||||||
executable_link_actions(toolchain), lmf.linker_flag, []
|
|
||||||
])
|
|
||||||
elif mode == "MOSTLY_STATIC":
|
|
||||||
result.append(
|
|
||||||
[feature_name,
|
|
||||||
CC_LINK_EXECUTABLE, lmf.linker_flag, []])
|
|
||||||
else:
|
|
||||||
result.append(
|
|
||||||
[feature_name,
|
|
||||||
link_actions(toolchain), lmf.linker_flag, []])
|
|
||||||
|
|
||||||
if toolchain.dynamic_library_linker_flag:
|
|
||||||
result.append([
|
|
||||||
None, DYNAMIC_LIBRARY_LINK_ACTIONS,
|
|
||||||
toolchain.dynamic_library_linker_flag, []
|
|
||||||
])
|
|
||||||
|
|
||||||
if toolchain.test_only_linker_flag:
|
|
||||||
result.append([
|
|
||||||
None,
|
|
||||||
link_actions(toolchain), toolchain.test_only_linker_flag,
|
|
||||||
["is_cc_test"]
|
|
||||||
])
|
|
||||||
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
def _prepend_feature(toolchain):
|
|
||||||
"""Create a new feature and make it be the first in the toolchain."""
|
|
||||||
features = toolchain.feature
|
|
||||||
toolchain.ClearField("feature")
|
|
||||||
new_feature = toolchain.feature.add()
|
|
||||||
toolchain.feature.extend(features)
|
|
||||||
return new_feature
|
|
||||||
|
|
||||||
|
|
||||||
def _get_feature(toolchain, name):
|
|
||||||
"""Returns feature with a given name or None."""
|
|
||||||
for feature in toolchain.feature:
|
|
||||||
if feature.name == name:
|
|
||||||
return feature
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def _migrate_expand_if_all_available(message):
|
|
||||||
"""Move expand_if_all_available field to flag_groups."""
|
|
||||||
for flag_set in message.flag_set:
|
|
||||||
if flag_set.expand_if_all_available:
|
|
||||||
for flag_group in flag_set.flag_group:
|
|
||||||
new_vars = (
|
|
||||||
flag_group.expand_if_all_available[:] +
|
|
||||||
flag_set.expand_if_all_available[:])
|
|
||||||
flag_group.expand_if_all_available[:] = new_vars
|
|
||||||
flag_set.ClearField("expand_if_all_available")
|
|
||||||
|
|
||||||
|
|
||||||
def _migrate_repeated_expands(message):
|
|
||||||
"""Replace repeated legacy fields with nesting."""
|
|
||||||
todo_queue = []
|
|
||||||
for flag_set in message.flag_set:
|
|
||||||
todo_queue.extend(flag_set.flag_group)
|
|
||||||
while todo_queue:
|
|
||||||
flag_group = todo_queue.pop()
|
|
||||||
todo_queue.extend(flag_group.flag_group)
|
|
||||||
if len(flag_group.expand_if_all_available) <= 1 and len(
|
|
||||||
flag_group.expand_if_none_available) <= 1:
|
|
||||||
continue
|
|
||||||
|
|
||||||
current_children = flag_group.flag_group
|
|
||||||
current_flags = flag_group.flag
|
|
||||||
flag_group.ClearField("flag_group")
|
|
||||||
flag_group.ClearField("flag")
|
|
||||||
|
|
||||||
new_flag_group = flag_group.flag_group.add()
|
|
||||||
new_flag_group.flag_group.extend(current_children)
|
|
||||||
new_flag_group.flag.extend(current_flags)
|
|
||||||
|
|
||||||
if len(flag_group.expand_if_all_available) > 1:
|
|
||||||
expands_to_move = flag_group.expand_if_all_available[1:]
|
|
||||||
flag_group.expand_if_all_available[:] = [
|
|
||||||
flag_group.expand_if_all_available[0]
|
|
||||||
]
|
|
||||||
new_flag_group.expand_if_all_available.extend(expands_to_move)
|
|
||||||
|
|
||||||
if len(flag_group.expand_if_none_available) > 1:
|
|
||||||
expands_to_move = flag_group.expand_if_none_available[1:]
|
|
||||||
flag_group.expand_if_none_available[:] = [
|
|
||||||
flag_group.expand_if_none_available[0]
|
|
||||||
]
|
|
||||||
new_flag_group.expand_if_none_available.extend(expands_to_move)
|
|
||||||
|
|
||||||
todo_queue.append(new_flag_group)
|
|
||||||
todo_queue.append(flag_group)
|
|
||||||
|
|
||||||
|
|
||||||
def _contains_dynamic_flags(toolchain):
|
|
||||||
for lmf in toolchain.linking_mode_flags:
|
|
||||||
mode = crosstool_config_pb2.LinkingMode.Name(lmf.mode)
|
|
||||||
if mode == "DYNAMIC":
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
def _rename_feature_in_toolchain(toolchain, from_name, to_name):
|
|
||||||
for f in toolchain.feature:
|
|
||||||
_rename_feature_in(f, from_name, to_name)
|
|
||||||
for a in toolchain.action_config:
|
|
||||||
_rename_feature_in(a, from_name, to_name)
|
|
||||||
|
|
||||||
|
|
||||||
def _rename_feature_in(msg, from_name, to_name):
|
|
||||||
if from_name in msg.implies:
|
|
||||||
msg.implies.remove(from_name)
|
|
||||||
for requires in msg.requires:
|
|
||||||
if from_name in requires.feature:
|
|
||||||
requires.feature.remove(from_name)
|
|
||||||
requires.feature.extend([to_name])
|
|
||||||
for flag_set in msg.flag_set:
|
|
||||||
for with_feature in flag_set.with_feature:
|
|
||||||
if from_name in with_feature.feature:
|
|
||||||
with_feature.feature.remove(from_name)
|
|
||||||
with_feature.feature.extend([to_name])
|
|
||||||
if from_name in with_feature.not_feature:
|
|
||||||
with_feature.not_feature.remove(from_name)
|
|
||||||
with_feature.not_feature.extend([to_name])
|
|
||||||
for env_set in msg.env_set:
|
|
||||||
for with_feature in env_set.with_feature:
|
|
||||||
if from_name in with_feature.feature:
|
|
||||||
with_feature.feature.remove(from_name)
|
|
||||||
with_feature.feature.extend([to_name])
|
|
||||||
if from_name in with_feature.not_feature:
|
|
||||||
with_feature.not_feature.remove(from_name)
|
|
||||||
with_feature.not_feature.extend([to_name])
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,69 +0,0 @@
|
||||||
"""Script migrating legacy CROSSTOOL fields into features.
|
|
||||||
|
|
||||||
This script migrates the CROSSTOOL to use only the features to describe C++
|
|
||||||
command lines. It is intended to be added as a last step of CROSSTOOL generation
|
|
||||||
pipeline. Since it doesn't retain comments, we assume CROSSTOOL owners will want
|
|
||||||
to migrate their pipeline manually.
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Tracking issue: https://github.com/bazelbuild/bazel/issues/5187
|
|
||||||
#
|
|
||||||
# Since C++ rules team is working on migrating CROSSTOOL from text proto into
|
|
||||||
# Starlark, we advise CROSSTOOL owners to wait for the CROSSTOOL -> Starlark
|
|
||||||
# migrator before they invest too much time into fixing their pipeline. Tracking
|
|
||||||
# issue for the Starlark effort is
|
|
||||||
# https://github.com/bazelbuild/bazel/issues/5380.
|
|
||||||
|
|
||||||
from absl import app
|
|
||||||
from absl import flags
|
|
||||||
from google.protobuf import text_format
|
|
||||||
from third_party.com.github.bazelbuild.bazel.src.main.protobuf import crosstool_config_pb2
|
|
||||||
from tools.migration.legacy_fields_migration_lib import migrate_legacy_fields
|
|
||||||
import os
|
|
||||||
|
|
||||||
flags.DEFINE_string("input", None, "Input CROSSTOOL file to be migrated")
|
|
||||||
flags.DEFINE_string("output", None,
|
|
||||||
"Output path where to write migrated CROSSTOOL.")
|
|
||||||
flags.DEFINE_boolean("inline", None, "Overwrite --input file")
|
|
||||||
|
|
||||||
|
|
||||||
def main(unused_argv):
|
|
||||||
crosstool = crosstool_config_pb2.CrosstoolRelease()
|
|
||||||
|
|
||||||
input_filename = flags.FLAGS.input
|
|
||||||
output_filename = flags.FLAGS.output
|
|
||||||
inline = flags.FLAGS.inline
|
|
||||||
|
|
||||||
if not input_filename:
|
|
||||||
raise app.UsageError("ERROR --input unspecified")
|
|
||||||
if not output_filename and not inline:
|
|
||||||
raise app.UsageError("ERROR --output unspecified and --inline not passed")
|
|
||||||
if output_filename and inline:
|
|
||||||
raise app.UsageError("ERROR both --output and --inline passed")
|
|
||||||
|
|
||||||
with open(to_absolute_path(input_filename), "r") as f:
|
|
||||||
input_text = f.read()
|
|
||||||
|
|
||||||
text_format.Merge(input_text, crosstool)
|
|
||||||
|
|
||||||
migrate_legacy_fields(crosstool)
|
|
||||||
output_text = text_format.MessageToString(crosstool)
|
|
||||||
|
|
||||||
resolved_output_filename = to_absolute_path(
|
|
||||||
input_filename if inline else output_filename)
|
|
||||||
with open(resolved_output_filename, "w") as f:
|
|
||||||
f.write(output_text)
|
|
||||||
|
|
||||||
def to_absolute_path(path):
|
|
||||||
path = os.path.expanduser(path)
|
|
||||||
if os.path.isabs(path):
|
|
||||||
return path
|
|
||||||
else:
|
|
||||||
if "BUILD_WORKING_DIRECTORY" in os.environ:
|
|
||||||
return os.path.join(os.environ["BUILD_WORKING_DIRECTORY"], path)
|
|
||||||
else:
|
|
||||||
return path
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
app.run(main)
|
|
Loading…
Reference in New Issue