I'm trying to use updated SPM for Swift4 with the following Package.swift file - PackageDescription API Version 4
import PackageDescription
let package = Package(
name: "Name",
dependencies : [
.package(url: "url", .branch("swift4"))
],
exclude: ["Tests"]
)
I have a correct version of SPM also:
Apple Swift Package Manager - Swift 4.0.0-dev (swiftpm-13081.9)
But I can not build the library by swift build command. I see the following error:
... error: type 'Version' has no member 'branch'
You're missing the tools version specifier in your manifest; add the following as the first line of your Package.swift:
// swift-tools-version:4.0
By default if that line is omitted, it'll default to manifest version 3 and also compiler version 3. For more information see SE-0152 or Swift Package Manager Manifest API Redesign on swift.org.
Related
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
]
)
I'm trying to compile using swift build
Package.swift
// swift-tools-version:4.2
// The swift-tools-version declares the minimum version of Swift required to build this package.
// swift-tools-version:x.x
import PackageDescription
let package = Package(
name: "MyKituraApp",
dependencies: [
.package(url: "https://github.com/IBM-Swift/Kitura", from: "2.7.0")
],
targets: [
.target(
name: "MyKituraApp",
dependencies: ["Kitura"],
path: "Sources"),
.testTarget(
name: "MyKituraAppTests",
dependencies: ["MyKituraApp"],
path: "Test")
]
)
But, I get the following error although I did add the path property.
'MyKituraApp' /src: error: could not find source files for target(s): MyKituraAppTests; use the 'path' property in the Swift 4 manifest to set a custom target path
Without knowing your project structure I can't give you a definite answer but I'll do my best!
I'm going to assume you've generated your project using the Swift Package Manager tool, something like this:
swift package init --type executable
So... Typically you shouldn't need to set the path property unless you've moved the tests for your application to another directory. The Swift Package Manager, by default, will create a Tests directory and when you do not provide a value for the path property the Swift Package Manager will look for that Tests directory by default when you run swift build. In your path property you are providing a value of Test not Tests
So my first solution to test would be:
To remove the path property from the .testTarget section
OR
Rename the path properties value to Tests rather than Test.
I've provided an example Package.swift that I was able to run swift build with:
// swift-tools-version:4.2
// The swift-tools-version declares the minimum version of Swift required to build this package.
import PackageDescription
let package = Package(
name: "MyKituraApp",
dependencies: [
.package(url: "https://github.com/IBM-Swift/Kitura", from: "2.7.0")
],
targets: [
.target(
name: "MyKituraApp",
dependencies: ["Kitura"],
path: "Sources"),
.testTarget(
name: "MyKituraAppTests",
dependencies: ["MyKituraApp"])
]
)
As you can see I've also removed an extra line from the top of the file:
// swift-tools-version:x.x
You've already provided a swift-tools-version at the top of your file, this line may end up confusing things later down the line.
I hope this helps!
The documentation about SPM is quite poor and most of the articles about it were published when SPM began.
I have implemented an algorithm (Hungarian algorithm) in Swift and was looking forward to publish it as a library in Github. I have had to use the SPM for the first time in this project to resolve another dependency and once it has started to work, it was perfect.
Now, I am not being able to use my library from another project. I have decided to start with a new fresh git repo cause I couldn't get the previous to work.
The library is named Hume and it has inside a Hume.swift file which defines a Hume class.
The steps I have gone through are these:
Created directory for the library
swift package init --type library
Populated the files with the code
Pushed to a GitHub repo + tagged the version
Created directory for the executable which is going to use the library
swift package init --type executable
Add the dependency in Package.swift
swift build
At this point, swift clones the repo of the library and compiles it without problems (as main.swift contains just a Hello world).
swift package generate-xcodeproj
An when I open the project and try to import my library, it seems the module name is recognized but when I try to declare an object, it says I can't declare a variable of a type that is a module.
This is the Package.swift file in the library:
// swift-tools-version:4.0
// The swift-tools-version declares the minimum version of Swift required to build this package.
import PackageDescription
let package = Package(
name: "Hume",
products: [
.library(
name: "Hume",
targets: ["Hume"]),
],
dependencies: [
.package(url: "https://github.com/aleph7/Upsurge.git", from: "0.10.2"),
],
targets: [
.target(
name: "Hume",
dependencies: ["Upsurge"]),
.testTarget(
name: "HumeTests",
dependencies: ["Hume"]),
]
)
The Library has only one file with this style:
import Upsurge
class Hume {
// Attributes
....
init(matriz:[[Double]]){
....
}
public func resuelve() -> (Double, [(Int, Int)]){
....
}
}
This is the Package.swift in the dummy executable:
// swift-tools-version:4.0
// The swift-tools-version declares the minimum version of Swift required to build this package.
import PackageDescription
let package = Package(
name: "aa",
dependencies: [
// Dependencies declare other packages that this package depends on.
// .package(url: /* package url */, from: "1.0.0"),
.package(url: "https://github.com/Jasagredo/Hume.git", from: "0.1.1"),
],
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: "aa",
dependencies: ["Hume"]),
]
)
The output when building:
~/Desktop/aa swift build
Fetching https://github.com/Jasagredo/Hume.git
Fetching https://github.com/aleph7/Upsurge.git
Cloning https://github.com/Jasagredo/Hume.git
Resolving https://github.com/Jasagredo/Hume.git at 0.1.1
Cloning https://github.com/aleph7/Upsurge.git
Resolving https://github.com/aleph7/Upsurge.git at 0.10.2
Compile Swift Module 'Upsurge' (30 sources)
Compile Swift Module 'Hume' (1 sources)
Compile Swift Module 'aa' (1 sources)
Linking ./.build/x86_64-apple-macosx10.10/debug/aa
~/Desktop/aa
But when I edit main.swift in the dummy executable, I find this error:
import Hume
var a = Hume(matriz: [[1,1],[1,1]]) //Cannot call value of non-function type 'module<Hume>'
Also, Xcode doesn't auto-suggest me the class Hume. I just don't know what I'm doing wrong.
Any help is appreciated.
I have finally managed to get things to work. The problem was the class (and it's init method) weren't declared as public. The rest of the configuration is correct.
I am trying to use Swift's package manager to import external modules in my project. My first module come from the Vapor project. I cannot seem to get it working. I start with
swift package init
swift package generate-xcodeproj
My Package.swift looks like this:
import PackageDescription
let package = Package(
name: "OpenTools",
products: [
.library(
name: "OpenTools",
targets: ["OpenTools"]),
],
dependencies: [
.package(url: "https://github.com/vapor/json.git", from: "2.0.0")
],
targets: [
.target(name: "OpenTools", dependencies: ["JSON"]),
]
)
I then run
swift package update
swift package generate-xcodeproj # to regenerate with dependencies
and then try to import the JSON package in my main file
import JSON
The modules are there as shown below but the import gets back with an No such module 'JSON' error.
Any thoughts?
Probably the problem lies within Xcode, as it does not know yet that JSON exists, because it was not built yet. This can easily be solved by just building your project (with cmd-B). With the generated xcodeproj, Xcode should know that it first needs to build JSON and then the rest, because JSON is marked as a dependency for your target.
You can check this, by navigating in Xcode to your target (when you click on the project description file) and afterwards to "Build Phases". Under Target Dependencies you should find your JSON module.
In addition you should find a JSON module under your targets, which compiles the sources you gathered from github.
Your project should also build when executing swift build in your project root.
With Xcode 11 you should be able to open Package.swift directly which will give you a proving ground for verifying the package manifest (aka: the Package.swift file) and compiling the target. This should help see what is actually causing the error that's preventing the module from being compiled.
I have the latest release versions of Swift and Xcode.
I am trying to use the Swift Package Manager to use this:
.package(url: "https://github.com/matejkosiarcik/Stopwatch.git", from: "0.1.0")
However, I have spent multiple days trying how to figure out how to embed this in my command line tool, or even in a brand new command line tool so that in Main.swift it doesn't give the error:
No such module 'Stopwatch'.
Would someone please explain how to do it for this exact package?
Thank you.
Note that the modules in a Swift Package are specified as targets, not as products.
Suppose you have the following product spec in your Package.swift:
products: [ .library(name: "MyProduct", targets: ["MyTarget1", "MyTarget2"])]
Then in some other package you use this product as a dependency in Package.swift:
.target(name: "TargetInSomeOtherPackage", dependencies: ["MyProduct"])
And in swift code you import modules:
import MyTarget1
import MyTarget2
In your case, you defined your product: .library(name: "Stopwatch", targets: ["lib"]). This means that you can use Stopwatch as a dependency, and import module lib in your Swift code. There is no module Stopwatch that you can import.