xcode 7でENABLE_BITCODEは何をしますか?


262

埋め込まれたビットコード用語に問題があります。
埋め込みビットコードとは何ですか?
いつ有効にするENABLE_BITCODEか、新しいXcodeで?Xcode 7で
有効にすると、バイナリはどうなりENABLE_BITCODEますか?

回答:


312

ビットコードとは、iTunes Connectに送信されるコードのタイプ「LLVMビットコード」を指します。これにより、Appleは特定の計算を使用してアプリをさらに最適化することができます(例:実行可能ファイルのサイズを縮小する)。Appleが実行可能ファイルを変更する必要がある場合、新しいビルドをアップロードしなくてもこれを行うことができます。

これは以下とは異なります。 スライシングは、デバイスの解像度とアーキテクチャに基づいて、Appleがユーザーのデバイス用にアプリを最適化するプロセスです。スライスにはビットコードは必要ありません。(例:5秒の@ 2x画像のみを含む)

アプリ間引きは、スライス、ビットコード、およびオンデマンドリソースの組み合わせです

ビットコードは、コンパイルされたプログラムの中間表現です。iTunes Connectにアップロードしたビットコードを含むアプリは、App Storeでコンパイルおよびリンクされます。ビットコードを含めると、Appleはアプリの新しいバージョンをストアに送信しなくても、将来アプリバイナリを再最適化できるようになります。

アプリ間引きに関するAppleのドキュメント


あなたが引用したものの何も、ビットコードを有効にすることはユーザーのデバイス上のアプリのサイズを減らすことを述べていません。ビットコードは、3xや2xなどのリソースとは関係ありません。
user102008

1
繰り返しますが、リソースはビットコードとは何の関係もありません。これはコードに関するものです。ユーザーによるコードの特定のアーキテクチャと特定のバージョンのリソースのみのダウンロードは、ビットコードとは関係のないスライシングです。
user102008

7
Appleがアプリのサイズを削減できるとは思わない。それはどこにもそれを言っていません。「Appleがアプリのバイナリをストアに再送信する必要なしに、将来的にアプリのバイナリを再最適化できるようになる」と書かれています。新しいアーキテクチャを備えた新しいデバイスが出てきます。このアーキテクチャを含む新しいバージョンを提出する必要はありません。
user102008

2
いいえ、スライスすると、アプリのリソースが特定のデバイスのグループに分離されます。ビットコードは、アップルが特定のアーキテクチャ用の実行可能ファイルを生成できるようにするものです。
Jon Shier 2015年

2
@JonShier Appleは、「スライスとは、さまざまなターゲットデバイス用のアプリバンドルのバリアントを作成して配信するプロセスです。バリアントには、ターゲットデバイスに必要な実行可能なアーキテクチャとリソースのみが含まれています。特定のデバイス用。
keji

80

埋め込みビットコードとは何ですか?

ドキュメントによると:

ビットコードは、コンパイルされたプログラムの中間表現です。iTunes Connectにアップロードしたビットコードを含むアプリは、App Storeでコンパイルおよびリンクされます。ビットコードを含めると、Appleはアプリの新しいバージョンをストアに送信しなくても、将来アプリバイナリを再最適化できるようになります。

更新:「Xcode 7の新機能」のこのフレーズは、長い間、スライシングでアプリのサイズを縮小するためにビットコードが必要だと考えるようになりました。

App Storeに送信するためにアーカイブすると、Xcodeはアプリを中間表現にコンパイルします。その後、App Storeは必要に応じてビットコードを64ビットまたは32ビットの実行可能ファイルにコンパイルします。

ただし、そうではありません。ビットコードスライスは独立して機能します。スライスとは、アプリのサイズを縮小してアプリバンドルバリアントを生成することであり、ビットコードとは、特定のバイナリ最適化です。非ビットコードアプリの実行可能ファイルに含まれているアーキテクチャを確認し、必要なものだけが含まれていることを確認して、これを確認しました。

