## 0.1 소프트웨어 스택 빌드 파이프라인의 엔드-투-엔드(End-to-End) 생명주기

## 0.1 소프트웨어 스택 빌드 파이프라인의 엔드-투-엔드(End-to-End) 생명주기

하나의 평범한 C++ 소스 코드가 드론 두뇌(Pixhawk)의 플래시 메모리에 박힐 하나의 기계어 펌웨어(.px4) 파일로 환골탈태하기까지, PX4 빌드 파이프라인은 정교하게 짜인 공장 컨베이어 벨트를 통과해야 한다. 개발자가 터미널 창에 무심코 치는 make 명령어 하나 뒤쪽에서 벌어지는 숨 막히는 엔드-투-엔드 생명주기(Lifecycle)의 전모를 분석한다.

Phase 1: Git Submodule 동기화 및 소스 트리(Source Tree) 준비
PX4는 단독 레포지토리가 아니다. MAVLink, NuttX RTOS, uAVCAN, EKF2 등 거대한 외부 라이브러리들을 git submodule 형태로 끌어안고 있다. 빌드의 첫 단계는 스크립트가 이 서브모듈들의 버전(Commit Hash)이 메인 트리가 요구하는 것과 완벽히 일치하는지 타당성 검사(Validation)를 수행하고, 누락되었다면 인터넷을 통해 동기화(git submodule update --init --recursive)시키는 것으로 시작된다.

Phase 2: CMake의 메타-제너레이션(Meta-Generation) 및 의존성 주입
터미널에서 전달된 타겟 타겟(예: px4_fmu-v6c_default) 식별자를 넘겨받은 CMakeLists.txt 파일들이 가동된다. CMake는 타겟 보드의 board_config.hdefault.px4board (Kconfig 기반) 명세서를 읽어들여, 수천 개의 소스 파일 디렉토리 중 이 타겟 보드에 컴파일해 넣을 모듈 플래그(예: +drivers/distance_sensor/tfmini)의 스위치를 ON 시킨다. 이와 동시에 Python 스크립트(Jinja2)를 호출하여 uORB .msg 구조체 파일들을 모조리 스캐닝한 후, C++ 헤더 파일과 토픽 등록 .cpp 코드를 build/ 숨김 디렉토리에 대량으로 찍어낸다(Auto-generation). 마지막으로 이 모든 작업 순서를 최적화한 Ninja 빌드 스크립트(build.ninja)를 뽑아낸다.

Phase 3: 임베디드 크로스 컴파일(Cross-Compilation) 및 목적 파일(.o) 생성
비로소 ARM GCC 컴파일러가 투입된다. 호스트 PC의 코어 수(N)만큼 병렬 스레드(Thread)를 통째로 점유한 능동형 빌더 Ninja가 타겟팅된 수백 개의 C/C++ 소스 파일을 읽어들여, ARM Cortex-M 코어 전용(예: cortex-m7, cortex-m4)의 기계어 목적 파일(.o)로 미친 듯이 전환시킨다. 이 과정에서 호스트 PC의 CPU는 최대 사용률(100\%)을 찍으며 터보 부스트 전력을 소모하게 된다.

Phase 4: 링크(Link) 및 펌웨어 패키징(Packaging)
번역이 끝난 수많은 .o 파일들은 링커(arm-none-eabi-ld)에 의해 뭉쳐져 단일 실행 파일(.elf)로 융합된다. 이때 타겟 보드의 메모리 구조지도(Linker Script, .ld)를 참조하여 Flash 영역과 RAM 영역 주소를 정확히 계산해 할당(Address Mapping)한다.
마지막으로, 생성된 바이트 배열 덩어리 코드 앞에 메타데이터(보드 ID, XML 형태의 파라미터 리스트, 압축 알고리즘) 헤더를 부착(Append)한 뒤, 서명을 더하여 비로소 부트로더(Bootloader)가 씹어넘길 수 있는 통합형 캡슐 파일인 .px4 이미지 빌드를 종료한다. 개발자는 이 산출물을 QGroundControl을 통해 플래싱하게 된다.