概念
虽然接触编程已经很久了,但一直不知道makefile和cmake等都是怎样的概念,他们又有什么样的关系。最近刚好有个契机,期望我去学习一下。这篇博客记录了我查阅了很多资料后自己目前的理解,与自己的实验。
我觉得我对这方面知识的匮乏,原因是一直是在VS等开发环境下进行编程。例如,我虽然理解C++这种语言需要编译,但是VS已经将这些东西都封装好了,对于像我这样的使用者来说,知不知道“编译器”这个概念对于我编程时没有区别。
但是,VS毕竟是Windows平台上微软的产品,很多软件是针对于不止Windows一个平台的,也没有说限定必须要用VS进行开发。那么我就想知道,抛开了VS,我该怎么编译代码,组织项目?
理论上,只要有编译器就可以对一个C++代码进行编译。不过,实际项目中代码文件是多个的,而其中又有错综复杂的依赖关系,需要以一个正确的顺序依次编译,出于这种考虑,make工具
站了出来。通过编写一个makefile文件
来指定目标文件们所各自依赖的东西,以及该目标完成所需要的的命令,来让make工具
自动地以一个正确的顺序编译这些代码。
不过,随着项目越来越大,连写makefile文件
也成为了一个巨大的工作量,同时不同平台也有着不同的makefile文件
。出于这种考虑,cmake工具
站了出来,通过编写一个CMakeList.txt 文件
,cmake工具
可以自动生成对应平台的makefile文件
和工程文件(如VS的工程文件)。cmake
算是对make
的一层更高级的抽象。
也就是说,他们之间的关系如下:
对于这3个层级:上层的工具依赖于底层,但底层的行为并不依赖于上层的工具。因此我想从最底层开始,逐步做一些实验。
1.尝试直接使用编译器对代码进行编译
较为知名的C++编译器有GCC、Clang,而VS所用的编译器是自己的MSVC编译器,exe是cl.exe
(我不清楚它和Clang是什么样的关系),可以在VS安装目录的MSVC下找到。关于它,官方文档有如下描述:
cl.exe is a tool that controls the Microsoft C++ (MSVC) C and C++ compilers and linker. cl.exe can be run only on operating systems that support Microsoft Visual Studio for Windows.
cl.exe 是一种工具,用于控制在 Microsoft C++ (MSVC) C 和C++编译器和链接器。 cl.exe 只能在支持 Microsoft Visual Studio for Windows 的操作系统上运行。
下面,我尝试调用cl.exe
对一个简单的源代码TestSrc.cpp
进行编译,这个代码简单地输出了“Hello YakSue”,内容如下:
#include<iostream>
using namespace std;
int main()
{
cout << "Hello YakSue" << endl;
return 0;
}
1.1找到cl.exe
cl.exe
应该在VS的目录下。我通过Everything小工具搜索我电脑上的cl.exe
发现:
我看到MSVC下有不止一个版本,目前我还不清楚区别。但我想对于这样一段的代码来讲可能区别不大,所以我随意挑了一个Hostx64\x64。
默认情况下,cl.exe
所在的路径不在系统环境变量的PATH
中(至少我这里是这样),因此为了在想调用它时可以优雅地只打一个cl
而不是还带上一长串路径,可以在环境变量PATH
中加入。不过我想尽量避免加环境变量,毕竟它是一个影响全局的东西,因此这里我在调用cl.exe
前先用path
命令加入了路径:
path C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\bin\Hostx64\x64
据我观察,这样做只是临时加入了一个路径,关闭cmd之后影响就会消失。
之后打出cl
就可以发现它找到了cl.exe
:
1.2加入include和lib路径
如果直接调用cl
编译TestSrc.cpp
,则会有如下报错:
看来#include<iostream>
由于路径问题没有找到。这可以理解,过去应该是VS已经帮助我加上了路径了。
这个问题上我参考了C++ -> 在Window7 命令行下使用微软编译工具 cl.exe - Davim - 博客园这篇博客,它通过加入环境变量来解决这个问题。我不知道有没有其他的解决方法,目前我只能也这么做。
除了iostream
的路径,还有其他的路径。除了include
,还有lib
的路径需要加入,最终我的环境变量添加了如下内容:
INCLUDE
:
LIB
:
1.3成功编译
完成了上面两步之后,成功编译了:
输出的exe在当前cmd的目录"C:\Users\admin"中。
直接打开这个exe,运行后会直接退出,看不到输出,所以需要在控制台来调用:
2.尝试使用Make工具来编译代码
关于Make工具
,或者说makefile
,这篇文档挺好的,我从中学到了很多。
不过,如果是在Windows上想用Cl.exe
进行编译,则需要的是NMake工具,官方文档中有如下的介绍:
The Microsoft Program Maintenance Utility (NMAKE.EXE) is a command-line tool included with Visual Studio that builds projects based on commands that are contained in a description file.
Microsoft 程序维护实用工具 (NMAKE.EXE) 是Visual Studio 附带的一个用来生成项目的命令行工具,它基于一个说明文件中的命令。
其中所说的“description file(说明文件)” 其实就是指makefile文件
,其官方文档中描述的格式和上面那篇文档中介绍的看起来一样。但我这方面我理解不深,我不确定二者是否有细微的差别。
也就是说,NMake工具
在定位上是和Make工具
平级的,下面我将尝试写一个makefile文件
文件,其中指定了要编译TestSrc.cpp
,然后启动NMake工具
。
2.1找到nmake.exe
nmake.exe
同样在VS目录的MSVC中。
path C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\bin\Hostx64\x64
设置路径后,即可让cmd找到nmake.exe
:
2.2写makefile
我的makefile内容如下:
TestTarget : TestSrc.obj
cl TestSrc.obj -o TestTarget
TestSrc.obj : TestSrc.cpp
cl TestSrc.cpp
意义是:
我的最终目标是TestTarget
,它依赖了TestSrc.obj
。要想生成TestTarget
,需要运行命令cl TestSrc.obj -o TestTarget
。
而为了生成TestSrc.obj
这个目标,我依赖于TestSrc.cpp
。要想生成TestSrc.obj
,需要运行命令cl TestSrc.cpp
。
2.3运行nmake
首先,要切换目录到makefile
和源代码的目录下:
D:
cd D:\Test
然后,运行nmake
:
nmake TestMakefile.mk
(更多关于nmake的用法,详细见官方文档)
即可看到:
会发现生成了三个东西:
其中TestSrc.exe
的生成是个意外,我应该不需要它,这应该是由于我的某个参数没有设置好。
调用TestTarget.exe
后,发现效果符合期望:
3.尝试使用CMake
这一部分我参考了CMake入门1——CMake与VS编译器和nmake的结合使用_yaoyuanyylyy的专栏-CSDN博客这篇博客,但是遇到了未被记录的问题,我写在了下面。
安装CMake
首先,先下载CMake
,可以在官网上下载。其中有很多版本,我选择了windows上的64位安装版
下载之后,安装时只有一处需要注意:
这里选择将CMake
加入到环境变量PATH
中,这样之后可以在命令行中使用CMake
:
确保VS安装了Cmake相关组件
一开始,我这边是没有安装的,用CMake图形界面
时,配置完尝试生成会失败,log中也只有一句:
The system is: Windows - 10.0.18362 - AMD64
(我尝试安装了这个版本的Win10 SDK,但当时看起来没有任何推进。所以我现在不确定Win10SDK是否是必要的。)
看到图形界面的提示不足,我想要在命令行中使用,所以我用了cmake ../ -G "Visual Studio 15 2017 Win64"
命令。随后出现了下面的错误提示:
Cmake could not find any instance of Visual Studio.
看来它连VS都没有找到。随后我看到了有人说VS中也有CMake的组件需要安装,于是我打开VS的安装器:
然后点修改
在单个组件
下找到用于 CMake 的Visual C++ 工具
,确保它是勾选的,然后点右下角修改
之后便开始安装所有勾选的项目中未安装的内容了,包括用于 CMake 的Visual C++ 工具
下面,尝试使用CMake去自动建立一个VS工程。
3.1.建立目录
D:\Test\TestCMake\src
是我的源代码目录,其中存放着TestSrc.cpp
。
D:\Test\TestCMake\build
预期将放入生成的二进制文件,以及工程文件。
3.2.准备CMakeLists.txt
我将CMakeLists.txt
放到了和源代码一起的D:\Test\TestCMake\src
目录。
他的内容如下:
cmake_minimum_required(VERSION 3.10.1)
project(TestProj)
add_executable(TestProjTarget TestSrc.cpp)
3.3.使用CMake GUI
首先将D:\Test\TestCMake\src
和D:\Test\TestCMake\build
填入对应的目录:
然后点击Configure按钮,指定自己的VS对应的版本:
点Finish之后,在D:\Test\TestCMake\build
目录生成了一些文件。
这一步不应该有报错。不过有红字是正常的:
他说了:点击Configure按钮来更新红色的变量
随后点击Generate:
就会看到生成的项目文件了:
会发现自动生成了一个名为TestProj
的解决方案,其中有三个项目,其中TestProjTarget
是之前在CMakeLists.txt
指定的。而另外两个似乎是自动帮我生成的,我还不清楚作用,回头可以继续研究下。
将TestProjTarget
设为启动项目之后,就可以正常调试与运行了。