Skip to content

Commit bcd25f5

Browse files
authored
Fix --quiet option not working with swift run #8844 (#8858)
Fixes an issue where the `--quiet` option had no effect when used with `swift run` and `swift build` command. ### Motivation: When using the `--quiet` option with `swift run` only error messages should be logged. ### Modifications: - Add `isQuiet` property to filter out messages based on the log level during build phases of the `native`, `xcode` and `swiftbuild` build system. - Remove duplicated declaration of the isVerbose property from different targets. ### Result: When the `--quiet` option is used with the `swift run` and `swift build` command only error messages are logged.
1 parent d28a243 commit bcd25f5

File tree

11 files changed

+191
-30
lines changed

11 files changed

+191
-30
lines changed
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// swift-tools-version: 5.6
2+
import PackageDescription
3+
4+
let package = Package(
5+
name: "TestableExe",
6+
targets: [
7+
.executableTarget(
8+
name: "Test",
9+
path: "."
10+
),
11+
]
12+
)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
print("done")

Sources/Basics/Observability.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,14 @@ public struct Diagnostic: Sendable, CustomStringConvertible {
443443
public var isBold: Bool {
444444
return true
445445
}
446+
447+
public var isVerbose: Bool {
448+
self <= .info
449+
}
450+
451+
public var isQuiet: Bool {
452+
self >= .error
453+
}
446454
}
447455
}
448456

Sources/Build/BuildOperation.swift

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1049,9 +1049,3 @@ extension BuildSubset {
10491049
}
10501050
}
10511051
}
1052-
1053-
extension Basics.Diagnostic.Severity {
1054-
var isVerbose: Bool {
1055-
return self <= .info
1056-
}
1057-
}

Sources/Build/LLBuildProgressTracker.swift

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,9 @@ final class LLBuildProgressTracker: LLBuildBuildSystemDelegate, SwiftCompilerOut
241241
}
242242

