iOS/Setting

빌드 시스템 (1)

Hamp 2025. 12. 29. 13:27
반응형


🏁 학습할 내용

  • 미리보기
    • 빌드 프로세스
    • 작업 tool
  • 순서 결정
  • 동작 과정
  • 증분 빌드
  • 우리가 신경써야할 것은 무엇인가?
  • 사용자 스크립트

👀 미리보기

 

자세히 들여다보기전에, 먼저 간단하게 알고가면 좋은 배경지식을 정리해보자.

 

🐝 빌드 프로세스 

 

  • 소스코드 컴파일 및 링크 (.m, .swift, exec .)
  • 리소스 복사 (헤더, asset카탈로그, 스토리보드)
  • 코드 사이닝 및 스크립트 실행

 

🔨 작업 tool

1️⃣ Clang

소스 코드 컴파일러

 

2️⃣ LD

여러 .o 파일과 라이브러리를 하나의 실행파일 또는 프레임워크로 결합

  • 심볼 해석
  • 주소 재배치
  • 정적/동적 라이브러리 연결
  • Mach-O 바이너리 생성
  • 입력: .o, .a, .dylib
  • 출력: 실행 파일, .app, .framework, .dylib

 

3️⃣ AC Tool (Asset Catalog Tool)

Asset.xcassets -> 바이너리 리소스로 컴파일

  • 입력: 이미지, Color Set, App Thinning 정보등
  • 출력: Assets.car(compiled asset catalog)
💡App Thinning이란

스토어와 운영체제가 사용자의 디바이스(기기) 특성과 OS 버전에 맞춰 필요한 부분만 다운로드하여 설치를 최적화하는 기술

 

4️⃣ IB Tool (Interface Builder Tool)

Stroyboard / XIB -> 컴파일된 리소스로 변환

  • 입력: .storyboard, .xib
  • 출력: 컴파일된 nib 파일, 런타임에 바로 로딩 가능한 형태

 

수천 개 이상의 실행들을 특정, arguments와 configuration에 지정된 순서로 실행됨

🛤️ 순서 결정

 

💡 종속성 정보
작업이 소비하는 입력 및 생성되는 출력

 

 

Complie 과정에서 .m파일 입력으로 받고, .o 출력하고

링커 작업은, 작업은 .o파일을 입력으로 받고, 실행파일 또는 라이브러리를 출력한다.

 

이런 특징을 정리하면 다음과 같다.

  • 종속성 그래프를 통해 의존성 정보가 어떻게 흐르는 지 알 수 있으며
  • 결과적으로 실행 순서를 파악할 수 있음
  • 만약 컴파일 작업 자체 lane이 완전히 독립적일 경우, 병렬로 실행할 수 잇음
  • 링커 작업은 이전 컴파일 작업 결과물을 입력으로 이용하니, 마지막에 실행되야

❓어떻게 동작할까?

 

🌳 종속성 그래프 (트리) 만들기

  • build description 정보인 프로젝트 파일 가져옴
  • 프로젝트 파일을 모든 파일을 parse 후, target과 의존 관계를 파악
  • build setting을 적용 후, directed graph(유향 그래프)인 트리형 구조로 변경
  • 트리를 통해, 실행되는 작업간의 모든 종속성을 파악할 수 있음

 

⤵️ 실행할 순서와 병렬 실행 확정 짓기

  • low-level execution engine(libuild)가 위에서 만들어진 트리를 받아, 종속성 스펙을 읽음
  • 실행되야하는 순서와 병렬로 실행할 수 있는 작업을 실행 

🚨 주의할 점

종속성 정보를 너무 많이 가질 수 없으므로, 빌드 시스템은 작업 실행중에 더 많은 정보를 발견할 수 있다.
그래서, 원래 그래프보다 더 많은 정보를 통해 더 짧은 경로를 이용할 수도 있다? 라는 의미인 듯

🏋️ 증분 빌드

 

