作者:JOE,原文鏈接,原文日期:2016-05-01
譯者:ckitakishi;校對:mmoaay;定稿:CMB
當前,有許多人正在努力將 Swift 3.0 引入到基于 ARM 的系統(tǒng)中。通過本文你將了解如何在運行 Ubuntu 16 (Xenial Xerus) 的樹莓派 2 或樹莓派 3 上構(gòu)建并使用 Swift 3.0。不過,我們暫時還沒有對它在 Raspbian 系統(tǒng)上的可用性進行測試 (看起來并不可以)。
一個善意的提醒:樹莓派 (以及所有 ARM 設(shè)備) 所支持的 Swift 3.0 仍然是測試版。 因此,盡管你可以在原型制作以及概念驗證時盡情使用,但利用它來構(gòu)筑產(chǎn)品還需三思。另外,我們有一個團隊,正以在 ARM 設(shè)備上使用 Swift 3.0 為目標而不懈努力,如果你有興趣加入,請發(fā)郵件到:admin@iachieved.it,我們將會邀請你加入 Slack 群組。
在樹莓派上部署 Xenial
也許你還不知道支持樹莓派的 Xenial 是存在的。不過沒關(guān)系,因為我以前也是!首先你可以通讀 Ubuntu Wiki 來了解它的核心內(nèi)容,然后在樹莓派上部署它。建議使用至少 8G 的 SD 卡。
安裝 Swift 3.0
我們的團隊致力于在 ARM 設(shè)備上使用 Swift,最近大家正在一臺樹莓派 3 上通過 Jenkins 來構(gòu)建樹莓派專用的二進制文件。看,下圖就是構(gòu)建設(shè)備!

