blob: d57aedfefa49e348b3a773076bc8db997020f75e [file] [log] [blame]
"""
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_library_shared.bzl", "cc_library_shared")
load("//build/bazel/rules/cc:cc_library_static.bzl", "cc_library_static")
load("//build/bazel/rules/cc:cc_library_headers.bzl", "cc_library_headers")
load("//build/bazel/rules/cc:cc_prebuilt_library_static.bzl", "cc_prebuilt_library_static")
load("//build/bazel/rules/cc:cc_binary.bzl", "cc_binary")
load(":cc_library_common_test.bzl", "target_provides_androidmk_info_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")
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_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()
),
)