[LLVM/Clang] LLVM/clangを知る【クロスコンパイル】

実行ファイルのアーキテクチャについて

前回の続きです。
ClangでC,C++,Objective-Cのソースをコンパイルすることが出来ました。

前回実行したClangでC++のソースコードをコンパイルしたコマンドを見てみます。

$ clang++ -o helloworld.o helloworld.cpp

特に対象のアーキテクチャは指定していません。
そのため、このコンパイルを実行した実行環境用にコンパイルされています。確認してみましょう。

実行ファイルのアーキテクチャを確認する

fileコマンドで実行ファイルの対象アーキテクチャを確認することが出来ます。

$ file helloworld.o 
helloworld.o: Mach-O 64-bit executable x86_64

このファイルを生成した環境は「MacBook Air 2012のIntel Core i5 1.8GHz」なので、実行対象がx86_64になっています。

クロスコンパイル

気づいたと思いますが、このままだとiPhoneなどでは実行できません。それはCPUのアーキテクチャが異なるためです。
この辺はプログラムを書いている上では大体ご存知だとは思いますが、CPUごとに命令、レジスタの数、レジスタの役割など諸々が異なるため動作しません。かと言って、iPhone上で開発作業を行いコンパイルするのは現実的ではありません。

これを解決するのがクロスコンパイルです。
開発機のアーキテクチャとは異なるアーキテクチャの実行ファイルを生成することが出来ます。Clangでも対象アーキテクチャを指定することでクロスコンパイルをすることが可能です。
これにより、XcodeでiPhoneの実行可能なファイルを生成することが出来ます。

クロスコンパイル for iPhone

ClangでiPhone用のアーキテクチャへコンパイルしてみます。

clang++ helloworld.cpp -o helloworld_ios.o -c -arch armv7s -isysroot /Applications/Xcode6-Beta6.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS8.0.sdk

まず-arch armv7sは対象アーキテクチャの指定になります。今回はarm7s用にビルドしてみました。
-isysrootで、コンパイルするための対象のSDKなどを指定します。共有ライブラリなどを利用するための設定になります。

生成したファイルを確認

先ほどのfileコマンドで確認。

$ file helloworld_ios.o 
helloworld_ios.o: Mach-O object arm

アーキテクチャがx86_64からarmに変わりました。
Macのコンソールでも実行ファイルと認識されなくなっています。

isysrootを指定しない場合のエラー

$ clang++ helloworld.cpp -o helloworld_ios.o -c -arch armv7s
In file included from helloworld.cpp:1:
In file included from /usr/include/c++/4.2.1/iostream:44:
In file included from /usr/include/c++/4.2.1/bits/c++config.h:41:
In file included from /usr/include/c++/4.2.1/bits/os_defines.h:61:
In file included from /usr/include/unistd.h:71:
In file included from /usr/include/_types.h:27:
In file included from /usr/include/sys/_types.h:32:
/usr/include/sys/cdefs.h:658:2: error: Unsupported architecture
#error Unsupported architecture
 ^
In file included from helloworld.cpp:1:
In file included from /usr/include/c++/4.2.1/iostream:44:
In file included from /usr/include/c++/4.2.1/bits/c++config.h:41:
In file included from /usr/include/c++/4.2.1/bits/os_defines.h:61:
In file included from /usr/include/unistd.h:71:
In file included from /usr/include/_types.h:27:
In file included from /usr/include/sys/_types.h:33:
/usr/include/machine/_types.h:34:2: error: architecture not supported
#error architecture not supported
 ^
In file included from helloworld.cpp:1:
In file included from /usr/include/c++/4.2.1/iostream:44:
In file included from /usr/include/c++/4.2.1/bits/c++config.h:41:
In file included from /usr/include/c++/4.2.1/bits/os_defines.h:61:
In file included from /usr/include/unistd.h:71:
In file included from /usr/include/_types.h:27:
/usr/include/sys/_types.h:94:9: error: unknown type name '__int64_t'
typedef __int64_t       __darwin_blkcnt_t;      /* total blocks */
        ^
/usr/include/sys/_types.h:95:9: error: unknown type name '__int32_t'
typedef __int32_t       __darwin_blksize_t;     /* preferred block size */
        ^
