搭建命令行工作环境

开始这部分前,读者需要了解:

  • Windows 下软件的安装
  • 命令行入门基础、常见的命令行工具
  • 了解“环境变量”的概念

一般所说的命令行工作环境,包含终端 + Shell(提供基础操作,如文件创建、网络通信),C/C++ 编译器(用来构建其他很多软件的必要程序),包管理器,以及其他形形色色的工具等。

工具链

我们先来介绍一下工具链(Toolchains)的概念。顾名思义,其意为一套“连锁”的工具,一般可以指我们构建软件过程中所需的编辑器、编译器、调试器等工具,以及开发软件所依赖的软件和软件库(也可以包含用于软件库的包管理器等)。

比如,在 Ubuntu 上,我们通常使用 GCC (GNU Compiler Collection) 作为编译器,使用 APT 作为包管理。

在 macOS 上,我们使用 Apple-Clang 编译器,并可以选择 Homebrew 作为包管理器,也可以选择比较少见的 MacPorts 作为包管理器。

在 Windows 上,我们可以使用 MSVC 作为编译器,使用 vcpkg 管理包(也可以手动管理各种软件包);也可以安装 MSYS2,使用其提供的 MinGW-w64 GCC 作为编译器,使用其携带的包管理器 pacman 管理软件包;也可以使用 WSL 上的环境(Linux 环境)进行开发。

要开发对应操作系统上的运行的程序,需要对应操作系统的标头文件以及相应的库文件。

为了构建适用不同的平台的软件,我们往往需要不同的工具链。在一台计算机上为其他不同平台或新平台构建软件的过程叫做“交叉编译(cross-compiling)”。

配置包管理器

操作系统一般都提供命令行操作的界面,支持一些实用 Shell 命令以及一些常用的命令行工具。

Linux 发行版一般会自带有相应的包管理器,如 apt、pacman 等。

但是像 Windows、macOS 等操作系统并不具有包管理器,通常需要用户手动安装包管理器。通常,包管理器会提供一个 Shell 脚本,用户只需要下载并执行这个脚本即可完成包管理器的安装。这个脚本所执行的配置过程一般包含“下载程序”和“将程序添加到环境变量”两个步骤。

实际上,由于互联网环境的复杂性,这个过程通常并不流畅,可能需要用户修改脚本中的内容,以便更好的执行程序的下载等任务。

包管理器的提供方也有可能提供一个安装器,用户只需要在图形界面中进行少许操作即可完成安装。当然,也有可能需要用户手动将包管理器可执行文件所在的位置添加进环境变量(像安装命令行工具那样),不过由于过程复杂容易出错,一般很少建议用户手动操作。

至于采取何种方式,需要根据软件的说明来决定。

不同的包管理器

我们会接触到很多包管理器,它们之间有一定的区别。通常来讲,一种是我们系统(或者环境)层面上的包管理器,这些包管理器通常安装的是实用程序,也负责解决这些程序、库之间的依赖问题,且通常安装的是事先构建好(pre-built)的软件;也有专门针对某种语言开发环境所使用的包管理器,这时所指的包一般指我们写程序所用到的程序库、SDK 等。

针对日常软件的安装,Windows 上可用的包管理器有 Chocolatey;macOS 上常用 Homebrew。这些包管理器有时候也能替我们安装一些开发用的软件或库。

至于专门用于软件开发的包管理器,针对 C++ 的有 vcpkg;针对 Python,有 pip;针对 Java,可以使用 maven 等。这些包管理器,可以帮助我们方便的安装和管理构建(build)程序所需的依赖(dependency)。

Windows 配置命令行工作环境

Windows 已经带有 Win32 控制台和 PowerShell 环境,这为我们提供了基础的命令行工作的环境。当然,除此之外,我们可以再选择使用一些包管理器管理自己的软件包。

比如,用户可以通过安装 Chocolatey,并通过其安装一些预构建好的软件(通常是闭源的)。 也可以使用 Scoop,这个比较适宜没有管理员权限的情况,并且软件也多一点。缺点是与国际互联网连接性较差时容易安装失败,且从安装失败的状态恢复比较麻烦。 亦可以使用 MS 官方的 WinGet,缺点是只能安装而不能卸载。