ビットコードを使用すると、Slicingと呼ばれる他のApp Thinningコンポーネントで、特定のアーキテクチャ用の特定の実行可能ファイルを含むアプリバンドルバリアントを生成できます。たとえば、iPhone 5Sバリアントには、arm64実行可能ファイル、iPad Mini armv7などのみが含まれます。

新しいXcodeでENABLE_BITCODEを有効にするのはいつですか?

iOSアプリの場合、ビットコードがデフォルトですが、オプションです。ビットコードを提供する場合、App Bundleのすべてのアプリとフレームワークにビットコードを含める必要があります。watchOSおよびtvOSアプリの場合、ビットコードが必要です。

新しいXcodeでENABLE_BITCODEを有効にすると、バイナリはどうなりますか?

Xcode 7リファレンスから:

この設定をアクティブにすると、ターゲットまたはプロジェクトが、それをサポートするプラットフォームおよびアーキテクチャのコンパイル中にビットコードを生成する必要があることを示します。アーカイブビルドでは、リンクされたバイナリにビットコードが生成され、アプリストアに送信されます。他のビルドの場合、コンパイラーとリンカーは、コードがビットコード生成の要件に準拠しているかどうかをチェックしますが、実際のビットコードは生成しません。

以下は、ビットコードの理解を深めるのに役立ついくつかのリンクです。


ENABLE_BITCODEがあってもビットコードは含まれますが、App Storeに送信する前に「ビットコードを含む」のチェックを外しますか?
allaire

「iOSアプリの場合、ビットコードがデフォルトですがオプションです。」えっ?また来てね..?それはORです。
NpC0mpl3t3 2017年

回答に記載されている@ NpC0mpl3t3は、iOSアプリではオプションですが、watchOSアプリとtvOSアプリでは必須です。
Maxim Pavlov 2017年

すばらしい助け!ここでのこの回答は、ビットコードを無効にする方法を示しています:stackoverflow.com/a/41418824/9190
Guerry

20

正確な質問は「ビットコードを有効にすることは何をするのか」なので、これまでに理解したいくつかの細かい技術的詳細を提供したいと思います。Appleがこのコンパイラのソースコードをリリースするまで、これのほとんどを100%確実に把握することは事実上不可能です

まず、AppleのビットコードはLLVMバイトコードと同じではないようです。少なくとも、それらの間の類似点を理解することはできませんでした。独自のヘッダー(常に「xar!」で始まる)があり、おそらくデータの重複を防ぐリンク時の参照マジックがあるようです。ハードコードされた文字列を書き出す場合、この文字列は、通常のLLVMバイトコードの場合のように2回ではなく、1回だけデータに挿入されます。

第2に、ビットコードは、実際にはバイナリアーカイブで、予想される別のアーキテクチャとして出荷されていません。x86とARMが1つのバイナリ(FATアーカイブ)に入れられるのと同じ方法では出荷されません。代わりに、「__ LLVM」という名前のアーキテクチャ固有のMachOバイナリの特別なセクションを使用します。これは、サポートされているすべてのアーキテクチャに同梱されています(つまり、複製されています)。これは彼らのコンパイラシステムに付属する短い問題であり、重複を避けるために将来修正される可能性があると思います。

Cコード(でコンパイルclang -fembed-bitcode hi.c -S -emit-llvm):

#include <stdio.h>

int main() {
    printf("hi there!");
    return 0;
}

LLVM IR出力:

; ModuleID = '/var/folders/rd/sv6v2_f50nzbrn4f64gnd4gh0000gq/T/hi-a8c16c.bc'
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-apple-macosx10.10.0"

