Що робить ENABLE_BITCODE у xcode 7?


262

У мене проблема з вбудованим терміном біт-коду.
Що таке вбудований біткод?
Коли ввімкнути ENABLE_BITCODEновий Xcode?
Що відбувається з двійковим кодом, коли його ввімкнено ENABLE_BITCODEу Xcode 7?

Відповіді:


312

Біткод відноситься до типу коду: "LLVM Bitcode", який надсилається до iTunes Connect. Це дозволяє Apple використовувати певні обчислення для подальшої оптимізації додатків (наприклад: можливо зменшення розмірів виконуваних файлів). Якщо Apple потребує змін у вашому виконуваному файлі, вони можуть це зробити, не завантажуючи нову збірку.

Це відрізняється від: Нарізання - процес оптимізації вашої програми Apple для пристрою користувача на основі роздільної здатності та архітектури пристрою. Для нарізки не потрібен біткод. (Напр., Включаючи @ 2x зображення на 5s)

Розрідження додатків - це поєднання нарізки, біткоду та ресурсів на вимогу

Біткод - це проміжне представлення складеної програми. Програми, які ви завантажуєте в iTunes Connect, які містять бітовий код, будуть зібрані та зв’язані в App Store. У тому числі біт-код дозволить Apple в майбутньому повторно оптимізувати ваш бінарний додаток без необхідності подавати нову версію вашого додатка в магазин.

Документація Apple щодо розрідження додатків


Ніщо в тому, що ви цитували, не говорить про те, що включення бітового коду зменшує розмір програми на пристрої користувача. Біткод не має нічого спільного з такими ресурсами, як 3x або 2x.
користувач102008

1
Знову ж таки, ресурси не мають нічого спільного з Bitcode, що стосується коду. Завантаження користувачами лише певних архітектур коду та певних версій ресурсів - це Slicing, що не має нічого спільного з Bitcode.
користувач102008

7
Я не погоджуюся, що це дозволяє Apple скоротити розмір програми. Ніде це не говорить. У ньому сказано, що "дозволить Apple в майбутньому повторно оптимізувати ваш бінарний додаток без необхідності подавати нову версію вашого додатка в магазин", що, на мою думку, дозволяє Apple перекомпілювати ваш додаток для нової архітектури, якщо вийде новий пристрій з новою архітектурою, не потрібно подавати нову версію, яка включає цю архітектуру.
користувач102008

2
Ні, нарізка розділяє ресурси ваших програм на групи для певних пристроїв. Біткод - це те, що дозволяє Apple генерувати виконуваний файл для певної архітектури.
Джон Шиер

2
@JonShier Apple каже: "Нарізка - це процес створення та доставки варіантів пакету додатків для різних цільових пристроїв. Варіант містить лише виконувану архітектуру та ресурси, необхідні для цільового пристрою". Таким чином, для нарізки є лише виконуваний код І ресурси для певного пристрою.
keji

80

Що таке вбудований біткод?

За документами :

Біткод - це проміжне представлення складеної програми. Програми, які ви завантажуєте в iTunes Connect, які містять бітовий код, будуть зібрані та зв’язані в App Store. У тому числі біт-код дозволить Apple в майбутньому повторно оптимізувати ваш бінарний додаток без необхідності подавати нову версію вашого додатка в магазин.

Оновлення: Ця фраза в "Нові функції в Xcode 7" змусила мене довго думати, що біткод потрібен для нарізки для зменшення розміру програми:

Коли ви архівуєте для подання в App Store, Xcode складе вашу програму в проміжне представлення. Потім App Store буде компілювати бітовий код в 64 або 32 бітові файли, якщо це необхідно.

Однак це не так, бітовий код і нарізка роботи незалежно один від одного: нарізка про зниження розміру додатків і створення додатків згорток варіантів і бітовий код про деякі бінарних оптимізацію. Я перевірив це, перевіривши включені архітектури у виконувані файли небітових програм та встановивши, що вони містять лише необхідні.

Бітовий код дозволяє інші App Розведення компонент під назвою нарізка для створення додатків згорток варіанти з конкретними виконуваними для конкретних архітектур, наприклад , варіант iPhone 5S буде включати в себе тільки arm64 исполняемом, IPad Mini ARMv7 і так далі.

Коли ввімкнути ENABLE_BITCODE в новому Xcode?

