当前位置: 首页 > news >正文

ubuntu 构建c++ 项目 (AI 生成)

将在 Windows 上使用 Visual Studio 解决方案(Solution)和项目(Project)构建的复杂 C++ 应用,迁移到 Ubuntu 上是一个典型的跨平台开发场景。你提到的结构(多个库项目、一个可执行文件项目、库之间的依赖、公共头文件目录)是大型项目的标准实践。

在 Linux/Ubuntu 环境下,我们有对应的概念和更强大的工具来处理这种复杂性。核心思想是使用 构建系统生成器 (Build System Generator),其中最主流、最强大的就是 CMake。

忘记手动调用 g++ 吧,对于大型项目,那是不可行的。我们需要一个能描述项目结构、依赖关系、编译选项的工具,然后让这个工具自动生成用于编译的指令(比如 Makefile)。这正是 Visual Studio 在后台为你做的事情,而在 Linux 上,我们使用 CMake 来明确地完成这个任务。

下面,我将为你分解这个过程。

核心概念的对应关系

首先,我们来理解一下 Windows 和 Ubuntu 在概念上的对应:

Windows (Visual Studio)Ubuntu/Linux (GCC/CMake)解释
解决方案 (.sln)根 CMakeLists.txt 文件整个软件的顶层描述,管理所有子项目。
目 (.vcxproj)子目录的 CMakeLists.txt 文件
静态库 (.lib)静态库 (.a)a 代表 “archive”。编译时,库的代码被完整地复制到最终的可执行文件中。
动态链接库 (.dll)共享库 (.so)so 代表 “shared object”。运行时,多个程序可以共享同一个库文件,减小体积。
项目依赖关系target_link_libraries在 CMake 中明确指定一个目标(如你的exe)需要链接哪些库(a, b, c)。
附加包含目录target_include_directories告诉编译器去哪里寻找 #include 的头文件。
编译和链接make (由 CMake 生成)执行实际的编译和链接命令。

迁移步骤与项目结构

假设你在 Windows 上的项目结构如下:

MySolution/
├── common_includes/ # 公共头文件
│ └── public_header.h
├── lib_a/ # 库 a
│ ├── a.h
│ └── a.cpp
├── lib_b/ # 库 b (可能依赖 lib_a)
│ ├── b.h
│ └── b.cpp
└── my_app/ # 最终的 exe 项目
└── main.cpp

迁移到 Ubuntu 并使用 CMake 构建,我们会创建一个类似的目录结构,并在关键位置添加 CMakeLists.txt 文件。

推荐的 Ubuntu/CMake 项目结构:

my_project/
├── CMakeLists.txt          # [1] 顶层 CMake 文件
├── common_includes/
│   └── public_header.h
├── lib_a/
│   ├── CMakeLists.txt      # [2] 库 a 的 CMake 文件
│   ├── a.h
│   └── a.cpp
├── lib_b/
│   ├── CMakeLists.txt      # [3] 库 b 的 CMake 文件
│   ├── b.h
│   └── b.cpp
└── app/├── CMakeLists.txt      # [4] 可执行文件的 CMake 文件└── main.cpp

如何编写 CMakeLists.txt

CMakeLists.txt 是一个纯文本文件,使用 CMake 的特定语法来描述构建过程。

  1. 顶层 CMakeLists.txt

这个文件是整个项目的入口,负责设置项目基本信息,并告诉 CMake 去哪些子目录寻找其他的 CMakeLists.txt。

CMake# my_project/CMakeLists.txt# 要求 CMake 的最低版本
cmake_minimum_required(VERSION 3.10)# 定义项目名称
project(MyAwesomeProject VERSION 1.0)# 设置 C++ 标准
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)# 将公共头文件目录添加到全局的包含路径中
# 这样所有子项目都能找到 common_includes 里的头文件
include_directories(common_includes)# 告诉 CMake 去处理这些子目录
add_subdirectory(lib_a)
add_subdirectory(lib_b)
add_subdirectory(app)
  1. lib_a 的 CMakeLists.txt

这个文件定义如何构建库 a。我们把它建成一个共享库 (.so)。

CMake# my_project/lib_a/CMakeLists.txt# add_library 命令用于创建一个库
# a_lib 是我们给这个库起的名字
# SHARED 表示创建共享库 (.so)。如果想创建静态库,用 STATIC (.a)
# a.cpp 是构建这个库所需的源文件
add_library(a_lib SHARED a.cpp)# 如果 a.h 在当前目录,通常需要将当前目录也加入到
# a_lib 这个目标的 "public" 包含路径中。
# 这样,任何链接到 a_lib 的项目都能自动找到 a.h。
target_include_directories(a_lib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
  1. lib_b 的 CMakeLists.txt

这个文件定义了库 b。关键在于,库 b 依赖库 a。

CMake# my_project/lib_b/CMakeLists.txt# 创建库 b
add_library(b_lib SHARED b.cpp)# 将当前目录设为 b_lib 的 public 包含路径
target_include_directories(b_lib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})# *** 这是关键:声明依赖关系 ***
# target_link_libraries 告诉 CMake,b_lib 需要链接到 a_lib。
# CMake 会自动处理链接顺序和头文件路径。
target_link_libraries(b_lib PUBLIC a_lib)

