Skip to content

Commit

Permalink
* fixed: compilation failed due swift lib not found (libswiftXPC.dyli…
Browse files Browse the repository at this point in the history
…b is not found in swift paths) (#783)

Recent Facebook FBSDKCoreKit has dependency to `libswiftXPC.dylib`. But it is not present in SDK and cause build to fail with message:

> libswiftXPC.dylib is not found in swift paths

this is happening during copying swift-libraries into App/Frameworks folder.
Same time this dependency is declared as weak:

> @rpath/libswiftXPC.dylib (compatibility version 1.0.0, current version 36.100.7, weak)

its seems to an option to skip missing swift libraries that are marked as weak.
these changes provided in this PR
  • Loading branch information
dkimitsa authored May 24, 2024
1 parent 833f6d3 commit 56914f5
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,7 @@ public void processFile(Resource resource, File file, File destDir)

protected void copyDynamicFrameworks(File destDir, File appExecutable) throws IOException {
final Set<String> swiftLibraries = new HashSet<>();
final Set<String> weakSwiftLibraries = new HashSet<>();
File frameworksDir = new File(destDir, "Frameworks");

for (String framework : config.getFrameworks()) {
Expand Down Expand Up @@ -380,7 +381,7 @@ public void processFile(Resource resource, File file, File destDir) throws IOExc
// check if this dylib depends on Swift
// and register those libraries to be copied
// to bundle.app/Frameworks
getSwiftDependencies(file, swiftLibraries);
getSwiftDependencies(file, swiftLibraries, weakSwiftLibraries);
}
}
}
Expand All @@ -392,7 +393,7 @@ public void processFile(Resource resource, File file, File destDir) throws IOExc

if (config.hasSwiftSupport() && config.getSwiftSupport().shouldCopySwiftLibs()) {
// find swift libraries that might be referenced in executable due static linking
getSwiftDependencies(appExecutable, swiftLibraries);
getSwiftDependencies(appExecutable, swiftLibraries, weakSwiftLibraries);

// workaround: check if libs contain reference to swift lib
// if project links against static swift library it requires
Expand All @@ -402,23 +403,30 @@ public void processFile(Resource resource, File file, File destDir) throws IOExc
String p = lib.getValue();
if (p.startsWith("libswift") && p.endsWith(".dylib") && !new File(p).exists()) {
swiftLibraries.add(p);
if (!lib.isForce()) weakSwiftLibraries.add(p);
}
}

// copy Swift libraries if required
if (!swiftLibraries.isEmpty()) {
copySwiftLibs(swiftLibraries, frameworksDir, true);
copySwiftLibs(swiftLibraries, weakSwiftLibraries, frameworksDir, true);
}
}
}

protected void getSwiftDependencies(File file, Collection<String> swiftLibraries) throws IOException {
protected void getSwiftDependencies(File file, Collection<String> swiftLibraries, Collection<String> weakSwiftLibraries) throws IOException {
String dependencies = ToolchainUtil.otool(file);
Pattern swiftLibraryPattern = Pattern.compile("@rpath/(libswift.+\\.dylib)");
// dependency string example
// @rpath/libswiftXPC.dylib (compatibility version 1.0.0, current version 36.100.7, weak)
Pattern swiftLibraryPattern = Pattern.compile("@rpath/(libswift.+\\.dylib)(?:.*(weak))?");
Matcher matcher = swiftLibraryPattern.matcher(dependencies);
while (matcher.find()) {
String library = matcher.group(1);
swiftLibraries.add(library);
if (matcher.groupCount() > 1) {
// `weak` was present, consider library for weak linking
weakSwiftLibraries.add(library);
}
}
}

Expand Down Expand Up @@ -562,13 +570,13 @@ protected void copyWatchApp(File installDir) throws IOException {
}
}

private File locateSwiftLib(File[] swiftDirs, String swiftLib) throws FileNotFoundException {
private File locateSwiftLib(File[] swiftDirs, String swiftLib) {
for (File swiftDir : swiftDirs) {
File f = new File(swiftDir, swiftLib);
if (f.exists())
return f;
}
throw new FileNotFoundException(swiftLib + " is not found in swift paths");
return null;
}

private File[] getSwiftDirs(Config config) throws IOException {
Expand Down Expand Up @@ -645,22 +653,29 @@ private File[] getDefaultSwiftDirs(String system) throws IOException {
return swiftDirs.toArray(new File[0]);
}

protected void copySwiftLibs(Collection<String> swiftLibraries, File targetDir, boolean strip) throws IOException {
protected void copySwiftLibs(Collection<String> swiftLibraries, Collection<String> weakSwiftLibraries,
File targetDir, boolean strip) throws IOException {
File[] swiftDirs = getSwiftDirs(config);

// dkimitsa: there is hidden dependencies possible between swift libraries.
// e.g. one swiftLib has dependency that is not listed in included framework
// solve this by moving through all swiftLibs and resolve their not listed dependencies
Set<String> libsToResolve = new HashSet<>(swiftLibraries);
Set<String> weakLibs = new HashSet<>(weakSwiftLibraries);
Map<String, File> resolvedLibs = new HashMap<>();
while (!libsToResolve.isEmpty()) {
for (String library : new HashSet<>(libsToResolve)) {
libsToResolve.remove(library);
if (!resolvedLibs.containsKey(library)) {
File swiftLibrary = locateSwiftLib(swiftDirs, library);
resolvedLibs.put(library, swiftLibrary);

getSwiftDependencies(swiftLibrary, libsToResolve);
if (swiftLibrary != null) {
resolvedLibs.put(library, swiftLibrary);
getSwiftDependencies(swiftLibrary, libsToResolve, weakLibs);
} else {
if (weakLibs.contains(library))
config.getLogger().warn("Weak " + library + " is not found in swift paths");
else throw new FileNotFoundException(library + " is not found in swift paths");
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -851,7 +851,7 @@ private void packageApplication(File appDir) throws IOException {
}

swiftSupportDir.mkdirs();
copySwiftLibs(Arrays.asList(swiftLibs), swiftSupportDir, false);
copySwiftLibs(Arrays.asList(swiftLibs), Collections.emptyList(), swiftSupportDir, false);
}
}

Expand Down

0 comments on commit 56914f5

Please sign in to comment.