Very Strange Errors From IB During Build With Swift Package, Using IBDesignable - swift

I have developed this shared package. It works fine.
In the package test harnesses (3 iOS apps), it works great, and also, the IB storyboard renders the control (It's an IBDesignable).
However, when I include it as a package in another app (I can't share the source), I get these really weird render failure messages:
Error: 'UIPickerView' is unavailable in tvOS
And so on. There's a bunch of "not available in tvOS" errors.
Here's what the log looks like:
The build happens, and the app runs fine. However, I'm wondering if this could cause problems in the App Store release process.
Well...DUH. It's an iOS package and utility, and leverages a lot of things like haptics.
The package explicitly states that it is iOS(12), and I can't see any indication of why my storyboard is insisting on trying to render as tvOS.
What am I missing? I think that I must be missing something from the Package.swift file, but it's pretty straightforward:
import PackageDescription
let package = Package(
name: "RVS_Spinner",
platforms: [
.iOS(.v12)
],
products: [
.library(
name: "RVS-Spinner",
targets: ["RVS_Spinner"])
],
targets: [
.target(name: "RVS_Spinner")
]
)

You need to wrap each of these problematic files in
#if os(iOS)
#endif
so that they don't get compiled for other platforms, as things you are referring are only available on iOS.
As far as i know, you can't stop a package from building on all platforms, but you can select which file to be compiled on which platform with the #if os() trick
I think you got confused by the platforms parameter in the Package.swift file. It is not saying where this package is available, it is saying the minimum version required for each platform.
Take a look at Apple's doc for the platforms parameter:
platforms - The list of minimum deployment targets per platform.

Related

Swift update deployment target to match package requirement

I'm new to swift development, so excuse the basic question, but when I import a package called SwiftHttp in a local package, I get this error:
Compiling for macOS 10.13, but module 'SwiftHttp' has a minimum deployment target of macOS 10.15:
So I've gone in to my project's setting, and changed the minimum deployments to macOS 11.0, both in the "project" section, and for all targets, but that error remains in the file. Is there anywhere else I need to update that setting? Or is there something I need to do to "propagate" that setting to the local package?
Images of what I have...
Project settings:
Target settings
Error:
I managed to fix it by explicitly setting a supported platform version in package.swift in my own package, which I use" in this project. The relevant part now looks like this:
let package = Package(
name: "Swiftodon",
platforms: [
.macOS(.v10_15),
.iOS(.v13),
.tvOS(.v13),
.watchOS(.v6)
],

How can I enable ABI stability for a SwiftPM package?

Given my bog standard Package Description of
let package = Package(
name: "MyLib",
products: [
.library(name: "MyLib", targets: ["MyLib"]),
],
dependencies: [],
targets: [
.target(
name: "MiniRxSwift",
dependencies: [],
swiftSettings: [
.define("<see below>")
]),
...
I'm trying to get swiftpm to pass the -enable-library-evolution flag through to swiftc, but I've been unsuccessful.
Using swiftSettings of .define("-enable-library-evolution"), I get a compile error which states
"error: conditional compilation flags must be valid Swift identifiers (rather than '-enable-library-evolution')"
I get the same error if I omit the leading hyphen e.g. `.define("enable-library-evolution")
I've tried the Xcode setting of .define("BUILD_LIBRARIES_FOR_DISTRIBUTION") which doesn't result in a compile error, but also doesn't result in the flag getting set, it instead results in -DBUILD_LIBRARIES_FOR_DISTRIBUTION on the command line for swiftc, which doesn't do anything.
After a bit more research, I worked out that .define in swiftSettings is hardwired to produce things with -D - hence it's name.
Instead I needed to use unsafeFlags, which does indeed result in the flag getting passed correctly to the swift compiler:
swiftSettings: [
.unsafeFlags(["-enable-library-evolution"])
]
BUT then when I attempt to consume this package, Xcode fails to load the package, with the error:
The package product 'MyLib' cannot be used as a dependency of this target because it uses unsafe build flags.
If I can't enable library evolution without unsafe build flags, and I can't use unsafe build flags in a library, then what can I do? What is the point of having unsafeFlags if you can't use any libraries which set them?
Why do you need ABI stability if you have access to the package? You should avoid it if possible. That said, you should be able to use unsafeFlags with editable packages (ones you have dragged into the project) but not ones you include the normal way via URL.
If you need to vend someone a swift package as a binary you will need to build your package as an XCFramework and then you can put that in a place where SwiftPM can depend on it. That means it can be hosted at a static place where you give the URL or it can be embedded in the git repo with the Package.swift manifest that you have for vending the package. The only tool I know of to help with this is found here which works for Swift only package when I have used it.

How to use Swift Package Manager's binaryTarget?

I'm trying to use Swift Package Manager's binaryTarget to include the Stripe xcframework available here https://github.com/stripe/stripe-ios/releases/tag/v19.3.0. The package manager doesn't complain, and lets me link to it, but I can't import it im. I've made a sample repo to show it here https://github.com/martyu/StripePackageTest. Am I missing something?
First of all, your example is not testable because you have forgotten to provide a version tag, so this is not a real package.
Second, and more important, I think you have a misconception about how a package works as a binary target. You seem to think that your Swift Package can contain code that sees the XCFramework. (That's why you are trying to import in the framework module in the Sources code of the package.) That's wrong. It's the app that imports the framework module. The package is merely a way of distributing the framework.
In other words, you can write a source code package or a framework-bearing package. One package cannot be both.
But of course you can write a source code package that depends on a framework-bearing package.
First, you don't need a version tag for it to be "real package". You can specify package dependencies via commit SHA and branch as well. Also you can add local package repos in xcode via file://. Note, this is NOT the same as a local dev override.
I didn't have much luck with swift build but I did get it to work fine by creating an app in Xcode and adding the package to it. I think this is what #matt is getting at. You need to import it into a project (xcode, or another SP) and then xcode will assemble all the dependencies when it ~~builds~~ feels like it.
Here's the modified Package.swift I used. I changed the name to Example (as that's presumably the SDK you are building which depends on Stripe). You can include "Stripe" in the Example library's targets if you want it embedded in its framework. Otherwise the client app just needs to import it as well (via the tickboxes when you add it in Xcode, or via dependencies in another Package.swift).
// swift-tools-version:5.3
// The swift-tools-version declares the minimum version of Swift required to build this package.
import PackageDescription
let package = Package(
name: "Example",
platforms: [
.iOS(.v11)
],
products: [
.library(
name: "Example",
type: .dynamic,
targets: ["Example"]),
.library(
name: "Stripe",
targets: ["Stripe"])
],
dependencies: [],
targets: [
// I thought this was defining the Stripe binaryTarget...
.binaryTarget(name: "Stripe",
url: "https://github.com/stripe/stripe-ios/releases/download/v19.3.0/Stripe.xcframework.zip",
checksum: "fe459dd443beee5140018388fd6933e09b8787d5b473ec9c2234d75ff0d968bd"),
// ... and then linking it to the Example project here via "dependencies" ...
.target(name: "Example", dependencies: ["Stripe"], path: "Sources")
// ... so when I'm in "Example" files, I thought I'd be able to import "Stripe" to them
]
)

Local swift package with local dependency

I have a project that I plan on developing in modules, the final application will be any number of the modules built together based on a configuration. I have a swift package that has all of my common code it it, we can call that the platform package. I then went to create my first feature, this went just fine however when I created the wrapper application to pull in each feature, I got this error from SPM in xcode11:
package 'Platform' is required using a revision-based requirement and it depends on local package
'Feature1', which is not supported.
Looking at the code base for SPM here (line 72)
https://github.com/apple/swift-package-manager/blob/master/Sources/PackageGraph/DependencyResolver.swift
It looks like this is something that is just not supported, the mixing of local and remote dependencies? Is this a limitation of SPM / should I be trying to use another tool for this type of app architecture?
In my case, I was trying to add a package, which I was developing, and its Package.swift contained dependencies of the form:
dependencies: [
.package(path: "../PackageName"),
// etc
Changing the references to specific repos solved the problem:
dependencies: [
.package(path: "http://github.com/..."),
// etc

Package Loading: "Ignoring duplicate product" (SwiftPM)

I'm trying to build a Swift package using the Swift Package Manager.
However, when I open the package in Xcode and click Run, I get the following warning:
How can I resolve this?
This is an issue often encountered if you are attempting to build a library/framework but also have a main.swift file in your target's root directory, like so:
.
The presence of a main.swift file makes SwiftPM believe that you are attempting to build a command line tool, and thus complains about the unnecessary (duplicate in name) library produced.
This warning may be confusing as it does not occur in projects initialized with the dynamic framework template from Xcode, for iOS, macOS, tvOS or watchOS.
In my case it was because I had the same name in both the products section and the Package e.g.
let package = Package(
name: "Example",
products: [
.library(
name: "Example",
targets: ["Example"]),
],
)
This seems to be the default behavior of swift init for some reason. I removed the .library entry and the warning went away.