Skip to content

Commit

Permalink
Propagate user link flags from deps on objc_library CcInfo provider
Browse files Browse the repository at this point in the history
Currently `objc_library` propagates frameworks to the CcInfo provider,
based on the target's built ObjC provider `sdk_frameworks` field. This
change aims to propagate both dylibs and frameworks from both the
ObjC provider, and merged `deps` CcInfo's.

PiperOrigin-RevId: 438387102
  • Loading branch information
Googler authored and copybara-github committed Mar 30, 2022
1 parent 0f9f740 commit 203f2c5
Show file tree
Hide file tree
Showing 2 changed files with 132 additions and 7 deletions.
46 changes: 39 additions & 7 deletions src/main/starlark/builtins_bzl/common/objc/objc_library.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,6 @@ cc_common = _builtins.toplevel.cc_common
coverage_common = _builtins.toplevel.coverage_common
apple_common = _builtins.toplevel.apple_common

def _rule_error(msg):
fail(msg)

def _attribute_error(attr_name, msg):
fail("in attribute '" + attr_name + "': " + msg)

Expand Down Expand Up @@ -71,10 +68,10 @@ def _build_linking_context(ctx, feature_configuration, cc_toolchain, objc_provid

libraries.extend(objc_provider.cc_library.to_list())

sdk_frameworks = objc_provider.sdk_framework.to_list()
user_link_flags = []
for sdk_framework in sdk_frameworks:
user_link_flags.append(["-framework", sdk_framework])
user_link_flags = _user_link_flags(
cc_info = merged_objc_library_cc_infos,
objc_provider = objc_provider,
)

direct_linker_inputs = []
if len(user_link_flags) != 0 or len(libraries) != 0 or objc_provider.linkstamp:
Expand Down Expand Up @@ -106,6 +103,41 @@ def _static_library(
alwayslink = alwayslink,
)

def _user_link_flags(*, cc_info, objc_provider):
"""Builds objc_library CcInfo user link flags for frameworks and dylibs.
Args:
cc_info: Merged CcInfo provider from objc_library target deps.
objc_provider: Current objc_library ObjC provider.
Returns:
List of user link flags for frameworks and dylibs.
"""

sdk_dylibs = objc_provider.sdk_dylib.to_list()
sdk_frameworks = objc_provider.sdk_framework.to_list()

all_user_link_flags = []
all_user_link_flags.extend(objc_provider.linkopt.to_list())

for linker_input in cc_info.linking_context.linker_inputs.to_list():
all_user_link_flags.extend(linker_input.user_link_flags)

for i, user_link_flag in enumerate(all_user_link_flags):
if user_link_flag.startswith("-l"):
sdk_dylibs.append("lib" + user_link_flag[2:])
elif user_link_flag == "-framework":
sdk_frameworks.append(all_user_link_flags[i + 1])

sdk_user_link_flags = []
for sdk_framework in depset(sdk_frameworks).to_list():
sdk_user_link_flags.append(["-framework", sdk_framework])
for sdk_dylib in depset(sdk_dylibs).to_list():
if sdk_dylib.startswith("lib"):
sdk_dylib = sdk_dylib[3:]
sdk_user_link_flags.append(["-l" + sdk_dylib])

return sdk_user_link_flags

def _objc_library_impl(ctx):
_validate_attributes(ctx)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
import com.google.devtools.build.lib.analysis.test.InstrumentedFilesInfo;
import com.google.devtools.build.lib.analysis.util.AnalysisMock;
import com.google.devtools.build.lib.analysis.util.ScratchAttributeWriter;
import com.google.devtools.build.lib.cmdline.LabelSyntaxException;
import com.google.devtools.build.lib.cmdline.RepositoryName;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.packages.NoSuchTargetException;
Expand Down Expand Up @@ -2444,4 +2445,96 @@ public void testDisableCoverageDoesNotPropagateSupportFiles() throws Exception {

assertThat(instrumentedFilesInfo.getCoverageSupportFiles().toList()).isEmpty();
}

private ImmutableList<String> getCcInfoUserLinkFlagsFromTarget(String target)
throws LabelSyntaxException {
return getConfiguredTarget(target)
.get(CcInfo.PROVIDER)
.getCcLinkingContext()
.getUserLinkFlags()
.toList()
.stream()
.map(CcLinkingContext.LinkOptions::get)
.flatMap(List::stream)
.collect(toImmutableList());
}

@Test
public void testSdkUserLinkFlagsFromSdkFieldsAndLinkoptsArePropagatedOnCcInfo() throws Exception {
scratch.file(
"x/BUILD",
"objc_library(",
" name = 'foo',",
" linkopts = [",
" '-lxml2',",
" '-framework AVFoundation',",
" ],",
" sdk_dylibs = ['libz'],",
" sdk_frameworks = ['CoreData'],",
" deps = [':bar', ':car'],",
")",
"objc_library(",
" name = 'bar',",
" linkopts = [",
" '-lsqlite3',",
" ],",
" sdk_frameworks = ['Foundation'],",
")",
"objc_library(",
" name = 'car',",
" linkopts = [",
" '-framework UIKit',",
" ],",
" sdk_dylibs = ['libc++'],",
")");

ImmutableList<String> userLinkFlags = getCcInfoUserLinkFlagsFromTarget("//x:foo");
assertThat(userLinkFlags).isNotEmpty();
assertThat(userLinkFlags).containsAtLeast("-framework", "AVFoundation").inOrder();
assertThat(userLinkFlags).containsAtLeast("-framework", "CoreData").inOrder();
assertThat(userLinkFlags).containsAtLeast("-framework", "Foundation").inOrder();
assertThat(userLinkFlags).containsAtLeast("-framework", "UIKit").inOrder();
assertThat(userLinkFlags).containsAtLeast("-lz", "-lc++", "-lxml2", "-lsqlite3");
}

@Test
public void testNoDuplicateSdkUserLinkFlagsFromMultipleDepsOnCcInfo() throws Exception {
scratch.file(
"x/BUILD",
"objc_library(",
" name = 'foo',",
" linkopts = [",
" '-lsqlite3',",
" '-framework UIKit',",
" ],",
" sdk_dylibs = ['libc++'],",
" sdk_frameworks = ['Foundation'],",
" deps = [':bar', ':car'],",
")",
"objc_library(",
" name = 'bar',",
" linkopts = [",
" '-lsqlite3',",
" '-framework CoreData',",
" ],",
" sdk_frameworks = ['Foundation'],",
")",
"objc_library(",
" name = 'car',",
" linkopts = [",
" '-framework UIKit',",
" '-framework CoreData',",
" ],",
" sdk_dylibs = ['libc++'],",
")");
ImmutableList<String> userLinkFlags = getCcInfoUserLinkFlagsFromTarget("//x:foo");
assertThat(userLinkFlags).isNotEmpty();
assertThat(userLinkFlags).containsAtLeast("-framework", "CoreData").inOrder();
assertThat(userLinkFlags).containsAtLeast("-framework", "Foundation").inOrder();
assertThat(userLinkFlags).containsAtLeast("-framework", "UIKit").inOrder();
assertThat(userLinkFlags).containsAtLeast("-lc++", "-lsqlite3");
ImmutableList<String> userLinkFlagsWithoutFrameworkFlags =
userLinkFlags.stream().filter(s -> !s.equals("-framework")).collect(toImmutableList());
assertThat(userLinkFlagsWithoutFrameworkFlags).containsNoDuplicates();
}
}

0 comments on commit 203f2c5

Please sign in to comment.