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)

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 committed May 6, 2024
1 parent 1206cb6 commit 2e6a130
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 2e6a130

Please sign in to comment.