Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 27 additions & 4 deletions rules/framework.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,26 @@ def apple_framework(name, apple_library = apple_library, **kwargs):
**framework_packaging_kwargs
)

def _validate_deps_minimum_os_version(framework_name, minimum_os_version, deps):
"""Validates that deps' minimum_os_versions are not higher than that of this target.
Note that Swift has already enforced that at compile time, while objective-c doesn't.

framework_name: the framework name
minimum_os_version: the minimum os version of this framework
deps: the deps of this framework
"""

for dep in deps:
if AppleBundleInfo in dep:
dep_bundle_info = dep[AppleBundleInfo]
dep_min_os_version = apple_common.dotted_version(dep_bundle_info.minimum_os_version)
if minimum_os_version.compare_to(dep_min_os_version) < 0:
fail(
"""A framework target's minimum_os_version must NOT be lower than those of its deps,
but framework {} with minimum_os_version {} depends on framework {} with minimum_os_version {}.
""".format(framework_name, minimum_os_version, dep_bundle_info.bundle_name, dep_min_os_version),
)

def _find_framework_dir(outputs):
for output in outputs:
prefix = output.path.rsplit(".framework/", 1)[0]
Expand Down Expand Up @@ -789,10 +809,8 @@ def _bundle_dynamic_framework(ctx, is_extension_safe, avoid_deps):
] + processor_result.providers,
)

def _bundle_static_framework(ctx, is_extension_safe, outputs):
def _bundle_static_framework(ctx, is_extension_safe, current_apple_platform, outputs):
"""Returns bundle info for a static framework commonly used intra-build"""
current_apple_platform = transition_support.current_apple_platform(apple_fragment = ctx.fragments.apple, xcode_config = ctx.attr._xcode_config)

partial_output = partial.call(
partials.extension_safe_validation_partial(
is_extension_safe = is_extension_safe,
Expand Down Expand Up @@ -844,6 +862,11 @@ def _apple_framework_packaging_impl(ctx):
transitive_deps = _attrs_for_split_slice(ctx.split_attr.transitive_deps, split_slice_key)
vfs = _attrs_for_split_slice(ctx.split_attr.vfs, split_slice_key)

current_apple_platform = transition_support.current_apple_platform(apple_fragment = ctx.fragments.apple, xcode_config = ctx.attr._xcode_config)

# Validates that the minimum_os_version is not lower than those of the deps.
_validate_deps_minimum_os_version(ctx.attr.framework_name, current_apple_platform.target_os_version, deps + transitive_deps)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it should be able to operate only on its direct dependencies, shouldn't it? If something transitive is lower, I'd think it would get flagged by the thing that depends on it directly. I'm just thinking that this might save some traversal time, but I don't know if it is substantial enough to have a notable impact.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed; since this will check at each level, there's no need to traverse further than one level down at each step.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually an apple_framework_packaging target doesn't directly depends on other apple_framework_packaging targets if one uses the macro apple_framework see https://github.com/bazel-ios/rules_ios/blob/master/rules/framework.bzl#L74-L117:

def apple_framework(name, apple_library = apple_library, **kwargs):
    ...
    framework_deps = []
    ...
    framework_deps.append(force_load_name)

    framework_deps += library.lib_names
    
    apple_framework_packaging(
        name = name,
        ...
        deps = framework_deps,
        ...
    )

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh, gross, but since the transitive deps are already being used in a bunch of places, I wouldn't think this would add additional impact then.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah. If you look at the implementation, transitive_deps is NOT all transitive deps of the apple_framework_packaging target. It actually only includes all intermediate libraries and the corresponding apple_framework's deps.


framework_files = _get_framework_files(ctx, deps)
outputs = framework_files.outputs

Expand Down Expand Up @@ -902,7 +925,7 @@ def _apple_framework_packaging_impl(ctx):
bundle_outs = _bundle_dynamic_framework(ctx, is_extension_safe = is_extension_safe, avoid_deps = avoid_deps)
avoid_deps_info = AvoidDepsInfo(libraries = depset(avoid_deps + ctx.attr.deps).to_list(), link_dynamic = True)
else:
bundle_outs = _bundle_static_framework(ctx, is_extension_safe = is_extension_safe, outputs = outputs)
bundle_outs = _bundle_static_framework(ctx, is_extension_safe = is_extension_safe, current_apple_platform = current_apple_platform, outputs = outputs)
avoid_deps_info = AvoidDepsInfo(libraries = depset(avoid_deps).to_list(), link_dynamic = False)
swift_info = _get_merged_swift_info(ctx, framework_files, transitive_deps)

Expand Down