/usr/include/sys/_types.h:96:9: error: unknown type name '__int32_t'
typedef __int32_t       __darwin_dev_t;         /* dev_t */
        ^
/usr/include/sys/_types.h:99:9: error: unknown type name '__uint32_t'
typedef __uint32_t      __darwin_gid_t;         /* [???] process and gro...
        ^
/usr/include/sys/_types.h:100:9: error: unknown type name '__uint32_t'
typedef __uint32_t      __darwin_id_t;          /* [XSI] pid_t, uid_t, o...
        ^
/usr/include/sys/_types.h:101:9: error: unknown type name '__uint64_t'
typedef __uint64_t      __darwin_ino64_t;       /* [???] Used for 64 bi...
        ^
/usr/include/sys/_types.h:107:9: error: unknown type name '__darwin_natural_t'
typedef __darwin_natural_t __darwin_mach_port_name_t; /* Used by mach */
        ^
/usr/include/sys/_types.h:109:9: error: unknown type name '__uint16_t'
typedef __uint16_t      __darwin_mode_t;        /* [???] Some file attributes */
        ^
/usr/include/sys/_types.h:110:9: error: unknown type name '__int64_t'
typedef __int64_t       __darwin_off_t;         /* [???] Used for file sizes */
        ^
/usr/include/sys/_types.h:111:9: error: unknown type name '__int32_t'
typedef __int32_t       __darwin_pid_t;         /* [???] process and gro...
        ^
/usr/include/sys/_types.h:131:9: error: unknown type name '__uint32_t'
typedef __uint32_t      __darwin_sigset_t;      /* [???] signal set */
        ^
/usr/include/sys/_types.h:132:9: error: unknown type name '__int32_t'
typedef __int32_t       __darwin_suseconds_t;   /* [???] microseconds */
        ^
/usr/include/sys/_types.h:133:9: error: unknown type name '__uint32_t'
typedef __uint32_t      __darwin_uid_t;         /* [???] user IDs */
        ^
/usr/include/sys/_types.h:134:9: error: unknown type name '__uint32_t'
typedef __uint32_t      __darwin_useconds_t;    /* [???] microseconds */
        ^
In file included from helloworld.cpp:1:
In file included from /usr/include/c++/4.2.1/iostream:44:
In file included from /usr/include/c++/4.2.1/bits/c++config.h:41:
In file included from /usr/include/c++/4.2.1/bits/os_defines.h:61:
In file included from /usr/include/unistd.h:75:
/usr/include/sys/_types/_intptr_t.h:30:9: error: unknown type name
      '__darwin_intptr_t'; did you mean '__darwin_ino_t'?
typedef __darwin_intptr_t       intptr_t;
        ^
/usr/include/sys/_types.h:103:26: note: '__darwin_ino_t' declared here
typedef __darwin_ino64_t __darwin_ino_t;        /* [???] Used for inodes */
                         ^
In file included from helloworld.cpp:1:
In file included from /usr/include/c++/4.2.1/iostream:44:
In file included from /usr/include/c++/4.2.1/bits/c++config.h:41:
In file included from /usr/include/c++/4.2.1/bits/os_defines.h:61:
In file included from /usr/include/unistd.h:80:
/usr/include/sys/_types/_size_t.h:30:9: error: unknown type name
      '__darwin_size_t'; did you mean '__darwin_ino_t'?
typedef __darwin_size_t        size_t; 
        ^
/usr/include/sys/_types.h:103:26: note: '__darwin_ino_t' declared here
typedef __darwin_ino64_t __darwin_ino_t;        /* [???] Used for inodes */
                         ^
In file included from helloworld.cpp:1:
In file included from /usr/include/c++/4.2.1/iostream:44:
In file included from /usr/include/c++/4.2.1/bits/c++config.h:41:
In file included from /usr/include/c++/4.2.1/bits/os_defines.h:61:
In file included from /usr/include/unistd.h:81:
/usr/include/sys/_types/_ssize_t.h:30:9: error: unknown type name
      '__darwin_ssize_t'
typedef __darwin_ssize_t        ssize_t; 
        ^
fatal error: too many errors emitted, stopping now [-ferror-limit=]
20 errors generated.

参照