https://developer.apple.com/kr/videos/play/wwdc2022/110364/
Xcode 빌드에서의 병렬 처리에 대한 오해 해소 - WWDC22 - 비디오 - Apple Developer
Xcode 빌드 시스템이 빌드에서 최대 병렬 처리를 추출하는 방법을 알아보세요. 프로젝트를 구조화하여 빌드 효율을 개선하는 방법을 살펴보고, Xcode에서 타겟의 빌드 단계 간의 관계를 해결하기
developer.apple.com
목차
- Core concept (xcode에서 빌드가 이루어지는 핵심 컨셉)
- Build Phases (target 빌드 시 xcode의 병렬화 증가 방법)
- Crosstarget-builds (많은 타겟들간 어떻게 서로 병렬화하고 빌드가 되는지)
Core concept

빌드는 Swift언어와 같은 고수준 언어를 기계어로 컴파일하고 실행파일을 만드는 과정입니다.
Xcode 빌드의 기본 컨셉은 다음과 같습니다.
소스코드(swift 파일)
> xcode가 swift 파일, 에셋 등과 같은 입력 파일을 컴파일 하기 위해 2개의 컴파일러 호출
> Clang, Swift 컴파일러가 결과물로 mach.O 파일 생성
> Linker가 생성된 파일을 소비하며 실행파일 생성
여기서 중요한 건 빌드 시스템은 이와 같은 과정을 수행하며 작업간 종속성이 있게 됩니다. 여기서 작업이란(컴파일링, 링킹, 에셋 컴파일링, 파일 복사 또는 코드 서명 등과 같이 전체 타겟을 빌드하기 위해 실행해야하는 작업)을 말합니다.
작업간 종속성 때문에 작업이 어떤 순서로 실행되는지에 대해 자세히 살펴보시죠.

작업 종속성이 없는 A작업부터 시작하게 됩니다.
A 작업을 완료해야만 B,C 작업의 차단이 해제되고 B의 작업이 완료되어야만 D,E작업의 차단이 해제됩니다.
차단이 해제된 작업(Unblock)을 다운스트림이라고 부르고 차단하는 작업은(Block) 업스트림이라고 부릅니다. (업스트림과 다운스트림으로 인해 대기시간이 길어지게 되면 빌드 시간이 길어집니다.)
많은 프로젝트는 두개 이상의 프레임워크 타겟이 붙으므로 앱 확장과 프레임워크가 붙은 앱 구조에서 좀 더 자세히 살펴보겠습니다.

Framework와 App Extension은 종속성이 없고, Framework와 App, Framework와 App Extension간 종속성이 있습니다.
따라서 빌드할 때 종속성이 없는 Framework와 App Extension 타겟먼저 작업이 시작됩니다.

Framework와 App Extension의 작업이 병렬적으로 이루어지고, 두 작업이 끝나면 App 작업을 시작할 수 있게 됩니다.
빌드는 두가지 종류가 있는데 위에는 클린 빌드(위에처럼 처음부터 끝까지 재컴파일되는 빌드)할 때를 시각적으로 보여준 것이고
증분 빌드(변경이 이루어진 부분만 재컴파일하는 빌드)를 하게 된다면 아래처럼 됩니다.

B, D, E 테스크가 재실행됩니다.
Build Timeline
xcode14부터 빌드 시간에 대해 시각적으로 분석하고 보는 법에 대해서도 가능해져서 설명 한번 해주었습니다.

이것을 누르면 빌드 타임라인을 볼 수 있습니다.

Build Phases
xcode에서 빌드 작업할 때 병렬화를 증가시킬 수 있는 방법을 소개해주었습니다.
일단 기본적으로 빌드 시스템에서 병렬이 가능한지 불가능한지 판단하는 기준은 각 작업의 입력과 출력을 고려하여 결정합니다.


위의 이미지를 보시면 Compile Sources와 Copy Resources는 입출력에 종속성이 없기 때문에 병렬작업이 가능합니다.
그러나 Link Binary with Libraries에서는 컴파일 출력물이 소비되어야하기 때문에 병렬 작업이 안됩니다.
그러나 Run Script 작업을 병렬로 변경할 수 있습니다.

기본적으로는 Run Script 작업은 데이터 경쟁을 막기 위해 직렬로 되어있습니다.

FUSE_BUILD_SCRIPT_PHASES=YES로 바꾸면 Run Script를 병렬로 처리할 수 있습니다.
근데 기본적으로 직렬인 이유가 데이터 경쟁을 막기 위해서인데 병렬로 처리하면 못막잖아요?
이 때에 조금 더 안전하게 처리하는 알려주었습니다.
입력과 출력 명시적으로 적어주기

그러면 입력과 출력 파일을 고려하여 xcode에서 알아서 병렬로 처리해줍니다.
만약, Run Script1의 출력 파일이 Run Script2의 입력 파일로 사용되어야 하는데 잊고 입출력 파일에 적어주지 않았는데 병렬로 작업하면 어떻게 될까요? 빌드에 실패하게 됩니다 ㅎㅎ..
그러면 이것은 어떻게 방지할까요?

