-ObjC flag causes duplicate symbols with Swift Packages

If you're referring to @ciauri's project above, there's no evidence of that in the build log. What's happening is:

  1. The Package target (Swift package target) is built, producing a relocatable object file (instead of a static library) (clang -r ... -o Package.o).

  2. The StaticLib target (Xcode static library target) is built, producing a static library. The file list passed to libtool contains the .o file from its own .swift source and the Package.o from the dependency. But, Package.o is also passed separately on the command line outside of the file list. libtool doesn't deduplicate these inputs, and even emits a warning about the conflict:

    warning same member name (Package.o) in output file used for input files: /path/to/Build/Products/Debug-iphonesimulator/Package.o and: /path/to/Build/Products/Debug-iphonesimulator/Package.o (due to use of basename, truncation, blank padding or duplicate input files)

  3. The App target (Xcode app target) is built. The linker takes the object files for the target's own .swift files as inputs in the file list, and then the command line also includes libStaticLib.a. It does not separately contain Package.o from step 1.

There's another way that we can verify that -ObjC is causing the problem hereā€”just remove it from the App target. If we do that, the App links fine, because there are no references to symbols from Package in App. Even if we have App reference a symbol in Package, it still works without -ObjC because the linker stops looking once it finds the first object file in libStaticLib.a that defines the symbols it's looking for. Since the two copies of Package.o are the same, it will never find symbols in the second one that it hasn't already found in the first one, so the duplicate never gets pulled in unless you force it.

6 Likes