应使用官方gcc或clang镜像(如image: gcc:12),避免裸系统镜像;CMake不指定生成器以默认Unix Makefiles为准;静态链接或显式打包依赖库确保产物可运行;GCC需-link -lstdc++fs,Clang需clang:16及以上并启用C++17标准。

GitLab CI 跑不起来 C++ 编译?先确认 clang 或 g++ 是否真在镜像里
很多构建直接失败,报 g++: command not found,不是配置写错了,是基础镜像压根没装编译器。GitLab 默认的 alpine 或 node 镜像都不带 C++ 工具链。
- 用官方
gcc镜像最省事:image: gcc:12(对应 GCC 12)或image: clang:16 - 别用
ubuntu:22.04这类裸系统镜像——你得自己apt update && apt install -y build-essential,CI 时间多花 40 秒起,还容易因源不稳定失败 - 如果必须定制镜像,确保
which g++和which cmake都能返回路径,CI job 里加一行g++ --version && cmake --version做快速验证
cmake 配置阶段总报 CMake Error: Could not create named generator
这是 cmake 版本和生成器参数不匹配的典型表现。GitLab Runner 默认没装 Ninja,但很多人盲目照抄文档写 -G Ninja,结果找不到生成器。
- 最稳方案:不指定生成器,让 CMake 自动选
Unix Makefiles(所有gcc镜像都自带make) - 想用 Ninja?先确认镜像支持:
gcc:12镜像里没有 Ninja,得手动装:apt-get update && apt-get install -y ninja-build -
cmake参数顺序很重要:-B build -S . -DCMAKE_BUILD_TYPE=Release,-B必须在-S后面,否则 CMake 会把build当作源码目录处理
构建产物怎么传出来?别只靠 artifacts 存二进制文件
artifacts 确实能存 ./build/myapp,但 CI 里生成的可执行文件常依赖动态库,直接下载到本地很可能 ./myapp: error while loading shared libraries。
- 静态链接更可靠:CMake 中加
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static"),或编译时传-DCMAKE_EXE_LINKER_FLAGS="-static" - 如果必须动态链接,用
ldd ./myapp | grep "not found"检查缺失库,再用cp把对应.so文件一起打进artifacts -
artifacts的paths不支持通配符递归,写build/*.so不会生效,得明确列出:build/myapp、build/libfoo.so
为什么本地能编译,CI 里 std::filesystem 编不过?
C++17 的 std::filesystem 在 GCC 8+ 才完整支持,但需要显式链接 -lstdc++fs;Clang 更麻烦,GCC 8+ 的 libstdc++ 有实现,但 Clang 默认用 libc++,它直到 Clang 15 才提供 std::filesystem。
立即学习“C++免费学习笔记(深入)”;
- 用 GCC 镜像时,在
target_link_libraries或编译命令末尾加-lstdc++fs - 用 Clang 镜像?换 GCC 镜像,或者升级到
clang:16并确认 CMake 设置了set(CMAKE_CXX_STANDARD 17)和set(CMAKE_CXX_STANDARD_REQUIRED ON) - 检查是否误用了
std::experimental::filesystem——它在 GCC 9+ 已被弃用,CI 镜像版本高反而会报错
CI 构建最耗时间的往往不是编译本身,而是环境不一致导致的反复试错。每次改完 .gitlab-ci.yml,先跑一次 which g++ && g++ --version && cmake --version,比盯着红色错误重试三次更省时间。









