mirror of https://github.com/bazelbuild/rules_cc
Move legacy_fields_migrator to rules_cc
Needed for --incompatible_disable_legacy_crosstool_fields migration: https://github.com/bazelbuild/bazel/issues/6861 Tracking issue: https://github.com/bazelbuild/bazel/issues/5883 RELNOTES: None. PiperOrigin-RevId: 225956311
This commit is contained in:
parent
f37a53e8c9
commit
e1d74cbe59
|
@ -0,0 +1,45 @@
|
|||
# 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.
|
||||
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"]) # Apache 2.0
|
||||
|
||||
py_binary(
|
||||
name = "legacy_fields_migrator",
|
||||
srcs = ["legacy_fields_migrator.py"],
|
||||
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",
|
||||
],
|
||||
)
|
||||
|
||||
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"],
|
||||
deps = [
|
||||
":legacy_fields_migration_lib",
|
||||
"//third_party/com/github/bazelbuild/bazel/src/main/protobuf:crosstool_config_py_pb2",
|
||||
],
|
||||
)
|
|
@ -0,0 +1,217 @@
|
|||
"""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_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_CXX_COMPILE_ACTIONS = [
|
||||
action for action in ALL_COMPILE_ACTIONS if action != "c-compile"
|
||||
]
|
||||
|
||||
ALL_LINK_ACTIONS = [
|
||||
"c++-link-executable", "c++-link-dynamic-library",
|
||||
"c++-link-nodeps-dynamic-library"
|
||||
]
|
||||
|
||||
# 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:
|
||||
# clear noop fields first
|
||||
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("default_python_top")
|
||||
toolchain.ClearField("default_python_version")
|
||||
toolchain.ClearField("python_preload_swigdeps")
|
||||
|
||||
_ = [_migrate_expand_if_all_available(f) for f in toolchain.feature]
|
||||
_ = [_migrate_expand_if_all_available(ac) for ac in toolchain.action_config]
|
||||
|
||||
# Create default_link_flags feature for linker_flag
|
||||
flag_sets = _extract_legacy_link_flag_sets_for(toolchain)
|
||||
if flag_sets:
|
||||
if _contains_feature(toolchain, "default_link_flags"):
|
||||
continue
|
||||
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 _contains_feature(toolchain, "default_compile_flags"):
|
||||
feature = _prepend_feature(toolchain)
|
||||
feature.enabled = True
|
||||
feature.name = "default_compile_flags"
|
||||
_add_flag_sets(feature, flag_sets)
|
||||
|
||||
toolchain.ClearField("compilation_mode_flags")
|
||||
|
||||
# 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 _contains_feature(toolchain, "unfiltered_compile_flags"):
|
||||
for f in toolchain.feature:
|
||||
if f.name == "unfiltered_compile_flags":
|
||||
feature = f
|
||||
break
|
||||
else:
|
||||
feature = toolchain.feature.add()
|
||||
feature.name = "unfiltered_compile_flags"
|
||||
feature.enabled = True
|
||||
|
||||
_add_flag_sets(
|
||||
feature, [[None, ALL_COMPILE_ACTIONS, toolchain.unfiltered_cxx_flag]])
|
||||
toolchain.ClearField("unfiltered_cxx_flag")
|
||||
|
||||
|
||||
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]
|
||||
flag_set = feature.flag_set.add()
|
||||
if with_feature is not None:
|
||||
flag_set.with_feature.add().feature[:] = [with_feature]
|
||||
flag_set.action[:] = actions
|
||||
flag_group = flag_set.flag_group.add()
|
||||
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, ALL_COMPILE_ACTIONS, toolchain.compiler_flag])
|
||||
toolchain.ClearField("compiler_flag")
|
||||
if toolchain.cxx_flag:
|
||||
result.append([None, ALL_CXX_COMPILE_ACTIONS, toolchain.cxx_flag])
|
||||
toolchain.ClearField("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.compiler_flag or
|
||||
cmf.cxx_flag) and not _contains_feature(toolchain, mode):
|
||||
feature = toolchain.feature.add()
|
||||
feature.name = mode
|
||||
|
||||
if cmf.compiler_flag:
|
||||
result.append([mode, ALL_COMPILE_ACTIONS, cmf.compiler_flag])
|
||||
|
||||
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, ALL_LINK_ACTIONS, toolchain.linker_flag])
|
||||
toolchain.ClearField("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 _contains_feature(toolchain, mode):
|
||||
feature = toolchain.feature.add()
|
||||
feature.name = mode
|
||||
|
||||
if cmf.linker_flag:
|
||||
result.append([mode, ALL_LINK_ACTIONS, 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)
|
||||
mode = LINKING_MODE_TO_FEATURE_NAME.get(mode)
|
||||
# if the feature is already there, we don't migrate, lmf is not used
|
||||
if _contains_feature(toolchain, mode):
|
||||
continue
|
||||
|
||||
# dynamic_linking_mode is also a marker feature it has a meaning
|
||||
# even when empty
|
||||
if lmf.linker_flag or mode == "dynamic_linking_mode":
|
||||
feature = toolchain.feature.add()
|
||||
feature.name = mode
|
||||
|
||||
if lmf.linker_flag:
|
||||
result.append([mode, ALL_LINK_ACTIONS, lmf.linker_flag])
|
||||
toolchain.ClearField("linking_mode_flags")
|
||||
|
||||
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 _contains_feature(toolchain, name):
|
||||
"""Returns True when toolchain contains a feature with a given name."""
|
||||
return any(feature.name == name for feature in toolchain.feature)
|
||||
|
||||
|
||||
def _migrate_expand_if_all_available(message):
|
||||
"""Move expand_if_all_available fields 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")
|
|
@ -0,0 +1,422 @@
|
|||
import unittest
|
||||
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 ALL_COMPILE_ACTIONS
|
||||
from tools.migration.legacy_fields_migration_lib import ALL_CXX_COMPILE_ACTIONS
|
||||
from tools.migration.legacy_fields_migration_lib import ALL_LINK_ACTIONS
|
||||
from tools.migration.legacy_fields_migration_lib import migrate_legacy_fields
|
||||
|
||||
|
||||
def assert_has_feature(self, toolchain, name):
|
||||
self.assertTrue(any(feature.name == name for feature in toolchain.feature))
|
||||
|
||||
|
||||
def make_crosstool(string):
|
||||
crosstool = crosstool_config_pb2.CrosstoolRelease()
|
||||
text_format.Merge("major_version: '123' minor_version: '456'", crosstool)
|
||||
toolchain = crosstool.toolchain.add()
|
||||
text_format.Merge(string, toolchain)
|
||||
return crosstool
|
||||
|
||||
|
||||
def migrate_to_string(crosstool):
|
||||
migrate_legacy_fields(crosstool)
|
||||
return to_string(crosstool)
|
||||
|
||||
|
||||
def to_string(crosstool):
|
||||
return text_format.MessageToString(crosstool)
|
||||
|
||||
|
||||
class LegacyFieldsMigrationLibTest(unittest.TestCase):
|
||||
|
||||
def test_deletes_unused_fields(self):
|
||||
crosstool = make_crosstool("""
|
||||
debian_extra_requires: 'debian-1'
|
||||
gcc_plugin_compiler_flag: 'gcc_plugin_compiler_flag-1'
|
||||
ar_flag: 'ar_flag-1'
|
||||
ar_thin_archives_flag: 'ar_thin_archives_flag-1'
|
||||
gcc_plugin_header_directory: 'gcc_plugin_header_directory-1'
|
||||
mao_plugin_header_directory: 'mao_plugin_header_directory-1'
|
||||
default_python_top: 'default_python_top-1'
|
||||
default_python_version: 'default_python_version-1'
|
||||
python_preload_swigdeps: false
|
||||
supports_normalizing_ar: false
|
||||
supports_thin_archives: false
|
||||
supports_incremental_linker: false
|
||||
supports_dsym: false
|
||||
""")
|
||||
output = migrate_to_string(crosstool)
|
||||
self.assertNotIn("debian_extra_requires", output)
|
||||
self.assertNotIn("gcc_plugin_compiler_flag", output)
|
||||
self.assertNotIn("ar_flag", output)
|
||||
self.assertNotIn("ar_thin_archives_flag", output)
|
||||
self.assertNotIn("gcc_plugin_header_directory", output)
|
||||
self.assertNotIn("mao_plugin_header_directory", output)
|
||||
self.assertNotIn("supports_normalizing_ar", output)
|
||||
self.assertNotIn("supports_thin_archives", output)
|
||||
self.assertNotIn("supports_incremental_linker", output)
|
||||
self.assertNotIn("supports_dsym", output)
|
||||
self.assertNotIn("default_python_top", output)
|
||||
self.assertNotIn("default_python_version", output)
|
||||
self.assertNotIn("python_preload_swigdeps", output)
|
||||
|
||||
def test_deletes_default_toolchains(self):
|
||||
crosstool = make_crosstool("")
|
||||
crosstool.default_toolchain.add()
|
||||
self.assertEqual(len(crosstool.default_toolchain), 1)
|
||||
migrate_legacy_fields(crosstool)
|
||||
self.assertEqual(len(crosstool.default_toolchain), 0)
|
||||
|
||||
def test_migrate_compiler_flags(self):
|
||||
crosstool = make_crosstool("""
|
||||
compiler_flag: 'clang-flag-1'
|
||||
""")
|
||||
migrate_legacy_fields(crosstool)
|
||||
output = crosstool.toolchain[0]
|
||||
self.assertEqual(len(output.compiler_flag), 0)
|
||||
self.assertEqual(output.feature[0].name, "default_compile_flags")
|
||||
self.assertEqual(output.feature[0].flag_set[0].action, ALL_COMPILE_ACTIONS)
|
||||
self.assertEqual(output.feature[0].flag_set[0].flag_group[0].flag,
|
||||
["clang-flag-1"])
|
||||
|
||||
def test_migrate_cxx_flags(self):
|
||||
crosstool = make_crosstool("""
|
||||
cxx_flag: 'clang-flag-1'
|
||||
""")
|
||||
migrate_legacy_fields(crosstool)
|
||||
output = crosstool.toolchain[0]
|
||||
self.assertEqual(len(output.cxx_flag), 0)
|
||||
self.assertEqual(output.feature[0].name, "default_compile_flags")
|
||||
self.assertEqual(output.feature[0].flag_set[0].action,
|
||||
ALL_CXX_COMPILE_ACTIONS)
|
||||
self.assertEqual(output.feature[0].flag_set[0].flag_group[0].flag,
|
||||
["clang-flag-1"])
|
||||
|
||||
def test_compiler_flag_come_before_cxx_flags(self):
|
||||
crosstool = make_crosstool("""
|
||||
compiler_flag: 'clang-flag-1'
|
||||
cxx_flag: 'clang-flag-2'
|
||||
""")
|
||||
migrate_legacy_fields(crosstool)
|
||||
output = crosstool.toolchain[0]
|
||||
self.assertEqual(output.feature[0].name, "default_compile_flags")
|
||||
self.assertEqual(output.feature[0].flag_set[0].action, ALL_COMPILE_ACTIONS)
|
||||
self.assertEqual(output.feature[0].flag_set[1].action,
|
||||
ALL_CXX_COMPILE_ACTIONS)
|
||||
self.assertEqual(output.feature[0].flag_set[0].flag_group[0].flag,
|
||||
["clang-flag-1"])
|
||||
self.assertEqual(output.feature[0].flag_set[1].flag_group[0].flag,
|
||||
["clang-flag-2"])
|
||||
|
||||
def test_migrate_linker_flags(self):
|
||||
crosstool = make_crosstool("""
|
||||
linker_flag: 'linker-flag-1'
|
||||
""")
|
||||
migrate_legacy_fields(crosstool)
|
||||
output = crosstool.toolchain[0]
|
||||
self.assertEqual(len(output.linker_flag), 0)
|
||||
self.assertEqual(output.feature[0].name, "default_link_flags")
|
||||
self.assertEqual(output.feature[0].flag_set[0].action, ALL_LINK_ACTIONS)
|
||||
self.assertEqual(output.feature[0].flag_set[0].flag_group[0].flag,
|
||||
["linker-flag-1"])
|
||||
|
||||
def test_compilation_mode_flags(self):
|
||||
crosstool = make_crosstool("""
|
||||
compiler_flag: "compile-flag-1"
|
||||
cxx_flag: "cxx-flag-1"
|
||||
linker_flag: "linker-flag-1"
|
||||
compilation_mode_flags {
|
||||
mode: OPT
|
||||
compiler_flag: "opt-flag-1"
|
||||
cxx_flag: "opt-flag-2"
|
||||
linker_flag: "opt-flag-3"
|
||||
}
|
||||
""")
|
||||
migrate_legacy_fields(crosstool)
|
||||
output = crosstool.toolchain[0]
|
||||
self.assertEqual(len(output.compilation_mode_flags), 0)
|
||||
assert_has_feature(self, output, "opt")
|
||||
|
||||
self.assertEqual(output.feature[0].name, "default_compile_flags")
|
||||
self.assertEqual(output.feature[1].name, "default_link_flags")
|
||||
|
||||
# flag set for compiler_flag fields
|
||||
self.assertEqual(len(output.feature[0].flag_set[0].with_feature), 0)
|
||||
self.assertEqual(output.feature[0].flag_set[0].flag_group[0].flag,
|
||||
["compile-flag-1"])
|
||||
|
||||
# flag set for cxx_flag fields
|
||||
self.assertEqual(len(output.feature[0].flag_set[1].with_feature), 0)
|
||||
self.assertEqual(output.feature[0].flag_set[1].flag_group[0].flag,
|
||||
["cxx-flag-1"])
|
||||
|
||||
# flag set for compiler_flag from compilation_mode_flags
|
||||
self.assertEqual(len(output.feature[0].flag_set[2].with_feature), 1)
|
||||
self.assertEqual(output.feature[0].flag_set[2].with_feature[0].feature[0],
|
||||
"opt")
|
||||
self.assertEqual(output.feature[0].flag_set[2].flag_group[0].flag,
|
||||
["opt-flag-1"])
|
||||
|
||||
# flag set for cxx_flag from compilation_mode_flags
|
||||
self.assertEqual(len(output.feature[0].flag_set[3].with_feature), 1)
|
||||
self.assertEqual(output.feature[0].flag_set[3].with_feature[0].feature[0],
|
||||
"opt")
|
||||
self.assertEqual(output.feature[0].flag_set[3].flag_group[0].flag,
|
||||
["opt-flag-2"])
|
||||
|
||||
# default_link_flags, flag set for linker_flag
|
||||
self.assertEqual(len(output.feature[1].flag_set[0].with_feature), 0)
|
||||
self.assertEqual(output.feature[1].flag_set[0].flag_group[0].flag,
|
||||
["linker-flag-1"])
|
||||
|
||||
# default_link_flags, flag set for linker_flag from
|
||||
# compilation_mode_flags
|
||||
self.assertEqual(len(output.feature[1].flag_set[1].with_feature), 1)
|
||||
self.assertEqual(output.feature[1].flag_set[1].with_feature[0].feature[0],
|
||||
"opt")
|
||||
self.assertEqual(output.feature[1].flag_set[1].flag_group[0].flag,
|
||||
["opt-flag-3"])
|
||||
|
||||
def test_linking_mode_flags(self):
|
||||
crosstool = make_crosstool("""
|
||||
linker_flag: "linker-flag-1"
|
||||
compilation_mode_flags {
|
||||
mode: DBG
|
||||
linker_flag: "dbg-flag-1"
|
||||
}
|
||||
linking_mode_flags {
|
||||
mode: MOSTLY_STATIC
|
||||
linker_flag: "mostly-static-flag-1"
|
||||
}
|
||||
""")
|
||||
migrate_legacy_fields(crosstool)
|
||||
output = crosstool.toolchain[0]
|
||||
self.assertEqual(len(output.compilation_mode_flags), 0)
|
||||
self.assertEqual(len(output.linking_mode_flags), 0)
|
||||
|
||||
# flag set for linker_flag
|
||||
self.assertEqual(len(output.feature[0].flag_set[0].with_feature), 0)
|
||||
self.assertEqual(output.feature[0].flag_set[0].flag_group[0].flag,
|
||||
["linker-flag-1"])
|
||||
|
||||
# flag set for compilation_mode_flags
|
||||
self.assertEqual(len(output.feature[0].flag_set[1].with_feature), 1)
|
||||
self.assertEqual(output.feature[0].flag_set[1].with_feature[0].feature[0],
|
||||
"dbg")
|
||||
self.assertEqual(output.feature[0].flag_set[1].flag_group[0].flag,
|
||||
["dbg-flag-1"])
|
||||
|
||||
# flag set for linking_mode_flags
|
||||
self.assertEqual(len(output.feature[0].flag_set[2].with_feature), 1)
|
||||
self.assertEqual(output.feature[0].flag_set[2].with_feature[0].feature[0],
|
||||
"static_linking_mode")
|
||||
self.assertEqual(output.feature[0].flag_set[2].flag_group[0].flag,
|
||||
["mostly-static-flag-1"])
|
||||
|
||||
def test_coverage_compilation_mode_ignored(self):
|
||||
crosstool = make_crosstool("""
|
||||
compilation_mode_flags {
|
||||
mode: COVERAGE
|
||||
compiler_flag: "coverage-flag-1"
|
||||
cxx_flag: "coverage-flag-2"
|
||||
linker_flag: "coverage-flag-3"
|
||||
}
|
||||
""")
|
||||
output = migrate_to_string(crosstool)
|
||||
self.assertNotIn("compilation_mode_flags", output)
|
||||
self.assertNotIn("coverage-flag-1", output)
|
||||
self.assertNotIn("coverage-flag-2", output)
|
||||
self.assertNotIn("coverage-flag-3", output)
|
||||
self.assertNotIn("COVERAGE", output)
|
||||
|
||||
def test_dynamic_linking_mode_is_added_even_when_empty(self):
|
||||
crosstool = make_crosstool("""
|
||||
linking_mode_flags {
|
||||
mode: DYNAMIC
|
||||
}
|
||||
""")
|
||||
output = migrate_to_string(crosstool)
|
||||
self.assertNotIn("linking_mode_flags", output)
|
||||
self.assertNotIn("DYNAMIC", output)
|
||||
self.assertIn("name: \"dynamic_linking_mode\"", output)
|
||||
|
||||
def test_linking_mode_features_are_not_added_when_present(self):
|
||||
crosstool = make_crosstool("""
|
||||
linking_mode_flags {
|
||||
mode: DYNAMIC
|
||||
linker_flag: 'dynamic-flag'
|
||||
}
|
||||
linking_mode_flags {
|
||||
mode: FULLY_STATIC
|
||||
linker_flag: 'fully-static-flag'
|
||||
}
|
||||
linking_mode_flags {
|
||||
mode: MOSTLY_STATIC
|
||||
linker_flag: 'mostly-static-flag'
|
||||
}
|
||||
linking_mode_flags {
|
||||
mode: MOSTLY_STATIC_LIBRARIES
|
||||
linker_flag: 'mostly-static-libraries-flag'
|
||||
}
|
||||
feature { name: "static_linking_mode" }
|
||||
feature { name: "dynamic_linking_mode" }
|
||||
feature { name: "static_linking_mode_nodeps_library" }
|
||||
feature { name: "fully_static_link" }
|
||||
""")
|
||||
output = migrate_to_string(crosstool)
|
||||
self.assertNotIn("linking_mode_flags", output)
|
||||
self.assertNotIn("DYNAMIC", output)
|
||||
self.assertNotIn("MOSTLY_STATIC", output)
|
||||
self.assertNotIn("MOSTLY_STATIC_LIBRARIES", output)
|
||||
self.assertNotIn("MOSTLY_STATIC_LIBRARIES", output)
|
||||
self.assertNotIn("dynamic-flag", output)
|
||||
self.assertNotIn("fully-static-flag", output)
|
||||
self.assertNotIn("mostly-static-flag", output)
|
||||
self.assertNotIn("mostly-static-libraries-flag", output)
|
||||
|
||||
def test_unfiltered_compile_flags_is_not_added_when_already_present(self):
|
||||
crosstool = make_crosstool("""
|
||||
unfiltered_cxx_flag: 'unfiltered-flag-1'
|
||||
feature { name: 'something_else' }
|
||||
feature { name: 'unfiltered_compile_flags' }
|
||||
feature { name: 'something_else_2' }
|
||||
""")
|
||||
migrate_legacy_fields(crosstool)
|
||||
output = crosstool.toolchain[0]
|
||||
self.assertEqual(output.feature[0].name, "something_else")
|
||||
self.assertEqual(output.feature[1].name, "unfiltered_compile_flags")
|
||||
self.assertEqual(output.feature[1].flag_set[0].action, ALL_COMPILE_ACTIONS)
|
||||
self.assertEqual(output.feature[1].flag_set[0].flag_group[0].flag,
|
||||
["unfiltered-flag-1"])
|
||||
self.assertEqual(output.feature[2].name, "something_else_2")
|
||||
|
||||
def test_unfiltered_compile_flags_is_added_at_the_end(self):
|
||||
crosstool = make_crosstool("""
|
||||
feature { name: 'something_else' }
|
||||
unfiltered_cxx_flag: 'unfiltered-flag-1'
|
||||
""")
|
||||
migrate_legacy_fields(crosstool)
|
||||
output = crosstool.toolchain[0]
|
||||
self.assertEqual(output.feature[0].name, "something_else")
|
||||
self.assertEqual(output.feature[1].name, "unfiltered_compile_flags")
|
||||
self.assertEqual(output.feature[1].flag_set[0].action, ALL_COMPILE_ACTIONS)
|
||||
self.assertEqual(output.feature[1].flag_set[0].flag_group[0].flag,
|
||||
["unfiltered-flag-1"])
|
||||
|
||||
def test_default_link_flags_is_added_first(self):
|
||||
crosstool = make_crosstool("""
|
||||
linker_flag: 'linker-flag-1'
|
||||
feature { name: 'something_else' }
|
||||
""")
|
||||
migrate_legacy_fields(crosstool)
|
||||
output = crosstool.toolchain[0]
|
||||
self.assertEqual(output.feature[0].name, "default_link_flags")
|
||||
self.assertEqual(output.feature[0].enabled, True)
|
||||
self.assertEqual(output.feature[0].flag_set[0].flag_group[0].flag,
|
||||
["linker-flag-1"])
|
||||
|
||||
def test_default_link_flags_is_not_added_when_already_present(self):
|
||||
crosstool = make_crosstool("""
|
||||
linker_flag: 'linker-flag-1'
|
||||
feature { name: 'something_else' }
|
||||
feature { name: 'default_link_flags' }
|
||||
""")
|
||||
migrate_legacy_fields(crosstool)
|
||||
output = crosstool.toolchain[0]
|
||||
self.assertEqual(output.feature[0].name, "something_else")
|
||||
self.assertEqual(output.feature[1].name, "default_link_flags")
|
||||
|
||||
def test_default_compile_flags_is_not_added_when_no_reason_to(self):
|
||||
crosstool = make_crosstool("""
|
||||
feature { name: 'something_else' }
|
||||
""")
|
||||
migrate_legacy_fields(crosstool)
|
||||
output = crosstool.toolchain[0]
|
||||
self.assertEqual(output.feature[0].name, "something_else")
|
||||
self.assertEqual(len(output.feature), 1)
|
||||
|
||||
def test_default_compile_flags_is_first(self):
|
||||
crosstool = make_crosstool("""
|
||||
compiler_flag: 'compiler-flag-1'
|
||||
feature { name: 'something_else' }
|
||||
""")
|
||||
migrate_legacy_fields(crosstool)
|
||||
output = crosstool.toolchain[0]
|
||||
self.assertEqual(output.feature[0].name, "default_compile_flags")
|
||||
self.assertEqual(output.feature[0].enabled, True)
|
||||
self.assertEqual(output.feature[0].flag_set[0].flag_group[0].flag,
|
||||
["compiler-flag-1"])
|
||||
|
||||
def test_default_compile_flags_not_added_when_present(self):
|
||||
crosstool = make_crosstool("""
|
||||
compiler_flag: 'compiler-flag-1'
|
||||
feature { name: 'something_else' }
|
||||
feature { name: 'default_compile_flags' }
|
||||
""")
|
||||
migrate_legacy_fields(crosstool)
|
||||
output = crosstool.toolchain[0]
|
||||
self.assertEqual(output.feature[0].name, "something_else")
|
||||
self.assertEqual(output.feature[1].name, "default_compile_flags")
|
||||
self.assertEqual(len(output.feature[1].flag_set), 0)
|
||||
|
||||
def test_migrate_expand_if_all_available_from_flag_sets(self):
|
||||
crosstool = make_crosstool("""
|
||||
action_config {
|
||||
action_name: 'something'
|
||||
config_name: 'something'
|
||||
flag_set {
|
||||
expand_if_all_available: 'foo'
|
||||
flag_group {
|
||||
flag: '%{foo}'
|
||||
}
|
||||
flag_group {
|
||||
expand_if_all_available: 'bar'
|
||||
flag: 'bar'
|
||||
}
|
||||
}
|
||||
}
|
||||
feature {
|
||||
name: 'something_else'
|
||||
flag_set {
|
||||
action: 'c-compile'
|
||||
expand_if_all_available: 'foo'
|
||||
flag_group {
|
||||
flag: '%{foo}'
|
||||
}
|
||||
flag_group {
|
||||
expand_if_all_available: 'bar'
|
||||
flag: 'bar'
|
||||
}
|
||||
}
|
||||
}
|
||||
""")
|
||||
migrate_legacy_fields(crosstool)
|
||||
output = crosstool.toolchain[0]
|
||||
self.assertEqual(output.action_config[0].action_name, "something")
|
||||
self.assertEqual(len(output.action_config[0].flag_set), 1)
|
||||
self.assertEqual(
|
||||
len(output.action_config[0].flag_set[0].expand_if_all_available), 0)
|
||||
self.assertEqual(len(output.action_config[0].flag_set[0].flag_group), 2)
|
||||
self.assertEqual(
|
||||
output.action_config[0].flag_set[0].flag_group[0]
|
||||
.expand_if_all_available, ["foo"])
|
||||
self.assertEqual(
|
||||
output.action_config[0].flag_set[0].flag_group[1]
|
||||
.expand_if_all_available, ["bar", "foo"])
|
||||
|
||||
self.assertEqual(output.feature[0].name, "something_else")
|
||||
self.assertEqual(len(output.feature[0].flag_set), 1)
|
||||
self.assertEqual(
|
||||
len(output.feature[0].flag_set[0].expand_if_all_available), 0)
|
||||
self.assertEqual(len(output.feature[0].flag_set[0].flag_group), 2)
|
||||
self.assertEqual(
|
||||
output.feature[0].flag_set[0].flag_group[0].expand_if_all_available,
|
||||
["foo"])
|
||||
self.assertEqual(
|
||||
output.feature[0].flag_set[0].flag_group[1].expand_if_all_available,
|
||||
["bar", "foo"])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
|
@ -0,0 +1,53 @@
|
|||
"""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
|
||||
|
||||
flags.DEFINE_string("input", None, "Input CROSSTOOL file to be migrated")
|
||||
flags.DEFINE_string("output", None,
|
||||
"Output path where to write migrated CROSSTOOL.")
|
||||
|
||||
|
||||
def main(unused_argv):
|
||||
crosstool = crosstool_config_pb2.CrosstoolRelease()
|
||||
|
||||
input_filename = flags.FLAGS.input
|
||||
output_filename = flags.FLAGS.output
|
||||
|
||||
if not input_filename:
|
||||
raise app.UsageError("ERROR input unspecified")
|
||||
if not output_filename:
|
||||
raise app.UsageError("ERROR output unspecified")
|
||||
|
||||
f = open(input_filename, "r")
|
||||
input_text = f.read()
|
||||
text_format.Merge(input_text, crosstool)
|
||||
f.close()
|
||||
|
||||
output_text = migrate_legacy_fields(crosstool)
|
||||
|
||||
f = open(output_filename, "w")
|
||||
output_text = text_format.MessageToString(crosstool)
|
||||
f.write(output_text)
|
||||
f.close()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
app.run(main)
|
Loading…
Reference in New Issue