今天會學到的
30 天走到這裡,我們已經學了:
今天就把這些全部串起來,實際做一次完整專案實戰:
從寫程式、建置、測試、打包、安裝,到 CI/CD 自動化。
步驟
C_final_proj/
├─ inc/
│  └─ dog_meme.h
├─ src/
│  ├─ dog_meme.c
│  └─ main.c
├─ tests/
│  └─ test_dog.c
├─ CMakeLists.txt
└─ CMakePresets.json
#pragma once
int dog_add(int a, int b);
#include "dog_meme.h"
int dog_add(int a, int b) {
    return a + b;
}
#include <stdio.h>
#include "dog_meme.h"
int main() {
    int result = dog_add(2, 40);
    printf("dog_add(2,40) = %d\n", result);
    return 0;
}
#include <assert.h>
#include "dog_meme.h"
int main() {
    assert(dog_add(2, 40) == 42);
    return 0;
}
cmake_minimum_required(VERSION 3.21)
project(C_FINAL_PROJ VERSION 1.0.0 LANGUAGES C)
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# 建立靜態函式庫
add_library(dog_meme STATIC src/dog_meme.c)
target_include_directories(dog_meme PUBLIC ${CMAKE_SOURCE_DIR}/inc)
# 建立執行檔
add_executable(app src/main.c)
target_link_libraries(app PRIVATE dog_meme)
target_compile_options(app PRIVATE -Wall -Wextra -Wpedantic)
target_compile_definitions(app PRIVATE APP_VERSION="1.0.0")
# 測試
include(CTest)
enable_testing()
add_executable(test_dog tests/test_dog.c)
target_link_libraries(test_dog PRIVATE dog_meme)
add_test(NAME dog_meme_add_test COMMAND test_dog)
# 安裝與打包
install(TARGETS app RUNTIME DESTINATION bin)
install(DIRECTORY inc/ DESTINATION include)
include(CPack)
set(CPACK_PACKAGE_NAME "dog_meme_proj")
set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION})
set(CPACK_GENERATOR "TGZ")
{
  "version": 6,
  "configurePresets": [
    {
      "name": "debug-ninja",
      "generator": "Ninja",
      "binaryDir": "${sourceDir}/build/debug",
      "cacheVariables": {
        "CMAKE_BUILD_TYPE": "Debug",
        "CMAKE_EXPORT_COMPILE_COMMANDS": "ON"
      }
    },
    {
      "name": "release-ninja",
      "generator": "Ninja",
      "binaryDir": "${sourceDir}/build/release",
      "cacheVariables": {
        "CMAKE_BUILD_TYPE": "Release"
      }
    },
    {
      "name": "asan",
      "inherits": "debug-ninja",
      "cacheVariables": {
        "CMAKE_C_FLAGS": "-fsanitize=address -g",
        "CMAKE_CXX_FLAGS": "-fsanitize=address -g"
      }
    }
  ],
  "buildPresets": [
    { "name": "debug", "configurePreset": "debug-ninja", "jobs": 8 },
    { "name": "release", "configurePreset": "release-ninja", "jobs": 8 },
    { "name": "asan", "configurePreset": "asan", "jobs": 8 }
  ],
  "testPresets": [
    { "name": "ctest-debug", "configurePreset": "debug-ninja", "output": { "outputOnFailure": true } }
  ]
}
cmake --preset debug-ninja
cmake --build --preset debug
ctest --preset ctest-debug --output-on-failure
cpack --config build/debug/CPackConfig.cmake
cmake --install build/debug --prefix ./dist
安裝後的結構:
dist/
├─ bin/app
└─ include/dog_meme.h
.github/workflows/cmake.yml
name: CMake CI
on: [push, pull_request]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Configure
        run: cmake --preset release-ninja
      - name: Build
        run: cmake --build --preset release
      - name: Test
        run: ctest --preset ctest-debug --output-on-failure
      - name: Package
        run: cpack --config build/release/CPackConfig.cmake
小結
到這裡,挖已經30天的,真是辛苦大家也辛苦自己了!
在這30天的鐵人中,我們總共學會