-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Build settings for warning treating rules (SE-0443, draft) #8315
base: main
Are you sure you want to change the base?
Conversation
@swift-ci test |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Aside from the two places where we can go quadratic in the number of command-line arguments, this is looking good to me. But I'm not super familiar with the SwiftPM code base.
// `-w` (suppress warnings) and the other warning control flags are mutually exclusive | ||
for index in args.indices.reversed() { | ||
let arg = args[index] | ||
if arg.starts(with: "-W"), arg.count > 2 { | ||
// we consider the following flags: | ||
// -Wxxxx | ||
// -Wno-xxxx | ||
// -Werror | ||
// -Werror=xxxx | ||
// -Wno-error | ||
// -Wno-error=xxxx | ||
args.remove(at: index) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This loop could be a filter
, which would make it linear-time rather than quadratic.
for index in args.indices.reversed() { | ||
let arg = args[index] | ||
switch arg { | ||
case "-warnings-as-errors", "-no-warnings-as-errors": | ||
args.remove(at: index) | ||
case "-Wwarning", "-Werror": | ||
guard args.indices.contains(index + 1) else { | ||
throw InternalError("Unexpected '\(arg)' at the end of args") | ||
} | ||
args.remove(at: index + 1) | ||
args.remove(at: index) | ||
default: | ||
break | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also technically quadratic. Even though it's a little ugly, I think I'd still rather do it with a filter
var removeNextArg = false
args = args.filter { arg in
if removeNextArg {
removeNextArg = true
return false
}
switch arg {
case "-warnings-as-errors", "-no-warnings-as-errors":
return false
case "-Wwarning", "-Werror":
removeNextArg = true
return false
default:
return true
}
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, the quadratic complexity is an oversight on my part. Good thing you noticed.
TBH, using an external state in a filter makes me a bit uneasy. The documentation for filter
doesn't guarantee that the predicate will be invoked in any particular order, so I'd try to avoid it.
I don't insist though. If you think a filter here is fine, I don't mind. But what do you think about something more "manual", e.g:
var readIndex = args.startIndex
var writeIndex = args.startIndex
let endIndex = args.endIndex
while readIndex < endIndex {
let arg = args[readIndex]
switch arg {
case "-warnings-as-errors", "-no-warnings-as-errors":
break
case "-Wwarning", "-Werror":
readIndex += 1 // -Wwarning and -Werror have an argument
if readIndex >= endIndex {
throw InternalError("Unexpected '\(arg)' at the end of args")
}
default:
if readIndex != writeIndex {
args[writeIndex] = args[readIndex]
}
writeIndex += 1
}
readIndex += 1
}
if writeIndex < endIndex {
args.removeSubrange(writeIndex..<endIndex)
}
A couple of general questions. Placing these flags in the package manifest, means all consumers of this package will build with the same settings. I was just wondering if it's a concern that consumers may want to set them differently. For example, if they are specifying additional warning setting flags on the Also, as we're working on adopting Swift Build to replace our native build system, we would need to make sure this is handled there as well. |
Mind you the pitch and evolution proposal predates my participation so maybe this has already been addressed. I'll need to catch up. |
That's a good question. AFAIK, the additional flags (-Xcc, -Xcxx, -Xswiftc) are placed after the internally generated flags, but I didn't really check that. I'll dive into it later. If it's not the case, I think we should make it so. However, I need a confirmation from the maintainers that that's really the desired behavior.
I've raised a discussion about that, but it seems like the Swift Build maintainers prefer a simpler approach to these flags. swiftlang/swift-build#248
The original proposal (SE-0443) doesn't address this API, but we're working on fixing that. We will probably write a new pitch. |
@swift-ci Please test |
@swift-ci please test windows |
Following up on this question. The additional arguments the used provided are placed after the ones SwiftPM generates. So if we consider the following Package.swift: let package = Package(
name: "MyExecutable",
platforms: [
.macOS(.v13),
],
targets: [
.target(
name: "cfoo",
cSettings: [
.enableWarning(name: "all"),
.disableWarning(name: "unused-parameter"),
.treatAllWarnings(as: .error),
.treatWarning(name: "unused-variable", as: .warning),
]
),
.target(
name: "cxxfoo",
cxxSettings: [
.enableWarning(name: "all"),
.disableWarning(name: "unused-parameter"),
.treatAllWarnings(as: .error),
.treatWarning(name: "unused-variable", as: .warning),
]
),
.executableTarget(
name: "swiftfoo",
swiftSettings: [
.treatAllWarnings(as: .error),
.treatWarning(name: "DeprecatedDeclaration", as: .warning),
]
),
]
) And build it with additional arguments like this: swift-build --very-verbose -Xcc -Wno-error -Xswiftc -no-warnings-as-errors We will get the following invocations of the compilers:
Given that these flags are evaluated left-to-right it gives the user some control here at the build stage.
|
This change adds warning control settings. The flags for Swift targets are described by SE-0443, for Clang targets - here.
Common API for all three languages (Swift, C, and C++)
Warning control methods for C and C++ only
Settings and their corresponding compiler flags
treatAllWarnings(as: .error)
-warnings-as-errors
-Werror
treatAllWarnings(as: .warning)
-no-warnings-as-errors
-Wno-error
treatWarning(name: "XXXX", as: .error)
-Werror XXXX
-Werror=XXXX
treatWarning(name: "XXXX", as: .warning)
-Wwarning XXXX
-Wno-error=XXXX
enableWarning(name: "XXXX")
-WXXXX
disableWarning(name: "XXXX")
-Wno-XXXX
Notes