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

Add rules for building SDK frameworks for explicit module compilation #562

Draft
wants to merge 55 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
c27f34e
Add rules for building SDK frameworks for explicit module compilation
dierksen Sep 15, 2022
e0f837c
Merge branch 'master' into framework_repo_rule
dierksen Sep 16, 2022
567d839
split out repo rule; bump bazel and rules_swift
dierksen Sep 28, 2022
183306e
revert arm64-to-sim tweak
dierksen Sep 28, 2022
399edef
testing some stuff
dierksen Sep 29, 2022
59fe2f4
add umbrella dep under the hood
dierksen Sep 30, 2022
b02c8ac
Merge branch 'master' into framework_repo_rule
dierksen Oct 11, 2022
87de123
Merge branch 'framework_repo_rule' into framework_tinkering
dierksen Oct 11, 2022
e905fe1
further repo rule cleanup
dierksen Oct 17, 2022
9792e61
change .bazelrc for now
dierksen Oct 17, 2022
0b47395
symlink in xctest framework, pass to testonly swift libraries
dierksen Oct 18, 2022
1b7afe4
cleanup
dierksen Oct 20, 2022
ebb38c2
Bump macos image, bazel, and carthage versions
dierksen Oct 20, 2022
90aa093
Merge branch 'xc13' into framework_repo_rule
dierksen Oct 20, 2022
0a92978
gradually trying to fix tests
dierksen Oct 21, 2022
c891e65
bump cocoapods to 1.11 to add ruby 3 support
dierksen Oct 21, 2022
55c9710
newest bazel release
dierksen Oct 21, 2022
e83f15d
update gemfile.lock
dierksen Oct 21, 2022
901234d
bump checkout action, mark mixed framework test as manual for now
dierksen Oct 21, 2022
efc8ff6
disable another one
dierksen Oct 21, 2022
fd3db05
Merge branch 'master' into xc13
dierksen Nov 1, 2022
7d01fbe
try newer carthage fix
dierksen Nov 2, 2022
a6d85c3
re-enable a couple of tests for now
dierksen Nov 2, 2022
0d11ade
reverts
dierksen Nov 2, 2022
3eee080
Merge branch 'master' into xc13
dierksen Nov 3, 2022
865789c
revert more formatting
dierksen Nov 4, 2022
de887dd
update test simulators
dierksen Nov 4, 2022
29dc203
just change the diff
dierksen Nov 7, 2022
8d06a2a
tweak diff
dierksen Nov 7, 2022
5f3bfd0
Merge branch 'xc13' into framework_repo_rule
dierksen Nov 7, 2022
ed943d9
tweak repos for testing on github
dierksen Nov 7, 2022
9dc858f
Merge branch 'master' into framework_repo_rule
dierksen Nov 7, 2022
b921c35
fix deps array (ugh), fix watch simulator cpu
dierksen Nov 8, 2022
c17cbbe
add -k to tests so i can see progress at least
dierksen Nov 8, 2022
8a6de35
Merge branch 'master' into framework_repo_rule
dierksen Nov 14, 2022
a076ac1
reverts, test cleanup
dierksen Nov 14, 2022
893bddb
bump rules versions
dierksen Nov 14, 2022
5422ec0
trying to clean up while preserving existing tests
dierksen Nov 14, 2022
e09da21
upgrade stardoc due to rules_proto changes :-/
dierksen Nov 14, 2022
5951403
alias XCTest dummy module so it doesn't replace the real one
dierksen Nov 16, 2022
fc1b9b3
trying one more thing
dierksen Nov 16, 2022
bb6bbf1
more tweaks, getting closer
dierksen Nov 17, 2022
a8278b0
Merge branch 'master' into framework_repo_rule
dierksen Nov 17, 2022
82b3662
whitespace revert
dierksen Nov 17, 2022
6346d6d
revert vscode change
dierksen Nov 17, 2022
d505eb0
attempting to generate for intel mac, might need to iterate a bit
dierksen Nov 17, 2022
723efe9
this stupid diff test again
dierksen Nov 17, 2022
510bee3
add default mapping to mac to deal with darwin cpu weirdness
dierksen Nov 17, 2022
1504731
one more tweak for intel mac
dierksen Nov 17, 2022
9795596
add frameworks dep to arm64-to-sim
dierksen Nov 17, 2022
ebf77f8
make config flag, fix import underlying module flag
dierksen Nov 17, 2022
997b0f9
tweak config setting
dierksen Nov 17, 2022
55f13ec
address lingering nit
dierksen Nov 18, 2022
4e34aec
add -k to tests
dierksen Nov 18, 2022
0e4c235
hopefully green test setup
dierksen Nov 18, 2022
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
3 changes: 0 additions & 3 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
{
"files.exclude": {
dierksen marked this conversation as resolved.
Show resolved Hide resolved
"bazel-*": true
},
"editor.formatOnSave": true,
}
17 changes: 15 additions & 2 deletions tools/toolchains/xcode_configure/xcode_configure.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
installed on the local host.
"""

load(":xcode_sdk_frameworks.bzl", "create_xcode_framework_targets")

_EXECUTE_TIMEOUT = 120

def _search_string(fullstring, prefix, suffix):
Expand Down Expand Up @@ -73,6 +75,12 @@ def _xcode_version_output(repository_ctx, name, version, aliases, developer_dir)
tvos_sdk_version = _search_sdk_output(xcodebuild_result.stdout, "appletvos")
macos_sdk_version = _search_sdk_output(xcodebuild_result.stdout, "macosx")
watchos_sdk_version = _search_sdk_output(xcodebuild_result.stdout, "watchos")
versions_dict = {
dierksen marked this conversation as resolved.
Show resolved Hide resolved
"ios": ios_sdk_version,
"tvos": tvos_sdk_version,
"macos": macos_sdk_version,
"watchos": watchos_sdk_version,
}
build_contents += "xcode_version(\n name = '%s'," % name
build_contents += "\n version = '%s'," % version
if aliases:
Expand All @@ -86,7 +94,7 @@ def _xcode_version_output(repository_ctx, name, version, aliases, developer_dir)
if watchos_sdk_version:
build_contents += "\n default_watchos_sdk_version = '%s'," % watchos_sdk_version
build_contents += "\n)\n"
return build_contents
return build_contents, versions_dict

VERSION_CONFIG_STUB = "xcode_config(name = 'host_xcodes')"

Expand Down Expand Up @@ -213,18 +221,21 @@ def _darwin_build_file(repository_ctx):
aliases = toolchain.aliases
developer_dir = toolchain.developer_dir
target_name = "version%s" % version.replace(".", "_")
buildcontents += _xcode_version_output(
version_output, versions_dict = _xcode_version_output(
repository_ctx,
target_name,
version,
aliases,
developer_dir,
)
buildcontents += version_output
target_label = "':%s'" % target_name
target_names.append(target_label)
if (version.startswith(default_xcode_version) and
version.endswith(default_xcode_build_version)):
default_xcode_target = target_label
if repository_ctx.attr.explicit_modules:
create_xcode_framework_targets(xcode_version_name = target_name, developer_dir = developer_dir, versions = versions_dict, repository_ctx = repository_ctx)
buildcontents += "xcode_config(name = 'host_xcodes',"
if target_names:
buildcontents += "\n versions = [%s]," % ", ".join(target_names)
Expand Down Expand Up @@ -275,6 +286,7 @@ xcode_autoconf = repository_rule(
attrs = {
"xcode_locator": attr.string(),
"remote_xcode": attr.string(),
"explicit_modules": attr.bool(),
dierksen marked this conversation as resolved.
Show resolved Hide resolved
},
)

Expand All @@ -284,4 +296,5 @@ def xcode_configure(xcode_locator_label, remote_xcode_label = None):
name = "local_config_xcode",
xcode_locator = xcode_locator_label,
remote_xcode = remote_xcode_label,
explicit_modules = True,
thiagohmcruz marked this conversation as resolved.
Show resolved Hide resolved
)
141 changes: 141 additions & 0 deletions tools/toolchains/xcode_configure/xcode_sdk_frameworks.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
PLATFORM_TUPLES = [
("AppleTVOS", "tvos"),
("AppleTVSimulator", "tvos"),
("MacOSX", "macos"),
("WatchOS", "watchos"),
("WatchSimulator", "watchos"),
("iPhoneOS", "ios"),
("iPhoneSimulator", "ios"),
]

def _find_all_frameworks(sdk_path):
frameworks_dir = sdk_path.get_child("System").get_child("Library").get_child("Frameworks")
if not frameworks_dir.exists:
# Skip things like DriverKit
return []
frameworks = frameworks_dir.readdir()
return [
f.basename.replace(".framework", "")
for f in frameworks
if f.basename.endswith(".framework") and not f.basename.startswith("_")
]

def _build_file_header():
return """load("@build_bazel_rules_swift//swift:swift.bzl", "swift_module_alias", "swift_c_module")