변화가 영향을 미치는 범위만 찾아서 필요한 파일만 재컴파일하는 빌드

 

🧪 원리

  • Swift는 모든 swift 파일 내부의 타입, 프로토콜, extension등을 분석해 파일 간의 의존성 그래프를 만듬
  • 빌드 프로세스의 각 작업은 hash 형태로된 signature가 있음
  • 해당 hash는 파일 경로, 수정 타임스탬프 등의 통계 데이터가 포함되어있음
  • 빌드 시스템은 현재 빌드와 이전빌드signature를 비교하여 다시 실행할 지 여부를 결정함

 

🥳 증분 빌드가 가능할 떄

  • swift 컴파일러는 각 파일을 인터페이스 파일을 생성
    • 인터페이스 파일에는 Stored property, function signature, protocol등의 정보가 있음
  • 만약 함수 내부(body)가 바뀌면, 인터페이스 파일은 그대로, 다른 파일 영향없음 증분 빌드 가능
  • stored property, public API가 변경되면, 인터페이스가 바뀜, 증분 빌드 불가 ❌

 

😭 증분 빌드가  불가능할 떄

  • 모듈 public interface 변경
  • struct stored property 변경
  • protocol 변경
  • extension에 public method 추가
  • Swift version 변경
  • optimization level 변경
  • Package / Pod 업데이트
  • DerivedData 삭제
  • Build setting 변경
  • bridging header(ObjC) 변경 (objc를 최소화 해야하는 이유

🕵️‍♀️ 우리가 신경써야할 것

 

빌드 순서는 결국 종속성 그래프를 통해 결정됨

 

우리는 그래프 구조에 따라 작업을 잘 실행할 수 있도록 도와줘야함

  • 작업을 순서대로 올바르게 수행되도록
  • 가능한 멀티코어 하드웨어를 활용해 병렬화 할 수 있도록

 

🔴 우리는 종속성을 신경써줘야함

 

📩 종속성의 근원

 

1️⃣ Built -in

빌드 시스템에 내장된 지식 관련

  • 컴파일러, 링커, resources(asset 카탈로그, ...) 등에 대한 규칙
  • Build Rules: 특정 파일 종류별로 어떤  처리를 할 것인지를 정의

 

2️⃣ Target Dependencies

Target 빌드 순서를 결정

  • 여기서는 SampleTestsSample을 의존하므로, Sample의 빌드 순서가 우선 (일방적으로)
  • 병렬 실행 여부에, 큰 영향을 줌 
  • 커스텀 run script가 작성되면 병렬 실행 전에 우선적으로 run script가 실행되야함 (데이터 레이스 떄문에)
  • 그래서 조금 느려질 수 있음

 

3️⃣ Implicit Dependencies

Link Binary With Libraries에 필요한 Target을 명시

  • scheme editor에서 Find Implict dependencies가 활성화되어 있다면(기본적으로 켜져있음)
  • 위에서 본 Target Dependenices에 의존 관계가 없더라도, 의존성 설정이 가능

 

4️⃣ Build phase Dependencies

  • scheme editor > parallelize build가 해제되어있다면, Build Phase에 정해진 순서로 실행될 수 있음
  • 만약 옵션이 켜져있다면, 빌드시스템이 더 나은 빌드 순서로 실행할 수 있음

 

5️⃣ Scheme order Dependencies

scheme editor에서 설정하는 빌드 관련 설정

🤖 사용자 스크립트

 

🔴  다른 빌드 단계와 다른 점

  • Input과 output을 명시적으로 입력해줘야한다.
    • 불필요한 스크립트 재실행하지 않아도됨
    • 정확한 의존성 정보를 제공함으로써, 빌드 성능을 높힐 수 있다.
  • 결과적으로 빌드 프로세스에서 데이터 경쟁이 발생하지 않도록 연속적으로 스크립트 단계를 한 번에 실행

 

그렇다면, 스크립트는 병렬 실행 및 증분 빌드가 불가능할까?? 

 

놉, 그렇지 않다. 

 

🏖️ SandBoxing Script

 

❓스크립트를 병렬로 실행하려면?

  • 만약 타겟의 스크립트가 종속성 분석을 기반으로 실행되고, 입력 및 출력의 전체목록을 지정했다면, 병렬실행이 충분히 가능하다.
  • 하지만 스크립트 Phase를 병렬로 실행할 경우, 빌드 시스템은 입출력 목록에 의존하게된다.
  • 불완전한 입출력 목록은 디버그가 매우 어려운 데이터 레이스를 유발 시킬 수 있다.

 

🧩 역할

 샌드 박싱은 스크립트가 실수로
소스 파일 및 중간 빌드 객체에 엑세스를 차단하는 선택정 기능

 

🙋 어떤 방식으로 샌드박싱은 데이터 경쟁과 잘못된 엑세스를 방지할까?

먼저 샌드박싱일 없을 때는 어떤 상황인지, 실제 예제를 살펴보자.

 

 

첫번 째 스크립트는 raw.txt파일을 일고 내용의 체크섬을 계산 후, 결과를
DERIVED_FILE_DIR/checksum.txt에 write

 

두번 째 스크립트는 동일한 raw.txt과 생성된 체크섬을 읽어, html 파일에 삽입

 

🤬 만약 정확한 입출력에 대한 종속성 정보가 선언되지 않을경우,
빌드 시스템은 두 스크립트를 병렬로 실행

(FUSE_BUILD_SCRIPT_PHASES가 활성화 되어있을 경우)

 

이렇게되면 2개의 문제가 발생할 수 있다.

  • 첫번쨰로, html 생성 스크립트에서 checksum 결과가 없기때문에 스크립트가 실패될 수 있다.
  • 두번째는, 디스크에 있는 이전 결과의 checksum결과가 html 생성에 사용될 수 있다.ㅊㅊ

 

 

만약 샌드박싱이 되어있다면, 다음과 같이 HTML 생성 스크립트가 checksum.txt를
읽으려고 시도하자마다 실패하게되고, 깔끔한 가이드를 알려준다.

 

 

이후, 올바른 입출력에 대한 종속성 정보를 잘 선언할 경우, 위 문제는 깔끔히 해결되면,

여전히 관련 없는 빌드 단계는 병렬로 실행할 수 있다.

 

 

ENABLE_USER_SCRIPT_SANDBOXING을 YES로 설정하면 샌드박싱기능을 사용할 수 있다.

 

 

 


출처

https://zeddios.tistory.com/919

 

Behind the Scenes of the Xcode Build Process (1)

안녕하세요 :) Zedd입니다. 티스토리 앱이 완전히 리뉴얼 됐네요!! https://apps.apple.com/kr/app/%ED%8B%B0%EC%8A%A4%ED%86%A0%EB%A6%AC-tistory/id906304982 ‎티스토리 - TISTORY ‎티스토리 블로거만을 위한 모바일 앱! 티

zeddios.tistory.com

https://vapor3965.tistory.com/40

 

WWDC 18 - Behind the Scenes of the Xcode Build Process

세션보면서 정리한 내용입니다. 해석이 잘못된 경우가 있을수있으니 발견하시면 댓글로 남겨주시면 감사하겠습니다🙏🏻 https://developer.apple.com/videos/play/wwdc2018/415/ Behind the Scenes of the Xcode Build P

vapor3965.tistory.com

https://ios-development.tistory.com/1828

 

[iOS - swift] 전체빌드와 증분빌드 차이점

전체빌드 개념단어 그대로 캐싱 없이, a부터 z까지 모든 파일을 빌드하는 것 cf) 빌드란?소스 코드들을 실행 가능한 형태로 메모리에 올리는 것증분빌드 개념증분 빌드(Incremental Build)는 “변화가

ios-development.tistory.com

https://www.youtube.com/watch?v=yo8_luxkSXY&t=40s

반응형