LoginSignup
13
15

More than 5 years have passed since last update.

C言語とSwiftを一つのプロジェクトで混在させてみる(OS X, Linux)

Last updated at Posted at 2016-05-20

概要

  • C言語で書かれたソースとSwiftで書かれたソースをコンパイルして一つの実行ファイルを作成する方法を書いてみる。
    • 応用編として、実行ファイルではなく動的ライブラリ(Swiftモジュール)を作成することも可能だけど、ここでは書いてない。
  • OS XでもLinuxでもできる方法を書く。即ち、Xcodeは使わない。

要約

  1. clangでC言語ソースからオブジェクトファイルを作成
  2. swiftcでオブジェクトファイルと一緒にSwiftソースをコンパイル
  3. 以上(これだけで解った貴方はこの記事を読む必要はありません)

環境

  • OS X = OS X El Capitan + Xcode 7.3 (Swift 2.2)
  • Linux = CentOS 7 + Swift 2.2.1
OS X
$ clang --version
Apple LLVM version 7.3.0 (clang-703.0.29)
Target: x86_64-apple-darwin15.5.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin

$ swift --version
Apple Swift version 2.2 (swiftlang-703.0.18.1 clang-703.0.29)
Target: x86_64-apple-macosx10.9
Linux
$ clang --version
clang version 3.8.0 (tags/RELEASE_380/final)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /usr/local/bin

$ swift --version
Swift version 2.2.1 (swift-2.2.1-RELEASE)
Target: x86_64-unknown-linux-gnu

ソースファイル

説明を簡単にするために、今回用意したファイルは3つだけ。

$ ls
c.c  c.h  swift.swift
c.h
#include <stdio.h>
void c_function(const char * string);
c.c
#include "c.h"
void c_function(const char * string) {
  (void)printf("%s", string);
}
swift.swift
c_function("Hello, I'm Swift.\n")

コンパイル手順

C言語ソースからオブジェクトファイルを作成

OS X, Linux共通
$ clang -c c.c -oc.o
$ ls
c.c  c.h  c.o  swift.swift

できた。
別にclangでなくてgccでもいい。

オブジェクトファイルと一緒にSwiftソースをコンパイル

OS X
$ xcrun --sdk macosx swiftc swift.swift c.o -import-objc-header c.h
ld: warning: object file (c.o) was built for newer OSX version (10.11) than being linked (10.9)
$ ls
c.c     c.h     c.o     main        swift.swift
$ ./main
Hello, I'm Swift.

Linux
$ swiftc swift.swift c.o -import-objc-header c.h
$ ls
c.c  c.h  c.o  main  swift.swift
$ ./main
Hello, I'm Swift.

できた。これでおわり。
ね、簡単でしょう?1

NG集

-import-objc-header?

なにそれ美味しいの?

なぜかswiftc --helpとしてもこのオプションは表示されない2

-import-objc-headerがないと?

$ swiftc swift.swift c.o
swift.swift:1:1: error: use of unresolved identifier 'c_function'
c_function("Hello, I'm Swift.\n")
^~~~~~~~~~

…ですよね。

-import-c-headerではない。

C言語のヘッダなので-import-c-headerとしたくなるけど…。

$ swiftc swift.swift c.o -import-c-header c.h
<unknown>:0: error: unknown argument: '-import-c-header'

…怒られた。
Objective-Cは言語仕様上C言語を完全に包含するので-import-objc-headerでCのヘッダを読み込んでも問題ないというのは、理論的に言えばそうなんだけど…なんか気持ち悪いような。

OS Xでxcrunを使わないと?

OS X
$ swiftc swift.swift c.o -import-objc-header c.h
(略)./c.h:1:10: error: 'stdio.h' file not found
#include <stdio.h>
         ^
<unknown>:0: error: failed to import bridging header 'c.h'

C言語の標準ライブラリのヘッダがみつからない。Linuxでは問題ないんだけど。

もう少し回りくどい方法

C言語ソースからオブジェクトファイルを作成したあとに、Swiftでもオブジェクトファイルを作成してから、まとめてみる。
つまり…

OS X, Linux共通
$ clang -c c.c -oc.o
$ ls
c.c  c.h  c.o  swift.swift

これは一緒。
次はSwiftでもオブジェクトファイルを作成する:

OS X
$ xcrun --sdk macosx swiftc -c swift.swift -oswift.o -import-objc-header c.h
$ ls
c.c     c.h     c.o     swift.o     swift.swift
Linux
$ swiftc -c swift.swift -oswift.o -import-objc-header c.h
$ ls
c.c  c.h  c.o  swift.o  swift.swift

こうやってできたc.oとswift.oをまとめる:

OS X, Linux共通
$ swiftc swift.o c.o 2> /dev/null
$ ls
c.c  c.h  c.o  main  swift.o  swift.swift
$ ./main
Hello, I'm Swift.

できた。
ちなみに、clang swift.o c.o -omainとすると、libswiftCore.{dylib,so}はどこにあんねん、と言われる(Linuxではすごく分かりにくいエラーメッセージが出た)。
ということで、OS Xならclang swift.o c.o -omain -L/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx -lswiftCoreでコンパイル(リンク)はできるけど、実行しようとすると

OS X
$ ./main
dyld: Library not loaded: @rpath/libswiftCore.dylib
  Referenced from: (略)./main
  Reason: image not found
Trace/BPT trap: 5

とか言われる。
…素直にswiftcを使おう。


  1. OS Xでwarningが出てるけど実質無害。OS XのSwift 2.2のターゲットをみるとx86_64-apple-macosx10.9となっているので、c.oも10.9のSDKを使ってコンパイルすればいいのかもしれない…が、ここでは無視。 

  2. 自分は"Xcodeなしで楽しむSwift (REPLからライブラリ生成まで) #Objective-CやCをブリッジする"で知りました。 

13
15
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
15