package(default_visibility = ["//visibility:public"])

"""

IMPORTS_FILE = "bazel_xcode_imports.swift"

def _get_dependency_graph(repository_ctx, developer_dir, sdk_path, target_triple):
frameworks = _find_all_frameworks(sdk_path)
swift_lib_dir = sdk_path.get_child("usr").get_child("lib").get_child("swift")
swift_libs = swift_lib_dir.readdir()
frameworks.extend([s.basename.replace(".swiftmodule", "") for s in swift_libs if s.basename.endswith(".swiftmodule") and not s.basename.startswith("_")])
dierksen marked this conversation as resolved.
Show resolved Hide resolved

import_file_content = "".join(["import {}\n".format(f) for f in frameworks])
repository_ctx.file(IMPORTS_FILE, content = import_file_content)
resource_dir = "{}/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift".format(developer_dir)

repository_ctx.report_progress("Scanning deps for {}".format(sdk_path))
deps_result = repository_ctx.execute(
[
"swiftc",
"-scan-dependencies",
"-sdk",
sdk_path,
"-resource-dir",
resource_dir,
"-target",
target_triple,
IMPORTS_FILE,
],
)
repository_ctx.delete(IMPORTS_FILE)
if deps_result.return_code != 0:
fail("Could not scan dependencies for {}\n{}".format(sdk_path, deps_result.stderr))
return json.decode(deps_result.stdout)

C_MODULE_TMPL = """swift_c_module(
name = "{name}_c",
module_name = "{name}",
system_module_map = "{module_map_file}",
deps = [
{deps}
],
)

