Hi, I'm just starting out with swift and have structured my code into several files. I used swift package init --type executable command to lay out the directories. Inside Sources/myProj, I've put two different swift files with two different functions i.e. file1.swift and file2.swift. Inside these I've one function in each i.e. funct1 and func2.
Now I want to use these functions in my main.swift file but I can't figure out how to import them. Maybe someone can help me out here.
Each folder under Sources is a module, in your manifest file package.swift you should include core as a dependency of myProj target, then in main.swift you have to import the module import core.
// 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: "01_sum_two_digits",
dependencies: [.package(path: "Sources/core")
// Dependencies declare other packages that this package depends on.
// .package(url: /* package url */, from: "1.0.0"),
],
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: "01_sum_two_digits",
dependencies: ["core"]),
.testTarget(
name: "01_sum_two_digitsTests",
dependencies: ["01_sum_two_digits", "core"]),
]
)
and getting an error: 01_sum_two_digits/Sources/core has no Package.swift manifest.
That's because you are including Sources/core as a Package dependency, but Sources/core is not a Package itself. Core is only a target dependency, meaning you only have to add it as a dependency in your targets.
let package = Package(
name: "01_sum_two_digits",
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: "01_sum_two_digits",
dependencies: ["core"]),
.testTarget(
name: "01_sum_two_digitsTests",
dependencies: ["01_sum_two_digits", "core"]),
]
)
I did this first but got an error error: product 'core' not found. it is required by package '01_sum_two_digits' target '01_sum_two_digitsTests'.
Here's my code:
// 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: "01_sum_two_digits",
dependencies: [
// Dependencies declare other packages that this package depends on.
// .package(url: /* package url */, from: "1.0.0"),
],
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: "01_sum_two_digits",
dependencies: ["core"]),
.testTarget(
name: "01_sum_two_digitsTests",
dependencies: ["01_sum_two_digits", "core"]),
]
)
Oh sorry, you have to define core as a target there. Try something like:
// 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: "01_sum_two_digits",
dependencies: [
// Dependencies declare other packages that this package depends on.
// .package(url: /* package url */, from: "1.0.0"),
],
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: "01_sum_two_digits",
dependencies: ["core"]),
.target(name: "core"),
.testTarget(
name: "01_sum_two_digitsTests",
dependencies: ["01_sum_two_digits", "core"]),
]
)
That's because declarations have access levelinternal by default, which means only available within the same module. You need to change your functions to public func for example.
That will create the following files: core.swiftdoc, core.swiftmodule, core.swiftsourceinfo, libcore.dylib
swiftc -I . -L . -lcore Sources/myProj/main.swift
That will create the main executable.
So you could do it that way, but there's probably a bunch of reasons why swift build is preferred (I assume that it is), like incremental build optimizations and things like that (whatever the .build directory is for).
If Swift's import were file-based I guess it would simpler, but I don't know why it's designed the way it is, and there's probably good reasons for it (less boilerplate for example?).
That would make things much more complicated, because then you would have to change the import statement each time you move a function to a different file. And what about closed source binaries? You wouldn't have access to the source files, so there would be no way to know which file each symbol was declared in.
Each of the customTest#.swift file checks individual functions written in file1.swift and file2.swift. I was hoping I could individually import functions (or use them individually) in these files one by one and test them separately. This is the reason I want to run these manually so that I can ensure that each function works well before integrating them into the main.swift file.
I was looking at swift test command but can't figure out how that works. Maybe there's a better way to do this instead of manually running everything. Please let me know if there's some substitute to this.
I would like to know more about how swift packages does all this compiling and linking automatically (just curious), it would be great if you can share link to some docs.
You really don't want to know this unless you're contributing the language itself. What you need to understand is the structure of a swift package and the commands you can run from the command line.
You can also use swift test --filter to run multiple specific tests using the following syntax:
swift test --filter 'customTest1/testFunc1|customTest1/testFunc2'