Merge branch 'main' into rules-based-toolchain-example

This commit is contained in:
Armando Montanez 2024-10-08 10:12:35 -07:00
commit b82c650543
35 changed files with 88 additions and 8641 deletions

View File

@ -16,7 +16,6 @@ x_defaults:
- "//examples/my_c_archive:all"
- "//examples/my_c_compile:all"
- "//examples/write_cc_toolchain_cpu:all"
- "//tools/migration:all"
- "//tests/..."
test_flags:
- "--test_timeout=120"
@ -29,7 +28,6 @@ x_defaults:
- "//examples/my_c_archive:all"
- "//examples/my_c_compile:all"
- "//examples/write_cc_toolchain_cpu:all"
- "//tools/migration:all"
- "//tests/..."
buildifier:

View File

@ -1,6 +1,12 @@
{
"homepage": "https://github.com/bazelbuild/rules_cc",
"maintainers": [],
"maintainers": [
{
"email": "ilist@google.com",
"github": "comius",
"name": "Ivo Ristovski List"
}
],
"versions": [],
"yanked_versions": {}
}

View File

@ -1,8 +1,12 @@
matrix:
platform: ["centos7", "debian10", "macos", "ubuntu2004", "windows"]
bazel:
- 6.x
- 7.x
tasks:
verify_targets:
name: "Verify build targets"
platform: ${{ platform }}
bazel: ${{ bazel }}
build_targets:
- "@rules_cc//cc/..."

View File

@ -1,5 +1,5 @@
{
"integrity": "",
"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"
}

View File

@ -1,12 +1,11 @@
module(
name = "rules_cc",
version = "0.0.10",
version = "0.0.12",
compatibility_level = 1,
)
bazel_dep(name = "bazel_skylib", version = "1.7.1")
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")
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")
bazel_dep(name = "rules_testing", version = "0.6.0", dev_dependency = True)
bazel_dep(name = "stardoc", version = "0.7.0", dev_dependency = True)

View File

@ -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(
name = "platforms",
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")
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(
name = "rules_testing",
sha256 = "02c62574631876a4e3b02a1820cb51167bb9cdcdea2381b2fa9d9b8b11c407c4",

View File

@ -15,7 +15,6 @@
filegroup(
name = "srcs",
srcs = glob([
"**/*.bzl",
"**/BUILD",
]) + [
"//cc/private/rules_impl:srcs",

View File

@ -13,11 +13,6 @@
# limitations under the License.
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(
name = "toolchain_rules",
@ -42,35 +37,3 @@ filegroup(
]),
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",
)

View File

@ -40,7 +40,7 @@ cc_action_type = rule(
`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
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
doing this, because every toolchain that encounters the action will need to be configured to

View File

@ -235,6 +235,8 @@ cc_action_type_set(
":cpp_compile_actions",
":c_compile_actions",
":assembly_actions",
":objc_compile",
":objcpp_compile",
],
)

View File

@ -17,13 +17,14 @@ load("//cc/toolchains:args.bzl", "cc_args")
visibility("public")
def cc_sysroot(name, sysroot, **kwargs):
def cc_sysroot(name, sysroot, args = [], **kwargs):
"""Creates args for a sysroot.
Args:
name: (str) The name of the target
sysroot: (bazel_skylib's directory rule) The directory that should be the
sysroot.
args: (List[str]) Extra command-line args to add.
**kwargs: kwargs to pass to cc_args.
"""
cc_args(
@ -33,7 +34,7 @@ def cc_sysroot(name, sysroot, **kwargs):
Label("//cc/toolchains/actions:c_compile"),
Label("//cc/toolchains/actions:link_actions"),
],
args = ["--sysroot={sysroot}"],
args = ["--sysroot={sysroot}"] + args,
format = {"sysroot": sysroot},
**kwargs
)

View File

@ -9,7 +9,7 @@ load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
exports_files(
["documented_api.bzl"],
visibility = ["//cc/toolchains:__subpackages__"],
visibility = ["//docs:__pkg__"],
)
bzl_library(

View File

@ -75,7 +75,7 @@ def cc_variable(name, type, **kwargs):
it's not possible to declare custom variables.
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:
```
@ -91,7 +91,7 @@ def cc_variable(name, type, **kwargs):
Args:
name: (str) The name of the outer variable, and the rule.
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.
"""
_cc_variable(name = name, type = json.encode(type), **kwargs)

View File

@ -102,7 +102,7 @@ This can help work around errors like:
providers = [ToolCapabilityInfo],
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`.
""",
),
},

View File

@ -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
tools to use for a given action. To simplify usage, some actions have been grouped together (for
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".
In Bazel, there is a little more granularity to the mapping, so the mapping doesn't follow the

View File

@ -19,11 +19,6 @@ load("//cc/private/toolchain:windows_cc_configure.bzl", _find_vc_path = "find_vc
MSVC_ENVVARS = _MSVC_ENVVARS
def find_vc_path(repository_ctx):
return _find_vc_path(repository_ctx)
def setup_vc_env_vars(repository_ctx):
return _setup_vc_env_vars(repository_ctx)
def escape_string(string):
return _escape_string(string)
find_vc_path = _find_vc_path
setup_vc_env_vars = _setup_vc_env_vars
escape_string = _escape_string

60
docs/BUILD Normal file
View File

@ -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
third_party/BUILD vendored
View File

@ -1 +0,0 @@
# Intentionally empty, only there to make //third_party a package.

View File

@ -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__",
],
)

View File

@ -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;
}

16
third_party/six.BUILD vendored
View File

@ -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"],
)

View File

@ -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"],
)

View File

@ -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,
)

View File

@ -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!")
}

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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,
)

View File

@ -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

View File

@ -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)