序
在我还在做后端的时候,当时程序员圈里就有个梗很火,说的是当时几种常用编程语言的鄙视链:做C++的鄙视做Java的,做Java的鄙视做C#的,而我很不幸,当时在鄙视链最底层。一开始只是当个笑话听听就算了,可是随着Java的不断兴盛以及C#的逐渐没落,心里还真的产生了一点自卑感。正是Java的开源和跨平台策略才让它异军突起,而微软前期的强大和过度自信让它一直保持着闭源的做法,而且始终不肯支持跨平台,用"闭关锁国"来形容都不为过。其实这也并不是问题的关键,毕竟IOS也是闭源的,也不见得它比安卓差,而最令开发人员接受不了的是微软的"朝令夕改",好好的技术不好好发展下去,动不动就推翻重做,开发人员疲于奔命似的地跟在后面,学习成本极高,简直苦不堪言。再后来,被"玩坏了"的程序员逐渐脱离了.NET阵营,转投了Java、C++以及其他一些新兴语言。微软这时候也意识到了问题的严重性,逐渐实现了开源和跨平台,但似乎是醒悟的有点晚了,已经很难恢复到之前的辉煌了,至少说它的明星产品C#已经荣光不在了。
我也是脱离阵营的那一批,那段时间总想着把Java学起来,否则工作都难找了;C++也可以,但是太难了,一时半会学不会。纠结中阴差阳错地玩起了前端,并一直持续到了现在,本来以为此生与后端再无交集了,没想到又会再次相遇。有一个C++的开源项目,需要学习掌握并能够修改或新增功能。起初是兴奋不已,毕竟可以接触到"鄙视链"的顶端啦,也圆了多年前的梦了。可是当我拉下代码一看,整个人都是懵逼的状态,这不是天书吗,完全找不到下手的地方。硬着头皮扒拉了两天代码之后,我决定放弃这种做法了。霸王硬上弓可不是好的学习方法,基础,还是基础,必须打牢!故本系列文章由此诞生了。虽然题目有点夸大了,看完本系列文章并不一定能成为大神啦,只是我们心中得有梦想嘛,如果没有梦想,那么我们和咸鱼有啥区别?通往大神之路注定崎岖坎坷,且跟我一步一个脚印!
正文
做为本系列第一篇自然是要从环境搭建开始,没有戏台再好的戏都出不来。
操作系统
程序预期是要部署在 Linux 操作系统上运行的,按常理来讲我们也应该在 Linux 下布置开发环境,最好是带图形界面的 Linux OS,毕竟面向控制台开发还是很蛋疼的。带图形界面的 Linux 使用起来跟 Windows 其实没有太大差别,只是操作习惯不同而已,而且开发、调试、运行一体,毫无障碍。但是要使用 Linux 还得安装双系统或虚拟机啊,这两样我都不想做,而且毕竟 Windows 才是从小陪我们到的操作系统啊,所以我更倾向于在 Windows 下做开发。那么问题来了,在 Windows 下开发开发 Linux 程序是否可行呢?答案是肯定的。应该还是有不少解决方案呢吧,这里只介绍 WSL 方案。
WSL
WSL(Windows Subsystem for Linux),即 Windows 下的 Linux 子系统,具备完整的 Linux 生态,同时可以直接与 Windows 系统的硬盘交互。
安装 WSL
我们要安装的 WSL 版本为2.0,相比 WSL1.0 它具备更完整的 Linux 内核、托管 VM 和完全的系统调用兼容性。安装 WSL2.0 之前我们得先了解一下先决条件:
- 不是所有的 Windows 操作系统都支持 WSL2.0 的,至少是 Windows 10 (1903以上) 以及 Windows 11 操作系统才可以。徽标键 + R 打开运行,输入 winver 可以检查 Windows 版本。
- 你的计算机得支持 Hyper-V 虚拟化。
以上两个条件是安装 WSL2 的必须条件,如果不能同时满足则不能安装 WSL2,但或许可以安装 WSL1,不过那不在本文的研究范围之内,感兴趣的同学可以自行研究。
WSL2.0 的安装过程大概分为以下几个步骤:
- 启用 WSL
- 启用虚拟化支持
- 安装 WSL2 Linux 内核升级包
- 设置 WSL 2 为默认值
- 安装 Linux 发行版
启用 WSL
以管理员身份打开 PowerShell,运行以下命令:
dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
或者使用界面操作:控制面板 → 程序 → 程序和功能 → 启用或关闭Windows功能 → 适用于 Linux 的 Windows 子系统勾选。
启用虚拟机平台
同样是在 PowerShell 里执行命令:
dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
如果是早期的 Windows 10 (1903, 1909) 版本系统,请使用以下命令:
Enable-WindowsOptionalFeature -Online -FeatureName VirtualMachinePlatform -NoRestart
或者界面操作:控制面板 → 程序 → 程序和功能 → 启用或关闭Windows功能 → 虚拟机平台勾选。
这步操作完之后建议先重启系统,否则会出现后面的步骤无法执行的情况。当然你也可以先不重启,但当你遇到问题无法解决的时候切记先别四处寻找答案,不妨先重启一下试试,我在安装的过程好像重启了两次。
安装 WSL2 Linux 内核升级包
下载 wsl_update_x64.msi 并安装。
设置 WSL 2 为默认值
还是 PowerShell,执行命令:
wsl --set-default-version 2
安装 Linux 发行版
这里的安装过程是要在微软商店(Microsoft Store)里进行的。输入 "linux" 关键字,就会出来很多操作系统,这里我们选择 Ubuntu 22.04.2 LTS,下载并安装即可。
到这里其实 WSL2 已经安装完成了,接下来就是使用 WSL 了。
使用 WSL
查看已安装的 WSL 使用 PowerShell 命令:
wsl --list --verbose
显示结果如下:
PS C:\WINDOWS\system32> wsl --list --verbose
NAME STATE VERSION
* Ubuntu-22.04 Running 2
可以看到刚刚安装的 Linux 系统,如果你安装了多个,则全部都会列出来。
从微软商店或开始菜单中启动之前安装的 Linux 系统,进入到系统界面,首次进入系统开始需要做一些配置,比如设置用户名、密码之类的。配置好之后,就可以正常使用 Linux 系统了。退出后再次进入后的界面如下:
Welcome to Ubuntu 22.04.2 LTS (GNU/Linux 5.10.16.3-microsoft-standard-WSL2 x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
This message is shown once a day. To disable it please create the
/home/helsing/.hushlogin file.
helsing@DESKTOP-HELSING:~$
因为我在首次进入系统时配置了新的用户名,所以打开系统后使用了我自定义的用户名,默认的可以使用 root 登录。
远程连接 WSL
为什么要远程连接 WSL?因为后面在 Windows 的 IDE 下调试 Linux 必须远程连接到 Linux 系统,这也是我们安装 WSL 的原因啊。我们先尝试使用 PowerShell 本地登录 WSL:
PS C:\WINDOWS\system32> ssh root@localhost -p 2222
显示登录成功。我们用这个连接信息在 IDE 中登录,结果显示登录失败,说明 IDE 中得通过远程连接才可以。我们要查看一下 WSL 的 IP,使用命令 ifconfig,注意:要使用这个命令需要先安装 net-tools。
apt install net-tools
运行 ifconfig 命令得到 IP 为 172.23.143.94,就是 inet 后面的值。
root@DESKTOP-HELSING:/# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 172.23.143.94 netmask 255.255.240.0 broadcast 172.23.143.255
inet6 fe80::215:5dff:feba:a089 prefixlen 64 scopeid 0x20<link>
ether 00:15:5d:ba:a0:89 txqueuelen 1000 (Ethernet)
RX packets 90562 bytes 121907011 (121.9 MB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 26563 bytes 25332553 (25.3 MB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1000 (Local Loopback)
RX packets 1160 bytes 22589469 (22.5 MB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 1160 bytes 22589469 (22.5 MB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
将 localhost 改为 IP,再进行登录尝试:
PS C:\WINDOWS\system32> ssh root@172.23.143.94 -p 2222
登录不成功,显示信息如下:
ssh: connect to host 172.23.143.94 port 2222: Connection refused
报的是 ssh 的错误,所以登录不成功的原因有可能是未安装 ssh 或 ssh 未正确配置。
尝试重新安装 ssh:
apt-get remove openssh-server
apt-get install openssh-server
如果安装失败的话,可以尝试使用 apt-get update 命令,尝试更新修复后再重试。
配置 ssh:
vim /etc/ssh/sshd_config
在 sshd_config 中修改或增加以下内容:
Port 2222 # 端口号(默认的22端口有可能被Windows另作他用了,为了避免端口冲突最好是改成别的)
ListenAddress 0.0.0.0 # 监听地址
PermitRootLogin yes # 允许使用root远程登录
PasswordAuthentication yes # 密码验证登录
配置完成后重启 ssh 服务:
service ssh restart
这时候再使用 PowerShell 进行远程登录,就显示登录成功了。
PS C:\WINDOWS\system32> ssh root@172.23.143.94 -p 2222
root@172.23.143.94's password:
Welcome to Ubuntu 22.04.2 LTS (GNU/Linux 5.10.16.3-microsoft-standard-WSL2 x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
Last login: Fri Nov 17 11:13:56 2023 from 172.23.128.1
root@DESKTOP-HELSING:~#
另外,网上看到有人说需要设置 Windows 的 SSH 功能,我好像没做这步操作,不过查看列表发现已经安装了。
如果你还未安装,可以参考以下方法:
Windows 10:设置 → 应用和功能 → 可选功能 → 添加应用 → OpenSSH 客户端
Windows 11:设置 → 可选功能 → 添加可选功能 → OpenSSH 客户端
IDE
前面我们说过了要在 Windows 下进行开发,那么 IDE 自然也是选择 Windows 下的了。这里我自然会选择宇宙最强之 IDE ------ VS 了,毕竟之前玩 C# 就是一直用它的,熟悉的不能再熟悉了。不过如果你坚持要在 Linux 下进行开发,也可以了解一下 Linux 下的这些 IDE:
QT Creator
大名鼎鼎的 QT,不用我说了。
下载:点这里
安装:
chmod +x qt-creator-opensource-linux-x86_64-7.0.2.run
./qt-creator-opensource-linux-x86_64-7.0.2.run
Visual Studio Code
一看就知道是 VS 系的,必须强大。
下载:点这里
安装:
sudo dpkg -i code_1.84.2-1699528352_amd64.deb
CLion
JetBrains 旗下的大作,用过 IDEA 的都知道这家公司,它家的 IDE 可以和微软的一教高下,并且一如既往的它家软件是要收费的。
下载:点这里
安装:直接解压,设置桌面快捷方式 jetbrains-clion.desktop:
[Desktop Entry]
Name=CLion
Exec=${clion_install_path}/bin/clion.sh %f
Icon=${clion_install_path}/bin/clion.svg
Type=Application
将 ${clion_install_path} 替换为实际路径。
本节内容参考自 ᴇʀɪᴄ ᴛᴇᴏ 的博客文章
以上就是 Linux 下的 C++ IDE 了,其实在 Windos 下各家基本都有自己对应的产品,这里就不赘述了。后面的内容都是基于 VS IDE。
创建项目
下面我们打开 VS,来创建我们的第一个 C++ 程序吧。
文件 → 新建 → 项目,选择 C++、Linux、控制台,设置项目名称,点击创建:
这样我们就创建好了一个 Linux C++ 控制台项目了,项目里面只有一个 main.cpp 文件,内容如下:
cpp
#include <cstdio>
int main()
{
printf("%s 向你问好!\n", "HelloWorld");
return 0;
}
我们将输出改成:
cpp
printf("%s\n", "Hello, World!");
点击调试运行,它会提示你要先创建一个 Linux 的远程连接,就是我们上面安装配置好的 WSL,将IP、端口号、用户名和密码等连接信息输入之后点确定即可。如果我们的 WSL 没有设置好远程访问,那么这个远程连接是创建不成功的。
配置成功后,打开项目的属性配置页,可以看到配置属性 远程生成计算机的值变为 172.23.143.94 (username=root, port=2222, authentication=Password)。
再次点击调试运行,项目正常编译,且已成功连接上了 Linux 系统,但还是报错了:
g++ exited with code 1, please see the Output Window - Build
或者
g++已退出,代码为1,请查看输出窗口 - 生成输出,了解详细信息(注意: 若要在输出窗口中查看详细信息,则可能需要在工具选项中更改生成输出详细信息)。
网上有人说是 Windows Defender 或杀毒软件引起的,有的说是是 Linux 下的 g++ 不支持 C++11导致的,而我的原因其实很直接,那就是 WSL 上面压根儿没安装 g++ 造成的。
cpp
g++ -v
或
g++ --version
上述命令用于检测 g++ 是否已安装,如果没有安装,会提示"Command not found",反之则会返回版本信息。
安装 g++
cpp
apt-get install gcc
apt-get install g++
apt-get install gdb
apt-get install gdbserver
或
yum install gcc
yum install g++
yum install gdb
yum install gdbserver
用哪种安装命令取决于你的 Linux 系列,这里不赘述了。
gcc:用于编译和链接 C 程序(g++ 依赖于 gcc,所以得先安装它)
g++:用于编译和链接 C++ 程序
gdb:用于本地调试 C/C++ 代码
gdbserver:用于远程调试 C/C++ 代码
安装完成之后,再此点击调试运行:
Linux 控制台成功输出信息,至此我们的 C++ 开发环境就部署完成了。 不过当我们在打开项目的时候,有可能会报一些错误:
xx.xx.xx.xx 缺少 zip:可能是在启动项目的时候做了什么跟 zip 有关的操作吧,那么我们在 WSL 上再把 zip 安装上去就可以了。
cpp
apt-get install zip
E0020 未定义标识符 "__builtin_free" :位置在外部依赖项的 stdio.h 文件下,__attr_dealloc_free 这个位置。这个字面意思就是标识符在使用之前尚未定义,这个错误我还没找到解决方法,不过并不影响程序运行,就暂时不管了。
cpp
#if defined __USE_MISC || defined __USE_XOPEN
/* Generate a unique temporary filename using up to five characters of PFX
if it is not NULL. The directory to put this file in is searched for
as follows: First the environment variable "TMPDIR" is checked.
If it contains the name of a writable directory, that directory is used.
If not and if DIR is not NULL, that value is checked. If that fails,
P_tmpdir is tried and finally "/tmp". The storage for the filename
is allocated by `malloc'. */
extern char *tempnam (const char *__dir, const char *__pfx)
__THROW __attribute_malloc__ __wur __attr_dealloc_free;
#endif
结
老子说:"合抱之木,生于毫末;九层之台,起于垒土; 千里之行,始于足下。"【见《道德经》 第六十四章】
我始终觉得世上再难的事情都并非不可为,关键是要找到通往目标的途径。正所谓万事开头难,最难的并不是在既有道路上持续行走,而是寻找道路的过程。现在我们的道路很明确了,地基也打好了,九层之台指日可待了。