Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
Tags
- RxCocoa
- 리펙터링
- HIG
- UICollectionView
- Human interface guide
- Xcode
- MVVM
- Clean Code
- collectionview
- ios
- 리팩토링
- 리펙토링
- 클린 코드
- uitableview
- 스위프트
- rxswift
- combine
- 애니메이션
- SWIFT
- Observable
- clean architecture
- tableView
- ribs
- uiscrollview
- map
- swiftUI
- Protocol
- UITextView
- swift documentation
- Refactoring
Archives
- Today
- Total
김종권의 iOS 앱 개발 알아가기
3[iOS - swift] 2. 모듈화 개념 - Binary File 개념 (Mach-O, CPU Architectures, Universal binary, lipo command) 본문
iOS 응용 (swift)
3[iOS - swift] 2. 모듈화 개념 - Binary File 개념 (Mach-O, CPU Architectures, Universal binary, lipo command)
jake-kim 2022. 6. 13. 23:57Tuist로 모듈화 최신 포스팅 글 목록 > https://ios-development.tistory.com/1303
1. 모듈화 개념 - Library vs Framework (static library, dynamic library, static framework, dynamic framework)
2. 모듈화 개념 - Binary File 개념 (Mach-O, CPU Architectures, Universal binary, lipo command)
3. 모듈화 개념 - XCFramework 생성, 사용 방법
Xcode의 Execute File의 형태
- Execute File은 Binary File형태로 존재
- Mac OS에서 대표적인 bin파일 안을 보면 binary file로 존재
// terminal에서 확인
$ cd
$ open /bin
- 이 중 echo 파일의 정보를 확인
$ file /bin/echo
- 위 파일 정보를 보면 다양한 단어(?)들이 존재
- Mach-O
- universal binary
- architectures: [x86_64:Mach-O 64-bit arm64e]
- x86은 인텔에서 만든 CPU 아키텍쳐, arm64는 애플에서 만든 모바일 CPU 아키텍쳐 (현재는 M1, M1x 처럼 노트북에도 탑재)
- Mach-O와 Universal binary 개념은 아래에서 계속
Execute File 포멧, Mach-O
- Mach-O (Mach Object File Format)
- Mach 기반의 커널 OS에서 사용하는 excuetable file,object file, library 파일 포멧을 의미
* 커널: 프로그램이 OS 영역에 직접 접근을 못하지만 Kernel을 통해 OS를 제어
- Mach 기반의 커널 OS에서 사용하는 excuetable file,object file, library 파일 포멧을 의미
Mach-O 용어
- File Types
- Executable (앱 실행을 위한 main binary)
- Dylib (Dynamic library)
- Bundle (링크될 수 없는 Dylib을 의미하고 dlopen()으로 실행)
- Image
- 실행 가능한 dylib, bundle
CPU Architecture
- Xcode > Project > Build Settings > Architectures
- 아이폰은 기종에 따라 다른 아키텍쳐의 CPU를 사용
- 빌드를 하면 Execute file이 생성(Binary File)되고 이 파일을 CPU에서 읽기 떄문에 CPU에 맞는 Architecture 생성이 필요
- armv7
- 아이폰: iPhone3S ~ iPhone5s
- 아이패드: iPad2 ~ iPad4
- arm64
- 아이폰: iPhone5S ~ 최신아이폰
- 아이패드: iPad5 ~ iPad9
- x86_64
- 64bit 기기에 대응하는 simulator, mac (32bit는 i386)
* 더 많은 정보는 이곳 참고
Build Active Architectures Only 옵션
- Yes로 이 옵션을 활성화하면, 해당 기기에 맞는 아키텍쳐용 빌드만 생성
- No로 이 옵션을 비활성화하면, 모든 기기에 대응되는 아키텍쳐용 빌드를 생성
- Debug환경에서는 Build Active Architecture Only를 Yes로하여 디버그 용도만 사용하는 아키텍쳐만 사용하게끔 처리 (default)
- ex) 시뮬레이터 빌드 - 인텍 맥 일경우 x86_64, 실리콘 맥 일경우 arm64 아키텍쳐로 빌드
- Xcode13에서는 시뮬레이터 동작을 위해 인텔 맥(x86_64), 실리콘 맥 CPU(arm64) 모두 지원
$ open /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/SDKSettings.json
Universal Binary (= Universal App)
- 두 개 이상의 아키텍쳐를 지원하는 excute file (바이너리 파일)
- 위 Build Active Architecture Only 옵션에서 false로 지정하거나 아래처럼 info.plist에 universal app으로 등록
- universal app - 하나의 프로젝트를 아이패드와 아이폰을 포함한 모든 버전의 iOS에서 실행되는 앱
- Apple의 UIRequiredDeivceCapabilities 문서에 따르면, armv7으로 RequiredDeviceCapabilities 세팅을 시도하면 Universal 앱이 가능
- UIRequiredDeviceCapabilities 값 설정은 Property List에서 사용
- 프로젝트 폴더에서 Info.plist에 아래 코드를 추가
<key>UIRequiredDeviceCapabilities</key> <array> <string>armv7</string> </array>
Universal Dynamic Framework
- 이전 1번글에서 알아본대로, dynamic framework는 리소스와 library가 포함된 번들이고, Heap영역에 주소를 저장해놓고 stack영역에서 binary 파일을 사용
- Universal이 붙은 dynamic framework는 말 그대로 프레임워크가 모든 기기에서 사용가능하도록 유지하는 방법
빌드하며, 프레임워크 바이너리 파일 확인
- 예제) Cocoapods으로 RxSwift와 Firebase를 받아서 각각 바이너리 파일 정보 확인
target 'ExBinaryFile' do
use_frameworks!
pod 'RxSwift'
pod 'Firebase'
end
- pod install 후 빌드 (빌드를 안하면 프레임워크 바이너리 파일이 생성되지 않으므로 주의)
- 프레임워크 위치 확인
- Pods/Products에서 framework하나를 선택한 후 위치를 복사
- file 명령어 사용하여 확인
- architecture, framework 정보 획득 (Dynamic인지 Static인지)
- 위 주소를 복사한 다음 끝에, /{프레임워크 이름} 을 붙여서 확인
file /Users/jake.k/Library/Developer/Xcode/DerivedData/ExBinaryFile-cusamfjziinzuwgokvoygiojkffz/Build/Products/Debug-iphoneos/FirebaseCore/FirebaseCore.framework/FirebaseCore
(결과)
- architecture는 armv7과 arm64를 지원
- static이 아닌 dynamic 파일임을 확인 가능
/Users/jake.k/Library/Developer/Xcode/DerivedData/ExBinaryFile-cusamfjziinzuwgokvoygiojkffz/Build/Products/Debug-iphoneos/FirebaseCore/FirebaseCore.framework/FirebaseCore: Mach-O universal binary with 2 architectures: [arm_v7:Mach-O dynamically linked shared library arm_v7Mach-O dynamically linked shared library arm_v7] [arm64:Mach-O 64-bit dynamically linked shared library arm64Mach-O 64-bit dynamically linked shared library arm64]
/Users/jake.k/Library/Developer/Xcode/DerivedData/ExBinaryFile-cusamfjziinzuwgokvoygiojkffz/Build/Products/Debug-iphoneos/FirebaseCore/FirebaseCore.framework/FirebaseCore (for architecture armv7): Mach-O dynamically linked shared library arm_v7
/Users/jake.k/Library/Developer/Xcode/DerivedData/ExBinaryFile-cusamfjziinzuwgokvoygiojkffz/Build/Products/Debug-iphoneos/FirebaseCore/FirebaseCore.framework/FirebaseCore (for architecture arm64): Mach-O 64-bit dynamically linked shared library arm64
(RxSwift 프레임워크도 확인)
- Firebase와 동일하게 지원
/Users/jake.k/Library/Developer/Xcode/DerivedData/ExBinaryFile-cusamfjziinzuwgokvoygiojkffz/Build/Products/Debug-iphoneos/RxSwift/RxSwift.framework/RxSwift: Mach-O universal binary with 2 architectures: [arm_v7:Mach-O dynamically linked shared library arm_v7Mach-O dynamically linked shared library arm_v7] [arm64]
/Users/jake.k/Library/Developer/Xcode/DerivedData/ExBinaryFile-cusamfjziinzuwgokvoygiojkffz/Build/Products/Debug-iphoneos/RxSwift/RxSwift.framework/RxSwift (for architecture armv7): Mach-O dynamically linked shared library arm_v7
/Users/jake.k/Library/Developer/Xcode/DerivedData/ExBinaryFile-cusamfjziinzuwgokvoygiojkffz/Build/Products/Debug-iphoneos/RxSwift/RxSwift.framework/RxSwift (for architecture arm64): Mach-O 64-bit dynamically linked shared library arm64
Xcode에서 simulator, device 설정에 따라 다른 바이너리 파일 생성
- 위에서는 Any iOS Device (arm64)를 선택 > 빌드 > 바이너리 파일을 확인했을때의 결과
- Simulator iPhone 13 Pro를 선택 > 빌드 한다면, Framework의 바이너리 파일이 변경되고 주소도 변경
- file 명령어로 확인해보면, 예상대로 현재 빌드 환경이 인텔 맥이므로 x86_64 아키텍처로 바이너리 파일 생성
- (만약 애플 실리콘 맥이면 arm64 바이너리 아키텍쳐로 나올 것)
/Users/jake.k/Library/Developer/Xcode/DerivedData/ExBinaryFile-cusamfjziinzuwgokvoygiojkffz/Build/Products/Debug-iphonesimulator/RxSwift/RxSwift.framework/RxSwift: Mach-O 64-bit dynamically linked shared library x86_64
Lipo 명령어
- 프레임워크에 저장된 아키텍쳐를 분리하거나, 합칠 수 있는 명령어
- 특정 Architecture를 제거할 수 있고 추가할 수 있는 명령어
- 보통 보안 앱과 같은 곳에서 특정 라이브러리는 시뮬레이터만 지원하고(x86_64) 디바이스에는 지원하지 않는 경우가 있는데 이런 경우 앱 아카이빙 시 AppThnining에서 오류가 발생
- lipo 명령어를 사용해서 Framework의 특정 Architecture를 지워서 해결이 가능
// https://stackoverflow.com/questions/42641806/check-and-remove-unsupported-architecture-x86-64-i386-in-ipa-archive
lipo -remove {architecture} {ProjectFramework_SDK} -o {ProjectFramework_SDK}
* 참고
https://zamcom.tistory.com/286
https://www.innerfence.com/howto/apple-ios-devices-dates-versions-instruction-sets
https://namu.wiki/w/Mach(%EC%BB%A4%EB%84%90)
https://ko.wikipedia.org/wiki/ARM_%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98
'iOS 응용 (swift)' 카테고리의 다른 글
Comments