21.2.2.2.1. DEPENDS에 uORB_msgs를 명시하여 메시지 생성 전처리(Pre-processing) 순서를 보장하는 원리
초보 PX4 개발자들이 컴파일 과정에서 가장 흔하게, 그리고 가장 당혹스럽게 마주하는 에러 로그는 다음과 같다.
fatal error: uORB/topics/my_custom_sensor.h: No such file or directory
개발자는 분명히 msg/my_custom_sensor.msg 파일을 정성껏 만들어 두었고, CMakeLists.txt 파일에 uORB 메시지 목록도 추가해 두었다. 그런데 почему(왜) 빌드 시스템은 저 헤더(.h) 파일이 존재하지 않는다고 비명을 지르는 것일까?
이 에러의 근본적인 원인은 바로 최신 빌드 시스템들이 도입한 ’병렬 컴파일(Parallel Compilation)’의 속도전과 그로 인해 발생하는 **경쟁 상태(Race Condition)**에 있다. 그리고 이를 우아하게 제압하는 마법의 단어가 바로 DEPENDS uORB_msgs이다.
1. uORB 메시지 처리의 2단 로켓 구조
우리가 msg/ 폴더에 작성하는 .msg 파일들은 순수한 텍스트 명세서에 불과하며, C++ 컴파일러가 직접 읽을 수 있는 언어가 아니다. 따라서 PX4 빌드 파이프라인은 컴파일(Compile)을 시작하기 전에 반드시 0단계로 전처리(Pre-processing) 단계를 거쳐야만 한다.
- 메시지 제너레이터(Message Generator) 가동: 파이썬(Python) 기반의 스크립트가
msg/폴더 안의 모든.msg파일들을 긁어모은다. - 헤더 파일 파생(Derivation): 파이썬 스크립트가 각
.msg파일의 내용을 파싱하여, C/C++ 구조체(struct) 형태를 띤.h헤더 파일들과.cpp소스 파일들로 트랜스파일링(Transpiling) 해낸다. 이 파일들은 보통build/<target>/uORB/topics/경로 아래에 동적으로 쏟아진다.
2. 병렬 빌드(Parallel Build)의 배신과 Race Condition
요즘 나오는 PC들은 CPU 코어 수가 8개, 16개에 달한다. Ninja 빌드 시스템이나 make -j8 같은 명령어는 전체 빌드 속도를 비약적으로 끌어올리기 위해, 서로 연관이 없어 보이는 모듈들을 동시 다발적으로(병렬) 컴파일하기 시작한다.
만약 여러분의 CMakeLists.txt에 어떠한 제동 장치도 없다면 다음과 같은 악몽이 펼쳐진다.
- [스레드 A] 파이썬 스크립트가
my_custom_sensor.msg를 읽어my_custom_sensor.h로 파생시키는 작업을 아직 ’시작’만 했다. - [스레드 B] 동시에 다른 CPU 코어에서는 여러분의 모듈인
custom_app.cpp를 컴파일러(gcc)에 밀어 넣는다. - 컴파일러가
custom_app.cpp파일의 상단에서#include <uORB/topics/my_custom_sensor.h>구문을 만난다. - 컴파일러가 디스크를 뒤져보지만, 스레드 A가 아직 파일을 바닥에 내려놓지 않았기 때문에 “File not found” 에러를 뿜으며 장렬하게 산화(Crash)한다.
이 현상이 바로 두 프로세스의 타이밍이 어긋나서 발생하는 전형적인 **경쟁 상태(Race Condition)**이다. 더 화가 나는 점은, 어떨 때는 스레드 A가 먼저 끝나서 빌드가 성공하다가도, 어떨 때는 실패하는 등 결과가 로또처럼 랜덤하게 바뀐다는 것이다.
3. DEPENDS uORB_msgs: 빌드 스케줄러의 신호등
px4_add_module() 매크로 블록 안에 추가하는 단 한 줄의 마법 주문:
DEPENDS
uORB_msgs
이 속성은 CMake 빌드 의존성 그래프(Dependency Graph)에 엄청나게 굵고 견고한 철사 줄을 하나 긋는 행위이다.
이 구문은 CMake 스케줄러에게 **“내 모듈(custom_app)을 컴파일하는 C++ 컴파일러 스레드는, uORB_msgs라는 이름표를 단 메시지 헤더 파생(Generation) 작업이 100% 완벽하게 종료될 때까지 무조건 대기(Wait)하라”**고 엄격하게 지시하는 신호등이다.
이 선언 덕분에, 아무리 CPU 코어가 많고 병렬화가 난무하더라도, 여러분의 모듈은 모든 .msg 파일들이 번지르르한 .h 헤더 파일로 변환되어 디스크에 예쁘게 놓이기 전까지는 절대 컴파일되지 않는다. ‘File not found’ 에러가 영구적으로 격리되는 것이다.
의존성 사슬을 완벽하게 꿰매었다면, 이제 이 모든 체스의 말(모듈들)을 체스판 위에 올려놓고 게임을 시작할 타겟 보드 구성 파일, .px4board의 파싱 메커니즘을 21.2.3 단원에서 엿볼 차례다.