PUBLIC vs PRIVATE: target_link_libraries 中的 PUBLIC 关键字很重要。它意味着:不仅 b_lib 自己需要链接 a_lib,任何链接到 b_lib 的目标(比如我们后面的可执行文件)也需要链接到 a_lib。这完美地处理了依赖传递。

  1. app (可执行文件) 的 CMakeLists.txt

最后,这个文件定义了如何构建最终的可执行文件,并链接它所需要的所有库。

CMake# my_project/app/CMakeLists.txt# add_executable 用于创建一个可执行文件
# my_app 是可执行文件的名字
# main.cpp 是所需的源文件
add_executable(my_app main.cpp)# *** 链接所有需要的库 ***
# 我们的 my_app 需要库 a 和库 b 的功能。
# 因为库 b 公开地依赖库 a,理论上我们只需要链接库 b 即可。
# 但为了清晰,可以都写上。CMake 很聪明,不会重复链接。
target_link_libraries(my_app PRIVATE b_lib)

编译整个项目的流程

在你配置好所有的 CMakeLists.txt 文件后,编译整个大型项目只需要几个简单的命令。

创建一个构建目录: 这是一个非常好的习惯,叫做“外部构建”(out-of-source build)。它将所有编译生成的文件(Makefile, .o 文件, .so 文件, 可执行文件)与你的源代码隔离开,保持源代码目录的干净。

    Bashcd my_project
mkdir build
cd build

运行 CMake: 在 build 目录下,运行 cmake 并指向源代码的根目录(… 代表上一级目录)。CMake 会读取你所有的 CMakeLists.txt 文件,并生成原生的构建文件(在 Linux 上默认是 Makefile)。

Bashcmake ..

如果一切顺利,CMake 会检查你的编译器和环境,并输出配置完成的信息。

运行 make: 现在,build 目录里有了一个 Makefile。你只需要运行 make 命令,它就会根据 Makefile 里的规则,以正确的顺序编译和链接所有的库和可执行文件。

Bashmake

make 会自动处理依赖。如果你只修改了 lib_b 的代码,make 只会重新编译 lib_b 和最终的 app,而不会去动 lib_a,非常高效。

运行你的程序: 编译完成后,你的可执行文件 my_app 和库文件 liba_lib.so, libb_lib.so 都会在 build 目录的相应子文件夹里。
你可以在 build/app 目录下找到你的可执行文件并运行它。

Bash./app/my_app

总结

将一个大型的、多项目的 Windows C++ 解决方案迁移到 Ubuntu,关键在于从 Visual Studio 的思维模式转换到 CMake 的思维模式。

  1. 核心工具: 使用 CMake 替代 Visual Studio 的解决方案和项目文件来描述项目结构和依赖。

  2. 项目结构: 保持清晰的目录结构,每个目标(库/可执行文件)在自己的目录里,并拥有一个 CMakeLists.txt。

  3. 描述依赖:

    • 使用 add_library() 定义库。

    • 使用 add_executable() 定义可执行文件。

    • 使用 target_link_libraries() 定义目标之间的依赖关系。

    • 使用 include_directories() 或 target_include_directories() 管理头文件路径。

  4. 编译流程: mkdir build && cd build, cmake …, make。这个三步曲是 Linux 下用 CMake 构建项目的黄金准则。

这个工作流不仅适用于 Ubuntu,也适用于 macOS 甚至 Windows(CMake 可以在 Windows 上生成 Visual Studio 的 .sln 文件!),是现代 C++ 跨平台开发的事实标准。

http://www.dtcms.com/a/346273.html

相关文章:

  • uboot添加ping命令的响应处理
  • Flowise 任意文件上传漏洞 含Flowise Docker安装、漏洞复现(CVE-2025-26319)
  • 【python】python进阶——推导式
  • 深入理解 Java IO 流 —— 从入门到实战
  • 力扣(在排序数组中查找元素的第一个和最后一个位置)
  • Codeforces 更换
  • 零知开源——基于ESP8266(ESP-12F)驱动YS-IR05F红外控制空调
  • SRE系列(二) | 从可用性到 SLI/SLO
  • nginx-限速-限制并发连接数-限制请求数
  • 洛谷 P3811 【模板】模意义下的乘法逆元-普及/提高-
  • html基本元素
  • 嵌入式第三十五天(网络编程(UDP))
  • 特大桥施工绳断 7 人亡:索力实时监测预警机制亟待完善
  • STM32F1 EXTI介绍及应用
  • tiktok滑块反爬分析verifyV2
  • Linux设备模型技术路线图
  • B树,B+树,B*树
  • Codeforces Round 1043 (Div. 3)
  • set_case_analysis应用举例
  • 技术里常说 没有银弹
  • 纳米软件自动化测试平台ATECLOUD产品手册之一——系统介绍
  • 声网如何让AI理解画面、情绪和你说的话
  • 【资源分享】(影视相关)
  • Claude Code 三类.md文件
  • Java 18 新特性及具体应用
  • WMS选型攻略:钱该省在哪?部署怎么定?
  • openEuler系统安装Ascend Docker Runtime的方法
  • open webui源码分析7—过滤器
  • 劳务工队:建筑工程的基石力量,行业生态的多元拼图
  • RKLLM 模型转换从0开始