Skip to content

Commit 0f8af55

Browse files
dschaefer2MaelRB
andauthored
Cherry-pick Fix --quiet option not working with swift run #8844 (#8858) (#8907)
Cherry-pick #8858 to 6.2. 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. --------- Co-authored-by: MaëlRB <[email protected]>
1 parent dfcb8c6 commit 0f8af55

File tree

11 files changed

+192
-30
lines changed

11 files changed

+192
-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
@@ -1044,9 +1044,3 @@ extension BuildSubset {
10441044
}
10451045
}
10461046
}
1047-
1048-
extension Basics.Diagnostic.Severity {
1049-
var isVerbose: Bool {
1050-
return self <= .info
1051-
}
1052-
}

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
@@ -355,6 +355,7 @@ public final class SwiftBuildSystem: SPMBuildCore.BuildSystem {
355355
}
356356

357357
func emitEvent(_ message: SwiftBuild.SwiftBuildMessage, buildState: inout BuildState) throws {
358+
guard !self.logLevel.isQuiet else { return }
358359
switch message {
359360
case .buildCompleted(let info):
360361
progressAnimation.complete(success: info.result == .ok)
@@ -432,6 +433,7 @@ public final class SwiftBuildSystem: SPMBuildCore.BuildSystem {
432433

433434
switch operation.state {
434435
case .succeeded:
436+
guard !self.logLevel.isQuiet else { return }
435437
progressAnimation.update(step: 100, total: 100, text: "")
436438
progressAnimation.complete(success: true)
437439
let duration = ContinuousClock.Instant.now - buildStartTime
@@ -743,12 +745,6 @@ extension String {
743745
}
744746
}
745747

746-
extension Basics.Diagnostic.Severity {
747-
var isVerbose: Bool {
748-
self <= .info
749-
}
750-
}
751-
752748
fileprivate extension SwiftBuild.SwiftBuildMessage.DiagnosticInfo.Location {
753749
var userDescription: String? {
754750
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
@@ -240,6 +240,7 @@ public final class XcodeBuildSystem: SPMBuildCore.BuildSystem {
240240
throw Diagnostics.fatalError
241241
}
242242

243+
guard !self.logLevel.isQuiet else { return }
243244
self.outputStream.send("Build complete!\n")
244245
self.outputStream.flush()
245246
}
@@ -408,9 +409,3 @@ extension BuildSubset {
408409
}
409410
}
410411
}
411-
412-
extension Basics.Diagnostic.Severity {
413-
var isVerbose: Bool {
414-
self <= .info
415-
}
416-
}

Tests/CommandsTests/BuildCommandTests.swift

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1330,6 +1330,85 @@ struct BuildCommandTestCases {
13301330
}
13311331
}
13321332

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

13351414
extension Triple {

0 commit comments

Comments
 (0)