Best strategy for `#if` when using DocC?

DocC just drops symbols behind #if unless the documentation is built under the matching conditions. I am curious what others do to mitigate this.

I toyed with applying a static check to the project to prohibit API symbols in #if, but there are too many things that cannot be refactored to satisfy that.

3 Likes

I have the same question for GRDB

This is currently expected. To get the most accurate data possible it is recommended that you build your documentation using the same settings you plan to use on the release version of your framework/app. This is done to ensure that the API data matches what will wind up in the product accurately.

I know it is expected. The use case is generating hosted documentation for a package where symbol availability differs between macOS, Linux, Windows, etc. The question is how to best organize the code or arrange the hosted documentation to minimize confusion about the differences.

3 Likes

The way to achieve this would be to generate symbol graphs on each of those respective platforms and then feed them all to docc at compilation time. DocC supports merging symbols that appear in multiple symbol graphs it receives as input.

So something like this:

  1. Run swift package dump-symbol-graph on macOS, Linux, Windows, etc and store the symbol graphs produced on each platform in a single directory.
  2. Run docc convert <path-to-docc-catalog> --additional-symbol-graph-dir <path-to-directory-with-symbol-graphs-from-all-platforms>

DocC will produce a single documentation archive that contains the symbols for all platforms – any symbols that appear in multiple platforms will be merged into a single page. Hypothetically they should be marked with their platform availability as well but I'm not sure how well supported that is currently – certainly something we would want to fix if it doesn't work.

12 Likes

Hi @ethankusters,

they should be marked with their platform availability

do you mean that DocC would determine a #if os() statement and would mark the function accordingly?

public struct MixedAPI {
    public init() {}
    public var prop1: String = ""
        
    #if os(visionOS)
    public func funcOnVisionOSOnly() {}
    #endif
}

I would love this but in my tests it doesn't work.

CDAppleDefaultAvailability entries will be applied.

If @available attribute(s) are used then the platform availability will be displayed correctly.

public struct MixedAPI {
    public init() {}
    public var prop1: String = ""
        
    #if os(visionOS)
    @available(visionOS, introduced: 1.0) 
    @available(iOS, unavailable) 
    public func funcOnVisionOSOnly() {}
    #endif
}

Do you know of any plans if/when DocC would determine a #if os() statement and would mark the function accordingly?

Understandably marking platform availability would not work for any other active compilation statements (e.g. if DEBUG)

i imagine this would require support at the lib/SymbolGraphGen level, there's currently no way to produce symbol graphs for a platform without actually compiling the code on that platform.

JSON parsing is also a huge performance bottleneck currently when merging symbol graphs, so i'm not sure if "build multiple symbol graphs" is scalable.