Swift 3.0 構(gòu)建設(shè)備
如果你好奇這一切是如何進行的,可以查看 Jenkins 構(gòu)建項目。坦率地說,我十分驚訝,因為它只花了 6 個小時就完成了 Swift 的編譯。
現(xiàn)在可以開始折騰了。首先,在你的樹莓派上下載 Swift 3.0 的構(gòu)建包 (build artifact) ,并將其解壓放置在某個目錄中,然后像下面這樣設(shè)置你的 PATH 值:
shell
cd $HOME
wget http://swift-arm.ddns.net/job/Swift-3.0-Pi3-ARM-Incremental/16/artifact/swift-3.0-2016-07-19-RPi23-ubuntu16.04.tar.gz
mkdir swift-3.0
cd swift-3.0 && tar -xzf ../swift-3.0.tgz
export PATH=$HOME/swift-3.0/usr/bin:$PATH
注意:把 Swift 3.0 放在 $HOME 并不是強制性的,我通常使用的路徑是:/opt/swift/swift-3.0。
一切就緒,讓我們馬上來體驗一下吧!
創(chuàng)建一個名為 helloWorld.swift 的文件:
print("Hello, world!")
然后你可以使用 swift helloWorld.swift 語句來執(zhí)行該文件,就像執(zhí)行腳本一樣:
shell
# swift helloWorld.swift
Hello, world!
如果你下載了 clang 并對它進行了正確配置的話,也可以另辟蹊徑,使用 swiftc 將上述文件編譯為可執(zhí)行文件:
shell
# swiftc helloWorld.swift
# ./helloWorld
Hello world!
倘若執(zhí)行 swiftc 時失敗并拋出error: link command failed with exit code 127 錯誤,則極有可能是因為你沒有正確下載或配置 clang:
shell
sudo apt-get update
sudo apt-get install -y libicu-dev
sudo apt-get install -y clang-3.6
sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-3.6 100
sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-3.6 100
接下來讓我們再來看一些有趣的小花絮吧:
導(dǎo)入 Glibc!
swiftcat.swift:
import Glibc
guard Process.arguments.count == 2 else {
print("Usage: swiftcat FILENAME")
exit(-1)
}
let filename = Process.arguments[1]
let BUFSIZE = 1024
var pp = popen("cat " + filename, "r")
var buf = [CChar](repeating:0, count:BUFSIZE)
while fgets(&buf, Int32(BUFSIZE), pp) != nil {
print(String(cString:buf), terminator:"")
}
exit(0)
編譯 (swiftc swiftcat.swift) 并執(zhí)行 (swiftcat)!
橋接 C 程序
鏈接已編譯對象文件也可以了!示例如下:
escapetext.c:
c
#include <string.h>
#include <stdlib.h>
#include <curl/curl.h>
int escapeText(const char* text, char** output) {
int rc = -1;
CURL* curl = curl_easy_init();
if (curl) {
char* escaped = curl_easy_escape(curl, text, strlen(text));
if (escaped) {
*output = (char*)malloc(strlen(escaped) + 1);
strcpy(*output, escaped);
curl_free(escaped);
rc = strlen(*output);
}
}
return rc;
}
escapetext.h:
c
int escapeText(const char* text, char** output);
import Glibc
guard Process.arguments.count == 2 else {
print("Usage: escapeswift STRING")
exit(-1)
}
let string = Process.arguments[1]
var buffer:UnsafeMutablePointer<Int8>? = nil
let rc = escapeText(string, &buffer)
guard rc > 0 else {
print("Error escaping text")
exit(-1)
}
if let escaped = buffer {
let escapedString = String(cString:escaped)
print("Escaped text: " + escapedString)
}
exit(0)
編譯并將所有文件鏈接在一起:
shell
# clang -c escapetext.c
# swiftc -c escapeswift.swift -import-objc-header escapetext.h
# swiftc escapeswift.o escapetext.o -o escapeswift -lcurl
然后運行:
shell
# ./escapeswift "foo > bar"
Escaped text: foo%20%3E%20bar
Swift 包管理
除非你很享受寫 makefile 和構(gòu)建腳本 (相信我,的確有人是這樣的),不然你可以在這里使用 Swift Package Manager 來協(xié)助管理軟件的包依賴。對于 Swift 3.0 引入的 SwiftPM,后面我們會寫更多與其相關(guān)的內(nèi)容,說起來,SwiftPM 提供了一個能夠在 armv 7 設(shè)備上工作的版本,這實在是一件令人很振奮的事情。不妨試一試下面的代碼:
shell
# mkdir finalCountdown && cd finalCountdown
# swift package init --type executable
Creating executable package: finalCountdown
Creating Package.swift
Creating .gitignore
Creating Sources/
Creating Sources/main.swift
Creating Tests/
然后再將 Sources/main.swift 的內(nèi)容替換為下面的代碼:
import Foundation
import Glibc
let thread = NSThread(){
print("Entering thread")
for i in (1...10).reversed() {
print("\(i)...", terminator:"")
fflush(stdout)
sleep(1)
}
print("\nExiting thread")
print("Done")
exit(0)
}
thread.start()
select(0, nil, nil, nil, nil)
現(xiàn)在,執(zhí)行 swift build 來構(gòu)建你的 finalCountdown 應(yīng)用:
shell
# swift build
Compile Swift Module 'finalCountdown' (1 sources)
Linking .build/debug/finalCountdown
# .build/debug/finalCountdown
Entering thread
10...9...8...7...6...5...4...3...2...1...
Exiting thread
Done
moreswift
如果你對在 x86 與 armv 7 系統(tǒng)上運行 Swift 3.0 編寫的應(yīng)用還是一知半解的話,可以看一看 moreswift 項目的 swift-3.0 分支。
這是什么版本?
當前的構(gòu)建并非是針對 Swift 3.0 預(yù)覽版進行的。如果需要驗證與 swift 二進制文件相關(guān)聯(lián)的 Git 哈希值,輸入 swift --version 即可:
shell
# swift --version
Swift version 3.0-dev (LLVM eb140647a6, Clang a9f2183da4, Swift bb43874ba1)
之后,你就可以直接在 Swift 倉庫里類似 https://github.com/apple/swift/tree/bb43874ba1 的 commit 記錄中,查看以最后一份合并到該版本的 commit 開始的歷史記錄。
致謝
很多人都一直在努力將 Swift 引入到 Linux ARM 設(shè)備中。下面這份名單只提到了他們中很少的幾個人。推薦你去訪問他們的博客;這些博客蘊藏著很多寶貴的信息和學(xué)習經(jīng)驗。
- William Dillon (@hpux735) http://www.housedillon.com
- Ryan Lovelett (@rlovelett) http://stackoverflow.com/users/247730/ryan
- Brian Gesiak (@modocache) http://modocache.io
- Karl Wagner http://www.springsup.com/
- @tienex tienex
- PJ Gray (@pj4533) Say Goodnight Software
- Cameron Perry (@mistercameron) http://mistercameron.com
請允許我再說一次,如果你有興趣加入由一群 Swift 愛好者組成的 Slack 小組,務(wù)必發(fā)郵件到 admin@iachieved.it,我會邀請你加入!
本文由 SwiftGG 翻譯組翻譯,已經(jīng)獲得作者翻譯授權(quán),最新文章請訪問 http://swift.gg。