CFS Development Part 2: Building and Running a Modular Hello World App with Core Flight System (cFS) and Conan
This guide walks you through creating a modular setup for building and running a standalone Core Flight System (cFS) application using Conan as the build and dependency manager. We’ll use a simple hello_world_app to demonstrate how to integrate with cFS and wrap up with a script to automate the entire process.
Directory Structure Overview
We’ll start with the following project layout:
CoreFlightSystem/
├── cFS/ # Core Flight System (cloned from nasa/cFS)
├── hello_world_app_1/ # Hello World Application Project
│ ├── fsw/src/ # Source files (.c and .h)
│ ├── build/ # Conan + CMake output
│ ├── CMakeLists.txt # App build definition
│ ├── conanfile.py # Conan config for building the app
│ └── run_cfs_with_hello_world.sh # Automation script
├── conan/
│ └── conanfile.py # Conan recipe for building and packaging cFSStep 1: Clone cFS
git clone https://github.com/nasa/cFS.git CoreFlightSystem/cFS
cd CoreFlightSystem/cFS
git submodule update --init --recursiveStep 2: Create Your App Directory
Inside CoreFlightSystem, create a directory for your application (e.g., hello_world_app_1). This folder can be a standalone Git repo for your app only.
Step 3: Add the Shared Conan Directory
The conan/ directory contains a Conan recipe for building cFS. This is shared across applications and only used to compile the core cFS.
Once cFS is compiled, you don’t need to recompile it unless the core cFS source changes.
Conan Setup
1. conan/conanfile.py – Packaging cFS
from conan import ConanFile
import os
class CFSConan(ConanFile):
name = "cfs"
version = "1.0"
package_type = "application"
settings = "os", "compiler", "build_type", "arch"
generators = "CMakeToolchain"
def source(self):
self.run("git clone --recurse-submodules https://github.com/nasa/cFS.git")
def build(self):
os.chdir("cFS")
self.run("make SIMULATION=native prep")
self.run("make")
def package(self):
self.copy("*.so", dst="bin/cpu1", src="cFS/build/exe/cpu1")
self.copy("core-cpu1", dst="bin/cpu1", src="cFS/build/exe/cpu1")
self.copy("*.h", dst="include", src="cFS")
self.copy("*.h", dst="include", src="cFS/psp/fsw/inc")
def package_info(self):
self.cpp_info.includedirs = [
os.path.join(self.package_folder, "include"),
os.path.join(self.package_folder, "include", "core_api"),
os.path.join(self.package_folder, "include", "osal"),
os.path.join(self.package_folder, "include", "msg"),
os.path.join(self.package_folder, "include", "psp"),
os.path.join(self.package_folder, "include", "default_cpu1")
]
self.cpp_info.libdirs = [os.path.join(self.package_folder, "bin/cpu1")]
self.cpp_info.libs = ["core-cpu1"]
Build and export the cFS package:
cd CoreFlightSystem/conan
conan create . --name=cfs --version=1.02. hello_world_app_1/conanfile.py – Hello World App
from conan import ConanFile
from conan.tools.cmake import CMake, cmake_layout
class HelloWorldApp(ConanFile):
name = "hello_world_app"
version = "1.0"
settings = "os", "compiler", "build_type", "arch"
requires = "cfs/1.0"
generators = "CMakeDeps", "CMakeToolchain"
def layout(self):
cmake_layout(self)
def build(self):
cmake = CMake(self)
cmake.configure()
cmake.build()
Build your app:
cd CoreFlightSystem/hello_world_app_1
conan install . --build=missing
conan build .Writing the Hello World App
hello_world_app.c:
#include "hello_world_app.h"
HELLO_WORLD_Data_t HELLO_WORLD_Data;
void Hello_AppMain(void)
{
HELLO_WORLD_Data.RunStatus = CFE_ES_RunStatus_APP_RUN;
OS_printf("Hello World App Initialized\n");
while (CFE_ES_RunLoop(&HELLO_WORLD_Data.RunStatus))
{
OS_printf("Hello World!\n");
OS_TaskDelay(5000);
}
}
hello_world_app.h:
#ifndef HELLO_WORLD_APP_H
#define HELLO_WORLD_APP_H
#include "cfe.h"
#include "osapi.h"
typedef struct
{
CFE_SB_PipeId_t CommandPipe;
uint32 RunStatus;
} HELLO_WORLD_Data_t;
extern HELLO_WORLD_Data_t HELLO_WORLD_Data;
void Hello_AppMain(void);
#endif
Integrating with cFS
Once the .so file is built, copy it to the cf/ directory and update the startup script:
cp build/Release/hello_world_app.so ../cFS/build/exe/cpu1/cf/Edit cfe_es_startup.scr:
CFE_APP, hello_world_app, Hello_AppMain, HELLO_WORLD_APP, 90, 16384, 0x0, 0;
Then run cFS:
cd ../cFS/build/exe/cpu1
sudo ./core-cpu1Expected output:
Hello World App Initialized
Hello World!Automating with run_cfs_with_hello_world.sh
#!/bin/bash
PROJECT_ROOT="$(pwd)"
BUILD_DIR="${PROJECT_ROOT}/build"
CF_DIR="${PROJECT_ROOT}/../cFS/build/exe/cpu1/cf"
SCR_FILE="${CF_DIR}/cfe_es_startup.scr"
APP_LIB="hello_world_app.so"
APP_SRC_LIB="${BUILD_DIR}/Release/${APP_LIB}"
APP_ENTRY="CFE_APP, hello_world_app, Hello_AppMain, HELLO_WORLD_APP, 90, 16384, 0x0, 0;"
CFS_EXECUTABLE="${PROJECT_ROOT}/../cFS/build/exe/cpu1/core-cpu1"
echo "==> Cleaning old build..."
rm -rf "${BUILD_DIR}"
echo "==> Running Conan install..."
conan install . --profile=default --build=missing || exit 1
echo "==> Running Conan build..."
conan build . || exit 1
echo "==> Copying ${APP_LIB} to ${CF_DIR}..."
cp "${APP_SRC_LIB}" "${CF_DIR}/" || exit 1
echo "==> Updating startup script..."
if ! grep -q "CFE_APP, hello_world_app," "${SCR_FILE}"; then
echo "${APP_ENTRY}" >> "${SCR_FILE}"
echo "Added hello_world_app entry."
else
echo "Entry already exists."
fi
echo "==> Starting cFS..."
cd "$(dirname "${CFS_EXECUTABLE}")" && sudo ./core-cpu1
Make it executable:
chmod +x run_cfs_with_hello_world.shRun with:
./run_cfs_with_hello_world.shThis video walks through the full process of compiling and running a standalone Core Flight System (cFS) application using Conan and CMake. I run the application with the output of “Hello World!” and then I edit and quickly compile and run “Hello World 2!” to show how the application is edited, compiled and run independently. It shows:
The demo confirms successful integration by displaying “Hello World!” messages from within the running cFS environment.

