{"id":113,"date":"2017-08-19T10:20:56","date_gmt":"2017-08-19T10:20:56","guid":{"rendered":"https:\/\/fred.appelman.net\/?p=113"},"modified":"2018-01-06T20:02:21","modified_gmt":"2018-01-06T20:02:21","slug":"organising-your-swift-source-code-using-swift-package-manager-spm","status":"publish","type":"post","link":"https:\/\/fred.appelman.net\/?p=113","title":{"rendered":"Organising your Swift source code using Swift Package Manager (SPM)"},"content":{"rendered":"<div class=\"entry\">\n<link rel=\"stylesheet\" href=\"http:\/\/cdnjs.cloudflare.com\/ajax\/libs\/highlight.js\/8.6\/styles\/mono-blue.min.css\"><script src=\"http:\/\/cdnjs.cloudflare.com\/ajax\/libs\/highlight.js\/8.6\/highlight.min.js\"><\/script><script>hljs.initHighlightingOnLoad();<\/script>\n<p>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 <a href=\"https:\/\/swift.org\/package-manager\/\">SPM<\/a> comes into play.<br \/>\nSo suppose you want to make a new tool named <code>smith<\/code> you would take the following steps:<\/p>\n<pre><code>\n$ mkdir smith\n$ cd smith\n$ swift package init --type executable\n<\/code><\/pre>\n<p>After executing these commands the following structure will be created:<\/p>\n<pre><code>\n.\n|-- Package.swift\n|-- Sources\n|   `-- main.swift\n`-- Tests\n<\/code><\/pre>\n<p>Running this new structure is quite simple:<\/p>\n<pre><code>\n$ swift build\nCompile Swift Module 'smith' (1 sources)\nLinking .\/.build\/debug\/smith\n$ .\/.build\/debug\/smith\nHello, world!\n<\/code><\/pre>\n<p>So I wanted to add a module that I would like to import into my source as a module.<br \/>\nSo I created the following structure:<\/p>\n<pre><code>\n.\n|-- Package.swift\n|-- Sources\n|   |-- MyModule\n|   |   `-- mystruct.swift\n|   `-- main.swift\n`-- Tests\n<\/code><\/pre>\n<p>Where the file <code>Sources\/MyModule\/mystruct.swift<\/code> has the following content:<\/p>\n<pre><code>\npublic struct MyStruct {\n  public static let CONST = \"MyConst\"\n}\n<\/code><\/pre>\n<p>And then <code>Sources\/swift.main<\/code> uses the module like this:<\/p>\n<pre><code>\nimport MyModule\n\nprint(\"Hello, world!\")\nprint(MyStruct.CONST)\n<\/code><\/pre>\n<p>No rocket science, I just wanted to see how to compile this.<\/p>\n<pre><code>\n$ swift build\nerror: the package has an unsupported layout, unexpected source file(s) found: \/Users\/fred\/tmp\/smith\/Sources\/main.swift\nfix: move the file(s) inside a module\n<\/code><\/pre>\n<p>So my next try was to move the main.swift into a subdirectory as well:<\/p>\n<pre><code>\n$ tree\n.\n|-- Package.swift\n|-- Sources\n|   |-- MyModule\n|   |   `-- mystruct.swift\n|   `-- smith\n|       `-- main.swift\n`-- Tests\n<\/code><\/pre>\n<p>And then:<\/p>\n<pre><code>\n$ swift build\nCompile Swift Module 'smith' (1 sources)\nCompile Swift Module 'MyModule' (1 sources)\n\/smith\/Sources\/smith\/main.swift:1:8: error: no such module 'MyModule'\nimport MyModule\n       ^\n<unknown>:0: error: build had 1 command failures\nerror: exit(1): \/Applications\/Xcode.app\/Contents\/Developer\/Toolchains\/XcodeDefault.xctoolchain\/usr\/bin\/swift-build-tool -f \/smith\/.build\/debug.yaml\n<\/code><\/pre>\n<p>As it turns out you cane tell SPM that the directory MyModule is a dependency of smith in the Package.swift file.<\/p>\n<p>Out of the box it looks like this:<\/p>\n<pre><code>\n\/\/ swift-tools-version:3.1\n\nimport PackageDescription\n\nlet package = Package(\n    name: \"smith\"\n)\n<\/code><\/pre>\n<p>So after changing this to:<\/p>\n<pre><code>\n\/\/ swift-tools-version:3.1\n\nimport PackageDescription\n\nlet package = Package(\n    name: \"smith\",\n    targets: [\n        Target(\n            name: \"smith\",\n            dependencies: [\"MyModule\"]\n        )\n    ],\n    dependencies: [\n    ]\n)\n<\/code><\/pre>\n<p>Everything now starts to work:<\/p>\n<pre><code>\n$ swift build\nCompile Swift Module 'MyModule' (1 sources)\nCompile Swift Module 'smith' (1 sources)\nLinking .\/.build\/debug\/smith\n$ .\/.build\/debug\/smith\nHello, world!\nMyConst\n<\/code><\/pre>\n<p>Mission accomplished.<\/p>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>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 $ &#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[15,10,12],"tags":[17,16,18],"class_list":{"0":"post-113","1":"post","2":"type-post","3":"status-publish","4":"format-standard","6":"category-spm","7":"category-swift","8":"category-swift-3","9":"tag-spm","10":"tag-swift","11":"tag-swift-3","12":"anons"},"_links":{"self":[{"href":"https:\/\/fred.appelman.net\/index.php?rest_route=\/wp\/v2\/posts\/113","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/fred.appelman.net\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/fred.appelman.net\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/fred.appelman.net\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/fred.appelman.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=113"}],"version-history":[{"count":3,"href":"https:\/\/fred.appelman.net\/index.php?rest_route=\/wp\/v2\/posts\/113\/revisions"}],"predecessor-version":[{"id":117,"href":"https:\/\/fred.appelman.net\/index.php?rest_route=\/wp\/v2\/posts\/113\/revisions\/117"}],"wp:attachment":[{"href":"https:\/\/fred.appelman.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=113"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/fred.appelman.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=113"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/fred.appelman.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=113"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}