找回密码
 立即注册
首页 业界区 业界 C++服务开发环境-万事开头难

C++服务开发环境-万事开头难

湄圳啸 2025-6-28 17:15:56
C++服务开发环境-万事开头难

对于开发人员来说,仅仅学习编程语言的语法是不够的,还需要学习这门编程语言对应的构建流程,不然写出来的代码怎么变成程序运行起来呢?
出生较晚的编程语言,如golang、python等,都有对开发者友好的构建工具链,golang开发者仅仅需要花少量时间就能学会go mod和go build,很方便的将源码打包成程序拿去运行。
而出身于40多年前的C/C++语言,构建工具的学习成本并不低,而且一直在更新换代。
今天主要介绍一套适合C++服务端开发者在自己个人电脑上愉快开发和测试的方法。如果你需要创建一个伟大的C++服务端项目,也可以参考这个方法。
C/C++编译和构建原理

当你创建了一个cpp源码文件时,这个文件在构建过程中,处于什么位置呢?
1.png

每个源代码文件都会被编译成一个.o结尾的目标文件,如果这个文件有main函数,则可以链接成可执行程序;没有main函数的话可以打包成静态库或者动态库,供别人的可执行程序使用。
1个.cpp文件对应1个.o文件,.h文件的内容会被include到.cpp中,所以.h可以看作不在编译过程中
多个没有main函数的.o文件,可以打包成一个静态库,也可以打包成一个动态库。
一个有main函数的.o文件,可以拿一些.o、.a、.so文件过来一起打包成一个可执行程序。
相关工具参考:
工具/概念作用说明g++ / clang++编译器,负责从 .cpp 编译成 .o 或链接为可执行文件ld链接器,负责将多个 .o 文件链接为可执行文件或库as汇编器,把 .s 文件转为 .o(有时作为中间步骤)nm查看 .o、.a、.so 文件中的符号(函数/变量名)objdump反汇编/查看二进制结构readelf查看 ELF 文件结构(更偏底层)strip去除调试符号,减小体积ar构建 .a 静态库(archive)ldd查看 ELF 的动态依赖库file查看文件类型,比如是不是 ELFelfutils一套处理 ELF 和 DWARF 调试信息的工具集传统C++开发环境和依赖安装

假设你的项目中有2个cpp文件,其中一个有main函数,则构建打包时是这样的流程。如果你使用系统库/第三方库选择的是release静态链接,则会把.a文件里相关的.o全都拷贝到app中,这样编译出来的app文件占用硬盘空间较大一点。
2.png

而如果libcaaa你选择的是.so链接方式,则.so中的.o文件不会拷贝到app中,而是app启动时系统才去指定的目录加载.so文件一起运行,如果运行app时找不到.so文件,app就无法启动。这样打包的app,由于没有拷贝.so的内容进来,所以没有用.a链接的app占硬盘空间。
3.png

共享链接的好处是如果有10个不同的app使用了同一个.so,那同时运行这10个app就仅需要在内存里加载1份.so文件。现代计算机的内存、硬盘空间便宜、性能好,所以大多数时候会选择静态链接,而很少使用共享链接。
当然,如果你的项目中没有main函数,而是写一些库给别人用。那就不会去链接系统库,而是直接将.o文件打包成.a和.so,供别的项目使用。
系统库/第三方库的来源:

  • apt/yum安装
  • 自动手动编译源码并拷贝到系统库目录
docker和WSL2介绍

在个人学习C++或者在自己电脑上开发C++服务端程序时,经常遇到一些问题:
自己的电脑是windows系统,没法编译和运行linux系统的程序,我尝试过的解决办法有:

  • 额外购买一台二手电脑装linux开发用;
  • 租用linux云服务器,远程开发,最低配置的50元左右一个月;
  • 自己的电脑装双系统,玩游戏时启windows,开发时启动linux;
  • 在windows上安装vmware虚拟化软件,通过虚拟机运行Linux;
  • 使用windows WSL1的ubuntu做开发;
上述方法都不是很灵活,但的确是我以前使用过的一些方法。
而现在有了一个更好的方案,就是docker,启动一个docker容器,在容器里面安装ubuntu环境,然后在这个ubuntu环境中进行开发。一般为每个C++项目创建一个docker环境。互不干扰,不同担心不同项目使用了不同版本的系统库。
但是docker是共享宿主机内核的,在windows系统上怎么能跑Linux的容器呢?答案是windows提供了WSL2机制,该机制相当于在windows内核中运行了一个linux内核。windows系统打开WSL2功能后,你的电脑就同时在运行windows和linux内核。有了这个linux内核,自然可以基于它来运行ubuntu环境的容器。
现在,当你在windows上安装docker desktop时,docker desktop默认就使用WSL2的linux内核来运行容器。
4.png

