header-img
Info :
  1. 1. CPU Architecture
  2. 2. Framework
  3. 3. embeded 설정
  4. 4. XCFramework ?
  5. 5. XCFramework 구현하기
  6. 6. static framework 만들기
  7. 7. 한 곳에서 작업하기
  8. 8. code signing

1. CPU Architecture

  • 아이폰은 기종에 따라 다른 아키텍처의 CPU를 사용함.
  • 빌드를 하면 Execute file이 생성되고 이 파일을 CPU에서 읽기 때문에 이에 맞는 아키텍처 생성이 필요함.
  • 기종별 아키텍처
    • armv7 : ~ iPhone 5s
    • arm64 : iPhone 5s ~
    • x86_64 : 64bit 기기에 대응하는 simulator, mac
  • 우리는 iOS 13부터 시작하므로 13 버전은 iPhone SE, 6s부터 시작이므로 arm64로만 빌드하면 될 것 같음.
  • Build Active Architecture Only
    • Release : Yes < arm64
    • Debug : No < simulator도 지원해야 함.

 

2. Framework

  • Static Framework
    • 구성 : source file + static lib + static linker
    • static linker를 통해 static lib의 코드가 execute file로 들어가 heap 메모리에 상주
    • static lib이 복사되므로 static framework를 여러 프레임워크에서 사용하면 코드 중복 발생
    • 장점 : 런타임 속도가 빠름, inline 개념
    • 단점 : 메모리 많이 사용, 여러 모듈에서 동일한 static lib을 임포트하면 그 횟수만큼 라이브러리가 복사되기 때문에 app size 측면에서의 용량 늘어나게 됨, 컴파일 속도 오래 걸림
  • Dynamic Framework
    • 구성 : source file + dynamic lib references + dynamic lib + static linker
    • 파일이 아닌 주소를 execute file에 저장하고 static linker를 통해서 stack으로 필요한 라이브러리들을 불러와서 사용하는 형태
    • 주소 정보들만 heap에 상주 (스태틱은 라이브러리 코드가 힙 메모리에 상주)
    • 장점 : 컴파일 속도가 상대적으로 빠르고 메모리 효율적 사용
    • 단점 : 런타임 속도가 느림(왜냐 런타임에 프레임워크를 로드하기 때문)

 

3. embeded 설정

  • dynamic lib의 경우 Targets > General > Frameworks, Libraries, and Embedded Content의 각 항목에 대해 Do Not Embeded로 설정하면 안 됨. 왜냐 dynamic lib들은 동적으로 런타임에 로딩되기 때문에 embeded 된 형태로 사용해야 함.
  • static lib은 두 가지로 나뉘게 됨. 빌드할 때 이미 라이브러리 내 코드들이 복사되는 형태이므로 do not embed해도 상관이 없지만! 리소스 번들을 사용해야 하는 경우 embeded 방식으로 선택해야 함. embeded 방식으로 사용하게 되면 코드 복사본이 두 개 생김. 하나는 빌드 시 이 라이브러리를 import하여 사용하는 곳에서 한 번 복사되고 애플리케이션 패키지 내에 프레임워크 형태로 하나 더 존재함.
 

 

4. XCFramework ?

  • 기존의 fat framework (x86_64 + armv7 + arm64) 형태는 하나의 프레임워크 안에 모든 빌드 아키텍처가 들어가 있기 때문에 용량도 커지고 불필요한 작업도 들어감
    • 약간 다른 의견을 드리자면 fat framework 에서 용량이 큰 문제는 xcframework도 똑같이 가지고 있습니다.
      fat framework로 빌드하더라도 빌드타임에 필요한 아키텍쳐 바이너리만 추출하여 빌드하기 때문에 단점이라 볼 수 없습니다.
      기존에는 fat 라이브러리 하나의 파일에서도 armv7, arm64는 iOS용, x86(i386), x86_64는 macOS용으로 구분이 되었습니다.
      기존에도 하나의 파일이었고, iOS용과 시뮬레이터용 파일이 별도로 존재하는 것은 아니었습니다.
      (별도로 존재할 경우 iOS 디바이스용 라이브러리에는 x86, x86_64가 포함되지 않았습니다.)
      xcframework가 나온 배경은 실리콘 기반의 맥 출시와 관련이 있습니다.
      실리콘 기반의 맥이 출시되면서 arm64 아키텍쳐가 iOS와 서로 겹치기 때문에 하나의 fat 파일로 만들지 못하는 문제를 해결하기 위해 고안된 방법입니다.
  • 반면 XCFramework는 각각의 아키텍처를 분리함.

 

