본문으로 건너뛰기

CMake로 빌드하기

PARA 애플리케이션은 SDK가 제공하는 CMake 모듈(share/cmake/Modules/PARA/Para.cmake)을 통해 빌드합니다. 이 모듈은 PARA 버전·표준·설치 규칙을 설정하고, 애플리케이션이 Functional Cluster를 손쉽게 링크하도록 헬퍼 매크로를 제공합니다.

1) SDK 부트스트랩

프로젝트는 SDK 위치(PARA_SDK)를 잡고 PARA CMake 모듈을 불러오는 작은 부트스트랩으로 시작합니다. 예제 Machine은 share/examples/Machine/cmake/ParaSdk.cmake를 사용하며, 그 내용은 다음과 같습니다.

macro(ParaSdk_Init)
# 환경변수 PARA_SDK를 캐시 변수로 승격
if ((NOT DEFINED PARA_SDK OR PARA_SDK STREQUAL "") AND (NOT "$ENV{PARA_SDK}" STREQUAL ""))
set(PARA_SDK "$ENV{PARA_SDK}" CACHE PATH "PARA SDK location" FORCE)
endif()

if (NOT DEFINED PARA_SDK OR PARA_SDK STREQUAL "")
message(FATAL_ERROR "[PARA] ERROR: The variable 'PARA_SDK' is not set")
elseif (NOT EXISTS "${PARA_SDK}")
unset(PARA_SDK CACHE)
message(FATAL_ERROR "[PARA] ERROR: The variable 'PARA_SDK' has invalid path")
endif()

list(APPEND CMAKE_MODULE_PATH ${PARA_SDK}/share/cmake/Modules)
include(PARA/Para)
endmacro()

ParaSdk_Init()

PARA_SDK환경 설정 스크립트가 설정하므로, 먼저 . ./para-env-setup.sh를 소싱해 두면 됩니다. 마지막의 include(PARA/Para)가 SDK의 Para.cmake 모듈을 불러오며, 내부에서 Para_Init()을 호출합니다.

2) 애플리케이션 정의

애플리케이션의 최상위 CMakeLists.txt는 앱 메타데이터를 정하고 Para_App()을 호출합니다. 다음은 예제 share/examples/Machine/apps/HelloWorld/CMakeLists.txt입니다.

set(PARA_APP_NAME HelloWorld)
set(PARA_APP_EXECUTABLE HelloWorld)
set(PARA_APP_VERSION 1.0.0)
set(PARA_APP_GEN_DIR ${CMAKE_CURRENT_SOURCE_DIR})

Para_App()

project(${PARA_APP_NAME}
VERSION ${PARA_APP_VERSION}
LANGUAGES CXX)

add_subdirectory(src)

Para_App()은 설치 경로를 opt/<PARA_APP_NAME>/(즉 bin/lib/etc/var)로 정하고, 앱의 매니페스트(PARA_APP_GEN_DIR/manifest)를 etc/로 설치합니다. 이렇게 opt/<PARA_APP_NAME>/ 아래에 배포 단위 구조가 만들어집니다.

3) 타깃 구성과 클러스터 링크

실제 실행 파일은 add_executable()로 만들고 Para_Target()으로 구성합니다. 예제 apps/HelloWorld/src/CMakeLists.txt는 다음과 같습니다.

add_executable(${PARA_APP_NAME})

Para_Target(${PARA_APP_NAME}
PARA_GEN_DIR ${PARA_APP_GEN_DIR}
PARA_LIBS_PRIVATE core exec log
OUTPUT_NAME ${PARA_APP_EXECUTABLE}
)

target_sources(${PARA_APP_NAME}
PRIVATE
main.cpp
)

Para_Target()의 주요 인자는 다음과 같습니다.