WSL2提供的linux内核对比vmware提供的linux内核有什么区别呢?
5.png

WSL提供的linux内核跟宿主机windows又更高的融合和共享能力,有更低的性能损耗。方便、高效的共享CPU/GPU/网络/硬盘等资源。并成为了docker和vscode的默认选择。不得不说微软考虑的还是很全面的。
而开发者需要做的,就是在自己电脑上打开WSL2功能(打开就会自动运行linux子系统了);在自己电脑上安装docker desktop,然后使用docker创建容器,容器默认就会运行在WSL的linux内核上。
6.png

这样,开发者即可通过vscode等IDE连接到容器中进行linux服务开发。同理,也可以在docker中运行mysql服务、redis服务、nginx服务、大语言模型等镜像,把部署中间件的工作也省了。
现代C++项目构建流程的栗子

接下来以一个C++开源项目举个实际的栗子,
这是一个linux上的高性能C++网络框架:https://github.com/scylladb/seastar,项目的README.md是这样写的:
7.png

第一步,运行install-dependencies.sh安装第三方依赖库,也就是前面说的那些.a和.so文件;
第二步,运行configure.py来生成build.ninja(类似makefile);
第三步,运行ninja(类似make,会调用gcc和ld等工具)进行编译;
如何在我的windows电脑编译运行它呢?
1.首先下载安装docker desktop:https://www.docker.com/products/docker-desktop/
安装docker-desktop过程中会打开windows的WSL2,当然你也可以手动打开WSL2:wsl.exe --update (注意,这一步可能出现各种网络失败,需要梯子)
2.下载seastar项目源码:git clone https://github.com/scylladb/seastar.git
3.可以看到,seastar项目提供了一个docker镜像用来进行编译,将seastar提供的dockerfile拷贝到根目录,并在根目录运行"docker build -t seastar-dev ."来构建docker镜像
8.png

4.镜像生成后,运行容器:
  1. docker run -it seastar-dev /bin/bash
复制代码
5.可以通过vscode或者docker-desktop界面,attach到该容器的shell中,在容器里下载seastar项目源码。
  1. apt update
  2. apt install git
  3. git clone https://github.com/scylladb/seastar.git # 在容器中下载seastar项目代码
  4. cd seastar # 进入项目
  5. # ./install-dependencies.sh # 由于docker build时运行过安装依赖脚本了,这里不用再运行了
  6. ./configure.py --mode=release # 生成build.ninja文件
  7. ninja -C build/release -j 4 # 4线程并发编译,产物生成到./build/release目录
复制代码
6.debug: 运行configure.py时报错:seastar里面一个小工具程序依赖的libc-ares-dev版本不对,镜像中安装的是1.33版本,seastar要求不能用这个版本,解决办法:apt卸载已经安装的libc-ares-dev v1.33,手工下载v1.34或其他版本的源码,编译并安装:
  1. apt remove libc-ares-dev
  2. apt autoremove
  3. apt install -y wget
  4. wget https://github.com/c-ares/c-ares/releases/download/v1.34.5/c-ares-1.34.5.tar.gz # 下载该库的源码包
  5. tar -xzf c-ares-1.34.5.tar.gz # 解压
  6. cd c-ares-1.34.5
  7. ./configure --prefix=/usr # 生成Makefile文件,设置安装路径
  8. make -j 4 # 4并发编译
  9. make install # 安装到系统目录
  10. ld /usr/lib/libcares.so /usr/lib/x86_64-linux-gnu/libcares.so # 为libcares.so文件建立软连接
  11. ldconfig # 重新加载系统.so文件列表
复制代码
结束

docker这种为每个程序、每个次编译环境都创建一个镜像环境的做法,极大的降低了环境准备的复杂性,虽然对硬件资源来说变得更浪费,但随着硬件性能提升、价格降低,这点浪费能带来开发效率的提升也是很划算的。特别是对于个人开发者来说。
windows也干脆直接选择集成了linux内核作为子系统,这样只要linux内核有的特性,在windows上同样能利用WSL享受到。
把这套能力直接套用在C++开发中,C++开发者也能专注代码开发,而不是把大部分研发时间用在研究环境搭建上。

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册