@.str = private unnamed_addr constant [10 x i8] c"hi there!\00", align 1
@llvm.embedded.module = appending constant [1600 x i8] c"\DE\C0\17\0B\00\00\00\00\14\00\00\00$\06\00\00\07\00\00\01BC\C0\DE!\0C\00\00\86\01\00\00\0B\82 \00\02\00\00\00\12\00\00\00\07\81#\91A\C8\04I\06\1029\92\01\84\0C%\05\08\19\1E\04\8Bb\80\10E\02B\92\0BB\84\102\148\08\18I\0A2D$H\0A\90!#\C4R\80\0C\19!r$\07\C8\08\11b\A8\A0\A8@\C6\F0\01\00\00\00Q\18\00\00\C7\00\00\00\1Bp$\F8\FF\FF\FF\FF\01\90\00\0D\08\03\82\1D\CAa\1E\E6\A1\0D\E0A\1E\CAa\1C\D2a\1E\CA\A1\0D\CC\01\1E\DA!\1C\C8\010\87p`\87y(\07\80p\87wh\03s\90\87ph\87rh\03xx\87tp\07z(\07yh\83r`\87th\07\80\1E\E4\A1\1E\CA\01\18\DC\E1\1D\DA\C0\1C\E4!\1C\DA\A1\1C\DA\00\1E\DE!\1D\DC\81\1E\CAA\1E\DA\A0\1C\D8!\1D\DA\A1\0D\DC\E1\1D\DC\A1\0D\D8\A1\1C\C2\C1\1C\00\C2\1D\DE\A1\0D\D2\C1\1D\CCa\1E\DA\C0\1C\E0\A1\0D\DA!\1C\E8\01\1D\00s\08\07v\98\87r\00\08wx\876p\87pp\87yh\03s\80\876h\87p\A0\07t\00\CC!\1C\D8a\1E\CA\01 \E6\81\1E\C2a\1C\D6\A1\0D\E0A\1E\DE\81\1E\CAa\1C\E8\E1\1D\E4\A1\0D\C4\A1\1E\CC\C1\1C\CAA\1E\DA`\1E\D2A\1F\CA\01\C0\03\80\A0\87p\90\87s(\07zh\83q\80\87z\00\C6\E1\1D\E4\A1\1C\E4\00 \E8!\1C\E4\E1\1C\CA\81\1E\DA\C0\1C\CA!\1C\E8\A1\1E\E4\A1\1C\E6\01X\83y\98\87y(\879`\835\18\07|\88\03;`\835\98\87y(\076X\83y\98\87r\90\036X\83y\98\87r\98\03\80\A8\07w\98\87p0\87rh\03s\80\876h\87p\A0\07t\00\CC!\1C\D8a\1E\CA\01 \EAa\1E\CA\A1\0D\E6\E1\1D\CC\81\1E\DA\C0\1C\D8\E1\1D\C2\81\1E\00s\08\07v\98\87r\006\C8\88\F0\FF\FF\FF\FF\03\C1\0E\E50\0F\F3\D0\06\F0 \0F\E50\0E\E90\0F\E5\D0\06\E6\00\0F\ED\10\0E\E4\00\98C8\B0\C3<\94\03@\B8\C3;\B4\819\C8C8\B4C9\B4\01<\BCC:\B8\03=\94\83<\B4A9\B0C:\B4\03@\0F\F2P\0F\E5\00\0C\EE\F0\0Em`\0E\F2\10\0E\EDP\0Em\00\0F\EF\90\0E\EE@\0F\E5 \0FmP\0E\EC\90\0E\ED\D0\06\EE\F0\0E\EE\D0\06\ECP\0E\E1`\0E\00\E1\0E\EF\D0\06\E9\E0\0E\E60\0Fm`\0E\F0\D0\06\ED\10\0E\F4\80\0E\809\84\03;\CCC9\00\84;\BCC\1B\B8C8\B8\C3<\B4\819\C0C\1B\B4C8\D0\03:\00\E6\10\0E\EC0\0F\E5\00\10\F3@\0F\E10\0E\EB\D0\06\F0 \0F\EF@\0F\E50\0E\F4\F0\0E\F2\D0\06\E2P\0F\E6`\0E\E5 \0Fm0\0F\E9\A0\0F\E5\00\E0\01@\D0C8\C8\C39\94\03=\B4\C18\C0C=\00\E3\F0\0E\F2P\0Er\00\10\F4\10\0E\F2p\0E\E5@\0Fm`\0E\E5\10\0E\F4P\0F\F2P\0E\F3\00\AC\C1<\CC\C3<\94\C3\1C\B0\C1\1A\8C\03>\C4\81\1D\B0\C1\1A\CC\C3<\94\03\1B\AC\C1<\CCC9\C8\01\1B\AC\C1<\CCC9\CC\01@\D4\83;\CCC8\98C9\B4\819\C0C\1B\B4C8\D0\03:\00\E6\10\0E\EC0\0F\E5\00\10\F50\0F\E5\D0\06\F3\F0\0E\E6@\0Fm`\0E\EC\F0\0E\E1@\0F\809\84\03;\CCC9\00\00I\18\00\00\02\00\00\00\13\82`B \00\00\00\89 \00\00\0D\00\00\002\22\08\09 d\85\04\13\22\A4\84\04\13\22\E3\84\A1\90\14\12L\88\8C\0B\84\84L\100s\04H*\00\C5\1C\01\18\94`\88\08\AA0F7\10@3\02\00\134|\C0\03;\F8\05;\A0\836\08\07x\80\07v(\876h\87p\18\87w\98\07|\88\038p\838\80\037\80\83\0DeP\0Em\D0\0Ez\F0\0Em\90\0Ev@\07z`\07t\D0\06\E6\80\07p\A0\07q \07x\D0\06\EE\80\07z\10\07v\A0\07s \07z`\07t\D0\06\B3\10\07r\80\07:\0FDH #EB\80\1D\8C\10\18I\00\00@\00\00\C0\10\A7\00\00 \00\00\00\00\00\00\00\868\08\10\00\02\00\00\00\00\00\00\90\05\02\00\00\08\00\00\002\1E\98\0C\19\11L\90\8C\09&G\C6\04C\9A\22(\01\0AM\D0i\10\1D]\96\97C\00\00\00y\18\00\00\1C\00\00\00\1A\03L\90F\02\134A\18\08&PIC Level\13\84a\D80\04\C2\C05\08\82\83c+\03ab\B2j\02\B1+\93\9BK{s\03\B9q\81q\81\01A\19c\0Bs;k\B9\81\81q\81q\A9\99q\99I\D9\10\14\8D\D8\D8\EC\DA\5C\DA\DE\C8\EA\D8\CA\5C\CC\D8\C2\CE\E6\A6\04C\1566\BB6\974\B227\BA)A\01\00y\18\00\002\00\00\003\08\80\1C\C4\E1\1Cf\14\01=\88C8\84\C3\8CB\80\07yx\07s\98q\0C\E6\00\0F\ED\10\0E\F4\80\0E3\0CB\1E\C2\C1\1D\CE\A1\1Cf0\05=\88C8\84\83\1B\CC\03=\C8C=\8C\03=\CCx\8Ctp\07{\08\07yH\87pp\07zp\03vx\87p \87\19\CC\11\0E\EC\90\0E\E10\0Fn0\0F\E3\F0\0E\F0P\0E3\10\C4\1D\DE!\1C\D8!\1D\C2a\1Ef0\89;\BC\83;\D0C9\B4\03<\BC\83<\84\03;\CC\F0\14v`\07{h\077h\87rh\077\80\87p\90\87p`\07v(\07v\F8\05vx\87w\80\87_\08\87q\18\87r\98\87y\98\81,\EE\F0\0E\EE\E0\0E\F5\C0\0E\EC\00q \00\00\05\00\00\00&`<\11\D2L\85\05\10\0C\804\06@\F8\D2\14\01\00\00a \00\00\0B\00\00\00\13\04A,\10\00\00\00\03\00\00\004#\00dC\19\020\18\83\01\003\11\CA@\0C\83\11\C1\00\00#\06\04\00\1CB\12\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00", section "__LLVM,__bitcode"
@llvm.cmdline = appending constant [67 x i8] c"-triple\00x86_64-apple-macosx10.10.0\00-emit-llvm\00-disable-llvm-optzns\00", section "__LLVM,__cmdline"

