Open fboundp opened 1 year ago
Adding @available(macOS 10.15, *)
to the definition of struct asyncissue
seems to fix this.
@fboundp Thanks for the report and your research into this! I think the best resolution here is to add the workaround as a suggestion in the error message.
I've tried reproducing this issue, but it seems to be working correctly here.
swift -v
output:
Apple Swift version 5.7 (swiftlang-5.7.0.127.4 clang-1400.0.29.50)
Target: arm64-apple-macosx13.0
14.0.1
import ArgumentParser
@main struct Root: AsyncParsableCommand { static var configuration = CommandConfiguration(subcommands: [Sub.self])
struct Sub: AsyncParsableCommand {
mutating func run() async throws {
print("Hello World")
}
}
}
I've tried reproducing it from both `main` and `1.2.0`.
I'm experiencing this issue using main, and with the annotation added.
Apple Swift version 5.7.2 (swiftlang-5.7.2.135.5 clang-1400.0.29.51)
Target: arm64-apple-macosx13.0
@timwredwards Can you provide some more detail on your project and what you're seeing?
Not sure if I'm seeing this same thing or something related, but I just went through a migration from ParsableCommand
to AsyncParsableCommand
and had the following experience:
First I (incorrectly) changed a subcommand from ParsableCommand
to AsyncParsableCommand
and encountered the (helpful and correct) "Asynchronous subcommand of a synchronous root" error message
Next I changed my root command struct from ParsableCommand
to AsyncParsableCommand
and encountered the following error message:
/ParsableCommand.:248: Fatal error:
--------------------------------------------------------------------
Asynchronous root command needs availability annotation.
The asynchronous root command `ExampleCLI` needs an availability
annotation in order to be executed asynchronously. To fix this issue,
add the following availability attribute to your `ExampleCLI`
declaration or set the minimum platform in your "Package." file.
@available(macOS 10.15, macCatalyst 13, iOS 13, tvOS 13, watchOS 6, *)
--------------------------------------------------------------------
Trace/BPT trap: 5
Then it seemed that no matter what I did I couldn't resolve this error. I tried adding the annotation to my struct as follows:
@available(macOS 10.15, macCatalyst 13, iOS 13, tvOS 13, watchOS 6, *)
struct ExampleCLI: AsyncParsableCommand {}
and I tried setting platforms
in Package.
as follows:
let package: Package = Package(
name: "example",
platforms: [
.macOS(.v13),
.macCatalyst(.v13),
.iOS(.v13),
.tvOS(.v13),
.watchOS(.v6),
]
}
...and still no dice.
Then I found this issue and noticed that some folks were having success with the @available
annotation, however in the snippets that were shared here I observed that most people are setting the @main
annotation on the root command (as recommended by the docs). However, I have been using a different struct as my entry point, like this:
// CLI Entrypoint
@main
struct CLI {
static var stdin: String?
static func main() {
// check for STDIN before parsing arguments
// usage:
// if let stdin: String = CLI.stdin {
// print("stdin: \(stdin)")
// }
self.stdin = standardInput()
ExampleCLI.main()
}
}
As soon as I set the @main
annotation on my root command, along with the @available
annotation as suggested by the error message, I was able to resolve the error. This seems like a bug, and also related to this issue, but I could also be doing something super obviously wrong.
I hope this helps! 😊
PS: I'm doing this whole root command wrapper struct as a dance around capturing standard input and stripping trailing -
(hyphen) characters (e.g. echo "helloworld" | examplecli --dosomething -
), which ArgumentParser seems to complain about. My standardInput()
function looks like this:
// FeatherDB CLI STDIN Helper
func standardInput() -> String? {
// Only read STDIN if the last argument is "-"
guard CommandLine.arguments.last == "-" else {
return nil
}
// Remove the trailing "-" argument to avoid tripping up ArgumentParser
CommandLine.arguments.removeLast()
// Read & return STDIN
var input: String = String()
while let line: String = readLine() {
input += line
}
return input
}
@natecook1000 👋 thanks for your work on ArgumentParser! Coming from a background in developing golang CLI tools – which has a robust ecosystem of stdlib & OSS libraries for CLI argument parsing – I've found it to be quite impressive. It has almost everything I could ask for!
Any suggestions RE: the behavior I described above? Should I open a separate issue for what I'm seeing, or do you think the behavior I observed is related to this issue?
Thanks in advance for your time! 😊
When attempting to create an application with a AsyncParsableCommand root and AsyncParsableCommand subcommands, a fatal error is thrown at runtime “Asynchronous subcommand of a synchronous root.”
ArgumentParser version:
1.2.0
Swift version:swift-driver version: 1.62.8 Apple Swift version 5.7 (swiftlang-5.7.0.127.4 clang-1400.0.29.50) Target: arm64-apple-macosx13.0
Checklist
main
branch of this packageSteps to Reproduce
source:
Expected behavior
When resulting command is run, help with a subcommand would be displayed.
Actual behavior