swiftlang / swift-package-manager

The Package Manager for the Swift Programming Language
Apache License 2.0
9.76k stars 1.35k forks source link

PackagePlugin's PackageManager.getSymbolGraph does not support binaryTarget #7580

Open Kyle-Ye opened 6 months ago

Kyle-Ye commented 6 months ago

Is it reproducible with SwiftPM command-line tools: swift build, swift test, swift package etc?

Description

Background Context: https://github.com/SwiftPackageIndex/SwiftPackageIndex-Server/issues/3061#issuecomment-2118726676

If a target has a dependency on binaryTarget. Then the call of PackageManager.getSymbolGraph to that target will get a directory contains no symbol graph.

It will break PackageManager.getSymbolGraph's client such as swift-docc-plugin.

The downstream user can generate doc using swift build and call docc convert to generate documentation. But if they migrate to swift-docc-plugin or swift-docc-plugin based service like SwiftPackageIndex, the documentation build will fail.

// ✅ Build Package Documentation via Xcode GUI

// ✅ Build Package Documentation manually
swift build --target DemoKit \
  -Xswiftc -emit-symbol-graph \
  -Xswiftc -emit-symbol-graph-dir -Xswiftc "./symbol-graph"

docc convert --additional-symbol-graph-dir ./symbol-graph ...

// ❌ Build Package Documentation via swift-docc-plugin
swift package generate-documentation --target DemoKit

Expected behavior

Produce SymbolGraph normally.

Actual behavior

Call swift-symbolgraph-extract with the arguments manually in terminal or adding the following patch to SymbolGraphExtract.swift

    public func extractSymbolGraph(
        ...
        try process.launch()
-       try process.waitUntilExit()
+       let result = try process.waitUntilExit()
+       if let error = String(bytes: try result.stderrOutput.get(), encoding: .utf8) {
+            print(error)
+.      }
    }

And you will get the following error message.

"<unknown>:0: error: missing required module \'MMKV\'\nError: Failed to load the module \'DemoKit\'. Are you missing build dependencies or include/framework directories?\nSee the previous error messages for details. Aborting.\n"

I have tried to add the framework manually via -F/-I/-L ${MMKV_framework_path} but none of them will work.

Steps to reproduce

For user side reproduce steps:

  1. Download the following DemoKit.zip package
  2. Run swift package generate-documentation --target DemoKit --verbose and no documentation will be created.

For swiftpm developer reproduce steps:

  1. Set up swiftpm repo development environment
  2. Build PackageDescription target first and then choose swift-package target
  3. Set working directory to DemoKit and the corresponding arguments on launch in Xcode 4.(Optional) Apply the diff mentioned above.

DemoKit.zip

Note: Here I use MMKV.xcframework as an example but any binary framework would have the same issue. The binary framework have nothing special here.

Swift Package Manager version/commit hash

5.10

Swift & OS version (output of swift --version ; uname -a)

5.10 & macOS 14.4.1

Kyle-Ye commented 6 months ago

Is this an expected unimplemented feature or a bug we should fix? Checking the repository's Git history, I believe @MaxDesiatov would have some insights on this scope. Could you help give a look at this? Thanks

QuietMisdreavus commented 2 months ago

Based on a similar discussion i just had with another developer, it looks like the underlying issue is that xcframework dependencies are being passed to swift-symbolgraph-extract with -I paths, rather than -F paths. If those flags are changed in that command, it should be able to generate symbol graphs successfully.

Kyle-Ye commented 2 months ago

Based on a similar discussion i just had with another developer, it looks like the underlying issue is that xcframework dependencies are being passed to swift-symbolgraph-extract with -I paths, rather than -F paths. If those flags are changed in that command, it should be able to generate symbol graphs successfully.

~I have tried to add the framework manually via -F/-I/-L ${MMKV_framework_path} but none of them will work.~

~eg. Run swift package generate-documentation --target DemoKit for DemoKit I attached above. It will fail and give us the full command of swift-symbolgraph-extract.~

~Change -I to -F still does not work for me here.~

xcrun \
swift-symbolgraph-extract \
-sdk \
/Applications/Xcode-16.0.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.0.sdk \
-F \
/Applications/Xcode-16.0.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/Library/Frameworks \
-I \
/Applications/Xcode-16.0.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/usr/lib \
-L \
/Applications/Xcode-16.0.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/usr/lib \
- -I \
+ -F \
/Users/kyle/Downloads/DemoKit/.build/artifacts/demokit/MMKV/MMKV.xcframework/macos-arm64_x86_64 \
-Xcc \
- -I \
+ -F \
-Xcc \
/Users/kyle/Downloads/DemoKit/.build/artifacts/demokit/MMKV/MMKV.xcframework/macos-arm64_x86_64 \
-I \
/Users/kyle/Downloads/DemoKit/.build/arm64-apple-macosx/debug/Modules \
-module-name \
DemoKit \
-target \
arm64-apple-macosx10.13 \
-module-cache-path \
/Users/kyle/Downloads/DemoKit/.build/arm64-apple-macosx/debug/ModuleCache \
-minimum-access-level \
public \
-skip-inherited-docs \
-emit-extension-block-symbols \
-output-dir \
/Users/kyle/Downloads/DemoKit/.build/arm64-apple-macosx/extracted-symbols/demokit/DemoKit
<unknown>:0: error: missing required module 'MMKV'
Error: Failed to load the module 'DemoKit'. Are you missing build dependencies or include/framework directories?
See the previous error messages for details. Aborting.

Update

Maybe some cache issue, after adding both -I and -F, it will work for me now. And delete -I with only -F will also work.

Kyle-Ye commented 2 months ago

-I ${MMKV_framework_path} is produced by SwiftModuleBuildDescription.additionalFlags. Trying to debug it and prepare a PR for it.