Skip to content

Commit

Permalink
Add support for bundling dylib deps from CcInfo (#2473)
Browse files Browse the repository at this point in the history
Fixes #2472

---------

Co-authored-by: Brentley Jones <[email protected]>
  • Loading branch information
gkoreman and brentleyjones committed Jun 25, 2024
1 parent 3c4111a commit 66de359
Show file tree
Hide file tree
Showing 12 changed files with 225 additions and 0 deletions.
1 change: 1 addition & 0 deletions apple/internal/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,7 @@ bzl_library(
"//apple/internal/partials:apple_bundle_info",
"//apple/internal/partials:apple_symbols_file",
"//apple/internal/partials:binary",
"//apple/internal/partials:cc_info_dylibs",
"//apple/internal/partials:clang_rt_dylibs",
"//apple/internal/partials:codesigning_dossier",
"//apple/internal/partials:debug_symbols",
Expand Down
3 changes: 3 additions & 0 deletions apple/internal/macos_rules.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,9 @@ def _macos_application_impl(ctx):
embeddable_targets = embedded_targets,
platform_prerequisites = platform_prerequisites,
),
partials.cc_info_dylibs_partial(
embedded_targets = embedded_targets,
),
partials.framework_import_partial(
actions = actions,
apple_mac_toolchain_info = apple_mac_toolchain_info,
Expand Down
5 changes: 5 additions & 0 deletions apple/internal/partials.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ load(
"@build_bazel_rules_apple//apple/internal/partials:embedded_bundles.bzl",
_embedded_bundles_partial = "embedded_bundles_partial",
)
load(
"@build_bazel_rules_apple//apple/internal/partials:cc_info_dylibs.bzl",
_cc_info_dylibs_partial = "cc_info_dylibs_partial",
)
load(
"@build_bazel_rules_apple//apple/internal/partials:extension_safe_validation.bzl",
_extension_safe_validation_partial = "extension_safe_validation_partial",
Expand Down Expand Up @@ -121,6 +125,7 @@ partials = struct(
codesigning_dossier_partial = _codesigning_dossier_partial,
debug_symbols_partial = _debug_symbols_partial,
embedded_bundles_partial = _embedded_bundles_partial,
cc_info_dylibs_partial = _cc_info_dylibs_partial,
extension_safe_validation_partial = _extension_safe_validation_partial,
framework_import_partial = _framework_import_partial,
framework_header_modulemap_partial = _framework_header_modulemap_partial,
Expand Down
14 changes: 14 additions & 0 deletions apple/internal/partials/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,20 @@ bzl_library(
],
)

bzl_library(
name = "cc_info_dylibs",
srcs = ["cc_info_dylibs.bzl"],
visibility = [
"//apple/internal:__pkg__",
],
deps = [
"//apple/internal:intermediates",
"//apple/internal:processor",
"@bazel_skylib//lib:partial",
"@build_bazel_apple_support//lib:apple_support",
],
)

bzl_library(
name = "clang_rt_dylibs",
srcs = ["clang_rt_dylibs.bzl"],
Expand Down
68 changes: 68 additions & 0 deletions apple/internal/partials/cc_info_dylibs.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# 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.

"""Partial implementation for gathering cc_info dylibs."""

load("@bazel_skylib//lib:partial.bzl", "partial")
load(
"@build_bazel_rules_apple//apple/internal:processor.bzl",
"processor",
)

def _cc_info_dylibs_partial_impl(
*,
embedded_targets):
"""Implementation for the CcInfo dylibs processing partial."""
bundle_files = []

for target in embedded_targets:
if CcInfo not in target:
continue
cc_info = target[CcInfo]
for linker_input in cc_info.linking_context.linker_inputs.to_list():
for library in linker_input.libraries:
if library.dynamic_library:
bundle_files.append(
(processor.location.framework, None, depset([library.dynamic_library])),
)

return struct(bundle_files = bundle_files)

def cc_info_dylibs_partial(
*,
embedded_targets):
"""Constructor for the CcInfo dylibs processing partial.
This partial searches through the embedded_targets for dynamic_libraries and adds them
as bundle_files destined for the Framework folder. The cc_* targets (like cc_library) can
depend on dynamic libraries (.dylibs), usually pulled in from a cc_import. These .dylibs are required
at runtime and are similar to .dlls on windows. The macos_application adds the /Contents/Frameworks
folder as an @rpath search path so placing all of the dylibs in this folder seems reasonable.
Generally, .dylibs should have their install name set to @rpath/libname.dylib for this strategy to work.
You can check the install name using
otool -L libname.dylib
and change it using
install_name_tool -id @rpath/libname.dylib libname.dylib
Args:
embedded_targets: The list of targets that may have CcInfo specifying dylibs that need to be bundled.
Returns:
A partial that returns the bundle location of all dylibs contained in the embedded_targets CcInfo, if there were any to
bundle.
"""
return partial.make(
_cc_info_dylibs_partial_impl,
embedded_targets = embedded_targets,
)
10 changes: 10 additions & 0 deletions test/starlark_tests/macos_application_tests.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,16 @@ def macos_application_test_suite(name):
tags = [name],
)

archive_contents_test(
name = "{}_archive_contains_ccinfo_deps_dylibs_test".format(name),
build_type = "simulator",
target_under_test = "//test/starlark_tests/targets_under_test/macos:app_with_ccinfo_dylib_deps",
contains = [
"$CONTENT_ROOT/Frameworks/libmylib_with_rpath.dylib",
],
tags = [name],
)

native.test_suite(
name = name,
tags = [name],
Expand Down
97 changes: 97 additions & 0 deletions test/starlark_tests/resources/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -1117,3 +1117,100 @@ swift_library(
linkopts = ["-Wl,-framework,AppIntents"],
tags = common.fixture_tags,
)

# --------------------------------------------------------------------------------
# C/C++ rules with data

cc_library(
name = "cc_lib_with_data",
srcs = ["main.cc"],
data = [
"//test/testdata/resources:basic_bundle",
],
tags = common.fixture_tags,
)

cc_library(
name = "cc_lib_with_structured_resources",
srcs = ["main.cc"],
data = [
":structured_resources_in_resources",
],
tags = common.fixture_tags,
)

cc_library(
name = "cc_lib_with_cc_import_with_data",
srcs = ["main.cc"],
deps = [
":cc_import_with_data",
],
)

cc_library(
name = "cc_lib_with_cc_import_with_structured_resources",
srcs = ["main.cc"],
deps = [
":cc_import_with_structured_resources",
],
)

cc_import(
name = "cc_import_with_data",
data = [
"//test/testdata/resources:basic_bundle",
],
tags = common.fixture_tags,
)

cc_import(
name = "cc_import_with_structured_resources",
data = [
":structured_resources_in_resources",
],
tags = common.fixture_tags,
)

# Targets for CcInfo dylib tests

# Generate a .dylib for testing as if it were a precompiled library supplied by a third party
cc_binary(
name = "ccinfo_dylibs_mylib-shared",
srcs = ["ccinfo_dylibs/mylib/lib.cpp"],
linkshared = True,
)

# Set up the rpath of the .dylib using install_name_tool. Bazel should probably do this again when packaging
genrule(
name = "ccinfo_dylibs_mylib-shared-with-rpath",
srcs = [":ccinfo_dylibs_mylib-shared"],
outs = ["libmylib_with_rpath.dylib"],
cmd = "install_name_tool -id @rpath/libmylib_with_rpath.dylib $(location :ccinfo_dylibs_mylib-shared) && cp $(location :ccinfo_dylibs_mylib-shared) $@",
)

# Import our dynamically linked library.
cc_import(
name = "ccinfo_dylibs_mylib-import",
hdrs = ["ccinfo_dylibs/mylib/lib.hpp"],
shared_library = ":ccinfo_dylibs_mylib-shared-with-rpath",
)

# Wrap our dylib in a cc_library so we can add data[] to it. This is common practice for adding
# data or include paths.
cc_library(
name = "ccinfo_dylibs_mylib-import-with-data",
data = ["ccinfo_dylibs/mylib/data.txt"],
deps = ["ccinfo_dylibs_mylib-import"],
)

# This is our main executable, except we make it into a cc_library so macos_application can do
# the actual linking.
cc_library(
name = "ccinfo_dylibs_libapp",
srcs = [
"ccinfo_dylibs/main.cpp",
],
deps = [
":ccinfo_dylibs_mylib-import-with-data",
],
)
6 changes: 6 additions & 0 deletions test/starlark_tests/resources/ccinfo_dylibs/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#include "mylib/lib.hpp"

int main(int, char **) {
MyLibFunc("Calling Mylib!");
return 1;
}
1 change: 1 addition & 0 deletions test/starlark_tests/resources/ccinfo_dylibs/mylib/data.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

3 changes: 3 additions & 0 deletions test/starlark_tests/resources/ccinfo_dylibs/mylib/lib.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#include <iostream>

void MyLibFunc(const char *myString) { std::cout << myString << "\n"; }
3 changes: 3 additions & 0 deletions test/starlark_tests/resources/ccinfo_dylibs/mylib/lib.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#pragma once

void MyLibFunc(const char *myString);
14 changes: 14 additions & 0 deletions test/starlark_tests/targets_under_test/macos/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -2907,3 +2907,17 @@ macos_unit_test(
"//test/starlark_tests/resources:objc_test_lib",
],
)

# ---------------------------------------------------------------------------------------
# Targets for CcInfo dylib bundling tests

macos_application(
name = "app_with_ccinfo_dylib_deps",
bundle_id = "com.google.example",
infoplists = [
"//test/starlark_tests/resources:Info.plist",
],
minimum_os_version = common.min_os_macos.baseline,
tags = common.fixture_tags,
deps = ["//test/starlark_tests/resources:ccinfo_dylibs_libapp"],
)

0 comments on commit 66de359

Please sign in to comment.