Draft Proposal: Target Specific Build Settings

That’s highly problematic; it leaves no ability to conditionally link something in the simulator vs device build.

Thanks for the feedback. The points you raised are all valid and SwiftPM will probably solve them with a future generic build settings model (and maybe extensible build tools for custom tools). This proposal is very focused towards compiler/linker specific arguments that come up very often. Think of this proposal as a way of bringing the current command-line -X* options to the manifest file but without chances of disrupting the build model due to arbitrary unsafe flags.

I wouldn't rush to classify this as highly problematic. It's just the first version of the API which can be extended. I am not sure if there are a lot of system libraries which can't be autolinked and require conditional linking on device vs simulator.

It seems like adding environment as an option would align with the targetEnvironment conditional compilation flag:

.when(platforms: [.iOS], environments: [.simulator], configuration: [.debug])

Is there an argument against doing it from the beginning?

I'd say it's the same argument as always: scope creep. The more we try to do in one go, the longer it takes to ship things and the harder it gets to evaluate the proposal.

In this case, it's not clear to me what "environment" means. Simulator vs device, sure, but does this generalise to anything else? How does "environment" interact with other concerns like "target architecture"?

2 Likes

I agree. I really want to keep this proposal super focused and avoid any feature creep, especially when we can easily extend the proposed API. Otherwise, we will miss any chance of getting this in Swift 5 timeframe.

1 Like

Overall design aside, I think it would be prudent to avoid using the unsafe prefix here for something unrelated to memory safety, which is how the term is used in Swift itself.

There are many situations where users have termed things "unsafe" when they mean "not recommended" or "undesirable"; I'm sure there are many other words that can carry the sense you're going for here.

What about uncheckedFlags? In other words, SwiftPM merely appends them to the command line without checking that they are compatible with other build settings.

8 Likes

What does it mean to be ineligible to act as a dependency? Does this mean it will be rejected when I try to resolve the dependency? Will there be ways to opt in to having a dependency with unsafe flags? For example, for a local dependency or one using a .branch dependency?

+1 to uncheckedFlags, it is clear and avoids collision with Swift memory safety concept.

I don't think there is a change of confusion with Swift's memory safety since these APIs are nested under package/target/<tool>Settings.

This is exactly the sense we're going for. Package authors should think twice before using unsafe flags. It is an escape hatch to enable experimentation. You can easily land yourself in trouble and break your build so it is important to communicate that there is a "gotcha" with this API.

uncheckedFlags sounds good at first but doesn't give a vibe that there might be some big caveat to it.

What about uncheckedFlags + Swift PM throwing some explicit warning before building the project?

That depends on implementation but basically it means you won't be able to build your package if you depend on a product from a dependency that product contains unsafe flags.

Yikes, I forgot adding this portion in the draft proposal. unsafeFlags will be supported in local dependencies but not branch or versioned dependencies.

A warning would be annoying. I could be using this in a target that I don't vend as a product or even my test targets.

I think it's unfortunate to prevent this for a branch dependency - a branch dependency on master for example is very similar in spirit to a local dependency.

Alternatively, what about having a command-line flag to swiftpm to say -i-know-what-im-doing-allow-unsafe-flags-in-deps? That would enable using unsafe flags as an escape hatch for things that are safe but haven't been explicitly modeled yet by swiftpm. This would be equivalent to using -Xswift -Xcxx et al, but on a per-target basis. This would be very useful to me for flags that have not been included in this first version of the settings API.

I think that sounds much better. We can have this flag instead of baking in the allowance for certain types of dependencies. I wonder if we should still disallow version-based dependencies from using unsafe flags even with this flag.

1 Like

I think the general idea of an escape hatch is sound, but it needs to be more explicit. Once you are specifying it, any dependency could also publish a new version with unsafe flags without you noticing that it happened. This could be a potential security risk, because you can use flags like -B to run arbitrary code during the build process. I think this would need to be a list of packages which are allowed to use unsafe flags instead.

Opting-in per dependency would be fine with me.

1 Like

So now that this is implemented, what is the recommended way to import a C library header into Swift? I have been using .systemLibrary() but if I now use linkedLibrary() the associated headers for the library I want to use are not imported.