We broke the public API by accident (fixed now) in SwiftNIO and now want to add automatic public API change detection to our CI to prevent this from happening again.
I think swift-api-digester
can help us there but I'm kind of unsure how to use it. I tried
swift build
xcrun /Users/johannes/devel/swift/build/Ninja-RelWithDebInfoAssert/swift-macosx-x86_64/bin/swift-api-digester -module-cache-path "$PWD/.build/x86_64-apple-macosx/debug" -module NIO -dump-sdk -o /tmp -swift-version 5
but it fails with
$ xcrun /Users/johannes/devel/swift/build/Ninja-RelWithDebInfoAssert/swift-macosx-x86_64/bin/swift-api-digester -module-cache-path "$PWD/.build/x86_64-apple-macosx/debug" -module NIO -dump-swift -o /tmp/output -swift-version 5
Stack dump:
0. Program arguments: /Users/johannes/devel/swift/build/Ninja-RelWithDebInfoAssert/swift-macosx-x86_64/bin/swift-api-digester -module-cache-path /Users/johannes/devel/swift-nio/.build/x86_64-apple-macosx/debug -module NIO -dump-swift -o /tmp/output -swift-version 5
0 swift-api-digester 0x000000010698ea58 llvm::sys::PrintStackTrace(llvm::raw_ostream&) + 40
1 swift-api-digester 0x000000010698dcd5 llvm::sys::RunSignalHandlers() + 85
2 swift-api-digester 0x000000010698f062 SignalHandler(int) + 258
3 libsystem_platform.dylib 0x00007fff5e6fdb5d _sigtramp + 29
4 libsystem_platform.dylib 0x00007ffeec5ff9b0 _sigtramp + 2381323888
5 swift-api-digester 0x000000010362f9b7 swift::ide::api::dumpSwiftModules(swift::CompilerInvocation const&, llvm::StringSet<llvm::MallocAllocator> const&, llvm::StringRef, std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >, swift::ide::api::CheckerOptions) + 1815
6 swift-api-digester 0x00000001035fd736 main + 1926
7 libdyld.dylib 0x00007fff5e5183d5 start + 1
Segmentation fault: 11
using -dump-all
it prints
$ xcrun /Users/johannes/devel/swift/build/Ninja-RelWithDebInfoAssert/swift-macosx-x86_64/bin/swift-api-digester -module-cache-path "$PWD/.build/x86_64-apple-macosx/debug" -module NIO -dump-sdk -o /tmp/output -swift-version 5
Failed to load module: NIO
but I have
$ ls -la .build/x86_64-apple-macosx/debug/NIO.swiftmodule
-rw-r--r-- 1 johannes staff 1059356 11 Apr 10:31 .build/x86_64-apple-macosx/debug/NIO.swiftmodule
mackoj
(Jeffrey Macko)
April 11, 2019, 10:22am
2
2 Likes
dmcyk
(Damian Malarczyk)
April 11, 2019, 9:04pm
3
I think you might be using wrong flags, I guess module-cache-path
is something internal to Clang and doesn't necessarily need to be used? I've been using -I
to add module search paths and that seems to be working.
I created an empty SPM project and did so:
$ swift build
$ xcrun swift-api-digester -dump-sdk -module ApiSpm -o foo -I .build/debug
There are some examples in the Swift repository in test/api-digester
.
@dmcyk Awesome, thank you, that totally worked!
Just as documentation, here's the commands that work for me. As an example, here's the API breakage diffing between NIO 1.13.2
and NIO 1.14.0
where we broke the API by accident. We fixed it according to SemVer by very quickly releasing a 1.14.1
which repairs it again:
Generate 1.13.2 API JSON
git checkout 1.13.2
swift build
xcrun ../build//Ninja-ReleaseAssert/swift-macosx-x86_64/bin/swift-api-digester \
-dump-sdk -module NIO -o nio-1.13.2.json -I .build/debug
Generate 1.40.0 API JSON
git checkout 1.14.0
swift build
xcrun ../build//Ninja-ReleaseAssert/swift-macosx-x86_64/bin/swift-api-digester \
-dump-sdk -module NIO -o nio-1.14.0.json -I .build/debug
Check for breakages
xcrun ../build//Ninja-ReleaseAssert/swift-macosx-x86_64/bin/swift-api-digester \
-diagnose-sdk --input-paths nio-1.13.2.json -input-paths nio-1.14.0.json
which outputs:
/* Generic Signature Changes */
/* RawRepresentable Changes */
/* Removed Decls */
Func EventLoopFuture.hopTo(eventLoop:) has been removed
/* Moved Decls */
/* Renamed Decls */
/* Type Changes */
Func EventLoopFuture.andAll(_:eventLoop:) has parameter 0 type change from [EventLoopFuture<Void>] to [EventLoopFuture<T>]
/* Decl Attribute changes */
/* Fixed-layout Type Changes */
/* Protocol Conformance Change */
/* Protocol Requirement Change */
/* Class Inheritance Change */
and as you can see, hopTo
was removed by accident as well as the andAll
change which is less severe. CC @tanner0101
6 Likes
jrose
(Jordan Rose)
April 15, 2019, 5:41pm
6
cc @Xi_Ge for any additional guidance
1 Like
Xi_Ge
(Xi Ge)
April 15, 2019, 5:50pm
7
These steps documented by @johannesweiss looks correct to me for API stability checking. An additional tip is to check ABI stability, one can simply pass -abi
for all these three steps. One example from the Swift stdlib can be found here: https://github.com/apple/swift/blob/master/test/api-digester/stability-stdlib-abi.swift
2 Likes
Thanks @Xi_Ge ! Now @tomerd and I are working on productising this so that SwiftNIO's CI will run swift-api-digester automatically. Unfortunately, we struggle to get it to work on Linux (filed as SR-10539 ). Anything obvious we're missing?
Aciid
(Ankit Aggarwal)
April 23, 2019, 4:25pm
9
That sounds cool. I wonder if we should add support for this tool in SwiftPM.
7 Likes
tkrajacic
(Thomas Krajacic)
April 23, 2019, 4:37pm
10
Right after resource support .
No seriously, that sounds like a fantastic idea. It would help the SPM package ecosystem a lot I guess!
3 Likes
Yes please, that would be super awesome! @Aciid should I file a bugs.swift.org or a Radar or smth?
1 Like
Aciid
(Ankit Aggarwal)
April 23, 2019, 6:01pm
12
JIRA sounds good. It would be great if you can include links or something to how NIO is using it.
1 Like
ktoso
(Konrad 'ktoso' Malawski 🐟🏴☠️)
April 24, 2019, 3:21am
14
As others said: That would be fantastic! Voted on the issue
It's something I've been missing from moving over from Scala ecosystem where we've built such tools (though in sbt via the plugin ecosystem).