API availability on linux?

Can someone tell me where I'm supposed to look to discover that URL.lines is not available on Linux? I don't see any mention of it here.

Thanks
-Dave

6 Likes

In fact, looking at the repository, it seems only 3 async APIs in Foundation have been ported to Linux:

URLSessionTask.swift:739: open func sendPing() async throws {
URLSessionTask.swift:801: public func send(_ message: Message) async throws -> Void {
URLSessionTask.swift:821: public func receive() async throws -> Message {

the short answer is you can’t, because linux isn’t a platform that can be described with the @available attribute.

the long answer is in general, this is not something that can be surfaced by documentation engines, the row of platform pills on a symbol’s doc page comes from its @available mixin, and this is technically orthogonal to whether a symbol is actually “available” on a particular platform. (although one could hope they would at least correlate.)

to illustrate why this can happen, consider:

extension URL
{
#if os(iOS)

    @available(Windows, unavailable,
        message: "iOS thinks this is unavailable on windows")
    var lines:AsyncLineSequence<URL.AsyncBytes> { ... }

#elseif os(Windows)

    @available(iOS, unavailable,
        message: "windows thinks this is unavailable on iOS")
    var lines:AsyncLineSequence<URL.AsyncBytes> { ... }

#endif
}

I think you're missing my point, which has nothing to do with language features or documentation engines. If Swift is going to be taken seriously as a cross-platform language and Foundation is going to be viewed as its uniform interface to platform-specifics, it has to be possible to discover which APIs can be used without digging through the Foundation sources.

13 Likes

for this to be possible we first need to decide “which” Foundation is the “real” Foundation we should be showing APIs for. as far as i am aware there are now at least three forks of Foundation out in the wild today:

  • the Foundation that is a system framework and ships with Apple OSes
  • the open source Foundation "corelibs" that ship with the toolchain and need to be statically linked or installed manually on linux
  • the open source FoundationEssentials that was recently announced and seems to be targeting an SPM-based distribution scheme

as i understand it, they are effectively three different frameworks with a lot of similar-looking API, but as you've observed, that have differences between them.

4 Likes

I appreciate the problem you're describing but I don't think we need to decide anything. The vendors of these frameworks have a responsibility to document their APIs and where there is overlap, accurately describe the overlap. How they get there and whether it's described as "Foundation" or something else doesn't matter to me.

4 Likes

i think that if you are using the open source flavor of Foundation on linux, the best solution for you is to simply read the documentation for the fork you are using, rather than the apple.com Foundation docs, which are generated from the Apple fork of the library.

i’ll point out that the swiftinit docs for URL do not show the lines property because swiftinit mirrors the Foundation fork for linux.

I'm not using a fork; I'm using the official Foundation that ships with Swift. Do separate docs exist for that? For which platforms? Linux? Windows? What about the next platform that comes along… do you see the problem I'm pointing out here?

1 Like

you are using a fork, you are using the official Foundation that ships with Swift. it just so happens that there are two official Foundations on ABI-stable and non-ABI stable platforms. and notably, you are not using the FoundationEssentials fork that ships as a package.

yes. i linked a mirror of those docs in the post above.

the way that documentation works is you compile a library, which emits a bunch of artifacts in a .build directory, and then you use the build artifacts to link a documentation bundle. it follows that you cannot compile a “universal” documentation bundle that applies to all swift platforms, for the exact same reason you cannot compile a “universal” binary that runs on all swift platforms.

it seems you are thinking of documentation as something that is generated by scanning source code, but this is not how documentation works. documentation is compiled, just like an executable. it makes sense to talk about things like cross-compilation (e.g. generating docs for macOS from a linux host, which to my knowledge, isn’t supported either), but it doesn’t make sense to talk about things like “universal” compilation.

by the way, this isn’t unique to Foundation. everything i mentioned above also applies to the standard library and third-party SPM packages. it just so happens that many SPM packages are very portable and vend the same API on all platforms, so it is less noticeable for them, and a lot of people browse docs generated for the wrong platform without ever realizing it.

Absolutely not. I'm thinking of documentation as an obligation of library vendors, produced completely by hand if necessary. For a library advertised/intended for abstracting away platform details to be effective in that job, there needs to be a central description of its portable subset.

14 Likes

The issue has two parts:

  • Foundation is a special situation because currently different libraries are actually used whether you are on an Apple system or elsewhere (Linux, Windows). This will change when using the new Foundation implementation.
  • The availability of some general kind of “platform indicator” for libraries (or parts of them). The platform check that you have in SPM for macOS versions is too limited.
1 Like

this might not be a popular opinion, but i remember the swift 3 days before we had SymbolGraphGen when documentation was written entirely by hand and you had to spend hours per type copying and pasting github URLs into markdown links, and i do not want to go back.

back then, it took a very long time to produce documentation, even for small packages with few (hundreds of) symbols. and this documentation frequently fell out of date because updating it was a tedious process that often slipped through the cracks in the course of a typical development cycle. and oftentimes the documentation would simply break on its own because files would move around and URLs would 404 until somebody noticed a problem and filed a GitHub issue.

today in 2023, this approach is simply not going to scale, to put it lightly. some packages vend thousands of declarations; SwiftSyntax on main currently contains 16,066 declarations, while SwiftNIOSSL has 10,762, not counting “synthesized” declarations inherited through protocol conformances, etc.

with macros coming into the picture with 5.9, API surfaces are likely to expand further, and writing docs by hand is going to be even less tenable.

i know firsthand how annoying it is to figure out what String method belongs to which module and what flavor of Foundation you need to use that API, and i don’t think the current state of swift documentation is ideal, or even acceptable by any means. but reverting to cataloging and formatting these docs by hand is just not realistic.

1 Like

Yes, as you already expressed this before: You want such documentation details as platform support better to be generated from what is expressed in your code. We are missing some features here.

But note that this is a complex problem: How should the author of a library e.g. define compatibility with Windows if she has no Windows available or is just not interested in testing every possible platform? (Certainly to be discussed in a separate topic.)

I feel like this thread is speaking more abstractly than OP, who asked about API availability on Linux for a library whose purpose is to provide an API to platforms like Linux. Looking at the readme it's very difficult to see what's available and the only formal documentation linked is Apple's Foundation.

Maybe this is just the state of documentation on cross-platform Foundation until the swift-foundation project is complete, but I don't think it's helpful deliberating the pros and cons of documentation compiled vs handwritten in response to "where do I see networking APIs available to Linux."

7 Likes

You don't really think I was suggesting that, do you?

I'm just saying that if one is going to vend a library to successfully serve a particular purpose, one must produce documentation that supports that purpose, by whatever means necessary. As long as Foundation is trying to “provide a level of OS independence, to enhance portability”, the Foundation vendors need to find a solution to this problem. I can think of ways to do it while still using automated documentation extraction and without changing the language, but that's not my problem to solve.

10 Likes

People are already working hard on the solution :+1:

i have run into a similar issue today while trying to port a linux-only package to macOS without having a mac computer available.

  1. i discovered that the signature of FilePermissions.init(rawValue:) differs between macOS and linux.

  2. because the CI log only showed error: the compiler is unable to type-check this expression in reasonable time, i wanted to discover the actual signature of this initializer through symbol documentation without print-debugging through the CI pipeline.

  3. i first clicked through the Swiftinit links until i reached CSystem.__mode_t, which points to UInt32. neither that typealias, nor any of the intermediate typealiases had any doccomments that indicated what it resolves to on macOS.

  4. i tried looking at the source for CInterop.swift, which also didn’t help.

#if os(Windows)
  public typealias Mode = CInt
#else
  public typealias Mode = mode_t
#endif

i have no idea what the solution here is, but i think it would have to account for the following:

  1. the problem is bigger than “is it available or not”, sometimes the signature itself is different on different platforms. so we cannot solve this with availability badges.

  2. sometimes the signature spelling is the same, and the only thing that differs is a typealias resolution, which lives in a completely different module/package. in this case, adding labels of any sort to the user-facing declaration would be pointless.

1 Like

Despite this thorny case, would you say there's been significant progress on the overall problem since I raised the issue last June?

i haven’t used swift-foundation enough to be able to make that assessment.

@sspringer any progress to report?