1. 初始化嵌入式DevOps项目结构

任务目标

为嵌入式项目创建一个标准化的DevOps目录结构,将源码、构建脚本、配置文件和文档分离管理,为后续接入CI/CD流水线提供清晰、可扩展的项目骨架。

目录结构设计

embedded-devops-demo/
├── CMakeLists.txt              # 顶层CMake构建入口
├── README.md                   # 项目说明文档
├── .gitignore                  # Git忽略规则
├── .gitlab-ci.yml              # GitLab CI流水线配置(占位)
├── src/                        # 源代码目录
│   ├── CMakeLists.txt
│   ├── main.c                  # 主程序入口
│   └── led_control.c           # LED控制模块实现
├── include/                    # 公共头文件目录
│   └── led_control.h
├── config/                     # 配置文件目录
│   └── board_def.h             # 板级硬件配置宏
├── scripts/                    # 构建与辅助脚本目录
│   ├── build.sh                # 一键构建脚本
│   └── flash.sh                # 固件烧录脚本(占位)
├── docs/                       # 文档目录
│   └── architecture.md         # 架构说明文档
└── tests/                      # 测试目录(预留)
    └── CMakeLists.txt          # 测试构建配置(空壳)

关键完整代码

以下代码为最小可复现实现,覆盖从空目录到可编译二进制文件的完整闭环。

# 1. 顶层 CMakeLists.txt
cmake_minimum_required(VERSION 3.16)
project(embedded_devops_demo C)

set(CMAKE_C_STANDARD 99)
set(CMAKE_C_STANDARD_REQUIRED ON)

# 如果使用交叉编译器,通过工具链文件指定
if(CMAKE_TOOLCHAIN_FILE)
    message(STATUS "Using toolchain: ${CMAKE_TOOLCHAIN_FILE}")
endif()

# 添加子目录
add_subdirectory(src)
add_subdirectory(tests)

# 2. src/CMakeLists.txt
# 生成目标固件库
add_library(app_objs OBJECT
    main.c
    led_control.c
)
target_include_directories(app_objs PRIVATE
    ${PROJECT_SOURCE_DIR}/include
    ${PROJECT_SOURCE_DIR}/config
)

# 生成可执行文件(模拟固件,实际嵌入式可替换为生成 .hex/.bin)
add_executable(firmware.elf $<TARGET_OBJECTS:app_objs>)
target_link_libraries(firmware.elf PRIVATE app_objs)

# 3. src/main.c
#include <stdio.h>
#include "led_control.h"
#include "board_def.h"

int main(void) {
    printf("Embedded DevOps Demo v%d.%d\n", VERSION_MAJOR, VERSION_MINOR);
    led_init();
    led_set_state(LED_ON);
    printf("LED state: %s\n", led_get_state() == LED_ON ? "ON" : "OFF");
    return 0;
}

// 4. src/led_control.c
#include "led_control.h"

static led_state_t current_state = LED_OFF;

void led_init(void) {
    current_state = LED_OFF;
}

void led_set_state(led_state_t state) {
    current_state = state;
}

led_state_t led_get_state(void) {
    return current_state;
}

// 5. include/led_control.h
#ifndef LED_CONTROL_H
#define LED_CONTROL_H

typedef enum {
    LED_OFF = 0,
    LED_ON  = 1
} led_state_t;

void led_init(void);
void led_set_state(led_state_t state);
led_state_t led_get_state(void);

#endif // LED_CONTROL_H

// 6. config/board_def.h
#ifndef BOARD_DEF_H
#define BOARD_DEF_H

#define VERSION_MAJOR 1
#define VERSION_MINOR 0

// 板级硬件配置示例
#define LED_GPIO_PORT   'A'
#define LED_GPIO_PIN    5

#endif // BOARD_DEF_H

// 7. tests/CMakeLists.txt(预留测试框架,当前为空)
# 测试目录预留,后续可添加CUnit或Unity测试框架

// 8. scripts/build.sh
#!/bin/bash
# 一键构建脚本
set -e

BUILD_DIR="build"
if [ ! -d "$BUILD_DIR" ]; then
    mkdir "$BUILD_DIR"
fi

cd "$BUILD_DIR"
cmake ..
make -j$(nproc)

echo "构建完成: $(pwd)/firmware.elf"

// 9. scripts/flash.sh
#!/bin/bash
# 烧录脚本占位,实际使用时替换为openocd/st-flash等命令
echo "烧录功能待实现,请根据实际硬件配置烧录工具"

// 10. .gitignore
build/
*.o
*.elf
*.hex
*.bin

// 11. .gitlab-ci.yml(占位,后续案例填充)
stages:
  - build

build-job:
  stage: build
  script:
    - chmod +x scripts/*.sh
    - ./scripts/build.sh
  artifacts:
    paths:
      - build/firmware.elf

运行与验证

  1. 创建项目结构:按上述目录结构创建文件夹和文件,或直接复制代码块内容到对应路径。
  2. 赋予脚本执行权限:chmod +x scripts/*.sh
  3. 执行构建:./scripts/build.sh
  4. 验证通过条件:
    • 构建脚本无报错退出,退出码为0
    • 生成 build/firmware.elf 文件
    • 运行 ./build/firmware.elf,预期输出:
    Embedded DevOps Demo v1.0
    LED state: ON
    

以上输出为代码逻辑直接推出的确定性结果,非实测数据。若需交叉编译,在CMake命令中通过 -DCMAKE_TOOLCHAIN_FILE 指定工具链文件即可,当前案例以本机编译验证结构正确性。