Is binary compilation restricted to library-evolution mode compilation?

When compiling a binary (xc)framework from a Swift Package, one must set BUILD_LIBRARY_FOR_DISTRIBUTION=YES. This has a number of implications.

Over the past few years I've stumbled upon uses cases where I would like to make binaries, but without providing the library evolution support. Example scenarios are build caching and internal distribution within an organisation.

I couldn't find a way to build working xcframeworks without setting BUILD_LIBRARY_FOR_DISTRIBUTION=YES.

If you don't set, the module interface file is not generated.

If you do set it, a number of things generally go wrong. Frozen enums, @escaping attributes, to @inline(able) attributes, etc. A lot of frameworks don't compile. swift-collections and swift-algorithms don't compile with that flag set.

TLDR, I have a use case where I would like to generate binaries (xcframeworks), but not guarantee library evolution. Is this possible, and if not, I'm curious what is the reason?

1 Like

I'll answer here just in order to share my own experience, and be corrected if I'm doing anything wrong. I jump on your boat, @Srdan_Rasic ;-)

As far as I know, BUILD_LIBRARY_FOR_DISTRIBUTION is indeed required for building XCFrameworks. On top of that, the Distributing binary frameworks as Swift packages documentation only mentions XCFrameworks as valid binaries artifacts for SPM packages:

To distribute code in binary form as a Swift package, create an XCFramework bundle, or artifact , that contains the binaries.

The SPM documentation itself mentions "binary artifact" but does not define the word. SE-0305 says:

In the current version of SwiftPM, binary targets only support libraries in an Xcode-oriented format called XCFramework , and only for Apple platforms.

A search for "binary" in the SPM repository did not reveal much more information.

One of the libraries I maintain has users who need to build XCFrameworks from it. The technique I have been using is:

  • Make sure (i.e. test) that I can build an XCFramework from the library. If any compiler error happens during this build, they must be fixed.
  • Document quite clearly that the library supports XCFramework but does not support library evolution. It is a "regular" library where semantic versioning applies to the API, but not the ABI. Support for library evolution is only a convenience for some users.
  • Be lazy. I only do the minimum reasonable amount of work for the XCFramework to build, and I wait for user requests until I start thinking deeply about details. Mainly, I do not intend to annotate code with @frozen or other attributes that would send a wrong message to users or maintainers. The wrong message would be that the library moves towards ABI-stability, and that a lot of thoughts has been put in the process. There is no such effort. ABI stability is so very hard.

In the end, I would suggest explaining to the maintainers of the packages that do not build under library evolution what is their opinion about your goal and your failed attempts (be explicit about your goal, in order to avoid the XY problem). Maybe you will be suggested an alternative. Or maybe they will listen and more libraries will support XCFrameworks :-)


You can create a XCFramework without enabling library evolution mode by passing -allow-internal-distribution to xcodebuild -create-xcframework.