Для додатків iOS біткод є типовим, але необов’язковим. Якщо ви надаєте біт-код, всі програми та рамки в комплекті додатків повинні включати біт-код. Для додатків watchOS та tvOS необхідний бітовий код.

Що відбувається з двійковим, коли ENABLE_BITCODE увімкнено у новому Xcode?

З посилання на Xcode 7:

Активізація цього параметра вказує на те, що мета або проект повинні генерувати бітовий код під час компіляції для платформ та архітектур, які його підтримують. Для архівів будується бітовий код у зв'язаному бінарному файлі для подання в магазин додатків. Для інших збірок компілятор і лінкер перевірять, чи відповідає код вимогам до генерування бітового коду, але не генерують фактичний біт-код.

Ось пара посилань, які допоможуть у більш глибокому розумінні Bitcode :


Чи буде включений бітовий код, якщо у мене є ENABLE_BITCODE, але зніміть прапорець "У тому числі біт-код", перш ніж надсилати його в App Store?
allaire

"Для додатків для iOS бітовий код є типовим, але необов'язковим." Так? Приходь ще..? Це АБО Не обов'язково ..?
NpC0mpl3t3

@ NpC0mpl3t3, як зазначено у відповіді, вона не є додатком для програм iOS, але необхідна для додатків watchOS та tvOS.
Максим Павлов

Відмінна допомога! Ця відповідь тут показано , як відключити бітового коду: stackoverflow.com/a/41418824/9190
Геррі

20

Оскільки точне запитання - "що дозволяє зробити біткод", я хотів би надати кілька тонких технічних деталей, які я до цього часу з'ясував. Більшість цього практично неможливо розібратися зі 100% впевненістю, поки Apple не випустить вихідний код цього компілятора

По-перше, схоже, що бітовий код Apple не є тим самим, що й байт-код LLVM. Принаймні, я не зміг з’ясувати жодної подібності між ними. Здається, є власний заголовок (завжди починається з "xar!") І, ймовірно, деяка магія посилання на час зв’язку, яка запобігає дублюванню даних. Якщо ви випишете рядок з твердим кодом, ця рядок буде введена в дані лише один раз, а не в два рази, як можна було б очікувати, якщо це був звичайний байт-код LLVM.

По-друге, біт-код насправді не постачається у двійковий архів як окрема архітектура, як можна було б очікувати. Він не поставляється так само, як, скажімо, x86 і ARM складаються в один двійковий (архів FAT). Натомість вони використовують спеціальний розділ у специфічному для архітектури бінарному MachO під назвою "__LLVM", який постачається з усіма підтримуваними архітектурами (тобто дублюються). Я припускаю, що це короткий випадок із їх компіляторною системою і може бути виправлений у майбутньому, щоб уникнути дублювання.

Код С (складений з clang -fembed-bitcode hi.c -S -emit-llvm):

#include <stdio.h>

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

ІЧ-вихід LLVM:

; 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)"}

Масив даних, що знаходиться в ІЧ, також змінюється залежно від оптимізації та інших параметрів генерації коду clang. Мені абсолютно невідомо, в якому форматі чи в чомусь це є.

Редагувати:

Слідом за підказкою у Twitter, я вирішив переглянути це та підтвердити. Я дотримувався цієї публікації в блозі і використовував його інструмент для вилучення бітових кодів, щоб вивести бінарний файл Archive Apple з виконавчого файлу MachO. І після вилучення архіву Apple за допомогою утиліти xar я отримав це (перетворений у текст з 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)"}

Єдина помітна відмінність між небітовим ІК-кодом та ІЧ-біт-кодом полягає в тому, що для кожної архітектури назви файлів були позбавлені лише 1, 2 тощо.

Я також підтвердив, що біткод, вбудований у двійковий файл, генерується після оптимізації. Якщо ви компілюєте з -O3 і витягаєте біт-код, це буде інакше, ніж якщо ви компілюєте з -O0.

І щоб отримати додатковий кредит, я також підтвердив, що Apple не надсилає біткод на пристрої під час завантаження програми iOS 9. Вони містять ряд інших дивних розділів, які я не визнаю як __LINKEDIT, але вони не включають __LLVM .__ пакет, і, таким чином, не включають бітовий код у кінцевий бінарний файл, який працює на пристрої. Як не дивно, Apple все ж постачає жирові файли з окремим 32/64-бітовим кодом на пристрої iOS 8.


Чи можна декомпілювати біт-код Apple? Тобто Apple тепер може бачити наш вихідний код?
маль

