Відповіді:
Біткод відноситься до типу коду: "LLVM Bitcode", який надсилається до iTunes Connect. Це дозволяє Apple використовувати певні обчислення для подальшої оптимізації додатків (наприклад: можливо зменшення розмірів виконуваних файлів). Якщо Apple потребує змін у вашому виконуваному файлі, вони можуть це зробити, не завантажуючи нову збірку.
Це відрізняється від: Нарізання - процес оптимізації вашої програми Apple для пристрою користувача на основі роздільної здатності та архітектури пристрою. Для нарізки не потрібен біткод. (Напр., Включаючи @ 2x зображення на 5s)
Розрідження додатків - це поєднання нарізки, біткоду та ресурсів на вимогу
Біткод - це проміжне представлення складеної програми. Програми, які ви завантажуєте в iTunes Connect, які містять бітовий код, будуть зібрані та зв’язані в App Store. У тому числі біт-код дозволить Apple в майбутньому повторно оптимізувати ваш бінарний додаток без необхідності подавати нову версію вашого додатка в магазин.
За документами :
Біткод - це проміжне представлення складеної програми. Програми, які ви завантажуєте в iTunes Connect, які містять бітовий код, будуть зібрані та зв’язані в App Store. У тому числі біт-код дозволить Apple в майбутньому повторно оптимізувати ваш бінарний додаток без необхідності подавати нову версію вашого додатка в магазин.
Оновлення: Ця фраза в "Нові функції в Xcode 7" змусила мене довго думати, що біткод потрібен для нарізки для зменшення розміру програми:
Коли ви архівуєте для подання в App Store, Xcode складе вашу програму в проміжне представлення. Потім App Store буде компілювати бітовий код в 64 або 32 бітові файли, якщо це необхідно.
Однак це не так, бітовий код і нарізка роботи незалежно один від одного: нарізка про зниження розміру додатків і створення додатків згорток варіантів і бітовий код про деякі бінарних оптимізацію. Я перевірив це, перевіривши включені архітектури у виконувані файли небітових програм та встановивши, що вони містять лише необхідні.
Бітовий код дозволяє інші App Розведення компонент під назвою нарізка для створення додатків згорток варіанти з конкретними виконуваними для конкретних архітектур, наприклад , варіант iPhone 5S буде включати в себе тільки arm64 исполняемом, IPad Mini ARMv7 і так далі.
Для додатків iOS біткод є типовим, але необов’язковим. Якщо ви надаєте біт-код, всі програми та рамки в комплекті додатків повинні включати біт-код. Для додатків watchOS та tvOS необхідний бітовий код.
З посилання на Xcode 7:
Активізація цього параметра вказує на те, що мета або проект повинні генерувати бітовий код під час компіляції для платформ та архітектур, які його підтримують. Для архівів будується бітовий код у зв'язаному бінарному файлі для подання в магазин додатків. Для інших збірок компілятор і лінкер перевірять, чи відповідає код вимогам до генерування бітового коду, але не генерують фактичний біт-код.
Ось пара посилань, які допоможуть у більш глибокому розумінні Bitcode :
Оскільки точне запитання - "що дозволяє зробити біткод", я хотів би надати кілька тонких технічних деталей, які я до цього часу з'ясував. Більшість цього практично неможливо розібратися зі 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.
xar!
це формат файлу архіву Apple.
Біткод (iOS, watchOS)
Біткод - це проміжне представлення складеної програми. Програми, які ви завантажуєте в iTunes Connect, які містять бітовий код, будуть зібрані та зв’язані в App Store. У тому числі біт-код дозволить Apple в майбутньому повторно оптимізувати ваш бінарний додаток без необхідності подавати нову версію вашого додатка в магазин.
В основному ця концепція дещо схожа на java, де байт-код запускається в різних JVM, і в цьому випадку біткод розміщується в магазині iTune і замість того, щоб проміжний код надавати різним платформам (пристроям), він надає скомпільований код, який не потрібен будь-яку віртуальну машину для роботи.
Таким чином, нам потрібно створити біт-код один раз, і він буде доступний для існуючих або найближчих пристроїв. Головний біль Apple - це скласти його сумісним із кожною платформою, яку вони мають.
Розробникам не потрібно вносити зміни та надсилати додаток знову для підтримки нових платформ.
Візьмемо для прикладу iPhone 5s, коли Apple представила x64
чіп у ньому. Хоча x86
програми були повністю сумісні з x64
архітектурою, але для повного використання x64
платформи розробник повинен змінити архітектуру або якийсь код. Щойно він зробив, додаток буде подано на розгляд магазину додатків.
Якщо ця концепція біт-коду була запущена раніше, то нам, розробникам, не потрібно вносити жодних змін для підтримки x64
бітової архітектури.
Оновлення
Apple уточнила, що нарізка відбувається незалежно від включення бітового коду. Це я спостерігав і на практиці, коли додаток, що не підтримує біт, буде завантажено лише у відповідній архітектурі для цільового пристрою.
Оригінал
Біткод. Заархівуйте додаток для подання в App Store у проміжному представництві, яке збирається у 64- або 32-бітні виконувані файли для цільових пристроїв при їх доставці.
Нарізка. Твори, включені в каталог активів і позначені для платформи, дозволяють App Store доставляти лише те, що потрібно для встановлення.
Як я читаю це, якщо ви підтримуєте біткод, завантажувачі вашої програми отримають лише скомпільовану архітектуру, необхідну для власного пристрою.