Multiple dynamic libraries in a package under SPM

We are currently building an app in Swift, reusing an internal C++ backend used in other platforms ( Linux/Windows/Mac ).

Current state of the project:

  • App W - ( Swift App )

    • Package X - Swift Package
      • Y.xcframework - Binary Target (ios-arm64 and ios-arm64-simulator)
        • Z.framework
          • Z - (C++ Backend as a library) Dynamic Library
          • Headers - Library header files
          • Frameworks (Folder) - Required .dylib’s for Z (
            • libA.dylib (Dependency of Z) [ 58 of them ]
            • libB.dylib (Runtime dependency of python) [ 123 of them ]
          • data - Supporting binary files for Z
          • conf - Supporting configuration files, both text and binary. for Z
          • python - Supporting .py scripts
            • C.py
            • D.py

Z.framework ( C++ ) contains 182 Dynamic Libraries.

Goal:

Validate the app for distribution with the Apple Store validation tool.

Learning when trying to solve the problem:

  • A framework can contain only one dynamic library (e.g. .dylib )
  • A framework cannot have nested frameworks within a Frameworks folder
  • Certain file types within a framework are not treated as resource files (e.g. .py files)

Possible solutions

  • Allow to have nested Frameworks in Z.framework.
    • It’s currently not allowed
  • Link 182 dynamic libraries into the project via SPM
    • Problem: Some of the libraries need to dynamically loaded at runtime (related to the python runtime)
    • Making the libraries static adds significantly technical challenges to the Z.framework.

Other questions:

What’s the best way to achieve this

Many of the requirements that you need to satisfy from the iOS side and the Python side are in conflict with each other, per your description. I can only comment on details from the iOS side, so you may also want to consult the Python community for options on their end.

As you found, nested dynamic libraries are not permitted on iOS. That's a stringent requirement that forces you down a narrow set of paths:

  1. Each nested library needs to be turned into its own framework package that looks identical to what File > New Target > Framework in Xcode produces, down to file name patterns, Info.plist keys, and so on. All of these frameworks need to be nested as a direct child of the app, with no nesting within frameworks.

  2. Switch to static linkage. It sounds like there's some dynamic loading requirements form the Python end, but maybe you can fold many of the individual frameworks required into one single library that is statically linked. Maybe you won't be able to get there in full and still need to go down the (1) path, but perhaps some amount of statically linking libraries will result in far fewer libraries.

  3. Pay attention to mergable libraries. It's a relatively new linker feature that is sort of between static and dynamic linking. However, it requires opting in during the build, so you'd need to consult the Python folks to see if they're ready to use such features.

If you want to talk about the details of any one of those choices without any Python specific details, I'm happy to do so, though I suspect the support you're looking for in solving these problems will be found from those within the Python community who have already gone down this path.

— Ed Ford,  DTS Engineer

Multiple dynamic libraries in a package under SPM
 
 
Q