Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make virtualize_frameworks the default #483

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
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
5 changes: 0 additions & 5 deletions rules/apple_patched.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ load("@build_bazel_rules_apple//apple:providers.bzl", "AppleFrameworkImportInfo"
load("@build_bazel_rules_swift//swift/internal:providers.bzl", "SwiftUsageInfo")
load("//rules/framework:vfs_overlay.bzl", "make_vfsoverlay")
load("//rules:providers.bzl", "FrameworkInfo")
load("//rules:features.bzl", "feature_names")

def apple_dynamic_framework_import(name, **kwargs):
"""Patches an apple_dynamic_framework_import target based on the problems reported in https://github.com/bazel-ios/rules_ios/issues/55
Expand Down Expand Up @@ -67,10 +66,6 @@ def _find_imported_framework_name(outputs):
return None

def _get_framework_info_providers(ctx, old_cc_info, old_objc_provider):
virtualize_frameworks = feature_names.virtualize_frameworks in ctx.features
if not virtualize_frameworks:
return []

hdrs_list = old_cc_info.compilation_context.headers.to_list()
hdrs = [h.path for h in hdrs_list]

Expand Down
100 changes: 4 additions & 96 deletions rules/framework.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -128,35 +128,7 @@ def _framework_packaging(ctx, action, inputs, outputs, manifest = None):
if inputs == [None]:
return []

virtualize_frameworks = feature_names.virtualize_frameworks in ctx.features
if virtualize_frameworks:
return inputs

if action in ctx.attr.skip_packaging:
return []
action_inputs = [manifest] + inputs if manifest else inputs
outputs = [ctx.actions.declare_file(f) for f in outputs]
framework_name = ctx.attr.framework_name
framework_dir = _find_framework_dir(outputs)
args = ctx.actions.args().use_param_file("@%s").set_param_file_format("multiline")
args.add("--framework_name", framework_name)
args.add("--framework_root", framework_dir)
args.add("--action", action)
args.add_all("--inputs", inputs)
args.add_all("--outputs", outputs)

if action in ["header", "private_header"]:
_framework_packaging_symlink_headers(ctx, inputs, outputs)
else:
ctx.actions.run(
executable = ctx.executable._framework_packaging,
arguments = [args],
inputs = action_inputs,
outputs = outputs,
mnemonic = "PackagingFramework%s" % action.title().replace("_", ""),
)

return outputs
return inputs

def _add_to_dict_if_present(dict, key, value):
if value:
Expand Down Expand Up @@ -337,11 +309,7 @@ def _get_framework_files(ctx, deps):
paths.join(framework_dir, "Modules", "module.modulemap"),
]

virtualize_frameworks = feature_names.virtualize_frameworks in ctx.features
if not virtualize_frameworks:
framework_manifest = ctx.actions.declare_file(framework_dir + ".manifest")
else:
framework_manifest = None
framework_manifest = None

# Package each part of the framework separately,
# so inputs that do not depend on compilation
Expand Down Expand Up @@ -391,49 +359,6 @@ def _get_direct_public_headers(provider, dep):
else:
fail("Unknown provider " + provider + " only CcInfo and Objc supported")

def _get_symlinked_framework_clean_action(ctx, framework_files, compilation_context_fields):
framework_name = ctx.attr.framework_name

outputs = framework_files.outputs
framework_manifest = outputs.manifest
framework_contents = _concat(
outputs.binary,
outputs.modulemap,
outputs.headers,
outputs.private_headers,
outputs.swiftmodule,
outputs.swiftdoc,
)

framework_root = _find_framework_dir(framework_contents)
if framework_root:
ctx.actions.run(
executable = ctx.executable._framework_packaging,
arguments = [
"--action",
"clean",
"--framework_name",
framework_name,
"--framework_root",
framework_root,
"--inputs",
ctx.actions.args().use_param_file("%s", use_always = True).set_param_file_format("multiline")
.add_all(framework_contents),
"--outputs",
framework_manifest.path,
],
outputs = [framework_manifest],
mnemonic = "CleaningFramework",
execution_requirements = {
"local": "True",
},
)
compilation_context_fields["framework_includes"] = depset(
direct = [paths.dirname(framework_root)],
)
else:
ctx.actions.write(framework_manifest, "# Empty framework\n")

def _copy_swiftmodule(ctx, framework_files):
inputs = framework_files.inputs
outputs = framework_files.outputs
Expand Down Expand Up @@ -810,32 +735,15 @@ def _apple_framework_packaging_impl(ctx):
))

# Compute cc_info and swift_info
virtualize_frameworks = feature_names.virtualize_frameworks in ctx.features
if virtualize_frameworks:
framework_info = _get_virtual_framework_info(ctx, framework_files, compilation_context_fields, deps, transitive_deps, vfs)
else:
framework_info = FrameworkInfo(
headers = outputs.headers,
private_headers = outputs.private_headers,
modulemap = outputs.modulemap,
swiftmodule = outputs.swiftmodule,
swiftdoc = outputs.swiftdoc,
)

# If not virtualizing the framework - then it runs a "clean"
_get_symlinked_framework_clean_action(ctx, framework_files, compilation_context_fields)
framework_info = _get_virtual_framework_info(ctx, framework_files, compilation_context_fields, deps, transitive_deps, vfs)

cc_info_provider = CcInfo(
compilation_context = cc_common.create_compilation_context(
**compilation_context_fields
),
)

if virtualize_frameworks:
cc_info = cc_common.merge_cc_infos(direct_cc_infos = [cc_info_provider])
else:
dep_cc_infos = [dep[CcInfo] for dep in transitive_deps if CcInfo in dep]
cc_info = cc_common.merge_cc_infos(direct_cc_infos = [cc_info_provider], cc_infos = dep_cc_infos)
cc_info = cc_common.merge_cc_infos(direct_cc_infos = [cc_info_provider])

# Propagate the avoid deps information upwards
avoid_deps = []
Expand Down
14 changes: 4 additions & 10 deletions rules/import_middleman.bzl
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
load("@build_bazel_rules_apple//apple:providers.bzl", "AppleFrameworkImportInfo")
load("//rules:features.bzl", "feature_names")
load("//rules/internal:objc_provider_utils.bzl", "objc_provider_utils")

_FindImportsAspectInfo = provider(fields = {
Expand Down Expand Up @@ -173,7 +172,6 @@ def _file_collector_rule_impl(ctx):
# This should be correctly configured upstream: see setup in rules_ios
fail("using import_middleman ({}) on wrong transition ({},{},is_device={})", ctx.attr.lablel, platform, arch, ctx.fragments.apple.single_arch_platform.is_device)

virtualize_frameworks = feature_names.virtualize_frameworks in ctx.features
merge_keys = [
"sdk_dylib",
"sdk_framework",
Expand Down Expand Up @@ -255,10 +253,6 @@ def _file_collector_rule_impl(ctx):
)

additional_providers = []
if not virtualize_frameworks:
dep_cc_infos = [dep[CcInfo] for dep in ctx.attr.deps if CcInfo in dep]
cc_info = cc_common.merge_cc_infos(direct_cc_infos = [], cc_infos = dep_cc_infos)
additional_providers.append(cc_info)

return [
DefaultInfo(files = depset(dynamic_framework_dirs + replaced_frameworks)),
Expand All @@ -277,23 +271,23 @@ import_middleman = rule(
This rule adds the ability to update the Mach-o header on imported
libraries and frameworks to get arm64 binaires running on Apple silicon
simulator. For rules_ios, it's added in `app.bzl` and `test.bzl`

Why bother doing this? Well some apps have many dependencies which could take
along time on vendors or other parties to update. Because the M1 chip has the
same ISA as ARM64, most binaries will run transparently. Most iOS developers
code is high level enough and isn't specifc to a device or simulator. There are
many caveats and eceptions but getting it running is better than nothing. ( e.g.
`TARGET_OS_SIMULATOR` )

This solves the problem at the build system level with the power of bazel. The
idea is pretty straight forward:
1. collect all imported paths
2. update the macho headers with Apples vtool and arm64-to-sim
3. update the linker invocation to use the new libs

Now it updates all of the inputs automatically - the action can be taught to do
all of this conditionally if necessary.

Note: The action happens in a rule for a few reasons. This has an interesting
propery: you get a single path for framework lookups at linktime. Perhaps this
can be updated to work without the other behavior
Expand Down
31 changes: 9 additions & 22 deletions rules/legacy_xcodeproj.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ load("@bazel_skylib//lib:paths.bzl", "paths")
load("//rules:hmap.bzl", "HeaderMapInfo")
load("//rules/framework:vfs_overlay.bzl", "VFSOverlayInfo", VFS_OVERLAY_FRAMEWORK_SEARCH_PATH = "FRAMEWORK_SEARCH_PATH")
load("//rules:additional_scheme_info.bzl", "AdditionalSchemeInfo")
load("//rules:features.bzl", "feature_names")

def _get_attr_values_for_name(deps, provider, field):
return [
Expand Down Expand Up @@ -199,17 +198,11 @@ def _xcodeproj_aspect_impl(target, ctx):
if entitlements:
deps.append(entitlements)

virtualize_frameworks = feature_names.virtualize_frameworks in ctx.features
if virtualize_frameworks:
# Effectivly for virtual frameworks we don't need to copy the files
# because they are read directly from the VFS
objc_copts = _xcodeproj_aspect_collect_objc_copts(deps, target, ctx)
swift_copts = _xcodeproj_aspect_collect_swift_copts(deps, target, ctx)
hmap_paths = []
else:
objc_copts = []
swift_copts = []
hmap_paths = _xcodeproj_aspect_collect_hmap_paths(deps, target, ctx)
# Effectivly for virtual frameworks we don't need to copy the files
# because they are read directly from the VFS
objc_copts = _xcodeproj_aspect_collect_objc_copts(deps, target, ctx)
swift_copts = _xcodeproj_aspect_collect_swift_copts(deps, target, ctx)
hmap_paths = []

# TODO: handle apple_resource_bundle targets
env_vars = ()
Expand Down Expand Up @@ -406,7 +399,7 @@ env_script=$(mktemp /tmp/bazel-xcodeproj-intermediate.XXXXXX)
trap "rm -rf $env_script" EXIT

cat > $py_script << "EOF"
#!/usr/bin/env python3
#!/usr/bin/env python3
import json, sys, shlex
build_settings = json.load(sys.stdin)[0]["buildSettings"]
print("/bin/bash")
Expand Down Expand Up @@ -772,13 +765,8 @@ def _populate_xcodeproj_targets_and_schemes(ctx, targets, src_dot_dots, all_tran
"BAZEL_BUILD_TARGET_WORKSPACE": target_info.bazel_build_target_workspace,
}

virtualize_frameworks = feature_names.virtualize_frameworks in ctx.features
if virtualize_frameworks:
target_settings["OTHER_SWIFT_FLAGS"] = _swift_copts_for_target(target_name, all_transitive_targets)
target_settings["OTHER_CFLAGS"] = _objc_copts_for_target(target_name, all_transitive_targets)
else:
target_settings["BAZEL_SWIFTMODULEFILES_TO_COPY"] = _swiftmodulepaths_for_target(target_name, all_transitive_targets)
target_settings["HEADER_SEARCH_PATHS"] = _header_search_paths_for_target(target_name, all_transitive_targets)
target_settings["OTHER_SWIFT_FLAGS"] = _swift_copts_for_target(target_name, all_transitive_targets)
target_settings["OTHER_CFLAGS"] = _objc_copts_for_target(target_name, all_transitive_targets)

framework_search_paths = _framework_search_paths_for_target(target_name, all_transitive_targets)
target_settings["FRAMEWORK_SEARCH_PATHS"] = " ".join(framework_search_paths)
Expand All @@ -800,8 +788,7 @@ def _populate_xcodeproj_targets_and_schemes(ctx, targets, src_dot_dots, all_tran
)
extra_clang_flags = ["-D\'%s\'" % d for d in target_info.cc_defines.to_list()]

if virtualize_frameworks:
extra_clang_flags += ["-Xcc %s" % d for d in _objc_copts_for_target(target_name, all_transitive_targets)]
extra_clang_flags += ["-Xcc %s" % d for d in _objc_copts_for_target(target_name, all_transitive_targets)]

target_settings["BAZEL_LLDB_SWIFT_EXTRA_CLANG_FLAGS"] = " ".join(extra_clang_flags)

Expand Down
15 changes: 3 additions & 12 deletions rules/library.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -897,19 +897,10 @@ def apple_library(name, library_tools = {}, export_private_headers = True, names
srcs = swift_sources,
# Note: by default it used a vfs but not the entire virtual framwork
# feature.
copts = copts_by_build_setting.swift_copts + swift_copts + select({
"@build_bazel_rules_ios//:virtualize_frameworks": framework_vfs_swift_copts,
"//conditions:default": framework_vfs_swift_copts if enable_framework_vfs else [],
}) + additional_swift_copts,
deps = deps + private_deps + lib_names + select({
"@build_bazel_rules_ios//:virtualize_frameworks": [framework_vfs_overlay_name_swift],
"//conditions:default": [framework_vfs_overlay_name_swift] if enable_framework_vfs else [],
}),
copts = copts_by_build_setting.swift_copts + swift_copts + framework_vfs_swift_copts + additional_swift_copts,
deps = deps + private_deps + lib_names + [framework_vfs_overlay_name_swift],
swiftc_inputs = swiftc_inputs,
features = ["swift.no_generated_module_map"] + select({
"@build_bazel_rules_ios//:virtualize_frameworks": ["swift.vfsoverlay"],
"//conditions:default": [],
}),
features = ["swift.no_generated_module_map"] + ["swift.vfsoverlay"],
data = [module_data],
tags = tags_manual,
defines = defines + swift_defines,
Expand Down