"""

SWIFT_MODULE_TMPL = """swift_module_alias(
name = "{name}_swift",
deps = [
{deps}
]
)

"""

def _sub_bazel_path_vars(path, sdk_path, developer_dir):
path = path.replace(str(sdk_path), "__BAZEL_XCODE_SDKROOT__")
path = path.replace(str(developer_dir), "__BAZEL_XCODE_DEVELOPER_DIR__")
return path

def _rule_for_pkg(developer_dir, sdk_path, pkg):
module_path = pkg.get("modulePath", "")
if not module_path or IMPORTS_FILE in module_path:
dierksen marked this conversation as resolved.
Show resolved Hide resolved
return ""
module_name = module_path.replace(".pcm", "").replace(".swiftmodule", "")

pkg_deps = pkg.get("directDependencies", [])
deps = ["{}_c".format(d["clang"]) for d in pkg_deps if "clang" in d]
deps += ["{}_swift".format(d["swift"]) for d in pkg_deps if "swift" in d]
deps_string = "\n".join(sorted([" \":{}\",".format(d) for d in deps]))
thiagohmcruz marked this conversation as resolved.
Show resolved Hide resolved

clang = pkg.get("details", {}).get("clang", {})
if clang:
return C_MODULE_TMPL.format(
name = module_name,
module_map_file = _sub_bazel_path_vars(clang["moduleMapPath"], sdk_path, developer_dir),
deps = deps_string,
)

return SWIFT_MODULE_TMPL.format(
name = module_name,
deps = deps_string,
)

def _create_build_file_for_sdk(repository_ctx, developer_dir, sdk_path, output_folder, target_triple):
scan_deps = _get_dependency_graph(repository_ctx, developer_dir, sdk_path, target_triple)

build_file = _build_file_header()

for pkg in scan_deps.get("modules", []):
build_file += _rule_for_pkg(developer_dir, sdk_path, pkg)

build_file_path = output_folder.get_child("BUILD.bazel")
repository_ctx.file(build_file_path, build_file)

def _platform_target_triple(platform, target_name, version):
return "{cpu}-apple-{platform}{version}{suffix}".format(
cpu = "arm64_32" if target_name == "watchos" else "arm64",
platform = target_name,
version = version,
suffix = "-simulator" if platform.endswith("Simulator") else "",
)

def create_xcode_framework_targets(repository_ctx, xcode_version_name, developer_dir, versions):
"""Creates a BUILD file for all the SDK frameworks contained in a given Xcode version."""
developer_dir_path = repository_ctx.path(developer_dir)
platforms_dir = developer_dir_path.get_child("Platforms")
for platform_name, target_name in PLATFORM_TUPLES:
platform_dir = platforms_dir.get_child(platform_name + ".platform")
platform_version = versions[target_name]
dierksen marked this conversation as resolved.
Show resolved Hide resolved

sdk_dir = platform_dir.get_child("Developer").get_child("SDKs").get_child("{}.sdk".format(platform_name))
target_triple = _platform_target_triple(platform_name, target_name, platform_version)

output_folder = repository_ctx.path(xcode_version_name).get_child(platform_name)
_create_build_file_for_sdk(repository_ctx, developer_dir_path, sdk_dir, output_folder, target_triple)
dierksen marked this conversation as resolved.
Show resolved Hide resolved