인자의미
PARA_LIBS_PUBLIC / PARA_LIBS_PRIVATE링크할 Functional Cluster 목록. 각 항목 <lib>에 대해 find_package(para-<lib> REQUIRED)para::<lib>로 링크합니다(예: corepara::core).
PARA_GEN_DIR생성된 헤더/IDL(매니페스트·DDS IDL 등)이 위치한 디렉토리. 인클루드 경로와 설치 규칙에 사용됩니다.
OUTPUT_NAME산출 실행 파일 이름

위 예제는 core exec log를 링크합니다. 즉 빌드 후 이 앱은 para::core·para::exec·para::log에 의존합니다. 통신을 사용한다면 com을 추가합니다.

4) 최소 애플리케이션 코드

예제 apps/HelloWorld/src/main.cpp는 PARA 애플리케이션의 표준 골격을 보여 줍니다 — ara::core 초기화, ara::log 로거 생성, ara::exec::ExecutionClient로 실행 상태 보고.

#include "ara/core/initialization.h"
#include "ara/exec/execution_client.h"
#include "ara/log/logger.h"

static std::atomic<bool> g_running{true};

int main(int argc, char* argv[])
{
ara::core::Initialize(argc, argv);

auto& logger = ara::log::CreateLogger("MAIN", "HelloWorld Main Context",
ara::log::LogLevel::kDebug);

// 종료 핸들러: EM이 보내는 SIGTERM에 graceful 대응
auto terminationHandler = [&logger]() {
logger.LogWarn() << "SIGTERM received — shutting down";
g_running = false;
};

auto clientResult = ara::exec::ExecutionClient::Create(terminationHandler);
if (!clientResult.HasValue()) {
logger.LogError() << "Failed to create ExecutionClient";
return 1;
}
auto client = std::move(clientResult).Value();

// 실행 상태를 EM에 보고: kRunning
auto reportResult = client.ReportExecutionState(ara::exec::ExecutionState::kRunning);
if (!reportResult.HasValue()) {
logger.LogError() << "Failed to ReportExecutionState";
return 1;
}

int32_t count = 0;
while (g_running) {
logger.LogInfo() << "Hello, World! (" << count << ")";
++count;
std::this_thread::sleep_for(std::chrono::seconds(1));
}

ara::core::Deinitialize();
return 0;
}

위 코드는 예제 main.cpp를 핵심 흐름 중심으로 옮긴 것입니다(원본은 HELLO_WORLD_VERBOSE 환경변수로 로그 출력을 제어합니다). ExecutionClient::Create()ReportExecutionState()가 모두 ara::core::Result를 반환하여 HasValue()/Value()로 결과를 다루는 점에 주목하세요 — 이는 PARA 전반의 오류 처리 패턴입니다(API 레퍼런스 참조).

5) 빌드 실행

예제 Machine 전체를 빌드하는 흐름은 다음과 같습니다.

# 1. SDK 환경 구성 (PARA_SDK 등 설정)
cd /path/to/para-sdk
. ./para-env-setup.sh

# 2. 예제 Machine 빌드
cd share/examples/Machine
cmake -S . -B build
cmake --build build

6) 빌드한 앱 실행

빌드 산출물은 PARA 런타임(EM) 위에서 실행합니다. Para_Init()은 설치 시 실행 래퍼 para-exec.sh를 생성하는데, 이 스크립트는 PARA_CONF/PARA_DATA/PARA_APPL을 설치 위치로 잡은 뒤 EM을 실행합니다. CMAKE_INSTALL_PREFIX를 따로 지정하지 않으면 Para.cmake가 설치 위치를 build/install로 기본 설정합니다.

# 빌드 결과 설치 (기본 설치 위치: build/install)
cmake --install build

# 설치 디렉토리에서 런타임 실행 (생성된 래퍼)
cd build/install
./para-exec.sh

EM이 기동되면 런타임 동작 모델대로 MachineFGStartup으로 전환되고, 각 앱의 매니페스트 state-dependencies에 따라 프로세스가 fork됩니다. 출력 로그는 para-tui로 확인합니다(SDK에는 dlt-daemon만 포함되며, DLT 도구를 별도로 설치했다면 dlt-receive도 사용할 수 있습니다).