I have a prebuild plugin that runs ls
and one that runs echo
. If I purposefully pass them bad input I see the error message in both Xcode and in the command line. If I pass them something valid, my expectation would be to see output messages in the build log as well but I don't. Where does it go? How do I see it? And is this related to why > and >> can't be passed as arguments?
FWIW when I put print statements in my own custom local executable they do show up in the build log. Print statements from the plugin code also show up in the build log. It's just the output from the executable when it's an external binary so far. I have not yet tried a non-system binary.
func logDirectoryContents(toLog:Path, output:Path) -> PackagePlugin.Command {
.prebuildCommand(
displayName: "Test prebuild",
executable: .init("/bin/ls"),
arguments: ["-1t", toLog.string],
//known can't be done... a shame.
//arguments: ["-1", toLog.string, ">>", output.string ],
//environment: T##[String : CustomStringConvertible],
outputFilesDirectory: output.removingLastComponent()
)
}
func echoTest(toEcho:some StringProtocol, outputDir:Path) -> PackagePlugin.Command {
.prebuildCommand(
displayName: "Results from echo",
executable: .init("/bin/zsh"),
arguments: ["-c", "echo \(toEcho)"],
outputFilesDirectory: outputDir
)
}
I understand that to make this work I can build my own tool that opens a Process. In the mean time I'm curious though about how the plugin system works.
The invocationDelegate
has a handleOutput
function which the comment says handles both stderr
and stdout
?
/// Invoked when the plugin emits arbtirary data on its stdout/stderr. There is no guarantee that the data is split on UTF-8 character encoding boundaries etc. The script runner delegate just passes it on to the invocation delegate.
func handleOutput(data: Data) {
invocationDelegate.pluginEmittedOutput(data)
}
But looking in the code base it appear to only be called for stderr not for stdout ever. From handleOutput the stderr infor can be easily traced through the code to where it ends up in the Diagnostics in BuildOperation
stdout
appears instead to be handled by a FileHandle.writePluginMessage
and the file handle eventually winds up at
if let handler = handle.readabilityHandler {
handler(handle)
}
info on readabilityHandler
But then it I can't tell what actually gets DONE with it? Who gets the contents of stdout? Why do the print statements in my local executable show up but output from ls
and echo
don't? Are they not all stdout
?
Related?
- [SR-15692] Output currently printed to stdout stream should go through the same system as diagnostics (with a new `output` severity) · Issue #4364 · apple/swift-package-manager · GitHub
- Handling stdout/stderr/terminationStatus from .prebuildCommand · Issue #6469 · apple/swift-package-manager · GitHub