I have been trying out Swift on Ubuntu 20.10 and am having trouble importing packages. Swift is installed properly. I am always getting error: no such module, no matter which package I try.
Here is my Package.swift (Embassy as an example):
// 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: "test",
/* products: [
.executable(name: "test", targets: ["test"])
],*/
dependencies: [
// Dependencies declare other packages that this package depends on.
// .package(url: /* package url */, from: "1.0.0"),
.package(url: "https://github.com/envoy/Embassy.git",
from: "4.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 this package depends on.
.target(
name: "test",
dependencies: []),
.testTarget(
name: "testTests",
dependencies: ["test"]),
]
)
main.swift(under Sources/test)
import Foundation
import Embassy
let loop = try! SelectorEventLoop(selector: try! KqueueSelector())
let server = DefaultHTTPServer(eventLoop: loop, port: 8080) {
(
environ: [String: Any],
startResponse: ((String, [(String, String)]) -> Void),
sendBody: ((Data) -> Void)
) in
// Start HTTP response
startResponse("200 OK", [])
let pathInfo = environ["PATH_INFO"]! as! String
sendBody(Data("the path you're visiting is \(pathInfo.debugDescription)".utf8))
// send EOF
sendBody(Data())
}
// Start HTTP server to listen on the port
try! server.start()
// Run event loop
loop.runForever()
In your Package.swift file you are declaring Embassy as a dependency, but you are not referencing that dependency in any of your targets. In the example you provided, you can alter your package like this:
// 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: "test",
dependencies: [
.package(url: "https://github.com/envoy/Embassy.git", from: "4.1.1"),
],
targets: [
// Reference the 'Embassy' package here.
.target(name: "test", dependencies: ["Embassy"]),
.testTarget(name: "testTests", dependencies: ["test", "Embassy"]),
]
)
Related
In my project I have two dependencies
.package(name: "Web3swift", url: "https://github.com/skywinder/web3swift.git", from: "3.0.6"),
.package(name: "Random", url: "https://github.com/vapor-community/random.git", .upToNextMinor(from: "1.2.0"))
the Random package also has Core dependencies (https://github.com/vapor/core.git), and the target package name Web3swift also has Core in it
let package = Package(
name: "Web3swift",
platforms: [
.macOS(.v10_15), .iOS(.v13)
],
products: [
.library(name: "web3swift", targets: ["web3swift"])
],
dependencies: [
.package(url: "https://github.com/attaswift/BigInt.git", .upToNextMinor(from: "5.3.0")),
.package(url: "https://github.com/krzyzanowskim/CryptoSwift.git", .upToNextMinor(from: "1.5.1"))
],
targets: [
.target(name: "secp256k1"),
.target(
name: "Core",
dependencies: ["BigInt", "secp256k1", "CryptoSwift"]
),
.target(
name: "web3swift",
dependencies: ["Core", "BigInt", "secp256k1"],
exclude: excludeFiles,
resources: [
.copy("./Browser/browser.js"),
.copy("./Browser/browser.min.js"),
.copy("./Browser/wk.bridge.min.js")
]
),
Now I have a problem:
multiple targets named 'Core' in: 'core', 'web3swift'; consider using the `moduleAliases` parameter in manifest to provide unique names
Can you please explain how to fix this?
When you look at the developer documentation, you'll note that this is only supported in Swift 5.7+. To fix the "...is unavailable" message, you'll need to update the header in Package.swift to: // swift-tools-version:5.7 (also requires XCode > 14).
For full details, you can refer to:
The Swift 5.7 release notes
The evolution proposal: SE-0339
AFAICT, your changes look correct.
I have a project that I recently added swift-docc-plugin to, so that I can export the DocC documentation as a static website.
// swift-tools-version:5.5
import PackageDescription
let package = Package(
name: "Saga",
platforms: [
.macOS(.v12)
],
products: [
.library(name: "Saga", targets: ["Saga"]),
.executable(name: "watch", targets: ["SagaCLI"])
],
dependencies: [
.package(url: "https://github.com/kylef/PathKit", from: "1.0.1"),
.package(url: "https://github.com/JohnSundell/Codextended.git", from: "0.1.0"),
.package(url: "https://github.com/apple/swift-docc-plugin.git", branch: "main"),
],
targets: [
.target(
name: "Saga",
dependencies: [
"PathKit",
"Codextended",
]
),
.executableTarget(
name: "SagaCLI",
dependencies: ["PathKit"]
),
.testTarget(
name: "SagaTests",
dependencies: ["Saga"]
),
]
)
The problem is that on Swift Package Index all builds on Swift 5.5 and below are failing:
error: package at 'https://github.com/apple/swift-docc-plugin.git' # 859caac534e94ace18b894ccd9ed301ae4aeda84 is using Swift tools version 5.6.0 but the installed version is 5.5.0 in https://github.com/apple/swift-docc-plugin.git
See https://swiftpackageindex.com/builds/1DF06709-E2CA-4F56-B793-9CC7C8FC0A9D for a full build log.
How do I solve this? I could remove swift-docc-plugin from the dependencies I guess, and add it every time I want to export the docs, but that seems like a ridiculously annoying workaround. I don't really want to increase the minimum version of my library just because of swift-docc-plugin either.
The solution was pretty easy in the end. Just add this to the end of Package.swift
#if swift(>=5.6)
package.dependencies += [
.package(url: "https://github.com/apple/swift-docc-plugin", from: "1.0.0")
]
#endif
Unfortunately, I don’t think there’s a way around that due to the way we’re testing a package by building it.
Here's some more detail: https://github.com/SwiftPackageIndex/SwiftPackageIndex-Server/issues/1633#issuecomment-1075899345
I am trying to use resources inside my Package.swift file:
// 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: "MyPackage",
products: [
.library(
name: "MyPackage",
targets: ["MyPackage"])
],
targets: [
.target(
name: "MyPackage",
resources: [
.process("Resources/one.xml"),
.process("Resources/two.json"),
.process("Resources/three.json"),
]
)
.testTarget(
name: "MyPackageTests",
dependencies: ["MyPackage"]
)
]
)
When I import and compile the package in another project, I am getting lots of errors, such as:
Cannot infer contextual base in reference to member 'target'
or:
Reference to member 'process' cannot be resolved without a contextual type
The files are located in my package project in Sources -> MyPackage -> Resources
I also tried .copy("Resources/one.xml"), etc
What am I missing?
You missed a , after the target close parentheses:
.target(
name: "BioSwift",
resources: [
.process("Resources/unimod.xml"),
.process("Resources/aminoacids.json"),
.process("Resources/elements.json"),
.process("Resources/enzymes.json"),
.process("Resources/functionalgroups.json"),
.process("Resources/hydropathy.json")
]
), // Here is the missed `,`
Also, you don't need to add files one by one! Instead, you can add a directory:
.process("Resources")
To exclude entire sections of a file, I can use macros to target platforms such as #if os(iOS) || os(watchOS).
Is there a way to do this in Package.swift, or another way to target a few files for specific platforms in Swift Package Manager?
Is there a way to do this in Package.swift ... ?
Swifty stuff also works in Package.swift since the package declaration file is itself a .swift file.
Here are some examples which use Swift 5.3 Package Manager Conditional Target Dependencies SE-0273 condition and when.
// swift-tools-version:5.3
import PackageDescription
// ...
targets: [
.target(
name: "BKSecurity",
dependencies: [
.product(name: "Crypto", condition: .when(platforms: [.linux])),
"BKFoundation"
]),
// swift-tools-version:5.3
import PackageDescription
// ...
targets: [
.target(
name: "CombineShim",
dependencies: [
.product(name: "OpenCombine",
package: "OpenCombine",
condition: .when(platforms: [.wasi, .linux])
)]
),
.target(
name: "TokamakShim",
dependencies: [
.target(name: "TokamakDOM", condition: .when(platforms: [.wasi])),
"SomeCommonDependency"
]
),
// swift-tools-version:5.3
import PackageDescription
let supportsCoreAudio: BuildSettingCondition =
.when(platforms: [.iOS, .macOS, .tvOS, .watchOS])
let supportsALSA: BuildSettingCondition =
.when(platforms: [.linux])
let package = Package(
name: "portaudio",
// ...
targets: [
.target(
name: "libportaudio",
dependencies: [],
cSettings: [
.define("PA_USE_COREAUDIO", supportsCoreAudio),
.define("PA_USE_ALSA", supportsALSA)
],
linkerSettings: [
.linkedLibrary("asound", supportsALSA),
.linkedFramework("CoreAudio", supportsCoreAudio),
.linkedFramework("CoreServices", supportsCoreAudio),
.linkedFramework("CoreFoundation", supportsCoreAudio),
.linkedFramework("AudioUnit", supportsCoreAudio),
.linkedFramework("AudioToolbox", supportsCoreAudio)
]),
]
//...
)
Note that #if os(…) can be used in Package.swift. However, Package.swift is evaluated, built and executed in the context of the build platform. So, #if os(…) is useful in the context when the target platform is the same as the build platform e.g. macOS, Linux or Windows.
Package.swift
import PackageDescription
let package = Package(
// ...
targets: {
var targets: [Target] = [
.testTarget(
name: "QuickTests",
dependencies: [ "Quick", "Nimble" ],
exclude: ["SomeFile.ext"]
),
]
#if os(macOS)
// macOS build platform
targets.append(contentsOf: [
.target(name: "QuickSpecBase", dependencies: []),
.target(name: "Quick", dependencies: [ "QuickSpecBase" ]),
])
#else
// not macOS build platform, e.g. linux
targets.append(contentsOf: [
.target(name: "Quick", dependencies: []),
])
#endif
return targets
}(),
)
See Also
The Swift Programming Language: Statements > Conditional Compilation Block
GitHub/Apple/swift: lib/Basic/LangOptions.cpp
Currently supported compilation OSs: macOS, tvOS, watchOS, iOS, Linux, FreeBSD,OpenBSD, Windows, Android, PS4, Cygwin, Haiku, WASI
GitHub/Apple/swift-evolution: SE-0273 Package Manager Conditional Target Dependencies
I'm facing problems while importing a library I created.
This is the Package.swift of my executable:
import PackageDescription
let package = Package(
name: "PayBackCodingChallenge",
dependencies: [
.package(url: "../NumberChecker", from: "1.0.0"),
],
targets: [
.target(
name: "PayBackCodingChallenge",
dependencies: []),
]
)
When I try to import NumberChecker in my main.swift I get the following message: No such module 'NumberChecker':
import NumberChecker
let arguments = CommandLine.arguments
if arguments.count != 3 {
print("USAGE: PayBackCodingChallenge [data] [target]")
print(" data: File containing list of numbers ")
print(" target: Target number")
} else {
let data = arguments[1]
let target = arguments[2]
print(data + " " + target)
}
My NumberChecker library is located in a directory at the same level as PayBackCodingChallenge and compiles correctly. What could be the problem?
Thanks in advance!
You should add NumberChecker as a dependency to PayBackCodingChallenge:
...
targets: [
.target(
name: "PayBackCodingChallenge",
dependencies: ["NumberChecker"]),
]
...