unplugged-system/build/bazel/rules/cc/cc_library_static_test.bzl

603 lines
20 KiB
Python

# Copyright (C) 2022 The Android Open Source Project
#
# 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//lib:paths.bzl", "paths")
load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts")
load("//build/bazel/rules/cc:cc_binary.bzl", "cc_binary")
load("//build/bazel/rules/cc:cc_library_headers.bzl", "cc_library_headers")
load("//build/bazel/rules/cc:cc_library_shared.bzl", "cc_library_shared")
load("//build/bazel/rules/cc:cc_library_static.bzl", "cc_library_static")
load("//build/bazel/rules/cc:cc_prebuilt_library_static.bzl", "cc_prebuilt_library_static")
load(
"//build/bazel/rules/test_common:flags.bzl",
"action_flags_absent_for_mnemonic_test",
"action_flags_present_only_for_mnemonic_test",
)
load("//build/bazel/rules/test_common:paths.bzl", "get_output_and_package_dir_based_path", "get_package_dir_based_path")
load("//build/bazel/rules/test_common:rules.bzl", "expect_failure_test")
load(":cc_library_common_test.bzl", "target_provides_androidmk_info_test")
def _cc_library_static_propagating_compilation_context_test_impl(ctx):
env = analysistest.begin(ctx)
target = analysistest.target_under_test(env)
cc_info = target[CcInfo]
compilation_context = cc_info.compilation_context
header_paths = [f.path for f in compilation_context.headers.to_list()]
for hdr in ctx.files.expected_hdrs:
asserts.true(
env,
hdr.path in header_paths,
"Did not find {hdr} in includes: {hdrs}.".format(hdr = hdr, hdrs = compilation_context.headers),
)
for hdr in ctx.files.expected_absent_hdrs:
asserts.true(
env,
hdr not in header_paths,
"Found {hdr} in includes: {hdrs}, should not be present.".format(hdr = hdr, hdrs = compilation_context.headers),
)
for include in ctx.attr.expected_includes:
absolute_include = get_package_dir_based_path(env, include)
asserts.true(
env,
absolute_include in compilation_context.includes.to_list(),
"Did not find {include} in includes: {includes}.".format(include = include, includes = compilation_context.includes),
)
for include in ctx.attr.expected_absent_includes:
absolute_include = get_package_dir_based_path(env, include)
asserts.true(
env,
absolute_include not in compilation_context.includes.to_list(),
"Found {include} in includes: {includes}, was expected to be absent".format(include = include, includes = compilation_context.includes),
)
for include in ctx.attr.expected_system_includes:
absolute_include = get_package_dir_based_path(env, include)
asserts.true(
env,
absolute_include in compilation_context.system_includes.to_list(),
"Did not find {include} in system includes: {includes}.".format(include = include, includes = compilation_context.system_includes),
)
for include in ctx.attr.expected_absent_system_includes:
absolute_include = get_package_dir_based_path(env, include)
asserts.true(
env,
absolute_include not in compilation_context.system_includes.to_list(),
"Found {include} in system includes: {includes}, was expected to be absent".format(include = include, includes = compilation_context.system_includes),
)
return analysistest.end(env)
_cc_library_static_propagating_compilation_context_test = analysistest.make(
_cc_library_static_propagating_compilation_context_test_impl,
attrs = {
"expected_hdrs": attr.label_list(),
"expected_absent_hdrs": attr.label_list(),
"expected_includes": attr.string_list(),
"expected_absent_includes": attr.string_list(),
"expected_system_includes": attr.string_list(),
"expected_absent_system_includes": attr.string_list(),
},
)
def _cc_library_static_propagates_deps():
name = "_cc_library_static_propagates_deps"
dep_name = name + "_dep"
test_name = name + "_test"
cc_library_static(
name = dep_name,
hdrs = [":hdr"],
export_includes = ["a/b/c"],
export_system_includes = ["d/e/f"],
tags = ["manual"],
)
cc_library_static(
name = name,
deps = [dep_name],
tags = ["manual"],
)
_cc_library_static_propagating_compilation_context_test(
name = test_name,
target_under_test = name,
expected_hdrs = [":hdr"],
expected_includes = ["a/b/c"],
expected_system_includes = ["d/e/f"],
)
return test_name
def _cc_library_static_propagates_whole_archive_deps():
name = "_cc_library_static_propagates_whole_archive_deps"
dep_name = name + "_dep"
test_name = name + "_test"
cc_library_static(
name = dep_name,
hdrs = [":hdr"],
export_includes = ["a/b/c"],
export_system_includes = ["d/e/f"],
tags = ["manual"],
)
cc_library_static(
name = name,
whole_archive_deps = [dep_name],
tags = ["manual"],
)
_cc_library_static_propagating_compilation_context_test(
name = test_name,
target_under_test = name,
expected_hdrs = [":hdr"],
expected_includes = ["a/b/c"],
expected_system_includes = ["d/e/f"],
)
return test_name
def _cc_library_static_propagates_dynamic_deps():
name = "_cc_library_static_propagates_dynamic_deps"
dep_name = name + "_dep"
test_name = name + "_test"
cc_library_shared(
name = dep_name,
hdrs = [":hdr"],
export_includes = ["a/b/c"],
export_system_includes = ["d/e/f"],
tags = ["manual"],
)
cc_library_static(
name = name,
dynamic_deps = [dep_name],
tags = ["manual"],
)
_cc_library_static_propagating_compilation_context_test(
name = test_name,
target_under_test = name,
expected_hdrs = [":hdr"],
expected_includes = ["a/b/c"],
expected_system_includes = ["d/e/f"],
)
return test_name
def _cc_library_static_does_not_propagate_implementation_deps():
name = "_cc_library_static_does_not_propagate_implementation_deps"
dep_name = name + "_dep"
test_name = name + "_test"
cc_library_static(
name = dep_name,
hdrs = [":hdr"],
export_includes = ["a/b/c"],
export_system_includes = ["d/e/f"],
tags = ["manual"],
)
cc_library_static(
name = name,
implementation_deps = [dep_name],
tags = ["manual"],
)
_cc_library_static_propagating_compilation_context_test(
name = test_name,
target_under_test = name,
expected_absent_hdrs = [":hdr"],
expected_absent_includes = ["a/b/c"],
expected_absent_system_includes = ["d/e/f"],
)
return test_name
def _cc_library_static_does_not_propagate_implementation_whole_archive_deps():
name = "_cc_library_static_does_not_propagate_implementation_whole_archive_deps"
dep_name = name + "_dep"
test_name = name + "_test"
cc_library_static(
name = dep_name,
hdrs = [":hdr"],
export_includes = ["a/b/c"],
export_system_includes = ["d/e/f"],
tags = ["manual"],
)
cc_library_static(
name = name,
implementation_whole_archive_deps = [dep_name],
tags = ["manual"],
)
_cc_library_static_propagating_compilation_context_test(
name = test_name,
target_under_test = name,
expected_absent_hdrs = [":hdr"],
expected_absent_includes = ["a/b/c"],
expected_absent_system_includes = ["d/e/f"],
)
return test_name
def _cc_library_static_does_not_propagate_implementation_dynamic_deps():
name = "_cc_library_static_does_not_propagate_implementation_dynamic_deps"
dep_name = name + "_dep"
test_name = name + "_test"
cc_library_shared(
name = dep_name,
hdrs = [":hdr"],
export_includes = ["a/b/c"],
export_system_includes = ["d/e/f"],
tags = ["manual"],
)
cc_library_static(
name = name,
implementation_dynamic_deps = [dep_name],
tags = ["manual"],
)
_cc_library_static_propagating_compilation_context_test(
name = test_name,
target_under_test = name,
expected_absent_hdrs = [":hdr"],
expected_absent_includes = ["a/b/c"],
expected_absent_system_includes = ["d/e/f"],
)
return test_name
def _cc_rules_do_not_allow_absolute_includes():
name = "cc_rules_do_not_allow_absolute_includes"
test_names = []
DISALLOWED_INCLUDE_DIRS = [
"art",
"art/libnativebridge",
"art/libnativeloader",
"libcore",
"libnativehelper",
"external/apache-harmony",
"external/apache-xml",
"external/boringssl",
"external/bouncycastle",
"external/conscrypt",
"external/icu",
"external/okhttp",
"external/vixl",
"external/wycheproof",
]
for include_dir in DISALLOWED_INCLUDE_DIRS:
binary_name = name + "_binary" + "_" + include_dir
library_headers_name = name + "_library_headers" + "_" + include_dir
library_shared_name = name + "_library_shared" + "_" + include_dir
library_static_name = name + "_library_static" + "_" + include_dir
cc_binary(
name = binary_name,
absolute_includes = [include_dir],
tags = ["manual"],
)
cc_library_headers(
name = library_headers_name,
absolute_includes = [include_dir],
tags = ["manual"],
)
cc_library_shared(
name = library_shared_name,
absolute_includes = [include_dir],
tags = ["manual"],
)
cc_library_static(
name = library_static_name,
absolute_includes = [include_dir],
tags = ["manual"],
)
for target in [
binary_name,
library_headers_name,
library_static_name,
library_shared_name,
]:
test_name = target + "_" + include_dir + "_test"
test_names.append(test_name)
expect_failure_test(
name = test_name,
target_under_test = target,
)
return test_names
def _cc_library_static_links_against_prebuilt_library_test_impl(ctx):
env = analysistest.begin(ctx)
actions = analysistest.target_actions(env)
asserts.equals(env, 2, len(actions), "Expected actions, got %s" % actions)
argv = actions[0].argv
expected_output_action1 = get_output_and_package_dir_based_path(env, "libcc_library_static_links_against_prebuilt_library_objs_only.a")
asserts.equals(env, 5, len(argv))
asserts.equals(env, "crsPD", argv[1])
asserts.equals(env, expected_output_action1, argv[2])
asserts.equals(env, get_output_and_package_dir_based_path(env, paths.join("_objs", "cc_library_static_links_against_prebuilt_library_cpp", "bar.o")), argv[3])
asserts.equals(env, "--format=gnu", argv[4])
argv = actions[1].argv
asserts.equals(env, 6, len(argv))
asserts.equals(env, "cqsL", argv[1])
asserts.equals(env, get_output_and_package_dir_based_path(env, "libcc_library_static_links_against_prebuilt_library.a"), argv[2])
asserts.equals(env, "--format=gnu", argv[3])
asserts.equals(env, expected_output_action1, argv[4])
asserts.equals(env, get_package_dir_based_path(env, "foo.a"), argv[5])
return analysistest.end(env)
_cc_library_static_links_against_prebuilt_library_test = analysistest.make(_cc_library_static_links_against_prebuilt_library_test_impl)
def _cc_library_static_links_against_prebuilt_library():
name = "cc_library_static_links_against_prebuilt_library"
test_name = name + "_test"
dep_name = name + "_dep"
cc_prebuilt_library_static(
name = dep_name,
static_library = "foo.a",
tags = ["manual"],
)
cc_library_static(
name = name,
srcs = ["bar.c"],
whole_archive_deps = [dep_name],
tags = ["manual"],
)
_cc_library_static_links_against_prebuilt_library_test(
name = test_name,
target_under_test = name,
)
return test_name
def _cc_library_static_linking_object_ordering_test_impl(ctx):
env = analysistest.begin(ctx)
actions = analysistest.target_actions(env)
asserts.equals(env, 1, len(actions), "Expected actions, got %s" % actions)
outputs = actions[0].outputs.to_list()
argv = actions[0].argv
asserts.equals(env, 4 + len(ctx.attr.expected_objects_in_order), len(argv))
asserts.equals(env, "crsPD", argv[1])
asserts.equals(env, outputs[0].path, argv[2])
for i in range(len(ctx.attr.expected_objects_in_order)):
obj = ctx.attr.expected_objects_in_order[i]
asserts.equals(env, obj, paths.basename(argv[3 + i]))
asserts.equals(env, "--format=gnu", argv[-1])
return analysistest.end(env)
_cc_library_static_linking_object_ordering_test = analysistest.make(
_cc_library_static_linking_object_ordering_test_impl,
attrs = {
"expected_objects_in_order": attr.string_list(),
},
)
def _cc_library_static_whole_archive_deps_objects_precede_target_objects():
name = "_cc_library_static_whole_archive_deps_objects_precede_target_objects"
dep_name = name + "_dep"
test_name = name + "_test"
cc_library_static(
name = dep_name,
srcs = ["first.c"],
tags = ["manual"],
)
cc_library_static(
name = name,
srcs = ["second.c"],
whole_archive_deps = [dep_name],
tags = ["manual"],
)
_cc_library_static_linking_object_ordering_test(
name = test_name,
target_under_test = name,
expected_objects_in_order = [
"first.o",
"second.o",
],
)
return test_name
def _cc_library_static_provides_androidmk_info():
name = "cc_library_static_provides_androidmk_info"
dep_name = name + "_static_dep"
whole_archive_dep_name = name + "_whole_archive_dep"
dynamic_dep_name = name + "_dynamic_dep"
test_name = name + "_test"
cc_library_static(
name = dep_name,
srcs = ["foo.c"],
tags = ["manual"],
)
cc_library_static(
name = whole_archive_dep_name,
srcs = ["foo.c"],
tags = ["manual"],
)
cc_library_shared(
name = dynamic_dep_name,
srcs = ["foo.c"],
tags = ["manual"],
)
cc_library_static(
name = name,
srcs = ["foo.cc"],
deps = [dep_name],
whole_archive_deps = [whole_archive_dep_name],
dynamic_deps = [dynamic_dep_name],
tags = ["manual"],
)
android_test_name = test_name + "_android"
linux_test_name = test_name + "_linux"
target_provides_androidmk_info_test(
name = android_test_name,
target_under_test = name,
expected_static_libs = [dep_name, "libc++_static", "libc++demangle"],
expected_whole_static_libs = [whole_archive_dep_name],
expected_shared_libs = [dynamic_dep_name, "libc", "libdl", "libm"],
target_compatible_with = ["//build/bazel/platforms/os:android"],
)
target_provides_androidmk_info_test(
name = linux_test_name,
target_under_test = name,
expected_static_libs = [dep_name, "libc++_static"],
expected_whole_static_libs = [whole_archive_dep_name],
expected_shared_libs = [dynamic_dep_name],
target_compatible_with = ["//build/bazel/platforms/os:linux"],
)
return [
android_test_name,
linux_test_name,
]
def _cc_library_static_link_action_should_not_have_arch_cflags():
name = "cc_library_static_link_action_should_not_have_cflags"
cpp_compile_test_name = name + "_CppCompile_test"
cpp_link_test_name = name + "_CppLink_test"
# https://cs.android.com/android/platform/build/soong/+/master:cc/config/arm_device.go;l=57-59;drc=de7c7847e7e028d46fdff8268689f30163c4c231
arm_armv7_a_cflags = ["-march=armv7-a", "-mfloat-abi=softfp"]
cc_library_static(
name = name,
srcs = ["foo.cpp"],
tags = ["manual"],
)
action_flags_present_only_for_mnemonic_test(
name = cpp_compile_test_name,
target_under_test = name + "_cpp",
mnemonics = ["CppCompile"],
expected_flags = arm_armv7_a_cflags,
target_compatible_with = [
"//build/bazel/platforms/os:android",
"//build/bazel/platforms/arch/variants:armv7-a-neon",
],
)
action_flags_absent_for_mnemonic_test(
name = cpp_link_test_name,
target_under_test = name,
mnemonics = ["CppLink"],
expected_absent_flags = arm_armv7_a_cflags,
target_compatible_with = [
"//build/bazel/platforms/os:android",
"//build/bazel/platforms/arch/variants:armv7-a-neon",
],
)
return [
cpp_compile_test_name,
cpp_link_test_name,
]
def _cc_library_static_defines_do_not_check_manual_binder_interfaces():
name = "_cc_library_static_defines_do_not_check_manual_binder_interfaces"
cpp_lib_name = name + "_cpp"
cpp_test_name = cpp_lib_name + "_test"
c_lib_name = name + "_c"
c_test_name = c_lib_name + "_test"
cc_library_static(
name = name,
srcs = ["a.cpp"],
srcs_c = ["b.c"],
tags = ["manual"],
)
action_flags_present_only_for_mnemonic_test(
name = cpp_test_name,
target_under_test = cpp_lib_name,
mnemonics = ["CppCompile"],
expected_flags = [
"-DDO_NOT_CHECK_MANUAL_BINDER_INTERFACES",
],
)
action_flags_present_only_for_mnemonic_test(
name = c_test_name,
target_under_test = c_lib_name,
mnemonics = ["CppCompile"],
expected_flags = [
"-DDO_NOT_CHECK_MANUAL_BINDER_INTERFACES",
],
)
non_allowlisted_package_cpp_name = name + "_non_allowlisted_package_cpp"
action_flags_absent_for_mnemonic_test(
name = non_allowlisted_package_cpp_name,
target_under_test = "//build/bazel/examples/cc:foo_static_cpp",
mnemonics = ["CppCompile"],
expected_absent_flags = [
"-DDO_NOT_CHECK_MANUAL_BINDER_INTERFACES",
],
)
return [
cpp_test_name,
c_test_name,
non_allowlisted_package_cpp_name,
]
def cc_library_static_test_suite(name):
native.genrule(name = "hdr", cmd = "null", outs = ["f.h"], tags = ["manual"])
native.test_suite(
name = name,
tests = [
_cc_library_static_propagates_deps(),
_cc_library_static_propagates_whole_archive_deps(),
_cc_library_static_propagates_dynamic_deps(),
_cc_library_static_does_not_propagate_implementation_deps(),
_cc_library_static_does_not_propagate_implementation_whole_archive_deps(),
_cc_library_static_does_not_propagate_implementation_dynamic_deps(),
_cc_library_static_links_against_prebuilt_library(),
_cc_library_static_whole_archive_deps_objects_precede_target_objects(),
] + (
_cc_rules_do_not_allow_absolute_includes() +
_cc_library_static_provides_androidmk_info() +
_cc_library_static_link_action_should_not_have_arch_cflags() +
_cc_library_static_defines_do_not_check_manual_binder_interfaces()
),
)