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"]),
]
...
Related
I am porting an objective c cocoa pod over to swift package manager. It has a bundle of fonts in the package. In the original pod spec, there was a link of code that created the bundle.
s.resource_bundles = {
'mathFonts' => [ 'fonts/*.otf', 'fonts/*.plist' ]
}
In the swift package, I created a static bundle, called mathFonts.bundle and added it to the package as shown below.
in the manifest file, I tried to copy the resources as shown below:
import PackageDescription
let package = Package(
name: "iosMath",
platforms: [
.iOS(.v8)
],
products: [
.library(
name: "iosMath",
targets: ["iosMath"]),
],
dependencies: [
],
targets: [
.target(
name: "iosMath",
resources: [.process("mathFonts.bundle")]), // **<- this is where I am adding the resources**
.testTarget(
name: "iosMathTests",
dependencies: ["iosMath"],
cSettings: [
.headerSearchPath("iosMath")// 5
]),
]
)
I'm getting a runtime crash here:
return [NSBundle bundleWithURL:[[NSBundle bundleForClass:[self class]] URLForResource:#"mathFonts" withExtension:#"bundle"]];
When I manually copy the bundle into the directory of the project that I am importing this package into, it works just fine. How do I include this bundle so that it is made accessible when the package is installed?
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"]),
]
)
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")
I'm developing a set of interlinked SPM modules as a test/demo, and I've run into a strange linker error.
The problem occurs in this example, which has a Package.swift file that looks like this:
import PackageDescription
let package = Package(
name: "Package_C",
platforms: [
.iOS(.v11),
.tvOS(.v11),
.macOS(.v10_14),
.watchOS(.v5)
],
products: [
.library(
name: "Package-C",
type: .dynamic,
targets: ["Package_C"])
],
dependencies: [
.package(name: "Package_A", url: "git#github.com:LittleGreenViper/SPMArticle-Package_A.git", from: "1.0.0")
],
targets: [
.target(
name: "Package_C",
dependencies: [
.product(name: "Package-A", package: "Package_A")
],
path: "src"
),
.testTarget(
name: "Package_CTests",
dependencies: [
"Package_C"
],
path: "test"
)
]
)
The package builds fine with swift build, and everything works great, when run from Xcode.
The issue happens when I run swift test. I get the following error:
Undefined symbols for architecture x86_64:
"_$s9Package_CAAV6indentABSi_tcfC", referenced from:
_$s14Package_CTests4testC0C7QuicklyyyFSSyKXEfu_ in Package_CTests.swift.o
ld: symbol(s) not found for architecture x86_64
[4/5] Linking Package_CPackageTests
It looks like Package_C is not being linked in, but everything appears to be absolutely kosher (also, remember that everything else works fine. swift test is the only place this fails).
It should be noted that this project works fine, and does almost exactly the same thing.
The only difference that I can see, is the naming conventions of the directories. I'd really hate for that to be the issue, but I'll mess around with that, next.
Can anyone see what I can't see?
EDITED TO ADD: I should note that the static/dynamic thing doesn't seem to be the issue. I get the same error, even when I change Package_C to static.
Ugh. Looks like the issue is that the naming convention needs to be followed.
I switched from this:
To this:
and it started working. No file contents (other than removing the two path arguments from the Package.swift file) were changed.
Here is the new Package.swift file:
// swift-tools-version:5.2
import PackageDescription
let package = Package(
name: "Package_C",
platforms: [
.iOS(.v11),
.tvOS(.v11),
.macOS(.v10_14),
.watchOS(.v5)
],
products: [
.library(
name: "Package-C",
type: .dynamic,
targets: ["Package_C"])
],
dependencies: [
.package(name: "Package_A", url: "git#github.com:LittleGreenViper/SPMArticle-Package_A.git", from: "1.0.0")
],
targets: [
.target(
name: "Package_C",
dependencies: [
.product(name: "Package-A", package: "Package_A")
]
),
.testTarget(
name: "Package_CTests",
dependencies: [
"Package_C"
]
)
]
)
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