diff --git a/compiler/compiler/src/main/java/org/robovm/compiler/target/AbstractTarget.java b/compiler/compiler/src/main/java/org/robovm/compiler/target/AbstractTarget.java index 54234277f..b30716c36 100755 --- a/compiler/compiler/src/main/java/org/robovm/compiler/target/AbstractTarget.java +++ b/compiler/compiler/src/main/java/org/robovm/compiler/target/AbstractTarget.java @@ -329,6 +329,7 @@ public void processFile(Resource resource, File file, File destDir) protected void copyDynamicFrameworks(File destDir, File appExecutable) throws IOException { final Set swiftLibraries = new HashSet<>(); + final Set weakSwiftLibraries = new HashSet<>(); File frameworksDir = new File(destDir, "Frameworks"); for (String framework : config.getFrameworks()) { @@ -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); } } } @@ -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 @@ -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 swiftLibraries) throws IOException { + protected void getSwiftDependencies(File file, Collection swiftLibraries, Collection 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); + } } } @@ -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 { @@ -645,22 +653,29 @@ private File[] getDefaultSwiftDirs(String system) throws IOException { return swiftDirs.toArray(new File[0]); } - protected void copySwiftLibs(Collection swiftLibraries, File targetDir, boolean strip) throws IOException { + protected void copySwiftLibs(Collection swiftLibraries, Collection 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 libsToResolve = new HashSet<>(swiftLibraries); + Set weakLibs = new HashSet<>(weakSwiftLibraries); Map 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"); + } } } } diff --git a/compiler/compiler/src/main/java/org/robovm/compiler/target/ios/IOSTarget.java b/compiler/compiler/src/main/java/org/robovm/compiler/target/ios/IOSTarget.java index 2302dfc35..437fd8b5e 100755 --- a/compiler/compiler/src/main/java/org/robovm/compiler/target/ios/IOSTarget.java +++ b/compiler/compiler/src/main/java/org/robovm/compiler/target/ios/IOSTarget.java @@ -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); } }