Skip to content

Commit

Permalink
remove module prefix from swiftinterface types
Browse files Browse the repository at this point in the history
Summary: Add a workaround for swiftlang/swift#56573 where we strip the module prefix for first party modules from types in swiftinterface files. This should give us the same type lookup logic as when compiling from source.

Reviewed By: NuriAmari

Differential Revision: D67802092

fbshipit-source-id: f074d8dfa816db20c6640ad53f93d227e70360db
  • Loading branch information
rmaz authored and facebook-github-bot committed Jan 6, 2025
1 parent 4e2c07d commit 236be3c
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 0 deletions.
1 change: 1 addition & 0 deletions prelude/apple/swift/swift_compilation.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -486,6 +486,7 @@ def _compile_swiftmodule(
"-emit-module-interface",
"-emit-module-interface-path",
output_swiftinterface.as_output(),
"-remove-module-prefixes",
])
_compile_with_argsfile(ctx, "emit_swiftinterface", ".swiftinterface", swiftinterface_argsfile, srcs, swiftinterface_cmd, toolchain, num_threads = 1)

Expand Down
83 changes: 83 additions & 0 deletions prelude/apple/tools/swift_exec.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,88 @@
# License, Version 2.0 found in the LICENSE-APACHE file in the root directory
# of this source tree.

import json
import os
import re
import subprocess
import sys

_RE_TMPDIR_ENV_VAR = "TMPDIR"
_FILE_WRITE_FAILURE_MARKER = "could not write"


def _expand_args(command):
for arg in command:
if arg.startswith("@"):
with open(arg[1:]) as argsfile:
return [line.rstrip() for line in argsfile.readlines()]

return []


def _get_modulemap(args):
for i in range(len(args)):
if args[i].startswith("-explicit-swift-module-map-file"):
if args[i + 1].startswith("-Xfrontend"):
path = args[i + 2]
else:
path = args[i + 1]

with open(path.strip()) as modulemap:
return json.load(modulemap)

return None


def _get_modulename(args):
return args[args.index("-module-name") + 1]


def _get_modules(command):
args = _expand_args(command)
modulemap = _get_modulemap(args)
if modulemap is None:
return set()

modules = set()
for entry in modulemap:
# We only remove prefixes from first party modules.
if "sdk_deps" in entry.get("clangModulePath", ""):
pass
elif "sdk_deps" in entry.get("modulePath", ""):
pass
else:
modules.add(entry["moduleName"])

modules.add(_get_modulename(args))

return modules


def _remove_swiftinterface_module_prefixes(command):
interface_path = command[command.index("-emit-module-interface-path") + 1]
modules = _get_modules(command)
if len(modules) == 0:
return

with open(interface_path) as f:
interface = f.read()

output = []
pattern = re.compile(r"(\w+)\.(\w+)")
for line in interface.splitlines():
outline = line
for m in pattern.finditer(line):
if m.group(1) in modules:
outline = outline.replace(m.group(0), m.group(2))

output.append(outline)

with open(interface_path, "w") as f:
f.write("\n".join(output))
f.write("\n")


def main():
env = os.environ.copy()
if "INSIDE_RE_WORKER" in env and _RE_TMPDIR_ENV_VAR in env:
Expand All @@ -35,6 +109,11 @@ def main():

command = sys.argv[1:]

# Check if we need to strip module prefixes from types in swiftinterface output.
should_remove_module_prefixes = "-remove-module-prefixes" in command
if should_remove_module_prefixes:
command.remove("-remove-module-prefixes")

# Use relative paths for debug information and index information,
# so we generate relocatable files.
#
Expand Down Expand Up @@ -79,6 +158,10 @@ def main():
)
sys.exit(1)

# https://github.com/swiftlang/swift/issues/56573
if should_remove_module_prefixes:
_remove_swiftinterface_module_prefixes(command)

sys.exit(result.returncode)


Expand Down

0 comments on commit 236be3c

Please sign in to comment.