Swift Package Manager: how do I archive? - swift

I have created a Swift Package via Xcode. This packaged defines a library:
let package = Package(
name: "SPMBasedA",
products: [
.library(
name: "SPMBasedA",
type: .static,
targets: ["SPMBasedA"]),
],
targets: [
.target(name: "SPMBasedA")
]
)
The scheme is well displayed in Xcode and project seems to compile properly, but whenever I archive, there are no products in the exported archive. Why is that, what am I doing wrong? How do I make the build artifacts appear? Is it related to SKIP_INSTALL? If so, how do I disable it in SPM?

Related

How to restrict access to package depencency embedded in SPM package?

Using Swift Package Manager I have packageB that is imported as dependency in packageA. My project1 only imports packageA, however I am still able to access packageB within the project1. Is there a way to restrict the access topackageB only to scope of packageA ?
My use case:
The packageA is an API package with multiple versions. I want to import into the project1 another (the newest) version of packageB and use only the new version within project1 API. The old version of packageB should be still used and embedded only inside packageA.
This is structure of my PackageA defined in Package.swift:
let package = Package(
name: "PackageA",
platforms: [
.iOS(.v11), .tvOS(.v11)
],
products: [
.library(
name: "PackageA",
targets: ["PackageA"]),
],
dependencies: [
.package(name: "PackageB",url: "https://my.packageB.git", from: "1.1.1"),
],
targets: [
.target(
name: "PackageA",
dependencies: ["PackageB"])
]
)

Swift Package Manager: How to build a framework?

I am trying to use a Swift Package Manager to produce a framework.
I have a target, and then a library product for the platform of iOS 13.
let package = Package(
name: "SPMBasedA",
platforms: [.iOS(.v13)],
products: [
.library(name: "SPMBasedA",
type: .dynamic,
targets: ["SPMBasedA"])
],
targets: [
.target(name: "SPMBasedA")
]
)
My problem is that, when I swift build, the library product produces either an archive .a or a dynamically loadable library, .dylib.
But I want a static Swift framework. How do I make an SPM project to compile into a .framework?

Swift Package manifest property 'defaultLocalization' not set

Experimenting with Swift Packages, I created a new package. Source files and resources from an existing Xcode project framework target were moved over into the new structure.
Attempting to build, the transcript shows an error:
manifest property 'defaultLocalization' not set; it is required in the presence of localized resources
How can this be solved so I can create a Swift package?
This is explained in WWDC2020 session 10169.
At around eleven and a half minutes into the video, Anders Bertelrud, Apple engineer Developer Tools introduces the topic. An example is shown using Xcode 12 to add a default localisation parameter to the package manifest.
This declares the language I'm using during development and will be
used as the fallback localization at runtime if no better match is
available. This is needed for any package that contains resources.
An example manifest including the defaultLocalization parameter can be seen as follows:
// 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: "MyPackageUI",
defaultLocalization: "en",
platforms: [
.iOS(.v13)
],
products: [
.library(
name: "MyPackageUI",
targets: ["MyPackageUI"]),
],
targets: [
.target(
name: "MyPackageUI",
dependencies: []),
.testTarget(
name: "MyPackageUITests",
dependencies: ["MyPackageUI"]),
]
)

How to you import a 3rd party framework as a dependency using Swift Package Manager?

I'm trying to create a project using Swift Package Manager, but I'm running into issues trying to include the Fabric.framework.
Here is my Package.swift
let package = Package(
name: "TestPackage",
platforms: [
.iOS(.v10), .macOS(.v10_12)
],
products: [
// Products define the executables and libraries produced by a package, and make them visible to other packages.
.library(
name: "TestPackage",
targets: ["TestPackageSwift", "TestPackageObjC"]),
],
dependencies: [
.package(url: "https://github.com/Alamofire/Alamofire.git", from: "4.8.2"),
.package(path: "./TestPackage/Libraries/Fabric.framework"),
],
targets: [
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
// Targets can depend on other targets in this package, and on products in packages which this package depends on.
.target(
name: "TestPackageSwift",
dependencies: ["Alamofire", "Fabric"],
path:"./TestPackage/Sources/Swift"),
.target(
name: "TestPackageObjC",
dependencies: ["Fabric"],
path:"./TestPackage/Sources/ObjC"),
.testTarget(
name: "TestPackageTests",
dependencies: ["TestPackageSwift", "TestPackageObjC"],
path:"./TestPackageTests/Sources"),
]
)
And here is the error I am getting:
error: ./TestPackage/Libraries/Fabric.framework has no Package.swift manifest
Is this even possible?
Thanks for the help!

How to specify the name of the output executable?

By default the SPM builds the executable target with the same name (uppercase) as the module folder containing its main.swift. How do I get it to build the binary with a different file name? I cannot find any instructions on the SPM manual.
With Swift 4, given DemoProject created with swift package init --type executable, make the changes to Package.swift (adding the products section).
// swift-tools-version:4.0
import PackageDescription
let package = Package(
name: "DemoProject",
products: [
.executable(name: "demo", targets: ["DemoProject"]),
],
dependencies: [],
targets: [
.target(
name: "DemoProject",
dependencies: []),
]
)
This will create an executable called demo.
Change executable name
In SPM 5.4, You can set executable name in products.
.executable(name: "ExecutableName", targets: ["ExecutableTargetName"])
Build the executable product directly
and if you want to build the executable directly, try command swift build --product ExecutableName
also you can get where the build result located with --show-bin-path parameter
for example swift build --product ExecutableName --show-bin-path
Demo Package.swift
// swift-tools-version:5.4
import PackageDescription
let package = Package(
name: "PackageName",
platforms: [
.iOS(.v11),
.macOS(.v10_15),
],
products: [
.library(name: "LibraryName", targets: ["LibraryTarget"]),
.executable(name: "ExecutableName", targets: ["ExecutableTargetName"])
],
dependencies: [...],
targets: [
.target(
name: "LibraryTarget",
dependencies: [...],
path: "Sources/..."
),
.executableTarget(
name: "ExecutableTargetName",
dependencies: [...],
path: "Sources/..."
),
]
)
I am in favor of using another build system, for example make, on top of swift build. Currently, swift build does not allow defining custom "hooks" to implement various build automation tasks - generating code, copying resources, deploying the executable, etc. Once you use make you can define whichever tasks you desire, in particular, renaming the binary.