What I'm trying to achieve
A Swift user should be able to build a dynamic library with Swift and use it anywhere - in apps written in other programming languages. Simple C types like integers seem to be the least common denominator that are supported in most programming languages. So a function like this
@_cdecl("meaningOfLife")
public func meaningOfLife() -> Int {
return 42
}
should be callable from an app written in a language other than Swift. What is missing here for a programmer who wants to call this function from their non-Swift app, is a separate file with a list of APIs available in the library.
How I did it in the past
I use swiftc
compiler. In the past I passed the -emit-clang-header-path
parameter to it, with C++ interoperabiliy turned on. This generated a header (.h) file that contained the desired list of APIs. In C and C++ it could be directly used by C/C++ compiler, and for programmers using other languages it provided a way to reason about available APIs and write language-specific bindings.
I don't use this approach anymore for the following reasons:
- In recent versions of Swift this parameter is not listed in the output of
swiftc -help
, nor evenswiftc -help-hidden
. - In Swift 6 it still works, but for the simple source code above it produces an enormous header file (170K, 5390 lines) full of C++ interoperability things. Obviously not what I want.
- For this approach C++ interoperability should be turned on (or else only Objective-C compatible header file is emitted). As of Swift 6.0.1 C++ iteroperability does not work on Windows.
How I do it now
Now I use similar -emit-objc-header-path
command-line parameter. It is documented in swiftc -help
, creates a header file of reasonable size (10K, 313 lines), and does not require C++ interoperability mode. What I don't like is the fact that Objective-C header file is hardly of any direct use, especially on Windows. It can only serve as a reference for writing another language-specific bindings, and for this purpose it is not very convenient.
What else I tried
In Swift 6 there is another command-line option: -emit-api-descriptor-path
, which looks like exactly what I need. But for the source code above it produces the following:
{
"target": "x86_64-unknown-windows-msvc",
"globals": [
{
"name": "$s14dynamicLibrary13meaningOfLifeSiyF",
"access": "public",
"file": "dynamicLibrary.swift",
"linkage": "exported"
},
{
"name": "meaningOfLife",
"access": "public",
"file": "dynamicLibrary.swift",
"linkage": "exported"
}
],
"interfaces": [],
"categories": [],
"version": "1.0"
}
I can live with the mysterious $s14dynamicLibrary13meaningOfLifeSiyF
, but as for the meaningOfLife() -> Int
function, this JSON does not mention that the function returns an Int
, and thus is completely useless for my purpose.
The question
Is there a way to list the APIs provided by my dynamic library (other than Objective-C header file)?