21.2.2.1. `CMakeLists.txt` 내 컴파일러 지시자 및 링커 옵션 제어

21.2.2.1. CMakeLists.txt 내 컴파일러 지시자 및 링커 옵션 제어

PX4 커스텀 모듈 디렉터리 내에 위치하는 CMakeLists.txt 파일의 본질은, px4_add_module() 매크로라는 그릇 안에 담을 **‘컴파일 레시피(Recipe)’**를 작성하는 것이다. C++ 소스 코드를 기계어로 번역하는 과정은 단숨에 일어나는 것이 아니라 전처리(Preprocessing) \rightarrow 컴파일(Compilation) \rightarrow 링킹(Linking)이라는 세 단계를 거치며, 이 각 단계마다 컴파일러(gcc 또는 clang)와 링커(ld)에게 세밀한 지시를 내려야 한다.

하지만 PX4 빌드 아키텍처는 개발자가 원시적인 컴파일러 플래그(예: -O3, -lpthread)를 직접 하드코딩하는 것을 極度(극도)로 혐오한다. 대신 px4_add_module()이 제공하는 속성(Property) 파라미터들을 활용하여 고상하게 의도를 전달하면, 매크로가 타겟 하드웨어 보드에 맞는 정확한 최적화 옵션과 링커 구문으로 번역해 주는 방식을 취한다.

1. 핵심 컴파일러 지시자 속성들

px4_add_module() 내부에 나열하는 핵심 파라미터 블록들은 컴파일러와 링커의 행동을 어떻게 제어할까?

1.1 SRCS (Source Files)

  • 기능: 컴파일 단위(Translation Unit)가 될 C++ 소스 파일(들)의 목록을 컴파일러에게 던져준다.
  • 작동 원리: 여기에 적힌 custom_app.cpp 파일들은 각각 독립적으로 컴파일되어 .obj 형태의 목적 파일(Object file)로 변환된 뒤, 최종적으로 하나의 모듈 라이브러리로 병합된다. 헤더 파일(.h)은 컴파일러가 소스 코드 내의 #include 구문을 타고 들어가 스스로 찾으므로 여기에 굳이 나열할 필요가 없다.

1.2 INCLUDES (Include Directories)

  • 기능: C++ 코드 내에서 꺾쇠 < > 나 따옴표 " " 로 묶인 헤더 파일을 찾을 때, 컴파일러가 뒤져봐야 할 추가적인 ’디렉터리 경로명(Path)’을 링커 테이블에 박아 넣는다.
  • 주의점: PX4 코어의 기본 경로(Math 라이브러리, uORB 구조체 경로 등)는 px4_add_module이 내부적으로 알아서 다 이어주기 때문에(Auto-linking), 보통 여러분이 서드파티 라이브러리(Third-party Library) 헤더 폴더를 새로 만들고 연결하려는 경우가 아니면 생략해도 무방하다.

1.3 DEPENDS (Dependencies)

  • 기능: 이 모듈을 C++ 컴파일러가 건드리기 그 이전에(Before), 절대적으로 먼저 컴파일되거나 생성되어 있어야 할(Pre-compiled) 타겟 모듈의 이름을 지정한다.
  • 동작 원리 (uORB_msgs의 비밀): PX4 모듈 개발 시 가장 흔히 볼 수 있는 DEPENDS uORB_msgs 구문이 바로 이 파라미터의 정체이다.
    개발자가 작성한 C++ 코드가 #include <uORB/topics/vehicle_status.h>를 참조하고 있는데, 만약 CMake 시스템이 uORB 메시지 생성기 스크립트(.msg \rightarrow .h 변환)보다 여러분의 모듈을 먼저 병렬 컴파일(Parallel Build) 해버린다면? 컴파일러는 “헤더 파일이 존재하지 않는다“며 빌드를 중단시킨다.
    DEPENDS는 빌드 순서를 강제하는 강력한 족쇄(Barrier) 역할을 수행하여 이러한 컴파일러 Race Condition을 방지한다.

이처럼 CMakeLists.txt 내의 파라미터들은 단순한 설정값이 아니라, 수천 개의 파일이 병렬로 컴파일되는 아수라장 속에서 내 모듈이 안전하게 기계어로 조립될 수 있도록 이정표를 꽂아주는 컴파일러 지시문이다.

이 기초적인 지시어들을 바탕으로, 펌웨어 전체의 심볼 테이블 룩업(Symbol Table Lookup)과 직결되는 MODULE 이름 네이밍 룰에 대해서는 다음 21.2.2.1.1 단원에서 상세히 알아본다.