; Function Attrs: nounwind ssp uwtable
define i32 @main() #0 {
  %1 = alloca i32, align 4
  store i32 0, i32* %1
  %2 = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([10 x i8]* @.str, i32 0, i32 0))
  ret i32 0
}

declare i32 @printf(i8*, ...) #1

attributes #0 = { nounwind ssp uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="core2" "target-features"="+ssse3,+cx16,+sse,+sse2,+sse3" "unsafe-fp-math"="false" "use-soft-float"="false" }
attributes #1 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="core2" "target-features"="+ssse3,+cx16,+sse,+sse2,+sse3" "unsafe-fp-math"="false" "use-soft-float"="false" }

!llvm.module.flags = !{!0}
!llvm.ident = !{!1}

!0 = !{i32 1, !"PIC Level", i32 2}
!1 = !{!"Apple LLVM version 7.0.0 (clang-700.0.53.3)"}

IRにあるデータ配列も、clangの最適化やその他のコード生成設定に応じて変化します。これがどのような形式であるかは、私には完全に不明です。

編集:

Twitterでのヒントに続いて、私はこれを再訪して確認することに決めました。私はこのブログ投稿をフォローし彼のビットコード抽出ツールを使用して、Apple ArchiveバイナリをMachO実行可能ファイルから取り出しました。そして、xarユーティリティでApple Archiveを抽出した後、これを取得しました(もちろんllvm-disでテキストに変換しました)