@malcolmhall, якщо він схожий на код LLVM, то лише своєрідно. У байт-коді LLVM є інформація про тип та інші підказки, які можуть зробити декомпіляцію набагато простішою та кориснішою. Однак я не знаю, що в біткоді Apple. Це, мабуть, принаймні дещо корисніше, але наразі невідомо, наскільки воно буде корисним. У будь-якому випадку я дуже сумніваюся, що це буде настільки сильна інформація, як скажімо, як .NET IL дозволяє майже ідеальну декомпіляцію на код C #
Earlz

Ви бачили формат файлу біткодів LLVM ? Магічне число різне, але Apple сильно натякає, що це формат біт-коду.
Джеффі Томас

"який постачається з усіма підтримуваними архітектурами (тобто, дублюються)", це не дублюється, тому що біт-код відрізняється для кожного
оброблюваного

2
За інформацією twitter.com/mistydemeo/status/644555663373307904 , xar!це формат файлу архіву Apple.
Рікінг

14

Біткод (iOS, watchOS)

Біткод - це проміжне представлення складеної програми. Програми, які ви завантажуєте в iTunes Connect, які містять бітовий код, будуть зібрані та зв’язані в App Store. У тому числі біт-код дозволить Apple в майбутньому повторно оптимізувати ваш бінарний додаток без необхідності подавати нову версію вашого додатка в магазин.


В основному ця концепція дещо схожа на java, де байт-код запускається в різних JVM, і в цьому випадку біткод розміщується в магазині iTune і замість того, щоб проміжний код надавати різним платформам (пристроям), він надає скомпільований код, який не потрібен будь-яку віртуальну машину для роботи.

Таким чином, нам потрібно створити біт-код один раз, і він буде доступний для існуючих або найближчих пристроїв. Головний біль Apple - це скласти його сумісним із кожною платформою, яку вони мають.

Розробникам не потрібно вносити зміни та надсилати додаток знову для підтримки нових платформ.

Візьмемо для прикладу iPhone 5s, коли Apple представила x64чіп у ньому. Хоча x86програми були повністю сумісні з x64архітектурою, але для повного використання x64платформи розробник повинен змінити архітектуру або якийсь код. Щойно він зробив, додаток буде подано на розгляд магазину додатків.

Якщо ця концепція біт-коду була запущена раніше, то нам, розробникам, не потрібно вносити жодних змін для підтримки x64бітової архітектури.


@ User102008 Нарізка є результатом включення бітового коду
Keji

@kdogisthebest: Ні, це не так. Ніде це не говорить. І я дивився відео WWDC про нарізання, і це не кожне згадування про ввімкнення Bitcode.
користувач102008

Inder Kumar Rathore, коли справа доходить до Enterprise App Store. Як вона справляється? чи підтримує корпоративний магазин додатків цю функцію?
damithH

@damithH Немає магазину додатків для підприємств, ми повинні зберігати програми на своїх серверах. Я не впевнений, чи буде функціонувати розрідження додатків для корпоративних програм чи ні. Але наскільки мені відомо, це не повинно бути для корпоративних програм
Inder Kumar Rathore

Оновіть зображення у своїй відповіді, воно не пов’язане з біткодом.
hsafarya

5

Оновлення

Apple уточнила, що нарізка відбувається незалежно від включення бітового коду. Це я спостерігав і на практиці, коли додаток, що не підтримує біт, буде завантажено лише у відповідній архітектурі для цільового пристрою.

Оригінал

Більш конкретно :

Біткод. Заархівуйте додаток для подання в App Store у проміжному представництві, яке збирається у 64- або 32-бітні виконувані файли для цільових пристроїв при їх доставці.

Нарізка. Твори, включені в каталог активів і позначені для платформи, дозволяють App Store доставляти лише те, що потрібно для встановлення.

Як я читаю це, якщо ви підтримуєте біткод, завантажувачі вашої програми отримають лише скомпільовану архітектуру, необхідну для власного пристрою.


У посібнику з розрідження додатків ( developer.apple.com/library/prerelease/ios/documentation/IDEs/… ) "Розрізання - це процес створення та доставки варіантів пакета додатків для різних цільових пристроїв. Варіант містить лише виконувану архітектуру і ресурси, необхідні для цільового пристрою. " Завантажувачі вашої програми, які отримують лише архітектуру, є частиною нарізки.
користувач102008
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.