Being on a Mac my initial development was using Xcode. There is nothing wrong with that but occonially I would like to just use the command line. That is where SPM comes into play.
So suppose you want to make a new tool named smith
you would take the following steps:
$ mkdir smith
$ cd smith
$ swift package init --type executable
After executing these commands the following structure will be created:
.
|-- Package.swift
|-- Sources
| `-- main.swift
`-- Tests
Running this new structure is quite simple:
$ swift build
Compile Swift Module 'smith' (1 sources)
Linking ./.build/debug/smith
$ ./.build/debug/smith
Hello, world!
So I wanted to add a module that I would like to import into my source as a module.
So I created the following structure:
.
|-- Package.swift
|-- Sources
| |-- MyModule
| | `-- mystruct.swift
| `-- main.swift
`-- Tests
Where the file Sources/MyModule/mystruct.swift
has the following content:
public struct MyStruct {
public static let CONST = "MyConst"
}
And then Sources/swift.main
uses the module like this:
import MyModule
print("Hello, world!")
print(MyStruct.CONST)
No rocket science, I just wanted to see how to compile this.
$ swift build
error: the package has an unsupported layout, unexpected source file(s) found: /Users/fred/tmp/smith/Sources/main.swift
fix: move the file(s) inside a module
So my next try was to move the main.swift into a subdirectory as well:
$ tree
.
|-- Package.swift
|-- Sources
| |-- MyModule
| | `-- mystruct.swift
| `-- smith
| `-- main.swift
`-- Tests
And then:
$ swift build
Compile Swift Module 'smith' (1 sources)
Compile Swift Module 'MyModule' (1 sources)
/smith/Sources/smith/main.swift:1:8: error: no such module 'MyModule'
import MyModule
^
:0: error: build had 1 command failures
error: exit(1): /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift-build-tool -f /smith/.build/debug.yaml
As it turns out you cane tell SPM that the directory MyModule is a dependency of smith in the Package.swift file.
Out of the box it looks like this:
// swift-tools-version:3.1
import PackageDescription
let package = Package(
name: "smith"
)
So after changing this to:
// swift-tools-version:3.1
import PackageDescription
let package = Package(
name: "smith",
targets: [
Target(
name: "smith",
dependencies: ["MyModule"]
)
],
dependencies: [
]
)
Everything now starts to work:
$ swift build
Compile Swift Module 'MyModule' (1 sources)
Compile Swift Module 'smith' (1 sources)
Linking ./.build/debug/smith
$ ./.build/debug/smith
Hello, world!
MyConst
Mission accomplished.