如何跑起来一个大型C++项目

6 min

须知

0. 后缀介绍

  • 常见的 C/C++ 源代码文件后缀的科普说明:
    • 源代码文件后缀:.c(C语言)、.cpp(C++)、.cc(C++)、.h(头文件)等。

    • 目标文件后缀:.o(Unix)、.obj(Windows)。

    • 库文件后缀:.a(静态库,Unix)、.so(共享库,Unix)、.dll(共享库,Windows)、.lib(静态库,Windows)。

    • 可执行文件后缀:.exe(Windows)、.out(Linux)。

    • 脚本和配置文件后缀:.make.mk.cmake

      • Makefile.txt.make.mk 本质上是等价的,都可以用于 make 构建系统,只是文件命名不同。
      • make 工具能读取这些文件格式

1. 相关工具

  • C++ 项目要跑起来,需要把源码编译,链接等过程。cmke 工具开源统一调度编译,链接过程需要用的工具链。

    • 编译( .c -> .obj

      • gcc(c),g++(c++),clang(现代编译器)
    • 链接(.obj -> .exe

      如果在Windows下

      • gcc(c),g++(c++),clang(这仨也可做链接器)
    • 运行

  • cmake

    • 前世今生

      • 编译器,链接器,这些是工具,本身只负责具体的功能。

      • 当项目中有几百个需要的g++ -c main.cpp -o main.o,类似的命令,有个脚本就十分重要了。

      • 写一个 Makefile 文件脚本。

        MyApp: main.o example.o
        	g++ main.o example.o -o MyApp
        
        main.o: main.cpp
        	g++ -c main.cpp -o main.o
        
        example.o: example.cpp
        	g++ -c example.cpp -o example.o
      • 但是缺点是:在不同平台,Makefile 都不一样。每次重写,太不方便了。

      • 所以有了 cmake

        • 跨平台的构建工具生成器

          • makeninja 是构建工具
            • ninjaMake 构建更快
            • 构建工具使用的编译器等等可以在 cmake 的配置文件中写
        • 可以生成构建文件

          • 适用于 makemakefile
          • 或适用于 ninjabuild.ninja
    • cmake 的配置—— cmakefile

      • 基本构成
        • 项目声明
        • 编译器设置
        • 源文件和目标文件定义
        • 依赖库的查找和链接
        • 安装规则
        • 测试和其他构建选项

2. 构建流程

2.1 单文件编译

  1. 使用 GCC/G++ 或 Clang/Clang++:

    gcc main.c -o main   # C 编译
    g++ main.cpp -o main # C++ 编译
    clang main.c -o main # 使用 Clang 编译 C
    clang++ main.cpp -o main # 使用 Clang 编译 C++

2.2 复杂项目编译

  1. 编写 CMakeLists.txt文件

    cmake_minimum_required(VERSION 3.10)
    project(MyProject)
    
    set(CMAKE_CXX_COMPILER g++)
    add_executable(MyApp main.cpp example.cpp)

    • cmake

      • 默认指定 make 构建工具

        • 生成 makefile 文件

          自动读取当前目录下的 CMakeLists.txt

          cmake .
          • cmake -S <source-dir> -B <build-dir> [options]
            • eg. : cmake -S . -B build
        • make 构建项目:

          直接运行当前文件夹下的 Makefile 文件

          make
      • 手动指定 Ninja 构建工具

        • 生成 build.ninja 文件

          cmake -G "Ninja" .

          make 一样,你也可以将源目录和构建目录分开来管理,使用 -S-B

          cmake -S . -B build -G "Ninja"
        • ninja 构建项目

          使用 ninja 命令来执行 build.ninja 文件进行构建。Ninja 会自动并行化构建过程,通常比 make 更高效。

          ninja
      • make install

        • 此命令会把 make 构建的二进制文件(在././build),移动到系统目录,如 /usr/local/bin/usr/local/lib/usr/local/include 等,这些目录是系统默认的查找路径。
        • 好处是可以不用手动设置环境变量

    • xmake

    • 优点

      • 不需要像 cmake 一样指定构建工具,生成完构建工具配置文件还要手动输入 make/ ninja
      • 只需要编写 xmake.lua ,直接 xmake 即可
    • 指南

      • 配置 xmake.lua 文件

        -- 定义项目名称
        set_project("my_project")
        
        -- 设置语言
        set_languages("c++20")
        
        -- 添加源文件
        target("my_project")
            set_kind("binary")  -- 目标类型(binary, static, shared等)
            add_files("src/*.cpp")  -- 添加源文件
            add_includedirs("include")  -- 添加头文件目录
        
      • 构建可执行文件

        • xmake
      • 运行文件

        • xmake run
      • 清理构建文件

        • xmake clean

3. 调试和测试工具

调试工具

  1. GDB(GNU 调试器)

    gdb ./main

4. 依赖管理

外部库管理

  • vcpkg

    • 下载配置

      • GitHub 安装

      • 配置环境变量

        export VCPKG_ROOT=/home/jexi/opt/vcpkg 
        export PATH=$PATH:/home/jexi/opt/vcpkg 
    • 安装第三方库

      ./vcpkg install xxx
      • 会被安装在 /home/jexi/opt/vcpkg/installed
    • cmakexmake 的调用

      • cmake

        • 操作

          • 查找库
          • 链接库
        • CMakeLists.txt 中配置

          # 最小CMake版本要求
          cmake_minimum_required(VERSION 3.15)
          
          # 项目名称
          project(MyProject)
          
          # 如果没有指定工具链文件,使用 vcpkg 的工具链文件
          if(NOT DEFINED CMAKE_TOOLCHAIN_FILE)
              set(CMAKE_TOOLCHAIN_FILE "$ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" CACHE STRING "vcpkg toolchain file" FORCE)
          endif()
          
          # 指定C++标准
          set(CMAKE_CXX_STANDARD 17)
          set(CMAKE_CXX_STANDARD_REQUIRED ON)
          
          # 查找Boost库
          find_package(Boost REQUIRED)
          
          # 添加可执行文件
          add_executable(myapp src/main.cpp)
          
          # 将Boost库链接到目标
          target_link_libraries(myapp Boost::Boost)
          
        • 后续正常 cmake .make

      • xmake

        • 操作

          • 表明 require
          • 加入包 链接
        • xmake.lua 中配置

          -- 指定 vcpkg 的路径
          set_toolchain("vcpkg", "/home/jexi/opt/vcpkg ")
          
          -- 或者使用环境变量配置
          -- set_toolchain("vcpkg", os.getenv("VCPKG_ROOT"))
          
          -- 添加需要的包
          add_requires("boost")
          
          -- 设置目标
          target("myapp")
              set_kind("binary")
              add_files("src/*.cpp")
              add_packages("boost")
        • 之后直接执行 xmake 就可以


5. 编译优化与分析工具

优化选项

  • -O0:无优化(默认)。
  • -O2:较高优化。
  • -O3:最高优化。
  • -g:生成调试信息。
  • -march=native:为本地 CPU 优化。

性能分析

  1. gprof

    g++ -pg main.cpp -o main
    ./main
    gprof ./main gmon.out
  2. perf

    perf record ./main
    perf report

参考资料