Confused by unsafe flags being disallowed in dependencies

The compiler decides whether to emit strong or weak references based on availability, and then if autolinking sees that all references found in a framework are weak, it uses weak linking. I don't think it applies this heuristic to an explicit -framework on the command line, though, on the grounds that you need to be able to override it somehow.

3 Likes

Question? Related to the original topic. I have 2 packages. One for Linux that uses unsafe flags to compile c++ code with Vulkan and OpenCV. Then a MacOS package using Metal and OpenCV with unsafe flags to provide the same API feature set.

Then I have a general package that runs on Linux/MacOS and fetches the required OS package. If I build the general package on Linux everything works. If I build on MacOS is complains about unsafe flags. Why is this. How do I get around it??

Also to clarify – both Linux/MacOS are using swift 5.1

2 Likes

Any ideas on a quick fix? I need a solution for MacOS without having to build a separate code base that needs to be maintained. It's kinda crappy that Swift works better on Linux than it does on MacOS. But maybe that's just because Apple likes to make it harder on developers and lock everything down.

2 Likes

Really need a workaround here!!!

3 Likes

Same issue. I don’t think this behavior is correct for a Package Manager should do, which limit the extension ability for framework author and framework consumer.

1 Like

I'm curious if some recent change now prevents unsafe flags from being used in local SPM dependencies. I see the pull request to allow unsafe flags in local SPM dependencies. I've created a sample project here: GitHub - yuzuquats/TestSPMLocalUnsafe so I'm wondering if there's something obvious I'm missing. Specifically, I'm doing the following:

  1. Create a local package with an unsafe flag
  2. Create a new xcode project
  3. Drag the local package folder into the left "file explorer" sidebar
  4. In the xcode project's "Framework, Libraries, and Embeded Content" -> Add the local package framework from step 1

This was working for me during the xcode 12 beta (12A8158a) but no longer with the newer releases (currently on 12A70209). Any help would be much appreciated!

1 Like

The detection of unsafe flags was incorrect in prior builds of Xcode and was missing them in cases where they're used by a target that's a transitive dependency of a product.

AFAIK, exceptions aren't supported at all by Xcode, but you might be able to work around it by putting a package in between and depending on the other one using .package(path:).

3 Likes

Thank you! Fixed this with the proposed workaround (.package(path:)). In case anyone is interested, you may have to reexport with @_exported import

1 Like

Was this ever addressed?

The issue is still happening for me.

I've filed a bug about this: [SR-15398] Xcode blocks local-branch SPM packages with unsafe flags in an app targets · Issue #4379 · apple/swift-package-manager · GitHub

Couldn't reply in jira so I'll copy my comment here

I'd also like to add that it could be nice to have an -allow-unsafe-flags flag for xcodeproj target and allow unsafe flags for local packages by default, for example, if I need -Xfrontend -warn-long-expression-type-checking for optimization debugging purposes I'd like to make it work out of the box, without need to wrap my local package into another local package... I'm not even sure it's actually unsafe :new_moon_with_face:

Project structure without a wrapper package is semantically correct and simple

- App.xcworkspace
- App.xcodeproj
- AppPackage

And the wrapper package seems pretty much redundant (actually it does nothing but exposing AppPackage.AppTarget to the App.xcodeproj via _AppPackage._AppTarget (we cant even keep naming for the target))

- App.xcworkspace
- App.xcodeproj
- _AppPackage
- AppPackage

My use case is for linking with private frameworks elegantly by exporting headers via a C target and linking against the relevant framework by passing an unsafe linker flag. By disallowing versioned packages from using unsafe flags, wrappers like this are barred from the semver world and the dependency resolution that comes with it. I understand that a version bump could introduce malicious flags, but I control all ends of the pipeline and would appreciate an option to override this safeguard.

In the meantime I'll be adding the package as a branch-item dependency, like a madman, because there is no alternative that offers the same ease of use for depending packages. GitHub - EricRabil/Paris: SPM-native private framework bindings