macOS 以及诸多 Linux 的发行版的命令行工作环境是类似的(Linux 发行版中大多为 bash;macOS 默认为 zsh,其使用与 bash 类似,也可选择 bash)。两者之间有着类似的工具,命令几乎可以通用。而 Windows 的 PowerShell 命令则别出一格,很多功能、操作的实现所用的命令并不相同。

而如果读者希望体验类 Unix 的开发环境、使用类 Unix 的命令行工具,可以使用虚拟机软件安装相关的系统,或者使用 Windows 提供的 WSL 功能(Windows Linux 子系统),也可以使用模拟类似环境的软件,如 Cygwin 和 MSYS2 等。

安装虚拟机可以体验最接近真实的 Linux 发行版体验,但该法的问题主要在于联动性和效率上:虚拟机的环境与 Windows 环境是有分离的,比如在虚拟机上构建的软件并不能直接在 Windows 上使用,只能在虚拟机环境中运行;而虚拟机往往也不能直接访问主机磁盘上的文件;WSL 虽然体验上与 Windows 更加融合,但本质上也属于虚拟机。简单地说,使用虚拟机就如同使用两台电脑。

不过,假如用户只是想在 Windows 上使用一些流行的(命令行)应用程序,比如 ffmpeg 和 gcc 等,可以去对应网站上下载构建好的二进制文件。

Windows 配置开发环境

理论上,微软的 MSVC 是最适合开发 Windows 上应用的编译器。用户可以选择只安装“MSVC 生成工具”,也可以选择直接安装 Visual Studio

假如只安装 MSVC 生成工具,读者可能需要搭配使用其他的代码编辑器编写代码,或者使用其他 IDE 或工具来获得图形化的代码编写与调试体验。

vcpkg 是一个在 Windows、Linux 和 macOS 上通用的包管理器,可以帮助用户管理 C/C++ 开发时可能使用到的软件库。之后将会 对 vcpkg 进行一个简单的介绍

当然,有的用户并不希望使用 MSVC,希望在 Windows 上继续使用 GCC 作为自己的编译工具(毕竟有些应用程序针对某一编译器做了相应的优化,更换编译器需要对代码进行较多的修改,而维护两个或多个版本是一件耗费精力的事情)。一个使 GCC 在 Windows 上可用的项目就叫做 MinGW,即 Minimal GNU on Windows。目前在 Windows 上常用的为 MinGW-w64,其为 MinGW 项目的一个分支,支持了 64 位系统以及新的 API。

有了编译器,用户就可以自己编译喜欢的应用了。但重新编译自然是耗时、耗费精力的过程。所以一些项目维护者本身,或者其他第三方组织,会提供构建好的二进制版本。但这就像我们之前说的,更新应用程序的操作需要用户手动操作。而有了包管理器,用户就可以通过包管理器轻松地实现软件包的获取和更新。

MSYS2 就是这样的一个项目。其旨在为用户提供使用 MinGW-w64 GCC 构建的原生的 Windows 程序,这样的程序能够更好的与其他 Windows 应用程序协作。MSYS2 使用 pacman 作为其包管理器,同时也提供了一个类 Unix 的开发环境。

MSYS2 安装后有三个子环境,“MSYS2 MSYS”、“MSYS2 MinGW 64-bit”、“MSYS2 MinGW 32-bit”。我们常用的是就是“MSYS2 MinGW 64-bit”环境。

MSYS2 为我们提供了类似 Linux 发行版的操作环境。在 MSYS2 的安装目录下有一个“home”目录,这个目录就是我们 MSYS2 环境中的家目录。MSYS2 环境中,Windows 下的各盘符被挂载在根目录下对应的目录上,比如“C盘”被挂载在 /c/ 下,“D盘”被挂载在 /d/ 下。

在“MSYS2 MinGW 64-bit”环境中,C/C++ 编译器为“MinGW gcc 64-bit”,如前所述,其可以生成 Windows 平台下原生的可执行文件(exe)。其包管理器安装的软件也是由 MinGW gcc 构建的软件。我们把这一整套称为“MSYS2 MinGW 64-bit”工具链。

当然,用户可以不使用 MSYS2,只安装 MinGW-w64 gcc 作为编译器,并手动安装其他需要的工具和包。

扩展阅读:

多个开发工具链

在不使用虚拟机的情况下,为了避免同一计算机上不同环境(工具链)的冲突,用户安装的开发工具的配置等通常不会直接写入系统的环境变量等,而是在配套的脚本中提供,或是以一定的命名前缀来进行区分。

