18.2.1.3 Jinja2 템플릿 엔진 연동: msg.h.jinja 및 msg.cpp.jinja를 통한 코드 변환 로직
앞선 절에서 px4_generate_messages.py 파이썬 스크립트가 .msg 파일들을 구문 분석(Parsing)하여 메모리 상에 완벽한 추상 구문 트리(AST)를 구축하는 과정까지 살펴보았다. 이제 남은 과제는 이 추상적인 데이터 구조를 인간(혹은 C++ 컴파일러)이 읽을 수 있는 실제 .h (헤더 파일) 및 .cpp (소스 파일) 텍스트로 찍어내는 일이다.
파이썬 스크립트 내부에서 무수히 많은 print("struct " + name + " {"); 와 같은 하드 코딩(Hard-coding) 방식으로 C++ 코드를 생성하게 되면 유지보수가 끔찍한 스파게티 코드가 될 것이다. PX4-Autopilot은 이 구조적 결함을 극복하기 위해 Jinja2 템플릿 엔진을 전격 도입했다.
1. Jinja2 템플릿 엔진의 개념
Jinja2는 원래 파이썬 기반 웹 프레임워크(Flask, Django 등)에서 동적 HTML 웹 페이지를 렌더링하기 위해 만들어진 범용 텍스트 템플릿 엔진이다.
Jinja2의 철학은 “뼈대(Template)와 데이터(Data)의 분리” 이다. 템플릿 파일에는 고정된 텍스트와 함께 {{ 변수명 }}, {% for 문 %}, {% if 문 %} 같은 템플릿 전용 제어 구문이 들어간다. 이 템플릿에 파이썬이 데이터를 밀어 넣으면(Inject), 엔진이 제어 구문을 계산하여 최종 텍스트 파일(C++ 소스 코드)을 완성해 낸다.
2. msg.h.jinja의 구조와 렌더링 과정
PX4 소스 체인 안에 존재하는 msg.h.jinja 파일은 자동으로 생성될 모든 C++ 토픽 구조체의 마스터 공면장(Blueprint)이다. 이 파일을 열어보면 대략 다음과 같은 혼종(C++ 코드와 Jinja 문법의 결합)의 코드를 볼 수 있다.
// (중략 ... 경고 주석)
#pragma once
#include <uORB/topics/uORBTopics.hpp>
// 1. AST에서 추출한 의존성 헤더 파일 동적 추가
{% for include in includes %}
#include <uORB/topics/{{ include }}.h>
{% endfor %}
// 2. 구조체 정의부
struct __EXPORT {{ msg_name }}_s {
uint64_t timestamp; // 구조체 공통 필수 필드
// 3. 필드(변수) 변환 루프
{% for field in fields %}
{% if field.is_array %}
{{ field.cpp_type }} {{ field.name }}[{{ field.array_size }}];
{% else %}
{{ field.cpp_type }} {{ field.name }};
{% endif %}
{% endfor %}
};
- 의존성 주입: 파이썬 파서가 파악해둔
includes리스트를 템플릿 엔진이 순회하며#include문을 정렬해 준다. - 구조체 명명:
.msg파일의 이름(예:vehicle_gps)에_s접미외를 붙여 구조체 이름(vehicle_gps_s)을 부여한다. - 필드 전개: 데이터 멤버들을 하나씩 돌면서 배열인지 단일 변수인지 판단(
if/else)하여 C++ 문법에 맞는 정확한 타입(cpp_type)과 변수명(name)을 찍어낸다.
3. msg.cpp.jinja의 메타데이터 블록 생성
반면, msg.cpp.jinja 파일의 주된 역할은 각 메시지의 C/C++ 내부 동작 구현과 더불어 uORB 메타데이터(Metadata) 블록을 생성하는 것이다.
메타데이터는 토픽의 이름, 구조체의 전체 크기(Byte 사이즈), 그리고 로깅(Logging) 모듈이 구조체 내부를 바이트 단위로 뜯어볼 수 있도록 돕는 포맷 스트링(Format String) 정보들을 담고 있는 런타임용 핵심 메커니즘이다. Jinja 템플릿 엔진은 파싱된 정보를 바탕으로 이 메타데이터 전역 변수를 자동으로 선언해 주며, 이 덕분에 PX4의 모든 모듈은 런타임에 동적으로 토픽들의 속성을 파악할 수 있게 된다. (메타데이터의 세부 내용은 18.2.3절에서 추가로 다룬다.)
4. 프레임워크 유지보수의 혁신
결론적으로 Jinja2 템플릿 엔진 설계의 도입은 PX4 개발자들에게 폭발적인 유지보수 생산성을 안겨주었다.
만약 100개가 넘는 토픽 구조체들에 공통적인 C++ 지시어(예: __attribute__((aligned(8))))를 일괄 추가해야 하거나, 모든 토픽 클래스에 print() 멤버 함수 원형을 찍어내야 한다면 어떻게 할까? 개발자는 그저 msg.h.jinja 템플릿 파일 딱 한 장을 열어 단 한 줄만 수정하면 그만이다. 다음 빌드 시, 100여 개의 C++ 파일이 새로운 규칙에 맞추어 일제히 물갈이(Re-generation)되며 완벽한 동기화를 이루게 된다.