bp2build: check in cc_library rules and unit test.
This change adds the Starlark code used by the bp2build-generated
targets for cc_library related types.
It also adds a sh_test unit test that analyzes the runfiles outputs of a
full cc_library generated by bp2build, starting with ld-android. It
analyzes that the shared and static libraries are of the right
filetypes, and that the shared library exports an expected set of
symbols.
This CL checks in cc_shared_library from rules_cc HEAD, without any
local changes for Roboleaf.
Test: TH
Test: bp2build, bazel test //build/bazel/tests/...
Change-Id: I4deb3fc3160e393b03b4bd550777146d6cad6de8
diff --git a/rules/cc_include_helpers.bzl b/rules/cc_include_helpers.bzl
index 07e1524..5d4f051 100644
--- a/rules/cc_include_helpers.bzl
+++ b/rules/cc_include_helpers.bzl
@@ -32,16 +32,3 @@
)
return include_deps
-
-def hdr_globs_for_srcs(srcs):
- """Return globs for headers in the directories matching the given srcs.
-
- This simulates hdrs_check = 'loose' by allowing src files to reference headers
- directly in the directories they are in."""
- globs = {}
- for src in srcs:
- dir_name = src.split("/")[:-1]
- dir_name += ["*.h"]
- dir_glob = "/".join(dir_name)
- globs[dir_glob] = True
- return native.glob(globs.keys())
diff --git a/rules/cc_library_static.bzl b/rules/cc_library_static.bzl
index 8ddd72a..8999863 100644
--- a/rules/cc_library_static.bzl
+++ b/rules/cc_library_static.bzl
@@ -1,10 +1,11 @@
-load("//build/bazel/rules:cc_include_helpers.bzl", "cc_library_header_suite", "hdr_globs_for_srcs")
+load("//build/bazel/rules:cc_include_helpers.bzl", "cc_library_header_suite")
load("@rules_cc//cc:find_cc_toolchain.bzl", "find_cpp_toolchain")
def cc_library_static(
name,
srcs = [],
deps = [],
+ hdrs = [],
copts = [],
includes = [],
local_include_dirs = [],
@@ -16,8 +17,6 @@
# combine deps and include deps
all_deps = deps + include_deps
- hdrs = hdr_globs_for_srcs(srcs)
-
mainlib_name = "%s_mainlib" % name
# Silently drop these attributes for now:
diff --git a/rules/cc_object.bzl b/rules/cc_object.bzl
index 6b7c656..cf60645 100644
--- a/rules/cc_object.bzl
+++ b/rules/cc_object.bzl
@@ -1,4 +1,4 @@
-load("//build/bazel/rules:cc_include_helpers.bzl", "cc_library_header_suite", "hdr_globs_for_srcs")
+load("//build/bazel/rules:cc_include_helpers.bzl", "cc_library_header_suite")
load("@rules_cc//cc:find_cc_toolchain.bzl", "find_cpp_toolchain")
# "cc_object" module copts, taken from build/soong/cc/object.go
@@ -105,6 +105,7 @@
def cc_object(
name,
copts = [],
+ hdrs = [],
asflags = [],
local_include_dirs = [],
srcs = [],
@@ -115,8 +116,6 @@
include_deps = cc_library_header_suite(local_include_dirs)
- hdrs = hdr_globs_for_srcs(srcs)
-
_cc_object(
name = name,
hdrs = hdrs,
diff --git a/rules/full_cc_library.bzl b/rules/full_cc_library.bzl
new file mode 100644
index 0000000..42cefba
--- /dev/null
+++ b/rules/full_cc_library.bzl
@@ -0,0 +1,63 @@
+load(":cc_library_static.bzl", "cc_library_static")
+load("@rules_cc//examples:experimental_cc_shared_library.bzl", "cc_shared_library", "CcSharedLibraryInfo")
+
+def cc_library(
+ name,
+ srcs = [],
+ hdrs = [],
+ deps = [],
+ transitive_export_deps = [],
+ user_link_flags = [],
+ copts = [],
+ linkopts = [],
+ **kwargs):
+ static_name = name + "_static"
+ shared_name = name + "_shared"
+ _cc_library_proxy(name = name,
+ static = static_name,
+ shared = shared_name)
+
+ cc_library_static(
+ name = static_name,
+ hdrs = hdrs,
+ srcs = srcs,
+ copts = copts,
+ linkopts = linkopts,
+ deps = deps,
+ )
+
+ cc_shared_library(
+ name = shared_name,
+ user_link_flags = user_link_flags,
+ # b/184806113: Note this is a pretty a workaround so users don't have to
+ # declare all transitive static deps used by this target. It'd be great
+ # if a shared library could declare a transitive exported static dep
+ # instead of needing to declare each target transitively.
+ static_deps = ["//:__subpackages__"],
+ roots = [static_name + "_mainlib"],
+ )
+
+
+def _cc_library_proxy_impl(ctx):
+ static_files = ctx.attr.static[DefaultInfo].files.to_list()
+ shared_files = ctx.attr.shared[DefaultInfo].files.to_list()
+
+ files = static_files + shared_files
+
+ return [
+ ctx.attr.shared[CcSharedLibraryInfo],
+ ctx.attr.static[CcInfo],
+ DefaultInfo(
+ files = depset(direct = files),
+ runfiles = ctx.runfiles(files = files),
+ )
+ ]
+
+_cc_library_proxy = rule(
+ implementation = _cc_library_proxy_impl,
+ attrs = {
+ "shared": attr.label(mandatory = True, providers = [CcSharedLibraryInfo]),
+ "static": attr.label(mandatory = True, providers = [CcInfo]),
+ },
+)
+
diff --git a/rules_cc/cc/BUILD b/rules_cc/cc/BUILD
index beb0baa..9a4b067 100644
--- a/rules_cc/cc/BUILD
+++ b/rules_cc/cc/BUILD
@@ -1,2 +1,6 @@
# Divergence from rules_cc: Use a stub BUILD file, as there are reduced
# dependencies in this fork.
+alias(
+ name = "toolchain_type",
+ actual = "@bazel_tools//tools/cpp:toolchain_type",
+)
diff --git a/rules_cc/examples/BUILD b/rules_cc/examples/BUILD
index c770074..c7da75d 100644
--- a/rules_cc/examples/BUILD
+++ b/rules_cc/examples/BUILD
@@ -25,6 +25,12 @@
)
bool_flag(
+ name = "enable_permissions_check",
+ build_setting_default = False,
+ visibility = ["//visibility:public"],
+)
+
+bool_flag(
name = "experimental_debug",
build_setting_default = False,
visibility = ["//visibility:public"],
diff --git a/rules_cc/examples/experimental_cc_shared_library.bzl b/rules_cc/examples/experimental_cc_shared_library.bzl
index 44d8c01..905bd27 100644
--- a/rules_cc/examples/experimental_cc_shared_library.bzl
+++ b/rules_cc/examples/experimental_cc_shared_library.bzl
@@ -109,7 +109,7 @@
if export in exports_map:
fail("Two shared libraries in dependencies export the same symbols. Both " +
exports_map[export].libraries[0].dynamic_library.short_path +
- " and " + linker_input.dynamic_library.short_path +
+ " and " + linker_input.libraries[0].dynamic_library.short_path +
" export " + export)
exports_map[export] = linker_input
return exports_map
@@ -162,9 +162,20 @@
return pattern.package == value.package and pattern.name == value.name
def _check_if_target_can_be_exported(target, current_label, permissions):
- # Divergence from rules_cc: Ignore permissions, as it does not fit the model of AOSP.
- # TODO(cparsons): Push an upstream change to disable permissions checking with a flag.
- return True
+ if permissions == None:
+ return True
+
+ if (target.workspace_name != current_label.workspace_name or
+ _same_package_or_above(current_label, target)):
+ return True
+
+ matched_by_target = False
+ for permission in permissions:
+ for permission_target in permission[CcSharedLibraryPermissionsInfo].targets:
+ if _check_if_target_under_path(target, permission_target):
+ return True
+
+ return False
def _check_if_target_should_be_exported_without_filter(target, current_label, permissions):
return _check_if_target_should_be_exported_with_filter(target, current_label, None, permissions)
@@ -263,7 +274,7 @@
linker_input.owner,
ctx.label,
ctx.attr.exports_filter,
- ctx.attr.permissions,
+ _get_permissions(ctx),
):
exports[owner] = True
can_be_linked_statically = True
@@ -293,6 +304,11 @@
return True
+def _get_permissions(ctx):
+ if ctx.attr._enable_permissions_check[BuildSettingInfo].value:
+ return ctx.attr.permissions
+ return None
+
def _cc_shared_library_impl(ctx):
cc_common.check_experimental_cc_shared_library()
cc_toolchain = find_cc_toolchain(ctx)
@@ -310,7 +326,7 @@
fail("Trying to export a library already exported by a different shared library: " +
str(export.label))
- _check_if_target_should_be_exported_without_filter(export.label, ctx.label, ctx.attr.permissions)
+ _check_if_target_should_be_exported_without_filter(export.label, ctx.label, _get_permissions(ctx))
preloaded_deps_direct_labels = {}
preloaded_dep_merged_cc_info = None
@@ -449,11 +465,13 @@
"static_deps": attr.string_list(),
"user_link_flags": attr.string_list(),
"_cc_toolchain": attr.label(default = "@bazel_tools//tools/cpp:current_cc_toolchain"),
+ "_enable_permissions_check": attr.label(default = "//examples:enable_permissions_check"),
"_experimental_debug": attr.label(default = "//examples:experimental_debug"),
"_incompatible_link_once": attr.label(default = "//examples:incompatible_link_once"),
},
- toolchains = ["@rules_cc//cc:toolchain_type"], # copybara-use-repo-external-label
+ toolchains = ["@bazel_tools//tools/cpp:toolchain_type"], # copybara-use-repo-external-label
fragments = ["cpp"],
+ incompatible_use_toolchain_transition = True,
)
for_testing_dont_use_check_if_target_under_path = _check_if_target_under_path
diff --git a/tests/bionic/BUILD b/tests/bionic/BUILD
new file mode 100644
index 0000000..b2a04fd
--- /dev/null
+++ b/tests/bionic/BUILD
@@ -0,0 +1,10 @@
+# This test requires bp2build to run and the generated BUILD files in the source tree.
+sh_test(
+ name = "verify_bionic_outputs",
+ srcs = ["verify_bionic_outputs.sh"],
+ data = [
+ "//bionic/linker:ld-android",
+ "//bionic/libdl:libdl_android",
+ ],
+ deps = ["@bazel_tools//tools/bash/runfiles"],
+)
diff --git a/tests/bionic/verify_bionic_outputs.sh b/tests/bionic/verify_bionic_outputs.sh
new file mode 100755
index 0000000..df22b47
--- /dev/null
+++ b/tests/bionic/verify_bionic_outputs.sh
@@ -0,0 +1,119 @@
+#!/usr/bin/bash
+#
+# Copyright 2021 Google Inc. 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.
+
+set -euo pipefail
+
+source "${RUNFILES_DIR}/bazel_tools/tools/bash/runfiles/runfiles.bash"
+
+# This should be abstracted to a unit-test library when it has more uses.
+function assert_contains_regex() {
+ local needle="$1"
+ local haystack="$2"
+ local message="${3:-Expected regexp "$needle" not found in "$haystack"}"
+ echo "${haystack}" | grep "${needle}" && return 0
+
+ echo "$message"
+ exit 1
+}
+
+# Test that a library is the expected filetype.
+function test_filetype() {
+ local filepath="$(readlink -f $1)"; shift
+ local regex="$1"; shift
+ local file_output="$(file ${filepath})"
+ assert_contains_regex "${regex}" "${file_output}"
+}
+
+# Test that the shared library contains a symbol
+function test_shared_library_symbols() {
+ local filepath="$(readlink -f $1)"; shift
+ local symbols="$1"; shift
+ local nm_output="$(nm -D "${filepath}")"
+ for symbol in "${symbols[@]}"
+ do
+ assert_contains_regex "${symbol}" "${nm_output}"
+ done
+}
+
+# Test file contents of //bionic/linker:ld-android
+function test_ld-android() {
+ local shared_library="$(rlocation __main__/bionic/linker/libld-android_shared.so)"
+ local static_library="$(rlocation __main__/bionic/linker/libld-android_static_mainlib.a)"
+
+ test_filetype "${shared_library}" "shared object.*dynamically linked"
+ test_filetype "${static_library}" "current ar archive"
+
+ symbols=(
+ __internal_linker_error
+ __loader_add_thread_local_dtor
+ __loader_android_create_namespace
+ __loader_android_dlopen_ext
+ __loader_android_dlwarning
+ __loader_android_get_application_target_sdk_version
+ __loader_android_get_exported_namespace
+ __loader_android_get_LD_LIBRARY_PATH
+ __loader_android_init_anonymous_namespace
+ __loader_android_link_namespaces
+ __loader_android_link_namespaces_all_libs
+ __loader_android_set_application_target_sdk_version
+ __loader_android_update_LD_LIBRARY_PATH
+ __loader_cfi_fail
+ __loader_dladdr
+ __loader_dlclose
+ __loader_dlerror
+ __loader_dl_iterate_phdr
+ __loader_dlopen
+ __loader_dlsym
+ __loader_dlvsym
+ __loader_remove_thread_local_dtor
+ __loader_shared_globals
+ _db_dlactivity
+ )
+
+ test_shared_library_symbols "${shared_library}" "${symbols}"
+}
+
+function test_libdl_android() {
+ local shared_library="$(rlocation __main__/bionic/libdl/liblibdl_android_shared.so)"
+ local static_library="$(rlocation __main__/bionic/libdl/liblibdl_android_static_mainlib.a)"
+
+ test_filetype "${shared_library}" "shared object.*dynamically linked"
+ test_filetype "${static_library}" "current ar archive"
+
+ symbols=(
+ android_create_namespace
+ android_dlwarning
+ android_get_exported_namespace
+ android_get_LD_LIBRARY_PATH
+ android_init_anonymous_namespace
+ android_link_namespaces
+ android_set_application_target_sdk_version
+ android_update_LD_LIBRARY_PATH
+ __loader_android_create_namespace
+ __loader_android_dlwarning
+ __loader_android_get_exported_namespace
+ __loader_android_get_LD_LIBRARY_PATH
+ __loader_android_init_anonymous_namespace
+ __loader_android_link_namespaces
+ __loader_android_set_application_target_sdk_version
+ __loader_android_update_LD_LIBRARY_PATH
+ )
+
+ test_shared_library_symbols "${shared_library}" "${symbols}"
+}
+
+test_ld-android
+test_libdl_android