์ค์ ์ปดํ์ผ, ๋งํน์ด ๋๋ ๋ค์ ๊ฒฐ๊ณผ๋ฌผ์ ๋ํด์๋ ์ ๋ชจ๋ฅด๋ ๊ฒ ๊ฐ๋ค. ์คํ ํ์ผ์ ์ด๋ป๊ฒ ๊ตฌ์ฑ๋์ด ์๋ ๊ฑธ๊น?
์ฐ๋ฆฌ๊ฐ ์ฌ์ฉํ๋ ํ๋ก๊ทธ๋จ๋ค์, ๋ฐ์ด๋๋ฆฌํ๋์ด ์๋ ํ์ผ์ ํํ๋ก ์กด์ฌํ๋ค. ๊ทธ๋ฐ๋ฐ, ์ด ์คํํ์ผ์ ํํ๋ OS์ ๋ฐ๋ผ ๋ค๋ฅธ ํํ๋ก ์กด์ฌํ๋ค. ํฐ๋ฏธ๋์์ ์ฐ๋ฆฌ๊ฐ ์ฌ์ฉํ๋ ls
์ binary file ์ ๋ณด๋ฅผ ์ณ๋ณด์.
file /bin/ls
/bin/ls: Mach-O universal binary with 2 architectures: [x86_64:Mach-O 64-bit executable x86_64] [arm64e:Mach-O 64-bit executable arm64e]
Mach-O? ์ด๊ฑด ์ฒ์ ๋ค์ด๋ณด๋ ๊ฒ ๊ฐ๊ณ , x86, arm64๋ ๋ค์ด๋ณธ ๊ฒ ๊ฐ๋ค. ํ์๋ cpu architecture๋ฅผ ๋งํ๋ค. x86์ ์ธํ ์์๋ง๋ cpu ์ํคํ ์ณ์ด๊ณ , arm์ apple ์ค๋ฆฌ์ฝ ์ํ์ด๋ค. ๊ทธ๋ผ ์ดํ๋ก๋ ์คํ ํ์ผ์ ํํ์ ๋ํด์ ์์๋ณด์.
Executable File Format
-
Mach-O : Mach Object File Format
- Mach kernel์ ๊ธฐ๋ณธ์ผ๋ก ํ๋ OS๋ค์์ ์ฌ์ฉํ๋ ์คํํ์ผ, ๋ชฉ์ ํ์ผ, ๋ผ์ด๋ธ๋ฌ๋ฆฌ, ์ฝ์ด๋คํ ํ์ผ ํฌ๋ฉง
- Mach kernel์ ์ฌ์ฉํ๋ OS : macOS, iOS, tvOS, watchOS, NeXTSTEP
-
PE: Portable Executable
- Windows OS์ ์คํํ์ผ, ๋ชฉ์ ํ์ผ, ๋ผ์ด๋ธ๋ฌ๋ฆฌ(DLL) ํ์ผ ํฌ๋ฉง
- ์คํํ์ผ ํ์ฅ์:
.EXE
-
ELF: Executable and Linkable Format
- Unix ๊ณ์ด ์คํํ์ผ, ๋ชฉ์ ํ์ผ, ๋ผ์ด๋ธ๋ฌ๋ฆฌ ํ์ผ ํฌ๋ฉง
- DWARF: ํ์ค ๋๋ฒ๊น ํ์ผ ํฌ๋ฉง - โDebugging With Attributed Record Formatsโ
-
a.out: Assembler Output
- ์ค๋๋ Unix-like OS์ ์คํํ์ผ, ๋ชฉ์ ํ์ผ, ๋ผ์ด๋ธ๋ฌ๋ฆฌ์์ ์ฌ์ฉ๋๋ ํ์ผ ํฌ๋ฉง
- a.out์ ์ผ๋ถ complier๋ linker๋ค์ output ์ด๋ฆ์ ์ง์ ํ์ง ์์์ ๋ default output name์ผ๋ก ์ฌ์ฉ๋จ
- ์ค์ ๋ก a.out format์ ์ฌ์ฉํ์ง๋ ์์
Mach-O Terminology
WWDC16, Optimizing App StartUp Time์ ์๋ ๋ด์ฉ์ด๋ค.
- File Types
- Executable
- ์ฑ ์คํ์ ์ํ main binary
- Dylib
- dynamic library (a.k.a DSO, DLL)
- Bundle
- ๋งํฌ๋ ์ ์๋ Dylib,
dlopen()
์ผ๋ก ์คํ๋๋ค. - plug-ins
- ๋งํฌ๋ ์ ์๋ Dylib,
- Executable
- Image
- ์คํ ๊ฐ๋ฅํ dylib, bundle ์๋ฏธ
- Framework
- resource, header์ ํจ๊ป directory๊ฐ ์๋ dylib
์ฌ๊ธฐ์ ํท๊ฐ๋ฆฌ๋๊ฒ ์ฉ์ด๋ค. Framework๋ ๊ทธ์์ฒด๋ก Bundle์ด๋ค. ๊ทธ๋ฆฌ๊ณ ๊ทธ Bundle์์ ์๋ Resource๋ค์ NSBundle
๋ก ๊ฐ์ ธ์์ ์ฌ์ฉ๊ฐ๋ฅํ๋ค. ์ฌ๊ธฐ์ Bundle์ ๋ ๋ค๋ฅธ ์๋ฏธ์ด๋ค. ๋ฌธ๋งฅ์ ๋ฐ๋ผ ์ดํดํ๋ ๊ฒ์ด ํ์ํ๋ค.
CPU Architectures
Build Setting์ Excluded Architectures์์ ์ค์ ๊ฐ๋ฅํ๋ค.
|architecture|์ ์ฉ ๊ธฐ๊ธฐ|๋น๊ณ |
|:----------:|:---:--------|::----|
|armv7|iPhone 4s, iPad3, iPad Mini1, ~iPod Touch5|32bit|
|armv7s|iPhone 5, iPhone 5C, iPad4|32bit, armv7 ํธํ|
|arm64|iPhone 5S ~ iPhone X [Max],
iPad Air1 ~ 2, iPad Pro1 ~ 2, ~iPad7, ~iPad Mini4
~iPad Touch7|64bit|
|arm64e|iPhone XR, iPhone XS [Max], iPhon 11 [Pro [Max]
iPad Pro3, iPad Air3, iPad Mini5|64bit, arm64 ํธํ|
|i386|32bit ๊ธฐ๊ธฐ์ ๋์ํ๋ Simulator|32bit|
|x86_64|64bit ๊ธฐ๊ธฐ์ ๋์ํ๋ Simulator, Mac|64bit|
Universal binary (Fat binary)
๋ ๊ฐ ์ด์์ ์ํคํ ์ณ๋ฅผ ์ง์ํ๋ ๋ฐ์ด๋๋ฆฌ ํ์ผ(์คํ ํ์ผ)
์๋ก ๋ค๋ฅธ ์ํคํ ์ณ๋ก ๋น๋๋ ๋ฐ์ด๋๋ฆฌ๋ฅผ ํ๋์ ๋ฐ์ด๋๋ฆฌ๋ก ๋ถ์ฌ ๋์ ๊ฒ (concatenating)
- Xcode > Build Settings > Architectures > Build Active Architecture Only
ํด๋น ์ต์ ์ ํค๋/๋๋์ ๋ฐ๋ผ output๋๋ app์ ์ํคํ ์ณ๊ฐ ๋ฌ๋ผ์ง๋ค. ๋ณดํต Debug๋ on, Release๋ off์ด๋ค. Debug๋ ๋ณดํต simulator, ํน์ device ํ๊ฒ์ผ๋ก๋ง ๋น๋ํ๊ณ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ ๊ตณ์ด ๋ค๋ฅธ ์ํคํ ์ณ์ ๋ํด ๋น๋ํ ํ์๊ฐ ์๋ค. ํ์ง๋ง realease ์๋ ์์์ ๊ธฐ๊ธฐ์ ๋์ํด์ผ ํ๊ธฐ ๋๋ฌธ์, ์ฌ๋ฌ๊ฐ ์ํคํ ์ณ๋ก ํ๋๋ก ํฉ์ณ์ ธ ์๋ ์คํํ์ผ์ ๋ง๋ค์ด์ผ ํ๋ค. ์ด๋ฐ ๋ ๊ฒ ์ฌ๋ฌ ์ํคํ ์ณ๋ฅผ ๋์ํ๋ ์คํํ์ผ์ **Universal binary(fat binary)**๋ผ ํ๋ค.
# Simulator, Build Active Architecture Only : Yes
$ file testFramework
testFramework: Mach-O 64-bit executable x86_64
# Simulator, Build Active Architecture Only, Apple Silicon Mac : Yes
$ file testFramework
testFramework: Mach-O 64-bit executable arm64
# Simulator, Build Active Arhitecture Only : No
$ file testFramework
testFramework: Mach-O universal binary with 3 architectures: [x86_64:Mach-O 64-bit executable x86_64] [i386:Mach-O executable i386] [arm64:Mach-O 64-bit executable arm64]
testFramework (for architecture x86_64): Mach-O 64-bit executable x86_64
testFramework (for architecture i386): Mach-O executable i386
testFramework (for architecture arm64): Mach-O 64-bit executable arm64
# Generic iOS Device, Build Active Architecture Only : No
$ file testFramework
testFramework: Mach-O universal binary with 2 architectures: [arm_v7:Mach-O executable arm_v7] [arm64:Mach-O 64-bit executable arm64]
testFramework (for architecture armv7): Mach-O executable arm_v7
testFramework (for architecture arm64): Mach-O 64-bit executable arm64
simulator๋ฅผ ์์ ๋ i386 ์ํคํ ์ณ๊ฐ ์ฌ๋ผ์ก๋ค. ๋ ๊ฐ๊ฐ์ ์ต์ ์ ๋ฐ๋ผ ๋ฐ์ด๋๋ฆฌ๊ฐ ๋ค๋ฅด๊ฒ ์์ฑ๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
Universal Dynamic Framework
Universal binary (library) + Resources
์ด์ ์ apple์์์ Framework๋ library์ resource๊ฐ ํฉ์ณ์ง ํํ๋ผ ํ๋ค. ๋ง์ฐฌ๊ฐ์ง๋ก Universal Dynamic Framework ๊ทธ๋ ๊ฒ ์๊ฐํ ์ ์๋ค. ๊ทธ๋ผ Framework ๋ฐฐํฌ๋ ์ด๋ค์์ผ๋ก ํ๋ ๊ฑธ๊น? ๋ชจ๋ ๊ธฐ๊ธฐ์์ ์ฌ์ฉ์ด ๊ฐ๋ฅํด์ผ ํ ํ ๋ฐ, ๋ชจ๋ ์คํํ์ผ์ Universal binary๋ก ๋ง๋ค์ด ๋ฐฐํฌํ๋ ๊ฑธ๊น? ๊ทธ๋ ๋ค.
$ cd RxSwift.framework
$ file RxSwift
RxSwift: Mach-O universal binary with 4 architectures: [i386:Mach-O dynamically linked shared library i386] [x86_64] [arm_v7] [arm64]
RxSwift (for architecture i386): Mach-O dynamically linked shared library i386
RxSwift (for architecture x86_64): Mach-O 64-bit dynamically linked shared library x86_64
RxSwift (for architecture armv7): Mach-O dynamically linked shared library arm_v7
RxSwift (for architecture arm64): Mach-O 64-bit dynamically linked shared library arm64
์๋ํํฐ ์ค ์ ๋ช ํ RxSwift๋ฅผ ๊ฐ์ ธ์์ ํ์ธํด๋ณด๋ฉด, Simulator๋ฅผ ์ํ architecture์ iOS Device๋ฅผ ์ํ architecture๊ฐ ๋ชจ๋ ํฌํจ๋์ด ์์์ ํ์ธํ ์ ์๋ค.
App Store Connect Upload Error
๊ทธ๋ผ ์ ์ํ๋ก app store์ ์ฌ๋ฆฌ๋ฉด ์ด๋ป๊ฒ ๋ ๊น?
โUnsupported Architecture. Your executable contains unsupported architecture โ[x86_64, i386]โ.โ
ใ ใ ์ ์ํคํ ์ณ์ ๋ํ ๊ฒ์ ์ ๊ฑฐํด์ฃผ์ด์ผ ํ๋ค. ์ด๋ฐ ๊ฒ์ Strip์ด๋ผ ํ๋ค. Framework์์ ํ์์๋ ์ํคํ ์ณ๋ฅผ ์ง์ฐ๊ณ ๋ค์ ํฉ์น๋ ๊ณผ์ ์ ๋งํ๋ค.
lipo
command
$ man lipo
---
NAME
lipo - create or operate on universal files
SYNOPSIS
lipo input_file command [option...]
DESCRIPTION
The lipo tool creates or operates on ``universal'' (multi-architecture) files. Generally, lipo reads a single input file and writes to a single output file,
although some commands and options accept multiple input files. lipo will only ever write to a single output file, and input files are never modified in
place.
# ํ์ํ architecture๋ค๋ง ์ถ์ถ
$ lipo -extract armv7 RxSwift -o RxSwift_armv7
$ lipo -extract arm64 RxSwift -o RxSwift_arm64
# ๋ถ๋ฆฌํ binary ํฉ์น๊ธฐ
$ lipo -o RxSwift-merged -create RxSwift_armv7 RxSwift_arm64
# ์ strip๋์๋์ง ํ์ธ
$ lipo -info RxSwift-merged
Architectures in the fat file: RxSwift-merged are: armv7 arm64
# ์ ๋ฆฌ
$ rm RxSwift_arm*
$ mv RxSwift-merged RxSwift
Reference
- stackoverflow - Submit to App Store issues: Unsupported Architecture x86
- hmac - duplicate symbol ์ด์
- Framework Programming Guide
- Comparison of executable file formats - wikipedia
- Optimizing App Startup Time (WWDC16)
- stackoverflow - Submit to App Store issues: Unsupported Architecture x86
- Comparison of executable file formats - wikipedia