ENABLE_USER_SCRIPT_SANDBOXING = YES로 설정해주는 것입니다.

위에 옵션을 설정해주면 Run Script에 샌드박싱 적용하여 빌드 시 Run Script가 명시된 입출력 파일이 아닌 파일에 접근하게 되면 에러를 발생시켜 빌드를 실패하게 만듭니다. (실패하여 어느 부분이 에러 메세지로 문제인지 알려줌)
Crosstarget-builds (많은 타겟들간 어떻게 서로 병렬화하고 빌드가 되는지)

위에서 나온 Core concept 내용과 비슷합니다. 타겟들이 많더라도 Core concept에서 나온 작업 순서와 동일하게 진행됩니다.
Swift 타겟의 소스코드를 바이너리 제품으로 빌드하는 것은 일반적으로 빌드 계획이나 컴파일 및 연결을 위한 많은 하위 작업들로 이루어진 복잡한 작업입니다. 이러한 작업의 조직화는 Xcode 도구 체인의 특수 도구인 Swift Driver에 위임됩니다.
Swift Driver는 타겟 소스 코드에 필요한 컴파일러 및 링커 호출을 구성하는 시기와 방법에 대한 정보를 가지고 있습니다.

xcode 14 이전에는 빌드 시스템과 Swift Driver 사이 경계로 인해 타겟 빌드 단계의 오케스트레이션 및 드라이버의 각 타겟 인스턴스에 의해 생성된 컴파일 하위 작업이 서로 독립적으로 발생했습니다. 각 구성 요소는 사용 가능한 시스템 리소스의 최대한 활용하고자 최선을 다했습니다.
좀 더 자세히 들여다보겠습니다.

Swift 타겟 종속성은 종속 항목이 공개 인터페이스를 캡쳐하는 바이너리 모듈 파일을 제공함으로서 해결됩니다.
이런 종속성 관계를 해결하면 다음과 같은 순서로 이어집니다.

Xcode 14에서는 Swift로 작성된 완전히 새로운 Swift 드라이버의 구현 덕분에 빌드 시스템과 컴파일러가 완전히 통합되었습니다.
빌드 시스템은 코드 컴파일을 위해 수행해야 하는 모든 작업의 중앙 일정 관리자 역할을 합니다. 이 중앙 계획 매커니즘을 통해 xcode는 세밀한 일정 결정을 내릴 수 있고 프로젝트를 빌드할 때 사용 가능한 리소스 만큼만 사용하도록 보장합니다.
빌드 시스템과 컴파일러가 통합되면서 빌드 수케줄러가 상호 보완을 고려하는 것이 중요합니다.

예를들어 8-코어 시스템에서의 사용 가능한 작업이 8개이고, 종속성이 충족되어 이동할 준비가 된 작업을 사용 가능한 실행 슬롯중 하나에 할당하는 것입니다.
코어수가 많다면, 더 많은 동시 작업을 할 수 있습니다. 이는 곧 더 많은 작업을 수행할 수 있는 유휴 코어를 가질 수 있는 가능성이 더 높다는 것을 의미하기도 합니다. (종속성 때문에 기다리는 작업들이 많으면, 놀고 있는 코어가 생길 수 있기 때문)
새로운 빌드 시스템은 스케쥴러가 이러한 유휴 시간을 크게 줄일 수 있도록 합니다.
Eager emission of modules
Xcode 14 이전

Xcode 14 및 Swift 5.7 이후
새롭게 타겟 모듈의 구성이 모든 프로그램 소스 파일에서 별도의 모듈-방출 작업에서 수행됩니다.

결과

업/다운스트림으로 인해 생긴 대기 시간이 크게 줄여졌습니다.
Eager linking
Xcode 14이전


Xcode 14 이후


이게 가능한 이유는
파랑색 Link가 주황색 Link에 종속성을 가지는 대신, 이전 빌드 프로세스에서 모듈-방출 작업에 의해 생성된 텍스트 기반 동적 라이브러리 스텁에 의존합니다. 이 스텁에는 종속성이 사용할 수 있도록 링크된 제품에 심볼 목록이 포함되어 있습니다.
주의!

빌드 옵션에서 Earger Linking이 Yes로 되어있어야 동작함
마무리
- 빌드 순서: 종속성이 없는 작업부터 처리됨.
- Build Phases > Run Script 직렬 옵션 > 병렬 옵션으로 변경하여 빌드 시간을 단축할 수 있음.
- Xcode 14이후 Swift Driver의 새로운 구현으로 작업간 종속성으로 인한 대기 시간이 줄어듬.
'WWDC' 카테고리의 다른 글
[WWDC18] Building Faster in Xcode (0) | 2025.04.04 |
---|---|
WWDC24 - Meet Swift Testing (3) | 2024.07.03 |