Update 22h later: I did not test out adding Paris as a revision-item, which allows me to specify a commit hash. I am now able to depend on specific snapshots of Paris across projects, without worrying about breaking changes.

I still think that being able to use semantic versioning with a package that uses unsafe flags should not be arbitrarily gatekeeped by the package manager. Until SPM is able to cover more advanced targets, there should be a mechanism to at least whitelist specific unsafe flags. Disallowing this outright makes it difficult to push the boundaries of what you can do with Swift.

2 Likes

Just to bump this thread, as running into this issue when lower level versioned libraries are using unsafe flags, it prevents these libs from being used by other packages.

Another vote for having ability to have this check to be a just a warning rather than full bail out.

2 Likes

Just a note here, it is very unlikely that we would ever change the behavior for unsafe flags since allowing arbitrary flags breaks the intended hermetic build model of packages and would render tools-versions and semantic versioning more or less meaningless.

1 Like

i have also run into this countless times and it has led me to conclude that SPM semantic versioning is more or less useless. many packages need "unsafe" configurations, including "official" packages like swift-atomics.

also, let us not pretend that semantic versioning is adhered to rigorously across the ecosystem in the first place.

4 Likes

I think it would be fairly reasonable to allow for opt-in for a given dependency on unsafe flags (not a blanket free-for-all).

It's definitely not arbitrary flags and we'd definitely bump the semantic version of the package if we ever would change those flags.

The longer term nicer option would be if SPM could support "all" needed use cases, but currently it instead becomes a blocker.

One simple example would be this one, where unsafe flags were required to workaround a compiler bug on Linux:

swiftSettings: [
   .unsafeFlags(["-Xfrontend", "-validate-tbd-against-ir=none"]), // due to https://bugs.swift.org/browse/SR-15629
 ]

This was the compiler bug

We have other similar examples related to linkage paths for system installed libraries (perhaps were just holding it wrong, WDIK).

It'd be fantastic to trust us, the users, to opt-in in a responsible way for such cases, as the alternative just now is that we're stuck (now that specific example happily has since been fixed and we could remove the flag, but for a long time that was not an option). A warning is fine even for opt-in, as we do want to clean it up as SPM matures and gains additional capabilities over time, we just don't want to get stuck in the meantime...

3 Likes

I don't actually see any unsafe flags in swift-atomics, am I looking in the wrong place?

Getting a 404 for this.

I don't have any issue with trusting users, my concern is entirely based on whether we can actually guarantee that packages stay working over a longer period of time and that they are portable as much as possible. These are important goals for SwiftPM.

An opt-in makes it somewhat trivial to depend on inherently unstable features like Swift frontend flags which could put us into a situation where the only choices are breaking a chunk of the package ecosystem or having to support features that were supposed to be unsupported in perpetuity.

Unsafe flags could also be non-portable in non-obvious ways, e.g. this just came up recently.

One thing that I am wondering about is whether it would be useful to allow unsafe flags for 0.x and prerelease versions since those carry inherent instability with them which makes any compatibility concerns way less severe. Would that be helpful for at least some of the use cases in this thread?

Another idea that was recently discussed was offering additional, inherently unstable APIs in the PackageDescription via @_spi. I wonder if there's some potential there to offer an API that can be opted in by versioned packages in a way that makes it very clear to authors that they are treading on somewhat unsupported grounds.

Oh, sorry - thought that was public, wanted to show concrete example, but here’s the relevant snippet:

swiftSettings: [
   .unsafeFlags(["-Xfrontend", "-validate-tbd-against-ir=none"]), // due to https://bugs.swift.org/browse/SR-15629
 ]

This was the compiler bug

I’ll need to read and digest the rest of your response and will reply separately - thanks.

on linux, the package needs

 -Xcc -mcx16 -Xswiftc -DENABLE_DOUBLEWIDE_ATOMICS 

to enable double-wide support, which is required for things like AtomicReference.

3 Likes