Xcode7以降では、ビルドしたオブジェクトにはデフォルトでbitcodeを埋め込むようになりました。
参考:Xcode7でのembed-bitcodeオプション
http://qiita.com/gamako/items/4ebfd048c5aed4f68595
、、、と思っていたら、どうやら必ずしもそうではないようです。
参考:Carthage と Bitcode 対応についてのまとめ
https://blog.ymyzk.com/2015/10/carthage-and-bitcode/
こちらによると、Archiveするとき以外はbitcodeは埋め込まれておらず、特にライブラリをビルドするときに困るとのことです。
そんな、、、、あんまりな仕様です。
実際に確認
簡単なプロジェクトで確認してみましょう。何も表示しない簡単なSwiftアプリを作ります。
% tree .
.
├── bcapp
│ ├── AppDelegate.swift
│ ├── Assets.xcassets
│ │ └── AppIcon.appiconset
│ │ └── Contents.json
│ ├── Base.lproj
│ │ ├── LaunchScreen.storyboard
│ │ └── Main.storyboard
│ ├── Info.plist
│ └── ViewController.swift
└── bcapp.xcodeproj
buildコマンドでのビルド
ビルドコマンドで実行して、ビルドレポート画面で出力ファイルのパスを確認します。otoolコマンドで中身を見てみましょう。
AppDelegate.swiftのコンパイル結果を確認します。確かにサイズが1しかありません。ほぼ空のようです。
% otool -l /Users/xxx/Library/Developer/Xcode/DerivedData/bcapp-btzqjrrqxtscqgeypwmncboajrur/Build/Intermediates/bcapp.build/Debug-iphoneos/bcapp.build/Objects-normal/arm64/AppDelegate.o
...(略)
Section
sectname __bitcode
segname __LLVM
addr 0x0000000000004f98
size 0x0000000000000001 # <-----サイズが1
offset 23872
align 2^0 (1)
reloff 0
nreloc 0
flags 0x00000000
reserved1 0
reserved2 0
Section
sectname __swift_cmdline
segname __LLVM
addr 0x0000000000004f99
size 0x0000000000000001 # <-----サイズが1
offset 23873
align 2^0 (1)
reloff 0
nreloc 0
flags 0x00000000
また、リンク結果のファイルをotoolで見てみると、LLVMのセクションすら含まれていません。
% otool -l /Users/xxx/Library/Developer/Xcode/DerivedData/bcapp-btzqjrrqxtscqgeypwmncboajrur/Build/Intermediates/bcapp.build/Debug-iphoneos/bcapp.build/Objects-normal/arm64/bcapp | grep LLVM
%
Archiveでのビルド
一方でArchiveした結果のほうはどうかというと、こちらはbitcodeのセクションにはそれっぽいサイズのデータが入っているようです。
% otool -l /Users/xxx/Library/Developer/Xcode/DerivedData/bcapp-btzqjrrqxtscqgeypwmncboajrur/Build/Intermediates/ArchiveIntermediates/bcapp/IntermediateBuildFilesPath/bcapp.build/Release-iphoneos/bcapp.build/Objects-normal/arm64/AppDelegate.o
... (中略)
Section
sectname __bitcode
segname __LLVM
addr 0x0000000000005090
size 0x00000000000085b0 # <--- それっぽいサイズ
offset 24056
align 2^4 (16)
reloff 0
nreloc 0
flags 0x00000000
reserved1 0
reserved2 0
Section
sectname __swift_cmdline
segname __LLVM
addr 0x000000000000d640
size 0x000000000000006b # <--- それっぽいサイズ
offset 58280
align 2^4 (16)
reloff 0
nreloc 0
flags 0x00000000
reserved1 0
reserved2 0
リンクした結果にLLVM情報が含まれています。ただし、こちらは__bundleという名前のセクションで収められているようです。
% otool -l /Users/xxx/Library/Developer/Xcode/DerivedData/bcapp-btzqjrrqxtscqgeypwmncboajrur/Build/Intermediates/ArchiveIntermediates/bcapp/IntermediateBuildFilesPath/bcapp.build/Release-iphoneos/bcapp.build/Objects-normal/arm64/bcapp
... (中略)
Load command 3
cmd LC_SEGMENT_64
cmdsize 152
segname __LLVM
vmaddr 0x000000010000c000
vmsize 0x000000000000c000
fileoff 49152
filesize 49152
maxprot 0x00000003
initprot 0x00000003
nsects 1
flags 0x4
Section
sectname __bundle
segname __LLVM
addr 0x000000010000c000
size 0x00000000000083db
offset 49152
align 2^0 (1)
reloff 0
nreloc 0
flags 0x00000000
reserved1 0
reserved2 0
__bundleを抜き出してみます。
% dd if=/Users/xxx/Library/Developer/Xcode/DerivedData/bcapp-btzqjrrqxtscqgeypwmncboajrur/Build/Intermediates/ArchiveIntermediates/bcapp/IntermediateBuildFilesPath/bcapp.build/Release-iphoneos/bcapp.build/Objects-normal/arm64/bcapp bs=1 skip=49152 count=0x83db of=bundle
33755+0 records in
33755+0 records out
33755 bytes transferred in 0.076648 secs (440390 bytes/sec)
bundleとはなんでしょうか?先頭をダンプしてみると、中身はxar形式のアーカイブのようです。
% hexdump -C -v -n 16 bundle
00000000 78 61 72 21 00 1c 00 01 00 00 00 00 00 00 03 ab |xar!............|
00000010
xarコマンドで展開してみます。1、2というファイルが出てきました。
% xar -x -f bundle
% ls -al
total 144
drwxr-xr-x 5 gamako staff 170 11 13 16:53 .
drwxr-xr-x 4 gamako staff 136 11 13 16:24 ..
-rw-r--r-- 1 gamako staff 9568 11 13 16:53 1
-rw-r--r-- 1 gamako staff 22032 11 13 16:53 2
-rw-r--r-- 1 gamako staff 33755 11 13 16:49 bundle
1, 2はbitcodeのようなので、llvm-disコマンドでLLVM−IRとして出力します。
clangのサイトからダウンロードしてきた3.7.0のコマンドだと警告がでますが、変換できました。
% /Users/xxx/Downloads/clang+llvm-3.7.0-x86_64-apple-darwin/bin/llvm-dis 1
/Users/xxx/Downloads/clang+llvm-3.7.0-x86_64-apple-darwin/bin/llvm-dis: warning: ignoring debug info with an invalid version (700000003) in 1
% /Users/xxx/Downloads/clang+llvm-3.7.0-x86_64-apple-darwin/bin/llvm-dis 2
/Users/xxx/Downloads/clang+llvm-3.7.0-x86_64-apple-darwin/bin/llvm-dis: warning: ignoring debug info with an invalid version (700000003) in 2
llファイルの中身からクラス名を検索してみると、なんとなく 1がViewController.swiftで、2がAppDelegate.swiftに対応しているようです。
% grep AppDelegate *.ll
2.ll:@7 = private unnamed_addr constant [24 x i8] c"_TtC5bcapp11AppDelegate\00"
2.ll:@8 = private unnamed_addr constant [21 x i8] c"C5bcapp11AppDelegate\00"
2.ll: br i1 %3, label %cacheIsNull.i, label %_TMaC5bcapp11AppDelegate.exit
2.ll: br label %_TMaC5bcapp11AppDelegate.exit
2.ll:_TMaC5bcapp11AppDelegate.exit: ; preds = %cacheIsNull.i, %entry
2.ll: br i1 %7, label %cacheIsNull.i, label %_TMaC5bcapp11AppDelegate.exit
2.ll: br label %_TMaC5bcapp11AppDelegate.exit
2.ll:_TMaC5bcapp11AppDelegate.exit: ; preds = %cacheIsNull.i, %entry
2.ll: br i1 %3, label %cacheIsNull.i, label %_TMaC5bcapp11AppDelegate.exit
2.ll: br label %_TMaC5bcapp11AppDelegate.exit
2.ll:_TMaC5bcapp11AppDelegate.exit: ; preds = %cacheIsNull.i, %entry
2.ll: br i1 %8, label %cacheIsNull.i, label %_TMaC5bcapp11AppDelegate.exit
2.ll: br label %_TMaC5bcapp11AppDelegate.exit
2.ll:_TMaC5bcapp11AppDelegate.exit: ; preds = %cacheIsNull.i, %entry
2.ll: br i1 %5, label %cacheIsNull.i, label %_TMaC5bcapp11AppDelegate.exit
2.ll: br label %_TMaC5bcapp11AppDelegate.exit
2.ll:_TMaC5bcapp11AppDelegate.exit: ; preds = %cacheIsNull.i, %once_done
% grep ViewController *.ll
1.ll:@"__hidden#25_" = global %"__type_hidden#0" { %"__type_hidden#0"* @"OBJC_METACLASS_$_NSObject", %"__type_hidden#0"* @"OBJC_METACLASS_$_UIViewController", %"__type_hidden#1"* @_objc_empty_cache, %"__type_hidden#1"* null, i64 ptrtoint ({ i32, i32, i32, i32, i8*, i8*, i8*, i8*, i8*, i8*, i8* }* @"__hidden#26_" to i64) }
1.ll:@"OBJC_CLASS_$_UIViewController" = external global %"__type_hidden#0"
1.ll:@"OBJC_METACLASS_$_UIViewController" = external global %"__type_hidden#0"
1.ll:@3 = private unnamed_addr constant [27 x i8] c"_TtC5bcapp14ViewController\00"
1.ll:@4 = private unnamed_addr constant [24 x i8] c"C5bcapp14ViewController\00"
1.ll:@"__hidden#35_" = internal global { void (%"__type_hidden#4"*)*, i8**, i64, %"__type_hidden#0"*, %"__type_hidden#1"*, %"__type_hidden#1"*, i64, i32, i32, i32, i16, i16, i32, i32, { i64, i8*, i32, i32, i8*, %"__type_hidden#2"** (%"__type_hidden#2"*)*, %"__type_hidden#3"*, i32, i32, i32 }*, void (%"__type_hidden#4"*)*, void (%"__type_hidden#4"*)*, %"__type_hidden#4"* (%"__type_hidden#6"*, i64, %"__type_hidden#4"*)*, i64 (%"__type_hidden#7"*, %"__type_hidden#2"*)*, i64 (%"__type_hidden#7"*, %"__type_hidden#4"*)* } { void (%"__type_hidden#4"*)* @"__hidden#5_", i8** @_TWVBO, i64 ptrtoint (%"__type_hidden#0"* @"__hidden#25_" to i64), %"__type_hidden#0"* @"OBJC_CLASS_$_UIViewController", %"__type_hidden#1"* @_objc_empty_cache, %"__type_hidden#1"* null, i64 add (i64 ptrtoint ({ i32, i32, i32, i32, i8*, i8*, { i32, i32, [4 x { i8*, i8*, i8* }] }*, i8*, i8*, i8*, i8* }* @"__hidden#28_" to i64), i64 1), i32 1, i32 0, i32 16, i16 7, i16 0, i32 128, i32 16, { i64, i8*, i32, i32, i8*, %"__type_hidden#2"** (%"__type_hidden#2"*)*, %"__type_hidden#3"*, i32, i32, i32 }* @"__hidden#29_", void (%"__type_hidden#4"*)* @"__hidden#0_", void (%"__type_hidden#4"*)* @"__hidden#3_", %"__type_hidden#4"* (%"__type_hidden#6"*, i64, %"__type_hidden#4"*)* @"__hidden#6_", i64 (%"__type_hidden#7"*, %"__type_hidden#2"*)* @"__hidden#9_", i64 (%"__type_hidden#7"*, %"__type_hidden#4"*)* @"__hidden#10_" }, section "__DATA,__objc_data, regular"
1.ll: br i1 %3, label %cacheIsNull.i, label %_TMaC5bcapp14ViewController.exit
1.ll: br label %_TMaC5bcapp14ViewController.exit
1.ll:_TMaC5bcapp14ViewController.exit: ; preds = %cacheIsNull.i, %entry
1.ll: br i1 %4, label %cacheIsNull.i, label %_TMaC5bcapp14ViewController.exit
1.ll: br label %_TMaC5bcapp14ViewController.exit
1.ll:_TMaC5bcapp14ViewController.exit: ; preds = %cacheIsNull.i, %entry
1.ll: br i1 %3, label %cacheIsNull.i, label %_TMaC5bcapp14ViewController.exit
1.ll: br label %_TMaC5bcapp14ViewController.exit
1.ll:_TMaC5bcapp14ViewController.exit: ; preds = %cacheIsNull.i, %entry
1.ll: br i1 %4, label %cacheIsNull.i, label %_TMaC5bcapp14ViewController.exit
1.ll: br label %_TMaC5bcapp14ViewController.exit
1.ll:_TMaC5bcapp14ViewController.exit: ; preds = %cacheIsNull.i, %entry
1.ll: br i1 %3, label %cacheIsNull.i, label %_TMaC5bcapp14ViewController.exit
1.ll: br label %_TMaC5bcapp14ViewController.exit
1.ll:_TMaC5bcapp14ViewController.exit: ; preds = %cacheIsNull.i, %entry
1.ll: br i1 %23, label %cacheIsNull.i, label %_TMaC5bcapp14ViewController.exit
1.ll: br label %_TMaC5bcapp14ViewController.exit
1.ll:_TMaC5bcapp14ViewController.exit: ; preds = %cacheIsNull.i, %20
1.ll:; <label>:39 ; preds = %_TMaC5bcapp14ViewController.exit
1.ll:; <label>:41 ; preds = %39, %_TMaC5bcapp14ViewController.exit
1.ll: br i1 %16, label %cacheIsNull.i, label %_TMaC5bcapp14ViewController.exit
1.ll: br label %_TMaC5bcapp14ViewController.exit
1.ll:_TMaC5bcapp14ViewController.exit: ; preds = %cacheIsNull.i, %entry
1.ll:; <label>:23 ; preds = %40, %_TMaC5bcapp14ViewController.exit
1.ll: %24 = phi i64 [ %44, %40 ], [ 0, %_TMaC5bcapp14ViewController.exit ]
1.ll:; <label>:40 ; preds = %_TMaC5bcapp14ViewController.exit
1.ll: br i1 %11, label %cacheIsNull.i, label %_TMaC5bcapp14ViewController.exit
1.ll: br label %_TMaC5bcapp14ViewController.exit
1.ll:_TMaC5bcapp14ViewController.exit: ; preds = %cacheIsNull.i, %.thread
1.ll:; <label>:24 ; preds = %_TMaC5bcapp14ViewController.exit
1.ll:; <label>:25 ; preds = %24, %_TMaC5bcapp14ViewController.exit
1.ll: br i1 %4, label %cacheIsNull.i, label %_TMaC5bcapp14ViewController.exit
1.ll: br label %_TMaC5bcapp14ViewController.exit
1.ll:_TMaC5bcapp14ViewController.exit: ; preds = %cacheIsNull.i, %entry
1.ll:; <label>:18 ; preds = %_TMaC5bcapp14ViewController.exit
1.ll:; <label>:20 ; preds = %_TMaC5bcapp14ViewController.exit
1.ll: br i1 %4, label %cacheIsNull.i, label %_TMaC5bcapp14ViewController.exit
1.ll: br label %_TMaC5bcapp14ViewController.exit
1.ll:_TMaC5bcapp14ViewController.exit: ; preds = %cacheIsNull.i, %entry
1.ll:; <label>:15 ; preds = %_TMaC5bcapp14ViewController.exit
1.ll:; <label>:18 ; preds = %_TMaC5bcapp14ViewController.exit
1.ll: br i1 %6, label %cacheIsNull.i, label %_TMaC5bcapp14ViewController.exit
1.ll: br label %_TMaC5bcapp14ViewController.exit
1.ll:_TMaC5bcapp14ViewController.exit: ; preds = %cacheIsNull.i, %entry
2.ll:@50 = private unnamed_addr constant [68 x i8] c"@\22UIViewController\2240@0:8@\22UIApplication\2216@\22NSArray\2224@\22NSCoder\2232\00"
Buildコマンドでもbitcodeを埋め込む
BITCODE_GENERATION_MODEという隠しオプションを使うと、Archive以外のビルドでもbitcodeの埋め込みができるようになるようです。埋め込みを常に行うためには、bitcode
という値をセットします。
ビルド結果をotoolでみてみると、確かにbitcodeが含まれているようです。
% otool -l /Users/xxx/Library/Developer/Xcode/DerivedData/bcapp-btzqjrrqxtscqgeypwmncboajrur/Build/Intermediates/bcapp.build/Debug-iphoneos/bcapp.build/Objects-normal/arm64/AppDelegate.o
...(中略)
Section
sectname __bitcode
segname __LLVM
addr 0x0000000000004eb0
size 0x00000000000082c0 # <-- それなりなサイズ
offset 23640
align 2^4 (16)
reloff 0
nreloc 0
flags 0x00000000
reserved1 0
reserved2 0
Section
sectname __swift_cmdline
segname __LLVM
addr 0x000000000000d170
size 0x000000000000006f # <-- それなりなサイズ
offset 57112
align 2^4 (16)
reloff 0
nreloc 0
flags 0x00000000
reserved1 0
reserved2 0
% otool -l /Users/xxx/Library/Developer/Xcode/DerivedData/bcapp-btzqjrrqxtscqgeypwmncboajrur/Build/Intermediates/bcapp.build/Debug-iphoneos/bcapp.build/Objects-normal/arm64/bcapp
...(中略)
Load command 3
cmd LC_SEGMENT_64
cmdsize 152
segname __LLVM
vmaddr 0x000000010000c000
vmsize 0x000000000000c000
fileoff 49152
filesize 49152
maxprot 0x00000003
initprot 0x00000003
nsects 1
flags 0x4
Section
sectname __bundle # <-- Archiveと同じように__bundleが埋め込まれている
segname __LLVM
addr 0x000000010000c000
size 0x00000000000083c9 # <-- それなりなサイズ
offset 49152
align 2^0 (1)
reloff 0
nreloc 0
flags 0x00000000
reserved1 0
reserved2 0
中身までは確認しませんが、大丈夫そうですね^^
こちらからは以上です。