XcodeでArchive以外のビルド結果にはbitcodeが埋め込まれない


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アプリを作ります。

```bash
% 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しかありません。ほぼ空のようです。


```bash
% 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のセクションすら含まれていません。

```bash
% 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のセクションにはそれっぽいサイズのデータが入っているようです。

```bash
% 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という名前のセクションで収められているようです。

```bash
% 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形式のアーカイブのようです。

```bash
% 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というファイルが出てきました。

```bash
% 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のコマンドだと警告がでますが、変換できました。

```bash
% /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に対応しているようです。

```bash
% 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
```

```bash
% 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`という値をセットします。


![bcapp.png](https://qiita-image-store.s3.amazonaws.com/0/55599/f8e4acbb-a52d-ab54-e4bc-a905b78f0272.png "bcapp.png")

ビルド結果をotoolでみてみると、確かにbitcodeが含まれているようです。

```bash
% 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
 
```

```bash
% 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
 
```

中身までは確認しませんが、大丈夫そうですね^^

こちらからは以上です。