5. XCFramework 구현하기

  • XCode에서 create > Framework로 프레임워크 프로젝트 생성
  • 만들어진 프로젝트 설정
    • Targets > Build Settings > Build Options > Build Libraries for Distribution > Yes
    • Targets > Build Settings > Linking > Mach-O Type > 원하는 동적/정적 라이브러리로 설정
    • Targest > Signing & Capabilities > Automatically manage signing 체크 해제, Bundle Identifier 지우고 엔터
  • 만들 함수 만든 후 cmd 창에서 내 프로젝트 위치로 이동
  • 아래 코드 세 개를 순차적으로 각각 실행해줌. 첫 번째는 archiving을 하여 시뮬레이터용 바이너리 파일(.xcarchive)를 만든 것이고 두 번째는 실제 아이폰용 바이너리 파일을 마지막은 두 바이너리 파일들을 합쳐서 하나의 XCFramework로 묶은 것임.
// simulator
xcodebuild archive -scheme 프로젝트명 \
-archivePath './build/iphone-simulator.xcarchive' \
-sdk iphonesimulator \
SKIP_INSTALL=NO \
BUILD_LIBRARY_FOR_DISTRIBUTION=YES
// iphone os
xcodebuild archive -scheme 프로젝트명 \
-archivePath './build/iphone.xcarchive' \
-sdk iphoneos \
SKIP_INSTALL=NO \
BUILD_LIBRARY_FOR_DISTRIBUTION=YES
// xcframework
xcodebuild -create-xcframework \
-framework "./build/iphone.xcarchive/Products/Library/Frameworks/프로젝트명.framework" \
-framework "./build/iphone-simulator.xcarchive/Products/Library/Frameworks/프로젝트명.framework" \
-output "./xcframework/만들_프레임워크명.xcframework"
  • 만들어진 "./xcframework/프레임워크명.xcframework" 파일을 복사해서 테스트하기 위한 프로젝트에 Frameworks 폴더를 생성하고 하위에 프레임워크명.xcframework 폴더만 넣어줌.
  • xcode에도 넣어주고 테스트용 프로젝트 > Targets > General > Frameworks, Libraries and Embeded Content에서도 추가해줌. Embeded & Sign으로 설정해줌. (아직 dynamic framework이기 때문)

 

6. static framework 만들기

  • 위 코드로 만든 프레임워크 프로젝트에서 Targets > Build Settings > Mach - O > static 으로 변경.

 

7. 한 곳에서 작업하기

  1. File > New > Workspace > 이름 지정 > 생성 (폴더는 프레임워크, 프레임워크를 테스트할 프로젝트 있는 폴더에서 생성)
  2. 프레임워크, 프레임워크를 테스트할 프로젝트 모두 닫기
  3. 만든 워크스페이스 열고 File > Add File to “workspace 이름” > 프레임워크, 프레임워크를 테스트할 프로젝트의 .xcodeproj 파일 추가
  4. 그 다음 왼쪽 hierarchy 창에서 프레임워크를 테스트할 프로젝트 누르고 Targets > General > Frameworks, Libraries, and Embeded Content에서 프레임워크 추가 후 Do not Embed로 속성 설정
  5. 해당 창의 상단에서 Build Phases > Link Binary With Libraries > 프레임워크 추가
  6. framework 내부에 .xib 파일이 있다면 그대로 복사해서 프레임워크를 테스트할 프로젝트에 넣어주고 하는게 훨씬 나음. 찾아보니 번들을 만들어서 그걸 또 프로젝트에 넣어주면 되는 것 같기는 한데 저는 안 됐습니다… 차라리 xib 파일을 최소화하고 연동할 때 넣어주는 것이 나을 것 같습니다. (번들 방식 : iOS static library)

 

8. code signing

framework의 경우 signing 해 줄 필요가 없는 것 같음.

프레임워크 > Targets > Signing & Capabilities 에서 Automatically manage signing 체크 해제한 후 Bundle Identifier 지우고 Team을 none으로 변경

https://github.com/Carthage/Carthage/issues/1378

 

더보기
CS/iOS, Swift