How to leverage swift-api-digester to compare API changes between two xcframework versions

Hi folks,

in our team we're trying to leverage the swift-api-digester that's shipped as part of the swift toolchain, running on macOS.

Problem statement:
Compare public API across two versions of binary framework A.xcframework

We have found this example that showcases comparing two sdks.

The example above showcases a comparisons between two sdks, which contain the frameworks under System/Library/Frameworks subfolder + requires specific sdk setup.

Is there a way to compare binary .xcframework or .framework using the swift-api-digester.
Could you please share working example?

Thanks a mil!

Best,
Boris

2 Likes

Hi,

I've created a GitHub repo that contains 2 versions (folders V1 and V2) of the same module ModuleA built as xcframework for iOS platform.

I've tried to use the swift-api-digester the get the API diff between the two versions of the module.

By running the following command:

xcrun swift-api-digester \
         -diagnose-sdk \
         -module ModuleA \ 
         -print-module \
         -I V2/ModuleA.xcframework/ios-arm64/ModuleA.framework/ModuleA \
         -BI V1/ModuleA.xcframework/ios-arm64/ModuleA.framework/ModuleA \ 
         -sdk /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk \       
         -bsdk /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk \ 
         -abi \
         -o moduleA_api_diff \
         -v

I'm getting this error:

Loading module: ModuleA...
Failed to load module: ModuleA
Scanning symbols...
Loading module: ModuleA...
Failed to load module: ModuleA
Scanning symbols...

Questions:

  1. Am I using the correct arguments to get the API diff of 2 module stable frameworks?
  2. Am I using the correct paths for -I and -BIarguments?

Iteration #2

Running following command

xcrun swift-api-digester \
-diagnose-sdk \
-module ModuleA \
-print-module \
-BF V1/ModuleA.xcframework/ios-arm64/ \
-F V2/ModuleA.xcframework/ios-arm64/ \
-BI V1/ModuleA.xcframework/ios-arm64/Modules \
-I V2/ModuleA.xcframework/ios-arm64/Modules \
-bsdk /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk \
-sdk /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk \
-use-interface-for-module ModuleA \
-abi \
-o api_diff \
-v

executes succesfully

Loading module: ModuleA...
Scanning symbols...
Loading module: ModuleA...
Scanning symbols...

but the API diff is empty.


/* Generic Signature Changes */

/* RawRepresentable Changes */

/* Removed Decls */

/* Moved Decls */

/* Renamed Decls */

/* Type Changes */

/* Decl Attribute changes */

/* Fixed-layout Type Changes */

/* Protocol Conformance Change */

/* Protocol Requirement Change */

/* Class Inheritance Change */

/* Others */

Expected result from swift-api-digester should reflect this diff between V1 and V2

Did you find a solution to compare binary frameworks?

Hi @OdNairy.

Unfortunately not. The swift-api-digester is currently not shipped under the Xcode toolchain and the lack of the documentation didn't lead me anywhere.

I wish there was a simple way to eg compare two public interfaces (.swiftinterface) on a PR level to catch the sensible breaking changes as early as possible.

Currently all we can do is probably just be vocal about this issue on the open swift bugs.

Boris, I have a good news – I was able to make swift-api-digester run for binary SDKs :tada:.
I also wrote some README which you can find here: https://github.com/mapbox/mapbox-maps-ios/tree/main/scripts/api-compatibility-check.

I wish there was a simple way to eg compare two public interfaces (.swiftinterface)

It would be SO easy, but overall the same. You have to "load" Clang modules to the digester, that's why you have to provide paths to all dependency swift modules.

4 Likes

Man, you're legend! :)

1 Like