用户通过配套的脚本,可以启动一个具有相应环境变量的窗口,在其中便可使用对应的工具。不需要时,直接关闭窗口即可,并不会影响和污染系统其他的程序。

之前我们说到,Shell 在启动子程序时,不止会将命令行参数传给程序,也会将当前的环境变量复制一份给子程序。

因此,当我们的编辑器(如 Visual Studio Code)或 IDE 需要使用这些开发环境时,可能需要从对应的命令行中启动相应的程序,以便让这些程序获得关于这些环境的信息。

用户应该在对应的环境中进行开发和运行。如果混用不同的环境,可能会导致一些意料之外的问题。

读者可以参考微软提供的链接 通过命令行使用 Microsoft C++ 工具集 - Microsoft Docs 查看相关的信息。

vcpkg

vcpkg 是一个在 Windows、Linux 和 macOS 上通用的包管理器,可以帮助用户管理 C/C++ 库。

Ubuntu 配置开发环境

Ubuntu 默认没有安装编译器,我们可以通过包管理器安装所需的软件工具等。

$ sudo apt update
$ sudo apt install build-essential
$ sudo apt install cmake

Ubuntu 的包管理器 apt

常用的 apt 命令主要有 updateinstallupgrade。使用这些命令,一般需要管理员权限。

$ sudo apt update      # 刷新本地的软件包信息,计算哪些软件包可以更新
$ sudo apt install gcc # 安装名为“gcc”的包
$ sudo apt upgrade     # 升级有更新的包

“本地的软件包信息”相当于从软件源下载到本地的一份索引,其中记录了软件源提供的软件包的版本和依赖关系等信息。只有更新了软件源缓存信息,才能知道是否有更新的软件包可以更新;同理,添加了新的软件源后,也需要执行这个操作,以获得到新添加的软件源上的信息,这样在执行 install 命令时,才能够搜索到需要的包。

存放包的远程的服务器通常称作“软件仓库”。

macOS 配置开发环境

首先,我们要安装一些基础的命令行工具。Xcode 是 Apple 的开发工具,我们可以选择只安装命令行工具。

$ xcode-select --install

键入以上命令后,macOS 会开始安装 Xcode 命令行工具,其中包括我们需要的编译器(Apple-Clang)。

macOS 默认没有包管理器。安装完成后,我们可以选择安装包管理器——Homebrew。具体安装步骤和使用这里不再赘述。

当然,选择安装 Xcode,也会安装 Xcode 命令行工具。但是作为一个完备的 IDE, Xcode 会十分庞大。

Homebrew

(待补充)

代码编辑器

常用的代码编辑器可以使用 Visual Studio Code,其跨平台可用,且免费开源;虽然只是编辑器,但有海量插件可以实现各种自动化的操作,某种程度上可以当成 IDE 使用。

可以说,不管在哪个平台上,VSCode 都是非常厉害好用的。不过在使用 C++ 的代码智能感知插件时要记得清理缓存,默认的上限是 5 GB,可以修改。

集成开发环境

集成开发环境(IDE)是包含了代码编辑、调试、协作等诸多功能的软件。除了我们刚刚提到的 Xcode 和 Visual Studio 等,也有 JetBrains 系的 IDE,如 CLion、PyCharm 等。不同于前两者,JetBrains 系的 IDE 一般不会附带安装构建需要的工具。这时就需要使用我们之前配置的编译工具链,有时也称为“外部生成工具”。

JetBrains 系的 IDE 也是跨平台的,社区版免费;同时提供学生优惠,即用教育邮箱(或其他方式)认证后可以使用专业版。其产品包括开发 C/C++ 项目用的 CLion ,也有编写 Python 的 PyCharm。

如何评价 JetBrains 的新 C/C++ IDE CLion?

如今,Visual Studio 提供免费的社区版,而商业版本需要收费。Visual Studio 在使用过程中可能会在项目文件夹下产生很大的缓存,使用时需要注意。

现代 IDE 基本都有代码补全语法检查等功能。为什么强调这些功能呢?比如代码补全功能不需要编程者记录确切的函数名,只需要几次击键就可以联想出函数名,可以提高编程效率,同时也能降低错误率。而语法检查则能让编程者及时发现错误,同样能够提高效率。

扩展阅读