Confused by unsafe flags being disallowed in dependencies

I'm continuing a discussion from https://github.com/apple/swift-package-manager/pull/1884 with @SDGGiesbrecht in the forums to stop polluting the PR.

Background: I'm using some experimental or advanced compiler flags in a multi-package setting, and was surprised that that PR seemed to block support for that.

I was using: .package(url: ..., .branch("experimental_branch")) when I ran into this issue, so perhaps this is just a bug? If so, I'm happy to contribute a fix that allows .branch to work.

2 Likes

This was part of the target-specific build settings proposal, see: https://github.com/apple/swift-evolution/blob/master/proposals/0238-package-manager-build-settings.md#unsafe-flags-all

The initial proposal did have an escape hatch which would bypass this limitation by using a command-line flag (something like --allow-unsafe-flags-in-dependencies). However, we decided to revisit this topic at a later point. I am not sure if using a command-line flag is the best idea. Maybe we should provide a API in the manifest file that allows you explicitly opt-in into using a package with unsafe flags. It'd be great if you wanted to explore this and come up with a proposal.

That said, I do think that this limitation doesn't make sense for local/branch-based package dependencies and I am planning to work on a patch to lift this limitation for those cases. Filed: https://bugs.swift.org/browse/SR-11225

3 Likes

Sounds good. Once you have the mechanism to allow unsafe, if necessary, we just need a bool attached to the Package.Dependency.Requirement for .rangeItem and .exact telling if it allows unsafe or not.

Seems like .exact("v1.0.0").allowUnsafeFlags() would be best, but that doesn't quite work.
However, .exactWithUnsafeFlags("v1.0.0") could work?

The pull request lifting the (accidental?) restriction from local and branch dependencies is here if you want to track its progress, @pschuh.

3 Likes

@SDGGiesbrecht That pull request is already merged and I am trying with this toolchain swift-DEVELOPMENT-SNAPSHOT-2019-08-22-a and still getting the error about .unsafeFlags in local dependencies. I am referring to local dependency with .package(path: "../first-dep").

1 Like

CC: @Aciid

@Aciid Can you help me about this? Is this change is available in DEVELOPMENT or 5.1 snapshots now?

It should be in the swift-DEVELOPMENT-SNAPSHOT-2019-08-22-a toolchain. Are you trying this in Xcode or using swift build? Note that SwiftPM changes are not picked up via snapshots in Xcode.

Thanks for the hint, I am trying with Xcode, because I am doing some tests with an iOS project. Will this changes be in the next Xcode beta?

I tried with Xcode 11 beta 7 today and the problem exists yet.

@Aciid, I tried again with Xcode 11 GM and it is the same. It does not allow local packages to have dependencies with unsafe flags. Do you know if it will be in the final version of Xcode 11 or not?

1 Like

Was this ever clarified? I'm getting conflicting information, or maybe just not looking in the right place, but SR-11225 and a few other forum posts gave me the impression that if a branch is specified (and/or revision?) that unsafeFlags would be allowed.

With Xcode 11.2, specifying a branch or revision with unsafeFlags doesn't allow compilation, but I was unsure if this was a bug or my own ineptitude.

What's the news of this ?

I talk about my use case. I'm using SwiftPM with Xcode (not open-source swift packge manager imple mentation)

I found that Swift Package Manager does not allows me to make a framework with -enable-library-evolution (Called BUILD_LIBRARY_FOR_DISTRIBUTION in Xcode)

So, I decide to add the compiler flags by my own, using the .swiftSettings. However, it does not works because of this. Showing:

The package product 'SDWebImageSwiftUI' cannot be used as a dependency of this target because it uses unsafe build flags.

So I'm sucked. And stop to support SwiftPM to let our user to choose CocoaPods && Carthage instead.

Another issue, I want to weak linking SwiftUI and Combine system framework. In Xcode, I can simply use -weak_framework SwiftUI -weak_framework Combine, or the Linked library to Optional (In Build Phase).

However, when using SwiftPM, again, it does not have a linkerSettings for weak linking (only non-weak linking, good). When using unsafeFlags, the error appears the same.

So, as a framework author, I found it hard to implements the same easy thing compared to Xcode project itself. And can anybody here tell me: Why Swift Package Manager using Swift 5.1, does not support -enable-library-evolution ?

Weak linking seems like a good point, we should consider adding settings for that. What is the use case for enabling library evolution? Swift packages are currently always build from source, so there should be no need to enable library evolution for them.

What is the use case for enabling library evolution?

You may be using swiftpm as a way to build a dynamic library that will be distributed in binary form, or statically linking your package module into a larger binary framework. These aren't convenient to do today, but they are possible if you can pass the library evolution flags when building. I think having a target setting to turn on library evolution would be genuinely useful, even if it's a bit niche for a package currently.

1 Like

Since most frameworks are auto-linked simply by importing them and you specify the minimum deployment version to the compiler, it would be nice if the auto-link information that gets emitted could decide whether the framework should be weakly linked or not based on whether the OS that the framework was first introduced in was later than the minimum deployment target. Then users wouldn't have to audit the use of -weak_framework flags. But, I don't believe the information about "when this framework first appeared" is recorded anywhere that the compiler could access it, so I don't think it's possible to do that today without manually providing that mapping?

The min deployment target version has Side effect, not only effect the weak linking, but also effect the Swift Standard library (For example, when you target iOS 11, you will have to copy libSwift.dylib into binary, your linker flags will use that instead of /usr/lib/libSwift.dylib). So it's not always a best solution to automatically resolve whice frameworks should be weak-linking, which are not.

And you're right, there are no "when this framework first appeared" information in compiler. It's in the Apple's release page about Public framework (note a framework can become runtime available in old firmware, until mark it public). So it's a solution in theroy, but not practice.

The simplest solution for this, it's that SwiftPM add a new function like

public static func linkedLibrary(_ library: String, _ condition: PackageDescription.BuildSettingCondition? = nil, type: LinkerSetting.LinkType = .weak ) -> PackageDescription.LinkerSetting

// or?
public static func weakLinkedLibrary(_ library: String, _ condition: PackageDescription.BuildSettingCondition? = nil) -> PackageDescription.LinkerSetting
Terms of Service

Privacy Policy

Cookie Policy