I'm currently trying to understand the mechanism of importing dependencies in a Swift package and I've run into an issue with tests. Hope someone can explain what I'm doing wrong. I'm going to describe the problem step-by-step so that you could easily reproduce it.
So I'm creating a new Swift package using swift package init --type executable. This command creates the basic Swift package structure:
Artems-MacBook-Pro:SwiftExample artem$ swift package init --type executable
Creating executable package: SwiftExample
Creating Package.swift
Creating README.md
Creating .gitignore
Creating Sources/
Creating Sources/SwiftExample/main.swift
Creating Tests/
Creating Tests/LinuxMain.swift
Creating Tests/SwiftExampleTests/
Creating Tests/SwiftExampleTests/SwiftExampleTests.swift
Creating Tests/SwiftExampleTests/XCTestManifests.swift
The package itself is called SwiftExample. As you can see the command also creates an example of a unit test case (SwiftExampleTests.swift).
Then I create a simple class called Car.swift and put it into the Sources/SwiftExample/Classes/ directory:
// Sources/SwiftExample/Classes/Car.swift
class Car {
init() {
print("I'm a car!")
}
}
In the main.swift file I can create an instance of the Car class and everything works pretty much fine:
// Sources/SwiftExample/main.swift
print("Hello, world!")
let car = Car()
The output would be:
Hello, world!
I'm a car!
But the problem is I cannot use this class in my test file. For example, I'm trying to create an instance of the Car class in the testExample() function of the SwiftExampleTests.swift file:
import XCTest
import class Foundation.Bundle
#testable import SwiftExample
final class SwiftExampleTests: XCTestCase {
func testExample() throws {
let car = Car()
<other code goes here>
}
<other code goes here>
}
As you can see I've imported the module itself using the keyword #testable. But when I run swift test command I'm getting this weird error:
Compile Swift Module 'SwiftExample' (2 sources)
Compile Swift Module 'SwiftExampleTests' (2 sources)
Linking ./.build/x86_64-apple-macosx10.10/debug/SwiftExample
/Users/artem/Playgrounds/SwiftExample/Tests/SwiftExampleTests/SwiftExampleTests.swift:9:13: warning: initialization of immutable value 'car' was never used; consider replacing with assignment to '_' or removing it
let car = Car()
~~~~^~~
_
Linking ./.build/x86_64-apple-macosx10.10/debug/SwiftExamplePackageTests.xctest/Contents/MacOS/SwiftExamplePackageTests
Undefined symbols for architecture x86_64:
"_$S12SwiftExample3CarCACycfC", referenced from:
_$S17SwiftExampleTestsAAC04testB0yyKF in SwiftExampleTests.swift.o
"_$S12SwiftExample3CarCMa", referenced from:
_$S17SwiftExampleTestsAAC04testB0yyKF in SwiftExampleTests.swift.o
ld: symbol(s) not found for architecture x86_64
<unknown>:0: error: link command failed with exit code 1 (use -v to see invocation)
error: terminated(1): /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift-build-tool -f /Users/artem/Playgrounds/SwiftExample/.build/debug.yaml test output:
I'm certainly doing something wrong here but I can't find any information on the matter in the official docs. Does somebody know what's happening here and how to fix that?
Apparently, the issue won't reproduce anymore in the latest Swift version. The Car class can be imported and the swift test command won't fail.
For the record, my current swift --version output is:
swift-driver version: 1.45.2 Apple Swift version 5.6.1 (swiftlang-5.6.0.323.66 clang-1316.0.20.12)
Target: arm64-apple-macosx12.0
Related
I am having trouble getting unit tests to run in Swift projects created with the Swift Package Manager (that is, any unit tests created by the Package Manager... those I create from within Xcode work fine from within Xcode). I am getting the same error on all projects generated from the Package Manager. To keep it simple, I tried on a very basic test project with as little modification from the default setup as possible, but still getting the error. Here are the steps to reproduce:
Create a new project with swift package init --type executable (module name is Hello)
Add the Xcode Project: swift package generate-xcodeproj
In Xcode build settings, ensure Enable Testability is Yes
In swift.main enter this simple test code:
import Foundation
let message = "Hello, world!"
print(message)
In HelloTests.swift:
import XCTest
#testable import Hello
class HelloTests: XCTestCase {
func testExample() {
XCTAssert(message == "Hello, world!")
}
static var allTests = [
("testExample", testExample),
]
}
Package.swift and XCTestManifests.swift left as-is.
It builds and runs fine with swift build and swift run Hello (Also, from within in Xcode).
However, when running swift test or running any test in Xcode, the build fails with the following error message:
Undefined symbols for architecture x86_64:
"Hello.message.unsafeMutableAddressor : Swift.String", referenced from:
implicit closure #1 : #autoclosure () throws -> Swift.Bool in HelloTests.HelloTests.testExample() -> () in HelloTests.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Somehow, it seems like it's failing to link the main module, so the symbols are not recognized. However, I can't tell what's wrong or how to fix it.
I downloaded one of the sample projects from GitHub, and generated the Xcode project. The tests for this project run perfectly in Xcode and the terminal. I've carefully compared the sample project to mine and can't tell what's different. Almost all setup code (Package.swift, file structure, etc.) and project setting are nearly identical. The only meaningful difference I can tell is that the sample project is a library/framework and mine is an executable (but seems like linking should work the same for both types). Otherwise, I can't tell what they are doing right and I am doing wrong.
I figured it out (thanks to Cristik's help). Executable modules are not testable (at least for now), so the solution was to move all definitions to a library module and leave just the main.swift file in the executable module. That way, all unit tests were run with the library as a dependency vs. the executable. The package.swift now looks like this:
let package = Package(
name: "HighestNumberPairing",
products: [
.executable(name: "HighestNumberPairing", targets: ["HighestNumberPairing"]),
.library(name: "NumberPairing", targets: ["NumberPairing"]),
],
dependencies: [],
targets: [
.target(
name: "HighestNumberPairing",
dependencies: ["NumberPairing"]),
.target(
name: "NumberPairing",
dependencies: []),
.testTarget(
name: "NumberPairingTests",
dependencies: ["NumberPairing"]),
]
)
The full program is here on Github.
Swift newbie here, using swift 3 on Linux with the package manager.
I have a package Regulate, executable, and a sibling package Utils, intended to be a library. Utils/Sources has a TextReader.swift file, with class TextReader and its init function both public. The Utils directory is a git repo, described in Regulate/Package.swift:
dependencies: [.Package(url: "../Utils", "1.0.0")]
I've tried 3 ways to instantiate a TextReader object in the Regulate program and gotten 3 error messages:
import Utils
...
let reader = TextReader(filename: name)
error: use of unresolved identifier 'TextReader'
import Utils
...
let reader = Utils.TextReader(filename: name)
error: module 'Utils' has no member named 'TextReader'
import class Utils.TextReader
error: no such decl in module
It looks like the library module needs some additional structure to declare its exports, perhaps.
What do I need to do here? Thanks!
D'oh! This looks like a name conflict.
When I use Utils2 instead of Utils, it works fine. With Utils it cloned and built the other module, but apparently went to some system module instead when I referenced it.
i use CCurl (https://github.com/IBM-Swift/CCurl.git) in my project (Kitura https://github.com/IBM-Swift/Kitura) then i call func curlHelperSetOptString , compile "swift build" and get an error:
duplicate symbol _curlHelperSetOptString in:
/Users/xxxx/Documents/server/ServerSwift/.build/debug/ServerSwift.build/UploadService.swift.o /Users/xxxx/Documents/server/ServerSwift/.build/debug/KituraNet.build/ClientRequest.swift.o
ld: 1 duplicate symbol for architecture x86_64 :0: error:
link command failed with exit code 1 (use -v to see invocation)
:0: error: build had 1 command failures
code:
import CCurl
var handle=curl_easy_init()
if (handle != nil) {
let url = "http: //example.com/"
let buffer=url.cString(using: .utf8)
curlHelperSetOptString(handle, CURLOPT_URL, buffer)
}
Help me ,plz
Actually it may be because we have defined the CCurl helper functions as extern inline, rather than as static inline. Apparently extern inline causes one of the references to the defined function to become an external name, which can cause problems if it is imported more than once.
We'll look into this.
IBM-Swift/CCurl.git 0.2.2 has been tagged. It contains a fix for the problem mentioned here.
You're probably including CCurl directly in your Package.swift when it's already included in Kitura-Net/Package.swift.
With most Swift modules, this wouldn't be a problem, but CCurl has to have a hack in it because libCurl contains mostly variadic functions and Swift doesn't import variadic functions from C libraries. The hack creates static functions in the C header file to create non-variadic version of the libCurl functions. It's those static functions that are being duplicated here (and each module is compiled separately, so you can't #ifndef around them because they can't see each other).
Try removing the CCurl dependency from your Package.swift file and just depend on the fact that it's being included for you, and hopefully you'll be okay.
Check that you don't have multiple entries under Build Phases/Compile Sources. If yes, remove them.
Also you could try cleaning your project or even run swift package generate-xcodeproj again.
It's because you are importing ccurl which is already imported in the kitura-net package.
I was trying to compile a swift 3 file which contains nothing but:
import Cocoa
The compiler output was:
<unknown>:0: error: missing required module 'os.log'
So I edited the file to be:
import os.log
import Cocoa
And now the compiler output is:
test.swift:1:8: error: no such module 'os.log'
I suspect that the compiler is having trouble finding the legitimate module os.log. I should note that I'm editing the file in VIM, and the same program works fine in my Swift playground.
You need this declaration:
import os
source
I've added a custom library (attach project) to my project.
If I use it in main.swift all is good.
But, if I try to make it like:
import ARISockets
class MyClass {
var listenSocket : PassiveSocketIPv4?
}
then it gives an error
dyld: Library not loaded
PS: I make Command Line Tool for a mac
PSS: Add library https://github.com/AlwaysRightInstitute/SwiftSockets