# 1. 컴파일 최적화 및 펌웨어 아티팩트(Artifact) 분석
PX4 컴파일 과정은 단순히 텍스트를 기계어로 번역하는 작업이 아니다. 한정된 플래시 메모리(1MB~2MB)와 극한의 CPU 사이클을 쥐어짜야 하는 비행 제어기 하드웨어 특성상, 빌드 파이프라인에는 잔혹할 정도의 **크기 최적화(Size Optimization)**와 데드 코드 절단(Dead Code Stripping) 기술이 인젝션(Injection) 되어 있다. 빌드가 내뿜는 최종 결과물, 즉 아티팩트(Artifact)들의 껍질을 벗겨본다.
컴파일러 최적화 플래그(Optimization Flag)의 예술
일반적인 리눅스 C++ 프로그램 빌드 시에는 메모리 캐시를 아낌없이 쓰는 속도 위주의 -O3 플래그를 애용하지만, PX4 보드 타겟 프로파일 내부에는 전역적으로 -Os (Optimize for Size) 지시어가 박혀있다. 컴파일러는 이 명령을 하달받는 순간, 약간의 CPU 캐시 미스(Cache Miss)를 감수하더라도 어셈블리어의 명령어 라인 수를 최대한 압축하여 바이너리 덩치를 줄이는 데 혈안이 된다.
특히 링커(Linker) 단계에서 발동되는 결정기인 --gc-sections (Garbage Collect Sections) 플래그는 압권이다. 개발자가 math.h 전체를 Include 했더라도, 실제로 소스 코드 상에서 단 한 번이라도 호출되지 않은(Unreferenced) 함수나 변수 블록은 링커가 자비 없이 잘라내어(Strip) 쓰레기통에 던져버린다. 이 기법 덕분에 수십만 줄의 매스(Math) 라이브러리와 EKF2 엔진을 때려 넣고도 최종 .px4 펌웨어의 몸무게를 1.5MB 대역으로 방어해 낼 수 있는 것이다.
바이너리 아티팩트(Artifact) 해부학: .elf 와 .px4
터미널에서 make px4_fmu-vX_default가 끝난 직후 build/px4_fmu-vX_default/ 폴더를 열어보면 두 개의 거대한 결과물이 나뒹군다. 각각의 역할과 성질은 완전히 다르다.
px4_fmu-vX_default.elf(Executable and Linkable Format): 이것은 펌웨어의 진정한 ’원본’이다. 기계어뿐만 아니라 소스 코드의 어떤 줄이 기계어 어디에 매핑되었는지를 알려주는 거대한 **디버깅 심볼(Debug Symbols)**과 메타데이터가 통째로 들어있어 파일 용량이 수십 MB에 달한다. 이 파일은 절대로 기체 플래시 메모리에 들어가지 않는다. 오직 J-Link 같은 하드웨어 디버거(GDB)가 칩 내부의 레지스터를 추적할 때 사용하는 ’코드 내비게이터’로만 쓰인다.px4_fmu-vX_default.px4: 이것이 당신이 그토록 원하던 진짜 펌웨어 패키지다. 위에서 언급한 무거운.elf원본에서 디버그 심볼과 잉여 껍데기를 모두 벗겨내고(Stripping), 순수한 순살 기계어 헥스(Hex) 바이너리만 뽑아낸 것이다. 여기에 PX4 툴체인은 보드 정보(Board ID), 펌웨어 버전, 그리고 파일 위변조 방지를 위한 SHA 해시(Hash) 서명을 앞뒤로 덧붙여(Append) 하나의 압축된 JSON 스타일 헤더 포맷(.px4)으로 포장한다. QGroundControl은 이 포장된 파일을 받아 버전 헤더를 읽고 기체의 궁합을 확인한 뒤 플래시에 밀어 넣는 것이다.