Câu trả lời:
Bitcode đề cập đến loại mã: "LLVM Bitcode" được gửi đến iTunes Connect. Điều này cho phép Apple sử dụng các tính toán nhất định để tối ưu hóa lại các ứng dụng hơn nữa (ví dụ: có thể thu nhỏ kích thước thực thi). Nếu Apple cần thay đổi khả năng thực thi của bạn thì họ có thể thực hiện việc này mà không cần bản dựng mới được tải lên.
Điều này khác với: Cắt lát là quá trình Apple tối ưu hóa ứng dụng của bạn cho thiết bị của người dùng dựa trên độ phân giải và kiến trúc của thiết bị. Cắt lát không cần Bitcode. (Ví dụ: chỉ bao gồm hình ảnh @ 2x trên 5s)
Ứng dụng Thinning là sự kết hợp giữa cắt, bitcode và tài nguyên theo yêu cầu
Bitcode là một đại diện trung gian của một chương trình được biên dịch. Các ứng dụng bạn tải lên iTunes Connect có chứa bitcode sẽ được biên dịch và liên kết trên App Store. Bao gồm bitcode sẽ cho phép Apple tối ưu hóa lại nhị phân ứng dụng của bạn trong tương lai mà không cần phải gửi phiên bản mới của ứng dụng cho cửa hàng.
Theo tài liệu :
Bitcode là một đại diện trung gian của một chương trình được biên dịch. Các ứng dụng bạn tải lên iTunes Connect có chứa bitcode sẽ được biên dịch và liên kết trên App Store. Bao gồm bitcode sẽ cho phép Apple tối ưu hóa lại nhị phân ứng dụng của bạn trong tương lai mà không cần phải gửi phiên bản mới của ứng dụng cho cửa hàng.
Cập nhật: Cụm từ này trong "Các tính năng mới trong Xcode 7" khiến tôi phải suy nghĩ rất lâu rằng Bitcode là cần thiết để Cắt lát để giảm kích thước ứng dụng:
Khi bạn lưu trữ để gửi tới App Store, Xcode sẽ biên dịch ứng dụng của bạn thành một đại diện trung gian. App Store sau đó sẽ biên dịch mã bit thành các tệp thực thi 64 hoặc 32 bit nếu cần.
Tuy nhiên, điều đó không đúng, Bitcode và Cắt lát hoạt động độc lập: Cắt lát là về việc giảm kích thước ứng dụng và tạo các biến thể gói ứng dụng và Bitcode là về một số tối ưu hóa nhị phân nhất định. Tôi đã xác minh điều này bằng cách kiểm tra các kiến trúc được bao gồm trong các tệp thực thi của các ứng dụng không phải là mã bitcoin và thấy rằng chúng chỉ bao gồm những kiến trúc cần thiết.
Bitcode cho phép thành phần Làm mỏng ứng dụng khác gọi là Cắt lát để tạo các biến thể gói ứng dụng với các tệp thực thi cụ thể cho các kiến trúc cụ thể, ví dụ: biến thể iPhone 5S sẽ chỉ bao gồm thực thi arm64, iPad Mini armv7, v.v.
Đối với các ứng dụng iOS, bitcode là mặc định, nhưng tùy chọn. Nếu bạn cung cấp bitcode, tất cả các ứng dụng và khung trong gói ứng dụng cần bao gồm bitcode. Đối với các ứng dụng watchOS và tvOS, bitcode là bắt buộc.
Từ tham chiếu Xcode 7:
Kích hoạt cài đặt này cho biết rằng mục tiêu hoặc dự án sẽ tạo ra bitcode trong quá trình biên dịch cho các nền tảng và kiến trúc hỗ trợ nó. Đối với các bản dựng Lưu trữ, bitcode sẽ được tạo trong tệp nhị phân được liên kết để gửi đến cửa hàng ứng dụng. Đối với các bản dựng khác, trình biên dịch và trình liên kết sẽ kiểm tra xem mã có tuân thủ các yêu cầu để tạo bitcode hay không, nhưng sẽ không tạo ra bitcode thực tế.
Đây là một vài liên kết sẽ giúp hiểu sâu hơn về Bitcode :
Vì câu hỏi chính xác là "điều gì cho phép bitcode làm gì", tôi muốn đưa ra một vài chi tiết kỹ thuật mỏng mà tôi đã tìm ra cho đến nay. Hầu hết điều này thực tế là không thể tìm ra với sự chắc chắn 100% cho đến khi Apple phát hành mã nguồn cho trình biên dịch này
Thứ nhất, bitcode của Apple không xuất hiện được điều tương tự như LLVM bytecode. Ít nhất, tôi đã không thể tìm ra bất kỳ sự tương đồng giữa chúng. Nó dường như có một tiêu đề độc quyền (luôn bắt đầu bằng "xar!") Và có thể là một số phép thuật tham chiếu thời gian liên kết ngăn chặn trùng lặp dữ liệu. Nếu bạn viết ra một chuỗi mã hóa cứng, chuỗi này sẽ chỉ được đưa vào dữ liệu một lần, thay vì hai lần như mong đợi nếu đó là mã byte LLVM bình thường.
Thứ hai, bitcode không thực sự được vận chuyển trong kho lưu trữ nhị phân như một kiến trúc riêng biệt như mong đợi. Nó không được vận chuyển theo cùng một cách như x86 và ARM được đưa vào một nhị phân (lưu trữ FAT). Thay vào đó, họ sử dụng một phần đặc biệt trong nhị phân MachO cụ thể của kiến trúc có tên "__LLVM", được vận chuyển với mọi kiến trúc được hỗ trợ (nghĩa là trùng lặp). Tôi cho rằng đây là một sự xuất hiện ngắn với hệ thống biên dịch của họ và có thể được sửa trong tương lai để tránh trùng lặp.
Mã C (được biên dịch với clang -fembed-bitcode hi.c -S -emit-llvm
):
#include <stdio.h>
int main() {
printf("hi there!");
return 0;
}
Đầu ra 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)"}
Mảng dữ liệu trong IR cũng thay đổi tùy thuộc vào tối ưu hóa và các cài đặt tạo mã khác của clang. Tôi hoàn toàn không biết định dạng này hay bất cứ thứ gì trong đó.
BIÊN TẬP:
Theo gợi ý trên Twitter, tôi quyết định xem lại điều này và xác nhận nó. Tôi đã theo dõi bài đăng trên blog này và sử dụng công cụ trích xuất bitcode của mình để đưa tệp nhị phân Apple Archive ra khỏi tệp thực thi MachO. Và sau khi giải nén Apple Archive bằng tiện ích xar, tôi đã nhận được điều này (chuyển đổi thành văn bản với 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)"}
Sự khác biệt đáng chú ý duy nhất thực sự giữa IR không mã bit và IR mã bit là tên tệp đã bị tước thành 1, 2, v.v. cho mỗi kiến trúc.
Tôi cũng xác nhận rằng bitcode được nhúng trong tệp nhị phân được tạo sau khi tối ưu hóa. Nếu bạn biên dịch bằng -O3 và trích xuất mã bit, nó sẽ khác với khi bạn biên dịch bằng -O0.
Và chỉ để có thêm tín dụng, tôi cũng xác nhận rằng Apple không gửi bitcode cho các thiết bị khi bạn tải xuống ứng dụng iOS 9. Chúng bao gồm một số phần lạ khác mà tôi không nhận ra như _ONEDIT, nhưng chúng không bao gồm gói __LLVM .__ và do đó dường như không bao gồm bitcode trong tệp nhị phân cuối cùng chạy trên thiết bị. Thật kỳ lạ, Apple vẫn gửi các mã nhị phân béo với mã 32 / 64bit riêng cho các thiết bị iOS 8.
xar!
là định dạng tệp lưu trữ của Apple.
Mã bit (iOS, watchOS)
Bitcode là một đại diện trung gian của một chương trình được biên dịch. Các ứng dụng bạn tải lên iTunes Connect có chứa bitcode sẽ được biên dịch và liên kết trên App Store. Bao gồm bitcode sẽ cho phép Apple tối ưu hóa lại nhị phân ứng dụng của bạn trong tương lai mà không cần phải gửi phiên bản mới của ứng dụng cho cửa hàng.
Về cơ bản khái niệm này có phần giống với java khi mã byte được chạy trên các JVM khác nhau và trong trường hợp này, mã bit được đặt trên cửa hàng iTune và thay vì đưa mã trung gian cho các nền tảng (thiết bị) khác nhau, nó cung cấp mã được biên dịch không cần bất kỳ máy ảo để chạy.
Do đó, chúng ta cần tạo bitcode một lần và nó sẽ có sẵn cho các thiết bị hiện có hoặc sắp tới. Đó là vấn đề đau đầu của Apple để biên dịch làm cho nó tương thích với từng nền tảng mà họ có.
Các nhà phát triển không phải thực hiện thay đổi và gửi lại ứng dụng để hỗ trợ các nền tảng mới.
Hãy lấy ví dụ về iPhone 5s khi apple giới thiệu x64
chip trong đó. Mặc dù x86
các ứng dụng hoàn toàn tương thích với x64
kiến trúc nhưng để sử dụng đầy đủ x64
nền tảng, nhà phát triển phải thay đổi kiến trúc hoặc một số mã. Sau khi hoàn thành, ứng dụng sẽ được gửi tới cửa hàng ứng dụng để xem xét.
Nếu khái niệm bitcode này được đưa ra trước đó thì chúng tôi các nhà phát triển không phải thực hiện bất kỳ thay đổi nào để hỗ trợ x64
kiến trúc bit.
Cập nhật
Apple đã làm rõ rằng việc cắt lát xảy ra độc lập với việc kích hoạt bitcode. Tôi cũng đã quan sát điều này trong thực tế, nơi một ứng dụng không kích hoạt mã bitcoin sẽ chỉ được tải xuống dưới dạng kiến trúc phù hợp với thiết bị đích.
Nguyên
Mã bit. Lưu trữ ứng dụng của bạn để gửi tới App Store trong một đại diện trung gian, được biên dịch thành các tệp thực thi 64 hoặc 32 bit cho các thiết bị đích khi được gửi.
Cắt lát. Tác phẩm nghệ thuật được tích hợp vào Danh mục tài sản và được gắn thẻ cho một nền tảng cho phép App Store chỉ cung cấp những gì cần thiết để cài đặt.
Cách tôi đọc điều này, nếu bạn hỗ trợ bitcode, những người tải xuống ứng dụng của bạn sẽ chỉ nhận được kiến trúc được biên dịch cần thiết cho thiết bị của riêng họ.