swiftwasm / swift

WebAssembly support for the Swift programming language
https://swiftwasm.org
1.3k stars 28 forks source link

Cannot import the main module of a executable in the test module #5375

Open gmondada opened 1 year ago

gmondada commented 1 year ago

Description Tests on a default Hello World carton project fails during compilation. Here is the result of carton test:

error: no such module 'carton_demo'
@testable import carton_demo
                 ^
note: module 'carton_demo' is the main module of an executable, and cannot be imported by tests and other targets

Executing swift test on the same project just works.

Steps to reproduce

mkdir carton_demo
cd carton_demo
carton init
carton test

Environment

gmondada commented 1 year ago

Full log

gabriele@GabeMacookM1Pro carton_demo % carton test        
- checking Swift compiler path: /Users/gabriele/.carton/sdk/wasm-5.7.1-RELEASE/usr/bin/swift
- checking Swift compiler path: /Users/gabriele/.swiftenv/versions/wasm-5.7.1-RELEASE/usr/bin/swift
- checking Swift compiler path: /Users/gabriele/Library/Developer/Toolchains/swift-wasm-5.7.1-RELEASE.xctoolchain/usr/bin/swift
Inferring basic settings...
- swift executable: /Users/gabriele/Library/Developer/Toolchains/swift-wasm-5.7.1-RELEASE.xctoolchain/usr/bin/swift
SwiftWasm Swift version 5.7.1 (swiftlang-5.7.1)
Target: arm64-apple-darwin22.4.0

Parsing package manifest: 
[debug]: evaluating manifest for 'carton_demo' v. unknown 
[warning]: /Users/gabriele/big/wasm-tests/poc1plus/carton_demo/Package.swift:9:10: warning: 'package(name:url:from:)' is deprecated: use package(url:from:) instead
        .package(name: "JavaScriptKit", url: "https://github.com/swiftwasm/JavaScriptKit", from: "0.15.0")
         ^- test bundle to run: /Users/gabriele/big/wasm-tests/poc1plus/carton_demo/.build/wasm32-unknown-wasi/debug/carton_demoPackageTests.wasm

Building the test bundle before running the test suite...
Compiling...
/Users/gabriele/Library/Developer/Toolchains/swift-wasm-5.7.1-RELEASE.xctoolchain/usr/bin/swift build -c debug --product carton_demoPackageTests -Xswiftc -color-diagnostics --triple wasm32-unknown-wasi
[0/1] Planning build
Building for debugging...
[1/5] Compiling carton_demoTests carton_demoTests.swift
/Users/gabriele/big/wasm-tests/poc1plus/carton_demo/Tests/carton_demoTests/carton_demoTests.swift:2:18: error: no such module 'carton_demo'
@testable import carton_demo
                 ^
note: module 'carton_demo' is the main module of an executable, and cannot be imported by tests and other targets

Process failed and produced following output: 
Process failed with non-zero exit status and following output:
 and following error output:
warning: 'carton_demo': /Users/gabriele/big/wasm-tests/poc1plus/carton_demo/Package.swift:9:10: warning: 'package(name:url:from:)' is deprecated: use package(url:from:) instead
        .package(name: "JavaScriptKit", url: "https://github.com/swiftwasm/JavaScriptKit", from: "0.15.0")
         ^

Error: Process failed with non-zero exit status and following output:
 and following error output:
warning: 'carton_demo': /Users/gabriele/big/wasm-tests/poc1plus/carton_demo/Package.swift:9:10: warning: 'package(name:url:from:)' is deprecated: use package(url:from:) instead
        .package(name: "JavaScriptKit", url: "https://github.com/swiftwasm/JavaScriptKit", from: "0.15.0")
         ^
yonihemi commented 1 year ago

Thanks for reporting @gmondada. I'm looking into it, seems to be swift driver misinterpreting an argument passed from SwiftPM when building. I wonder if it's just an issue that crept up in driver for non-regularly tested platforms (see Windows). The error message is coming from SwiftPM but is incorrect IMO, it's just reacting to the build failure by swiftc. We should:

kateinoigakukun commented 1 year ago

I did some investigations into this issue and found some facts:

  1. note: module 'XXX' is the main module of an executable, and cannot be imported by tests and other targets is emitted by SwiftPM based on error diagnostic messages from the compiler.
  2. The compiler diagnostic message is emitted because the executable target's XXX.swiftmodule file is missing at package visible build output directory (.build/debug or .build/release) and the file is placed under the intermediate output directory (e.g. .build/debug/XXX.build)
  3. The swiftmodule file is placed under the intermediate output directory because wasm32-unknown-wasi target does not support linking .executableTarget into .testTarget: https://github.com/apple/swift-package-manager/blob/5de521daa341d42208e32da7b3021ab0617cdf99/Sources/Build/BuildDescription/SwiftTargetBuildDescription.swift#L95-L98
  4. The reason why the linking is not supported on Wasm is we cannot rename entrypoint symbol by linker (wasm-ld): https://github.com/apple/swift-package-manager/pull/3804 On other platforms, SwiftPM build .executableTarget targets with renaming main to {moduleName}_main to avoid conflicting with .testTarget's entrypoint at link-time. For non-testing build, SwiftPM renames the entrypoint back to main by linker option. However, wasm-ld doesn't have the option for now, so we disable the feature now.

So required actions to support .executableTarget testing are:

  1. Add entrypoint renaming support to wasm-ld
  2. Enable main function renaming in SwiftPM like other platforms by updating the function
  3. Enable linking executable target in SwiftPM by updating the line

But I think it cannot be done before 5.8 release, so I think it's reasonable to update the template project generated by carton init to split .executableTarget and .target for --type executable for short term.