{"id":2040,"date":"2015-12-08T08:12:03","date_gmt":"2015-12-08T14:12:03","guid":{"rendered":"http:\/\/dev.iachieved.it\/iachievedit\/?p=2040"},"modified":"2016-04-24T11:20:11","modified_gmt":"2016-04-24T17:20:11","slug":"introducing-the-swift-package-manager","status":"publish","type":"post","link":"https:\/\/dev.iachieved.it\/iachievedit\/introducing-the-swift-package-manager\/","title":{"rendered":"Introducing the Swift Package Manager"},"content":{"rendered":"<p><img decoding=\"async\" src=\"https:\/\/img.shields.io\/badge\/OS-Linux-blue.svg?style=flat\" alt=\"Linux\" \/> <img decoding=\"async\" src=\"https:\/\/img.shields.io\/badge\/Swift-2.2-orange.svg?style=flat\" alt=\"Swift 2.2\" \/><\/p>\n<p><b>Update:<\/b>  If you don&#8217;t have Swift installed yet, head on over to our <a href=\"http:\/\/dev.iachieved.it\/iachievedit\/ubuntu-packages-for-open-source-swift\/\">Ubuntu Packages<\/a> page and get the latest with <code>apt-get install<\/code>.<\/p>\n<p>In today&#8217;s world any serious programming language is going to come with a <a href=\"https:\/\/en.wikipedia.org\/wiki\/Package_manager\">package manager<\/a>, an application designed to aid managing the distribution and installation of software &#8220;packages&#8221;.  Ruby has a <i>de jure<\/i> package management system with the <a href=\"https:\/\/en.wikipedia.org\/wiki\/RubyGems\">rubygems<\/a> application, formally added to the language in Ruby 1.9.  Python has various competing package management systems with pip, easy_install, and others.  NodeJS applications and libraries are delivered via <a href=\"https:\/\/www.npmjs.com\/\">npm<\/a>.<\/p>\n<p>As a part of the open source release of Swift, Apple has released a <a href=\"https:\/\/github.com\/apple\/swift-package-manager\">Swift Package Manager<\/a> designed for &#8220;managing distribution of source code, aimed at making it easy to share your code and reuse others\u2019 code.&#8221;  This is a bit of understatement of what the Swift Package Manager can do in that its real power comes in managing the compilation and link steps of a Swift application.<\/p>\n<p>In our <a href=\"http:\/\/dev.iachieved.it\/iachievedit\/more-swift-on-linux\/\">previous tutorial<\/a> we explored how to build up a Swift application that relied on Glibc functions, linking against libcurl routines with a bridging header, and linking against a C function we compiled into an object file.  You can see from the <a href=\"https:\/\/github.com\/iachievedit\/moreswift\/blob\/master\/translator\/Makefile\">Makefile<\/a>, there are a lot of steps and commands involved!<\/p>\n<p>In this post we&#8217;re going to replace all that with a succinct and clean Swift Package Manager <code>Package.swift<\/code> manifest and simplify our code while we&#8217;re at it.<\/p>\n<h2>Package.swift<\/h2>\n<p><code>Package.swift<\/code> is the equivalent of <b>npm<\/b>s <code>package.json<\/code>.  It is the blueprint and set of instructions from which the Swift Package Manager will build your application.  As of this writing (December 8, 2015), <code>Package.swift<\/code> contains information such as:<\/p>\n<ul>\n<li>the name of your application (package)\n<li>dependencies that your application relies on and where to retrieve them\n<li>targets to build\n<\/ul>\n<p>Unlike <code>package.json<\/code> however, <code>Package.swift<\/code> <i>is<\/i> Swift code, in the same way an <a href=\"http:\/\/www.scons.org\/doc\/2.4.0\/HTML\/scons-user\/ch02s05.html\"><code>SConstruct<\/code><\/a> file is Python.  As the Swift Package Manager evolves to meet the complex use cases of building large software packages it will undoubtedly grow to contain additional metadata and instructions on how to build your package (for example, <code>package.json<\/code> for NodeJS contains instructions on how to execute your unit tests).<\/p>\n<p>There&#8217;s quite a bit of documentation available for the Swift Package Manager on Github, so I won&#8217;t rehash it here, but will rather dive right in to a working example of a <code>Package.swift<\/code> for our translator application.<\/p>\n<pre class=\"lang:swift\">\nimport PackageDescription\n\nlet package = Package(\n  name:  \"translator\",\n  dependencies: [\n    .Package(url:  \"https:\/\/github.com\/iachievedit\/CJSONC\", majorVersion: 1),\n    .Package(url:  \"https:\/\/github.com\/PureSwift\/CcURL\", majorVersion: 1)\n  ]\n)\n<\/pre>\n<p>Each <code>Package.swift<\/code> file starts off with <code>import PackageDescription<\/code>.  <code>PackageDescription<\/code> is a new Swift module that comes with the binary distribution of Swift for the Ubuntu system.  The class <code>Package<\/code> is provided, which we utilize on the next line.<\/p>\n<p>Don&#8217;t let the &#8220;declarative&#8221; nature fool you, this is Swift code.  <code>package<\/code> gets assigned a new <code>Package<\/code> object which we&#8217;ve created with the <code>init(name: String? = nil, targets: [Target] = [], dependencies: [Dependency] = [])<\/code> initializer.<\/p>\n<p>The name attribute is self-explanatory, and <code>dependencies<\/code> is an array of package dependencies.  Our application will rely on two packages, CJSONC (which is a wrapper around libjson-c), and CcURL (a wrapper around, you guessed it, libcurl).<\/p>\n<p>The Swift Package Manager authors have devised an interesting mechanism by which to pull in package dependencies which relies on <a href=\"https:\/\/git-scm.com\/\">Git<\/a> and git tags.  We&#8217;ll get to that in a moment.<\/p>\n<h2>Directory Structure<\/h2>\n<p>The Swift Package Manager relies on the <a href=\"https:\/\/en.wikipedia.org\/wiki\/Convention_over_configuration\"><i>convention over configuration<\/i><\/a> paradigm for how to organize your Swift source files.  By this we simply mean, if you follow the convention the package manager expects, then you have to do very little with your <code>Package.swift<\/code>.  Notice that we didn&#8217;t specify the name of our source files in it.  We don&#8217;t have to because the package manager will figure it out by looking in expected locations.<\/p>\n<p>In short, the Swift Package Manager is happiest when you organize things like this:<\/p>\n<pre class=\"crayon:false\">\nproject\/Package.swift\n       \/Sources\/sourceFile.swift\n       \/Sources\/...\n       \/Sources\/main.swift\n<\/pre>\n<p>In our <code>Sources<\/code> directory we will place two files:  <code>Translator.swift<\/code> and <code>main.swift<\/code>.  <b>Note:<\/b>  Our previous tutorial used lowercase filenames, such as <code>translator.swift<\/code>.  This convention is used by NodeJS developers.  It appears that the Swift community is going with capitalized filenames.<\/p>\n<p><code>Translator.swift<\/code> has changed a bit from our previous version.  Here is the new version which leverages system modules rather than trying to link against C object files we created by hand.<\/p>\n<pre class=\"lang:swift\">\nimport Glibc\nimport Foundation\nimport CcURL\nimport CJSONC\n\npublic class Translator {\n\n  let BUFSIZE = 1024\n\n  public init() {\n  }\n\n  public func translate(text:String, from:String, to:String,\n                        completion:(translation:String?, error:NSError?) -> Void) {\n\n    let curl = curl_easy_init()\n\n    guard curl != nil else {\n      completion(translation:nil,\n                 error:NSError(domain:\"translator\", code:1, userInfo:nil))\n      return\n    }\n\n    let escapedText = curl_easy_escape(curl, text, Int32(strlen(text)))\n\n    guard escapedText != nil else {\n      completion(translation:nil,\n                 error:NSError(domain:\"translator\", code:2, userInfo:nil))\n      return\n    }\n    \n    let langPair = from + \"%7c\" + to\n    let wgetCommand = \"wget -qO- http:\/\/api.mymemory.translated.net\/get\\\\?q\\\\=\" + String.fromCString(escapedText)! + \"\\\\&langpair\\\\=\" + langPair\n    \n    let pp      = popen(wgetCommand, \"r\")\n    var buf     = [CChar](count:BUFSIZE, repeatedValue:CChar(0))\n    \n    var response:String = \"\"\n    while fgets(&buf, Int32(BUFSIZE), pp) != nil {\n      response = response + String.fromCString(buf)!\n    }\n    \n    let translation = getTranslatedText(response)\n\n    guard translation.error == nil else {\n      completion(translation:nil, error:translation.error)\n      return\n    }\n\n    completion(translation:translation.translation, error:nil)\n  }\n\n  private func getTranslatedText(jsonString:String) -> (error:NSError?, translation:String?) {\n\n    let obj = json_tokener_parse(jsonString)\n\n    guard obj != nil else {\n      return (NSError(domain:\"translator\", code:3, userInfo:nil),\n             nil)\n    }\n\n    let responseData = json_object_object_get(obj, \"responseData\")\n\n    guard responseData != nil else {\n      return (NSError(domain:\"translator\", code:3, userInfo:nil),\n              nil)\n    }\n\n    let translatedTextObj = json_object_object_get(responseData,\n                                                   \"translatedText\")\n\n    guard translatedTextObj != nil else {\n      return (NSError(domain:\"translator\", code:3, userInfo:nil),\n              nil)\n    }\n\n    let translatedTextStr = json_object_get_string(translatedTextObj)\n\n    return (nil, String.fromCString(translatedTextStr)!)\n           \n  }\n\n}\n<\/pre>\n<p>Two new <code>import<\/code> statements have been added for <code>CJSONC<\/code> and <code>CcURL<\/code>, and a routine we <i>did<\/i> have in C is now in pure Swift.  To be sure under the hood the compile and link system is relying on libraries that were compiled from C source code, but at the binary level, its all the same.<\/p>\n<p>Now, here is where it gets really simple to build!  Type <code>swift build<\/code> and watch magic happen:<\/p>\n<pre class=\"crayon:false\">\n# swift build\nCloning Packages\/CJSONC\nCloning Packages\/CcURL\nCompiling Swift Module 'translator' (2 sources)\nLinking Executable:  .build\/debug\/translator\n<\/pre>\n<p>That&#8217;s it!  Our binary is placed in <code>.build\/debug<\/code> and takes its name from our <code>Package.swift<\/code> file.  By default a debug build is created; if we want a release build, just add <code>-c release<\/code> to the command:<\/p>\n<pre class=\"crayon:false\">\n# swift build -c release\nCompiling Swift Module 'translator' (2 sources)\nLinking Executable:  .build\/release\/translator\n<\/pre>\n<p>Running our application:<\/p>\n<pre class=\"crayon:false\">\n# .build\/debug\/translator \"Hello world\\!\" from en to es\nTranslation:  \u00a1Hola, mundo!\n<\/pre>\n<h2>System Modules<\/h2>\n<p>Let&#8217;s talk about the two dependencies listed in our <code>Package.swift<\/code> manifest.  If you go to the Github repository of either &#8220;packages&#8221; you will find very little.  Two files, in fact:<\/p>\n<ul>\n<li><code>module.modulemap<\/code>\n<li><code>Package.swift<\/code>\n<\/ul>\n<p>and the <code>Package.swift<\/code> file is actually empty!<\/p>\n<p>The format of the <code>module.modulemap<\/code> file and its purpose is described in the <a href=\"https:\/\/github.com\/apple\/swift-package-manager\/blob\/master\/Documentation\/SystemModules.md\">System Modules<\/a> section of the Swift Package Manager documentation.  Let&#8217;s take a look at the CJSON one:<\/p>\n<pre class=\"crayon:false\">\nmodule CJSONC [system] {\n  header \"\/usr\/include\/json-c\/json.h\"\n  link \"json-c\"\n  export *\n}\n<\/pre>\n<p>All this file does is map a native C library and headers to a Swift module.  In short, if you create a <code>modulemap<\/code> file you can begin importing functions from all manner of libraries on your Linux system.  We&#8217;ve created a modulemap for <a href=\"https:\/\/github.com\/json-c\/json-c\">json-c<\/a> which is installed via <code>apt-get<\/code> on an Ubuntu system.<\/p>\n<p>The authors of the Swift Package Manager, in the <i>System Modules<\/i> documentation state:<\/p>\n<blockquote><p>\nThe convention we hope the community will adopt is to prefix such modules with C and to camelcase the modules as per Swift module name conventions. Then the community is free to name another module simply JPEG which contains more \u201cSwifty\u201d function wrappers around the raw C interface.\n<\/p><\/blockquote>\n<p>Interpretation:  if you&#8217;re providing a straight-up modulemap file and exposing C functions, name the module CPACKAGE.  If at a later date you write a Swift API that uses CPACKAGE underneath, you can call that module PACKAGE.  Thus when you see CJSONC and CcURL above you know that you&#8217;re dealing with direct C routines.<\/p>\n<h3>Creating a System Module<\/h3>\n<p>There are several examples of creating system modules in the documentation, but we&#8217;ll add one more.  Creating a system module is broken down into 3 steps:<\/p>\n<ul>\n<li>Naming the module\n<li>Creating the module.modulemap file\n<li>Versioning the module\n<\/ul>\n<pre>\nsudo apt-get install -y libdb5.3-dev # Since we're going to be using BerkeleyDB\nmkdir CDB\ncd CDB \ntouch Package.swift\n<\/pre>\n<p>In this directory (<code>CDB<\/code>) add <code>module.modulemap<\/code> with the following contents:<\/p>\n<pre>\nmodule CDB [system] {\n  header \"\/usr\/include\/db.h\"\n  link \"db\"\n  export *\n}\n<\/pre>\n<p>Package dependencies in <code>Package.swift<\/code> are specified with URLs and version numbers.  <a href=\"https:\/\/github.com\/apple\/swift-package-manager\/blob\/master\/Sources\/PackageDescription\/Version.swift\"><code>Version.swift<\/code><\/a> lays out the current versioning scheme of <code>major.minor.patch<\/code>.  We need a mechanism by which to version our system module, and the Swift Package Managers have developed a scheme by which you can use <a href=\"https:\/\/git-scm.com\/book\/en\/v2\/Git-Basics-Tagging\">git tags<\/a>.<\/p>\n<p>Now, I&#8217;m not sure if git tags will be the only way to specify the version of your package; it does have the downside of tying one to using git for source control of your Swift code.<\/p>\n<p>In our CDB directory.<\/p>\n<pre class=\"crayon:false\">\ngit init # Initialize a git repository\ngit add . # Add all of the files in our directory\ngit commit -m\"Initial Version\" # Commit\n[master (root-commit) d756512] Initial Version\n 2 files changed, 5 insertions(+)\n create mode 100644 Package.swift\n create mode 100644 module.modulemap\n<\/pre>\n<p>And the crucial step:<\/p>\n<pre class=\"crayon:false\">\ngit tag 1.0.0 # Tag our first version\n<\/pre>\n<p>Now we want to use our new module.  In a separate directory named <code>use-CDB<\/code>, adjacent to our <code>CDB<\/code> directory<\/code>, create a <code>Package.swift<\/code> file:<\/p>\n<pre class=\"lang:swift\">\nimport PackageDescription\n\nlet package = Package(\n  name:\"use-CDB\",\n  dependencies:[\n    .Package(url:\"..\/CDB\", majorVersion:1)\n  ]\n)\n<\/pre>\n<p>It&#8217;s important to note here your directory structure should look like this:<\/p>\n<pre class=\"crayon:false\">\n    CDB\/module.modulemap\n       \/Package.swift\nuse-CDB\/Package.swift\n<\/pre>\n<p>In <code>use-CDB<\/code> run <code>swift build<\/code>:<\/p>\n<pre class=\"crayon:false\">\n# swift build\nCloning Packages\/CDB\n<\/pre>\n<p>What <code>swift build<\/code> has done here is read the package descriptor and &#8220;pulled in&#8221; the dependency on the <code>CDB<\/code> package.  It so happens that this package is in your local filesystem vs. on a hosted Git repository like Github or BitBucket.  The <code>majorVersion<\/code> is the first tuple of your git tag.<\/p>\n<p>Now let&#8217;s say you made an error and needed to change up <code>module.modulemap<\/code>.  You edit the file, commit it, and then run <code>swift build<\/code> again.  <i>Unless<\/i> you retag you will not pick up these changes!  Versioning in action.  Either retag 1.0.0 with <code>git tag -f 1.0.0<\/code> (<code>-f<\/code> is for force), or bump your version number with a patch level, like <code>git tag 1.0.1<\/code>.<\/p>\n<p>To use our new system module we write a quick <code>main.swift<\/code> in <code>use-CDB<\/code>:<\/p>\n<pre class=\"lang:swift\">\nimport CDB\nimport Glibc\n\nvar myDatabase:UnsafeMutablePointer<DB> = nil\n\nlet rc = db_create(&myDatabase, nil, 0)\n\nguard rc == 0 else {\n  print(\"Unable to create database\")\n  exit(-1)\n}\n\nprint(\"Database created\")\n<\/pre>\n<p>Use <code>swift build<\/code> and it will pull in our <code>CDB<\/code> module for us to use.  The next step is to figure out how to use the <code>myDatabase<\/code> pointer to open the database!<\/p>\n<h2>Closing Remarks<\/h2>\n<p>It has been less than a week since Apple put Swift and the new package manager out on Github.  It&#8217;s under heavy churn right now and will undoubtedly rapidly gain new features as time goes on, but it is a great start to being able to quickly build Swift applications on a Linux system!<\/p>\n<h3>Getting the Code<\/h3>\n<p>You can get the new version of our translator application which uses the Swift Package Manager on Github.<\/p>\n<pre class=\"crayon:false\">\n# git clone https:\/\/github.com\/iachievedit\/moreswift\n# cd translator_swiftpm\n# swift build\nCloning Packages\/CJSONC\nCloning Packages\/CcURL\nCompiling Swift Module 'translator' (2 sources)\nLinking Executable:  .build\/debug\/translator\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Update: If you don&#8217;t have Swift installed yet, head on over to our Ubuntu Packages page and get the latest with apt-get install. In today&#8217;s world any serious programming language is going to come with a package manager, an application designed to aid managing the distribution and installation of software &#8220;packages&#8221;. Ruby has a de [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[11,19,5],"tags":[],"class_list":["post-2040","post","type-post","status-publish","format-standard","hentry","category-apple","category-linux","category-swift"],"_links":{"self":[{"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/posts\/2040"}],"collection":[{"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/comments?post=2040"}],"version-history":[{"count":32,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/posts\/2040\/revisions"}],"predecessor-version":[{"id":2812,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/posts\/2040\/revisions\/2812"}],"wp:attachment":[{"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/media?parent=2040"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/categories?post=2040"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dev.iachieved.it\/iachievedit\/wp-json\/wp\/v2\/tags?post=2040"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}