; ModuleID = '1'
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-apple-macosx10.10.0"

@.str = private unnamed_addr constant [10 x i8] c"hi there!\00", align 1

; Function Attrs: nounwind ssp uwtable
define i32 @main() #0 {
  %1 = alloca i32, align 4
  store i32 0, i32* %1
  %2 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str, i32 0, i32 0))
  ret i32 0
}

declare i32 @printf(i8*, ...) #1

attributes #0 = { nounwind ssp uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="core2" "target-features"="+ssse3,+cx16,+sse,+sse2,+sse3" "unsafe-fp-math"="false" "use-soft-float"="false" }
attributes #1 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="core2" "target-features"="+ssse3,+cx16,+sse,+sse2,+sse3" "unsafe-fp-math"="false" "use-soft-float"="false" }

!llvm.module.flags = !{!0}
!llvm.ident = !{!1}

!0 = !{i32 1, !"PIC Level", i32 2}
!1 = !{!"Apple LLVM version 7.0.0 (clang-700.1.76)"}

非ビットコードIRとビットコードIRの実際の唯一の注目すべき違いは、ファイル名がアーキテクチャごとに1、2などに省略されていることです。

また、バイナリに埋め込まれたビットコードが最適化後に生成されることを確認しました。-O3でコンパイルしてビットコードを抽出する場合、-O0でコンパイルする場合とは異なります。

また、追加のクレジットを得るために、iOS 9アプリをダウンロードしたときにAppleがデバイスにビットコードを出荷しないことも確認しました。これらには、__ LINKEDITのように私が認識できない他の奇妙なセクションがいくつか含まれていますが、__ LLVM .__ bundleが含まれていないため、デバイスで実行される最終的なバイナリにビットコードが含まれていないようです。奇妙なことに、Appleは依然として、32/64ビットの個別のコードを含むファットバイナリをiOS 8デバイスに出荷しています。


Appleのビットコードを逆コンパイルできますか?つまり、Appleはソースコードを見ることができますか?
Malhal 2015年

@malcolmhall LLVMコードに類似している場合は、ちょっとだけ。LLVMバイトコードには、タイプ情報と、逆コンパイルをはるかに簡単かつ便利にすることができるその他のヒントがあります。しかし、Appleのビットコードの内容がわかりません。それはおそらく少なくともいくらか有用ですが、現時点ではそれがどれほど有用であるかは不明です。どちらの方法でも、.NET ILがC#コードへのほぼ完全な逆コンパイルをどのように可能にするのかと同じくらい強力な情報になると私は強く疑います
Earlz