243243
func commandStatusChanged(_ command: SPMLLBuild.Command, kind: CommandStatusKind) {
244-
guard !self.logLevel.isVerbose else { return }
244+
guard !self.logLevel.isVerbose,
245+
!self.logLevel.isQuiet
246+
else { return }
245247
guard command.shouldShowStatus else { return }
246248
guard !self.swiftParsers.keys.contains(command.name) else { return }
247249

@@ -285,7 +287,7 @@ final class LLBuildProgressTracker: LLBuildBuildSystemDelegate, SwiftCompilerOut
285287

286288
self.delegate?.buildSystem(self.buildSystem, didFinishCommand: BuildSystemCommand(command))
287289

288-
if !self.logLevel.isVerbose {
290+
if !self.logLevel.isVerbose && !self.logLevel.isQuiet {
289291
let targetName = self.swiftParsers[command.name]?.targetName
290292
self.taskTracker.commandFinished(command, result: result, targetName: targetName)
291293
self.updateProgress()
@@ -395,6 +397,7 @@ final class LLBuildProgressTracker: LLBuildBuildSystemDelegate, SwiftCompilerOut
395397

396398
/// Invoked right before running an action taken before building.
397399
func preparationStepStarted(_ name: String) {
400+
guard !self.logLevel.isQuiet else { return }
398401
self.queue.async {
399402
self.taskTracker.buildPreparationStepStarted(name)
400403
self.updateProgress()
@@ -404,6 +407,7 @@ final class LLBuildProgressTracker: LLBuildBuildSystemDelegate, SwiftCompilerOut
404407
/// Invoked when an action taken before building emits output.
405408
/// when verboseOnly is set to true, the output will only be printed in verbose logging mode
406409
func preparationStepHadOutput(_ name: String, output: String, verboseOnly: Bool) {
410+
guard !logLevel.isQuiet else { return }
407411
self.queue.async {
408412
self.progressAnimation.clear()
409413
if !verboseOnly || self.logLevel.isVerbose {
@@ -416,6 +420,7 @@ final class LLBuildProgressTracker: LLBuildBuildSystemDelegate, SwiftCompilerOut
416420
/// Invoked right after running an action taken before building. The result
417421
/// indicates whether the action succeeded, failed, or was cancelled.
418422
func preparationStepFinished(_ name: String, result: CommandResult) {
423+
guard !self.logLevel.isQuiet else { return }
419424
self.queue.async {
420425
self.taskTracker.buildPreparationStepFinished(name)
421426
self.updateProgress()
@@ -431,7 +436,7 @@ final class LLBuildProgressTracker: LLBuildBuildSystemDelegate, SwiftCompilerOut
431436
self.outputStream.send("\(text)\n")
432437
self.outputStream.flush()
433438
}
434-
} else {
439+
} else if !self.logLevel.isQuiet {
435440
self.taskTracker.swiftCompilerDidOutputMessage(message, targetName: parser.targetName)
436441
self.updateProgress()
437442
}
@@ -466,6 +471,7 @@ final class LLBuildProgressTracker: LLBuildBuildSystemDelegate, SwiftCompilerOut
466471
}
467472

468473
func buildStart(configuration: BuildConfiguration) {
474+
guard !logLevel.isQuiet else { return }
469475
self.queue.sync {
470476
self.progressAnimation.clear()
471477
self.outputStream.send("Building for \(configuration == .debug ? "debugging" : "production")...\n")
@@ -484,7 +490,7 @@ final class LLBuildProgressTracker: LLBuildBuildSystemDelegate, SwiftCompilerOut
484490
self.progressAnimation.complete(success: success)
485491
self.delegate?.buildSystem(self.buildSystem, didFinishWithResult: success)
486492

487-
if success {
493+
if !self.logLevel.isQuiet, success {
488494
let message = self.cancelled ? "Build \(subsetString)cancelled!" : "Build \(subsetString)complete!"
489495
self.progressAnimation.clear()
490496
self.outputStream.send("\(message) (\(duration.descriptionInSeconds))\n")

Sources/CoreCommands/SwiftCommandObservabilityHandler.swift

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -221,9 +221,3 @@ extension ObservabilityMetadata {
221221
}
222222
}
223223
}
224-
225-
extension Basics.Diagnostic.Severity {
226-
fileprivate var isVerbose: Bool {
227-
return self <= .info
228-
}
229-
}

Sources/SwiftBuildSupport/SwiftBuildSystem.swift

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,7 @@ public final class SwiftBuildSystem: SPMBuildCore.BuildSystem {
378378
}
379379

380380
func emitEvent(_ message: SwiftBuild.SwiftBuildMessage, buildState: inout BuildState) throws {
381+
guard !self.logLevel.isQuiet else { return }
381382
switch message {
382383
case .buildCompleted(let info):
383384
progressAnimation.complete(success: info.result == .ok)
@@ -477,6 +478,7 @@ public final class SwiftBuildSystem: SPMBuildCore.BuildSystem {
477478

478479
switch operation.state {
479480
case .succeeded:
481+
guard !self.logLevel.isQuiet else { return }
480482
progressAnimation.update(step: 100, total: 100, text: "")
481483
progressAnimation.complete(success: true)
482484
let duration = ContinuousClock.Instant.now - buildStartTime
@@ -816,12 +818,6 @@ extension String {
816818
}
817819
}
818820

819-
extension Basics.Diagnostic.Severity {
820-
var isVerbose: Bool {
821-
self <= .info
822-
}
823-
}
824-
825821
fileprivate extension SwiftBuild.SwiftBuildMessage.DiagnosticInfo.Location {
826822
var userDescription: String? {
827823
switch self {

Sources/XCBuildSupport/XCBuildDelegate.swift

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,11 +69,14 @@ extension XCBuildDelegate: XCBuildOutputParserDelegate {
6969
queue.async {
7070
self.didEmitProgressOutput = true
7171
let text = self.logLevel.isVerbose ? [info.executionDescription, info.commandLineDisplayString].compactMap { $0 }.joined(separator: "\n") : info.executionDescription
72-
self.progressAnimation.update(step: self.percentComplete, total: 100, text: text)
72+
if !self.logLevel.isQuiet {
73+
self.progressAnimation.update(step: self.percentComplete, total: 100, text: text)
74+
}
7375
self.buildSystem.delegate?.buildSystem(self.buildSystem, willStartCommand: BuildSystemCommand(name: "\(info.taskID)", description: info.executionDescription, verboseDescription: info.commandLineDisplayString))
7476
self.buildSystem.delegate?.buildSystem(self.buildSystem, didStartCommand: BuildSystemCommand(name: "\(info.taskID)", description: info.executionDescription, verboseDescription: info.commandLineDisplayString))
7577
}
7678
case .taskOutput(let info):
79+
guard !self.logLevel.isQuiet else { return }
7780
queue.async {
7881
self.progressAnimation.clear()
7982
self.outputStream.send("\(info.data)\n")
@@ -84,24 +87,28 @@ extension XCBuildDelegate: XCBuildOutputParserDelegate {
8487
self.buildSystem.delegate?.buildSystem(self.buildSystem, didFinishCommand: BuildSystemCommand(name: "\(info.taskID)", description: info.result.rawValue))
8588
}
8689
case .buildDiagnostic(let info):
90+
guard !self.logLevel.isQuiet else { return }
8791
queue.async {
8892
self.progressAnimation.clear()
8993
self.outputStream.send("\(info.message)\n")
9094
self.outputStream.flush()
9195
}
9296
case .taskDiagnostic(let info):
97+
guard !self.logLevel.isQuiet else { return }
9398
queue.async {
9499
self.progressAnimation.clear()
95100
self.outputStream.send("\(info.message)\n")
96101
self.outputStream.flush()
97102
}
98103
case .targetDiagnostic(let info):
104+
guard !self.logLevel.isQuiet else { return }
99105
queue.async {
100106
self.progressAnimation.clear()
101107
self.outputStream.send("\(info.message)\n")
102108
self.outputStream.flush()
103109
}
104110
case .buildOutput(let info):
111+
guard !self.logLevel.isQuiet else { return }
105112
queue.async {
106113
self.progressAnimation.clear()
107114
self.outputStream.send("\(info.data)\n")
@@ -121,7 +128,7 @@ extension XCBuildDelegate: XCBuildOutputParserDelegate {
121128
self.outputStream.flush()
122129
self.buildSystem.delegate?.buildSystem(self.buildSystem, didFinishWithResult: false)
123130
case .ok:
124-
if self.didEmitProgressOutput {
131+
if self.didEmitProgressOutput && !self.logLevel.isQuiet {
125132
self.progressAnimation.update(step: 100, total: 100, text: "Build succeeded")
126133
}
127134
self.buildSystem.delegate?.buildSystem(self.buildSystem, didFinishWithResult: true)

Sources/XCBuildSupport/XcodeBuildSystem.swift

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,7 @@ public final class XcodeBuildSystem: SPMBuildCore.BuildSystem {
244244
throw Diagnostics.fatalError
245245
}
246246

247+
guard !self.logLevel.isQuiet else { return }
247248
self.outputStream.send("Build complete!\n")
248249
self.outputStream.flush()
249250
}
@@ -412,9 +413,3 @@ extension BuildSubset {
412413
}
413414
}
414415
}
415-
416-
extension Basics.Diagnostic.Severity {
417-
var isVerbose: Bool {
418-
self <= .info
419-
}
420-
}

Tests/CommandsTests/BuildCommandTests.swift

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1326,6 +1326,82 @@ struct BuildCommandTestCases {
13261326
}
13271327
}
13281328

1329+
@Test(
1330+
.bug("https://github.com/swiftlang/swift-package-manager/issues/8844"),
1331+
arguments: SupportedBuildSystemOnPlatform, BuildConfiguration.allCases
1332+
)
1333+
func swiftBuildQuietLogLevel(
1334+
buildSystem: BuildSystemProvider.Kind,
1335+
configuration: BuildConfiguration
1336+
) async throws {
1337+
try await withKnownIssue {
1338+
// GIVEN we have a simple test package
1339+
try await fixture(name: "Miscellaneous/SwiftBuild") { fixturePath in
1340+
//WHEN we build with the --quiet option
1341+
let (stdout, stderr) = try await executeSwiftBuild(
1342+
fixturePath,
1343+
configuration: configuration,
1344+
extraArgs: ["--quiet"],
1345+
buildSystem: buildSystem
1346+
)
1347+
// THEN we should not see any output in stderr
1348+
#expect(stderr.isEmpty)
1349+
// AND no content in stdout
1350+
#expect(stdout.isEmpty)
1351+
}
1352+
} when: {
1353+
ProcessInfo.hostOperatingSystem == .windows &&
1354+
buildSystem == .swiftbuild
1355+
}
1356+
}
1357+
1358+
@Test(
1359+
.bug("https://github.com/swiftlang/swift-package-manager/issues/8844"),
1360+
arguments: SupportedBuildSystemOnPlatform, BuildConfiguration.allCases
1361+
)
1362+
func swiftBuildQuietLogLevelWithError(
1363+
buildSystem: BuildSystemProvider.Kind,
1364+
configuration: BuildConfiguration
1365+
) async throws {
1366+
// GIVEN we have a simple test package
1367+
try await fixture(name: "Miscellaneous/SwiftBuild") { fixturePath in
1368+
let mainFilePath = fixturePath.appending("main.swift")
1369+
try localFileSystem.removeFileTree(mainFilePath)
1370+
try localFileSystem.writeFileContents(
1371+
mainFilePath,
1372+
string: """
1373+
print("done"
1374+
"""
1375+
)
1376+
1377+
//WHEN we build with the --quiet option
1378+
let error = await #expect(throws: SwiftPMError.self) {
1379+
try await executeSwiftBuild(
1380+
fixturePath,
1381+
configuration: .debug,
1382+
extraArgs: ["--quiet"],
1383+
buildSystem: buildSystem
1384+
)
1385+
}
1386+
1387+
guard case SwiftPMError.executionFailure(_, let stdout, let stderr) = try #require(error) else {
1388+
Issue.record("Incorrect error was raised.")
1389+
return
1390+
}
1391+
1392+
if buildSystem == .swiftbuild {
1393+
// THEN we should see output in stderr
1394+
#expect(stderr.isEmpty == false)
1395+
// AND no content in stdout
1396+
#expect(stdout.isEmpty)
1397+
} else {
1398+
// THEN we should see content in stdout
1399+
#expect(stdout.isEmpty == false)
1400+
// AND no output in stderr
1401+
#expect(stderr.isEmpty)
1402+
}
1403+
}
1404+
}
13291405
}
13301406

13311407
extension Triple {

0 commit comments

Comments
 (0)