假如想在 Windows 下进行 C++ 的开发,可以直接使用 Visual Studio 和相应的 C++ 插件来实现,但编译和构建过程是不可见的。为了更彻底地了解 C++ 工程的编译和构建,可以借助另外两个工具在 Windows 环境下实现。
是 Windows 系统下的一个编译环境,包含了 C++ 代码编译所需的三方库、头文件等,用于完成 C++ 源码的编译和链接。
安装:
在官网下载安装包:mingw-get-setup.exe ,双击开始安装,然后在 MinGW Installation Manager 中选择需要安装的工具库。Basic Setup
中的库都是比较常用的,例如编译代码使用的 g++
工具,这些最好都选中并安装。
配置:
将安装目录的 bin 目录配置到系统环境变量中的 Path 中,启动 cmd 命令行,输入一下指令验证上面选择的库是否安装成功,例如 g++ 库:
E:\C++\projects>g++ --version
g++ (MinGW.org GCC-6.3.0-1) 6.3.0
Copyright (C) 2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
输出上述内容则表示库安装成功。
测试编译:
随便编写一个 C++ 代码文件,然后使用 g++ 来编译生成可执行文件:
#include <iostream>
using namespace std;
int main()
{
cout << "Hello, World!";
return 0;
}
先编译但不链接,然后链接生成可执行文件:
$ g++ -c helloworld.cpp
$ g++ helloworld.o -o helloworld.exe
假如使用 -c
标识,则是编译但不链接,会生成对应的 .o
文件,不设置标识,则会直接生成最终的 .exe
可执行文件。
静态关联:
上述编译生成的可执行文件,双击打开都会提示 "无法启动此程序,因为计算机中丢失 libgcc_s_dw2-1.dll。..."
这样的错误(假如是在命令行中执行文件则不会报错,但会命令行窗口会一闪而过,看不到输出的结果)。这是因为 gcc 编译器 编译时默认使用的不是静态关联的方式,运行时找不到对应的库导致报错。
解决方案:可以直接将缺失的 dll 库手动复制到可执行文件目录下,当然这不是根治的方法,其实只要在链接时带上标识 -static-libgcc
来指定静态关联即可解决此问题:
$ g++ helloworld.o -o helloworld.exe -static-libgcc
后面使用 CMake 来构建的话,可以在 CMakeList.txt 配置编译参数。
上面安装的 MinGW 只能编译生成 32 位的可执行程序,而 MinGW-w64
可以编译生成 64 位或 32 位的可执行程序。安装步骤如下:
安装:
可以从 mingw-w64 官网 下载最新的安装包,也可以直接从 SourceForge 中去下载 mingw-w64-install.exe
下载完成后,直接双击安装包进行安装,除了修改一下安装目录,其余设置都是用默认设置接口。
这里直接下载安装程序进行安装的话,在安装过程需需要去服务器下载资源,似乎速度很慢,所以最后我改成直接从 这里 下载离线的完整压缩包:
根据自己的需求选择,此包为:64 位系统,且使用效率较好较新的 seh 异常处理模型(至于 win32 和 posix 的区别暂时还没搞懂)
配置:
通上面的 MinGW 一样,只需将安装目录下的 bin 目录配置到系统 Path 中即可。查询配置结果:
$ gcc --version
gcc (x86_64-posix-seh-rev0, Built by MinGW-W64 project) 8.1.0
Copyright (C) 2018 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
在执行 gcc 命令时,加上
-m32
生成 32 位可执行程序,加上-m64
生成 64 位可执行程序
一个跨平台的自动构建系统,使用一个 CMakeLists.txt 文件来描述构建过程(等同于 Linux 系统下编译构建 C/C++ 时使用的 Makefile 的作用),通常在编译一个多文件的工程时使用这样的工具。
安装:
直接下载官方 cmake-3.13.0-rc3-win64-x64.zip 包,解压即可,无需安装。
配置:
参考 MinGW 的配置方式,将解压后目录中的 bin 目录配置到系统 的 Path 参数中,通过命令行验证是否配置成功:
E:\C++\projects>cmake --version
cmake version 3.13.0-rc3
CMake suite maintained and supported by Kitware (kitware.com/cmake).
如上标识配置生效。
测试:
在测试目录下创建一个 CMakeLists.txt
文件:
cmake_minimum_required (VERSION 3.0) # cmake 最低版本
project (helloworld) # 工程名称
add_executable(helloworld helloworld.cpp) # 源文件
if(WIN32) # 静态关联配置
set(CMAKE_CXX_FLAGS "-static-libgcc")
endif(WIN32)
打开 cmake-gui.exe ,然后 source 目录选择工程目录,bin 目录可以随便自定义,然后点击 Configure
选择 MinGW Makefiles
,无报错的话,在命令行进入 bin 目录,输入 mingw32-make
编译工程:
E:\C++\projects\helloworld\build>mingw32-make
Scanning dependencies of target helloworld
[ 50%] Building CXX object CMakeFiles/helloworld.dir/helloworld.cpp.obj
[100%] Linking CXX executable helloworld.exe
[100%] Built target helloworld
成功编译出目标文件 helloworld.exe
,在命令行中执行如下:
E:\C++\projects\helloworld\build>helloworld.exe
Hello World!
命令行模式:
上面我们使用借助 cmake-gui.exe 工具完成了工程的编译,而实际上也可以直接通过命令行来完成:
$ mkdir build
$ cd build
$ cmake -G"Unix Makefiles" ../
-- The C compiler identification is GNU 8.1.0
-- The CXX compiler identification is GNU 8.1.0
-- Check for working C compiler: E:/C++/installs/x86_64-8.1.0-release-posix-seh-
rt_v6-rev0/mingw64/bin/gcc.exe
-- Check for working C compiler: E:/C++/installs/x86_64-8.1.0-release-posix-seh-
rt_v6-rev0/mingw64/bin/gcc.exe -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: E:/C++/installs/x86_64-8.1.0-release-posix-se
h-rt_v6-rev0/mingw64/bin/c++.exe
-- Check for working CXX compiler: E:/C++/installs/x86_64-8.1.0-release-posix-se
h-rt_v6-rev0/mingw64/bin/c++.exe -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: E:/C++/projects/helloworld/build
上面的步骤用于生成 makefile 文件,生成成功后,在执行 make 进行编译:
$ make
Scanning dependencies of target helloworld
[ 50%] Building CXX object CMakeFiles/helloworld.dir/helloworld.cpp.obj
[100%] Linking CXX executable helloworld.exe
[100%] Built target helloworld
然后在命令行中执行编译后的可执行文件:
$ .\helloworld.exe
Hello World!
关于 CMakeLists.txt
的语法还是需要再补充一下的,可以参考:cmake-tutorial
当然,在使用过程中会发现很多很微妙的地方,例如: link_directories
必须在 add_executable
之前使用,这样 target_link_libraries
才能从 link_directories
中指定的目录中去搜索库文件。
这里有必要梳理一下 gcc
、make
以及 cmake
的关系:
gcc
:
即 GNU Compiler Collection(GNU 编译器套件),也可以理解为编译器,可用于编译很多种编程语言(如:C、C++、Objective-C、Java 等);
make
:
可以看作一个智能的批处理工具,本身没有编译和链接功能,而是通过调用 makefile
文件中用户指定的命令来进行编译和链接的;
cmake
:
可以根据 CMakeLists.txt
文件,跨平台来生成对应平台的 makefile 文件。
综上所述:
gcc 是用于编译和链接和工具,编译少量文件可以直接使用 gcc 命令完成,但当源文件很多,用 gcc 命令去逐个编译则是很混乱且工作量巨大。
因此,需要借助 make 来来管理整个编译过程,make 安装 makefile 中的命令进行编译和链接,而 makefile 命令中就包含了调用 gcc 去编译某个源文件的命令。
而当工程规模非常大时,且需要跨平台时,手写 makefile 也开始变得麻烦,这是可以借助 cmake 来生成 makefile 。
MinGW-w64
就是 Windows 平台下集成了 gcc 和 make (gcc.exe
和 bin/mingw32-make.exe
)的工具 ,上面我们已经分别配置好了 MinGW-w64 和 CMake ,为了更好地配合这两个工具来完成工程的编译,下面需要再完成一点点额外的配置:
打开 MinGW-w64 的 bin 目录,拷贝一份 mingw32-make.exe
改名为 make.exe
:
$ make --version
GNU Make 4.2.1
Built for x86_64-w64-mingw32
Copyright (C) 1988-2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.