LLVMのビットコードファイル形式を見たことはありますか?マジックナンバーは異なりますが、Appleはこれがビットコード形式であることを強く示唆しています。
Jeffery Thomas

「サポートされているすべてのアーキテクチャで出荷されます(つまり、複製されます)」ビットコードはmach-oスライスごとに異なるため、複製されません
AlexDenisov

2
twitter.com/mistydemeo/status/644555663373307904によると、これxar!はAppleのアーカイブファイル形式です。
Riking

14

ビットコード(iOS、watchOS)

ビットコードは、コンパイルされたプログラムの中間表現です。iTunes Connectにアップロードしたビットコードを含むアプリは、App Storeでコンパイルおよびリンクされます。ビットコードを含めると、Appleはアプリの新しいバージョンをストアに送信しなくても、将来アプリバイナリを再最適化できるようになります。


基本的に、この概念はJavaにいくらか似ており、バイトコードは異なるJVMで実行され、この場合、ビットコードはiTuneストアに配置され、中間コードを異なるプラットフォーム(デバイス)に渡す代わりに、必要のないコンパイル済みコードを提供します。実行する仮想マシン。

したがって、ビットコードを一度作成する必要があり、既存または今後のデバイスで使用できるようになります。コンパイルして、各プラットフォームと互換性を持たせるのは、Appleの頭痛の種です。

開発者は、新しいプラットフォームをサポートするために、変更を加えてアプリを再度送信する必要はありません。

アップルがx64チップを導入したiPhone 5s の例見てみましょうx86アプリはx64アーキテクチャと完全に互換性がありますが、x64プラットフォームを完全に利用するには、開発者はアーキテクチャまたは一部のコードを変更する必要があります。完了したら、アプリはレビューのためにアプリストアに送信されます。

このビットコードの概念が以前にリリースされた場合、x64ビットアーキテクチャをサポートするために開発者が変更を加える必要はありません。


@ user102008スライシングはビットコードを有効にした結果です
keji

@kdogisthebest:いいえ、そうではありません。それはどこにもそれを言っていません。また、スライスに関するWWDCビデオを見てきましたが、Bitcodeを有効にすることについてすべて言及しているわけではありません。
user102008

Enterprise App Storeになると、クマー・ラトールがインダーになります。エンタープライズアプリストアはこの機能をサポートしていますか?
damithH 2015

@damithHエンタープライズアプリストアはありません。アプリをサーバーに保持する必要があります。アプリの間引きがエンタープライズアプリで機能するかどうかはわかりません。しかし、これまで私の知識としては、エンタープライズアプリケーション用があってはならない
インダー・クマールRathore

回答の画像を更新してください。これはビットコードとは関係ありません。
hsafarya

5

更新

Appleは、スライスはビットコードの有効は関係なく行われること明確にしています。これは、ビットコード非対応アプリがターゲットデバイスに適したアーキテクチャとしてのみダウンロードされる場合にも、実際に確認されています。

元の

より具体的には

ビットコード。アプリをアーカイブしてApp Storeに送信します。中間表現は、配信時にターゲットデバイスの64ビットまたは32ビットの実行可能ファイルにコンパイルされます。

スライス。アセットカタログに組み込まれ、プラットフォームのタグが付けられたアートワークにより、App Storeはインストールに必要なものだけを配信できます。

私がこれを読む方法、あなたがビットコードをサポートしているなら、あなたのアプリのダウンローダーは彼ら自身のデバイスに必要なコンパイルされたアーキテクチャーだけを得るでしょう。


アプリ間引きガイド(developer.apple.com/library/prerelease/ios/documentation/IDEs/…)で、「スライスは、さまざまなターゲットデバイス用のアプリバンドルのバリアントを作成および配信するプロセスです。バリアントには実行可能なアーキテクチャのみが含まれていますターゲットデバイスに必要なリソース。」アーキテクチャのみを取得するアプリのダウンローダーはスライスの一部です。
user102008
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.