编译(compile):
指将源代码翻译为机器码的过程.输入文件是C / CPP / H等文本文件,输出是OBJ目标文件。
编译器需要的是语法的正确,函数与变量的声明的正确。
链接(Link):
指的是把多个OBJ目标文件、LIB库文件链接成一个可执行文件的过程。链接过程的输入是OBJ / LIB等库文件,输出是EXE / DLL等可执行文件。
构建(build):
指包括编译在内的一系列处理过程。在大型工程中,构建涵盖了对源代码的编译、对库文件的链接,还有可能包含映像文件打包等其它附加操作。构建的范围是最大的
C/C++常用编译器
桌面操作系统
- MSVC (Microsoft Visual C/C++)编译器:
由微软开发,用于Windows系统下C/C++编译
- GCC(GNU Compiler Collection,GNU编译器套件):
GNU是在Linux上运行的一种自由的操作系统,基于此衍生出了许多工具。GCC是一套支持C、C++、Fortan、Pascal等语言的编译器套件,运行在Linux系统下。当然GCC现在也可用于Windows系统, MinGW (Minimalist GNU for Windows)提供了一套简单方便的Windows下的基于GCC 程序开发环境。后来经过区分,一般把针对C语言的编译器称为gcc、而把针对C++的编译器称为g++。
- LLVM Clang编译器:
Clang是一个由Apple主导编写,基于LLVM的C/C++/Objective-C编译器。更进一步来说,Clang只是一个编译器前端,其将上述的C类语言编译成一种“汇编语言(中间语言)”。接着,通过LLVM(Low Level Virtual Machine)作为后端,将这种“汇编语言”编译成针对不同机器的二进制机器语言。可在macOS、Linux、Windows等平台使用.
C/C++chang常用调试器
调试(Debug)是指通过调试器(Debugger)跟踪程序的运行过程,发现程序中的逻辑错误以及缺陷等问题。在调试过程中,我们可以监控程序的每一个细节,包括变量值、线程调度、内存情况等。一般的IDE都会自带调试器,目前常见的调试器列举如下:
- Remote Debugger:
VC/VS自带的调试器,由微软开发,与IDE紧密衔接,使用方便。
- WinDbg:
由微软开发的Windows系统下轻量级的调试器,功能齐全,但指令较为复杂。
- LLDB:
XCode自带的调试器,用于macOS系统下的开发。
- GDB(GNU symbolic debugger):
与编译器GCC同宗同源,最早用于Linux系统下的调试,现也能移植于WIndows与macOS系统。
CMakeLists.txt经过cmake命令得到makefile文件,然后再执行make命令得到可执行文件或库。
cmake
CMake是一个跨平台的安装(编译)工具,可以用简单的语句来描述所有平台的编译过程;他能够输出各种各样的makefile或者project(如.sln、.pro)文件,能测试编译器所支持的C++特性,类似UNIX下的automake。
下载地址:https://cmake.org/download/
在windows系统可以直接下载CMake (cmake-gui)软件进行操作。
在linux系统可以直接下载二进制程序,或者下载源码编译安装。
如果是源码安装,那就是走解压缩、配置、编译、安装的4步。
后续就是建立软连接
sudo ln -s /home/shl/tools/cmake-3.30.1-Linux-x86_64/bin/cmake /usr/bin/cmake
最后就是cmake --version 查看是否安装或者升级成功
Cmake 命令行参数
可以使用cmake -help 帮助查看
-D:用于设置 CMake 变量
cmake path_to_source_directory -DVAR_NAME=VALUE
如:
cmake ..\aws-sdk-cpp-1.11.370 -DCMAKE_BUILD_TYPE=Release //编译release
-G:用于指定生成器(generator)。生成器决定了 CMake 会生成哪种类型的构建系统文件,Visual Studio、Makefiles等
如:
cmake -G "Unix Makefiles" path_to_source_directory
cmake -G "Visual Studio 17 2022" path_to_source_directory //指定编译器版本
cmake -G "Visual Studio 16 2019 x64" path_to_source_directory //指定编译器、平台集
-B 和 -S:用于分别指定构建目录和源代码目录
例如,如果你想在一个名为"my_source_dir"的目录中构建一个项目,并将构建文件放在名为"my_build_dir"的目录中,你可以使用以下命令:
cmake -S my_source_dir -B my_build_dir
--build:用于执行构建过程
cmake --build path_to_build_directory
--config:用于指定构建类型,例如 Debug 或 Release。
cmake --build path_to_build_directory --config Release
--install : 用于指定的文件或者目录复制到指定的目录下,一般前面就设置intall的指定目录
cmake --install
CmakeLists.txt
CMakeLists.txt是CMake构建系统的核心文件,用于控制编译过程。以下是使用CMakeLists.txt的基本步骤:
设置CMake最低兼容版本:在CMakeLists.txt的开头,需要指定CMake的最低兼容版本,例如cmake_minimum_required(VERSION 3.10)。
设置项目名称:使用project()命令设置项目的名称。
添加管理文件间的相互依赖关系:CMakeLists.txt的主要作用是添加和管理文件间的相互依赖关系,例如主程序与库之间的依赖关系。
设置头文件的目录:使用include_directories()命令添加头文件的搜索路径。
添加源文件:使用add_executable()或add_library()命令添加可执行文件或库文件,并指定源文件。
链接库文件:使用target_link_libraries()命令链接其他库文件。
生成Makefile:在构建目录(通常是build目录)中运行cmake ..命令,这将生成Makefile和其他编译所需的文件。
编译:使用make命令进行编译。
CMakeLists.txt示例
先简单的写一个cpp文件,在include文件夹下放置test.h和test.cpp文件;LearnCmake.cpp主要包含main函数,test.h和test.cpp的主要内容是:
//test.h的内容
#pragma once
#include <iostream>
void fun();
//test.cpp的内容
#include "test.h"
void fun()
{
std::cout << "测试函数" << std::endl;
}
#include <iostream>
#include "test.h"
using namespace std;
int main()
{
fun();
cout << "输出结果" << endl;
system("pause");
return 0;
}
MyProject/
|── CMakeLists.txt
|── LearnCmake.cpp
|── include/
| |──test.h
| └──test.cpp
#所需的最低版本
cmake_minimum_required(VERSION 3.0)
#本CMakeLists.txt的project名称,用于生成learnCmake.sln
project(learnCmake)
#设置生成文件的路径,这将会把生成的可执行文件放置在 ${CMAKE_BINARY_DIR}/bin 文件夹中
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
#设置include文件夹路径,可以理解为附加包含目录
include_directories(include)
#先添加test.cpp文件到一个名为test_lib的库
add_library(test_lib include/test.cpp)
#将.cpp/.c/.cc文件生成可执行文件,a就是a.exe
add_executable(a LearnCMake.cpp)
# 将test_lib链接到a.exe,一定是先add_executable,再target_link_libraries
target_link_libraries(a test_lib)
首先,先将test.cpp编译成一个静态库,同时生成一个a.exe,再将静态库链接到a.exe内;顺序不能错了,不能先链接到exe(因为此时exe还未生成),再生成exe;这样从cmake里就能看到源码编译的过程,也是上面我说的第二条,也能更好地理解编译的过程。
常用的函数
include_directories
include_directories(路径)
规定.h头文件路径
link_directories
link_directories(路径)
# 规定.so/.a库文件路径
add_executable
add_executable(可执行文件名称 文件)
将.cpp/.c/.cc文件生成可执行文件
add_library
add_library(库文件名称 STATIC 文件)
将.cpp/.c/.cc文件生成.a静态库
注意,库文件名称通常为libxxx.so,在这里只要写xxx即可
target_link_libraries
target_link_libraries(库文件名称/可执行文件名称 链接的库文件名称)
对add_library或add_executable生成的文件进行链接操作 # 注意,库文件名称通常为libxxx.so,在这里只要写xxx即可
Project
project(<PROJECT-NAME> [<language-name>...])
project命令用于指定cmake工程的名称,实际上,它还可以指定cmake工程的版本号(VERSION关键字)、简短的描述(DESCRIPTION关键字)、主页URL(HOMEPAGE_URL关键字)和编译工程使用的语言(LANGUAGES关键字)
project(mytest VERSION 1.2.3.4)
project (mytest HOMEPAGE_URL “https://www.XXX(示例).com”)
${PROJECT_SOURCE_DIR} 和 <PROJECT-NAME>_SOURCE_DIR
是CMakeLists.txt所在的文件夹路径
常见的变量
CMAKE_SOURCE_DIR:当前 CMakeLists.txt 所在的源码目录的根路径。
CMAKE_BINARY_DIR:构建目录的根路径,即构建生成的可执行文件、库和其他构建输出的存放位置。
CMAKE_CURRENT_SOURCE_DIR:当前处理的 CMakeLists.txt 所在的源码目录的路径。
CMAKE_CURRENT_BINARY_DIR:当前处理的 CMakeLists.txt 所在的构建目录的路径。
CMAKE_CURRENT_LIST_DIR:当前处理的 CMakeLists.txt 所在的路径(源码目录或构建目录)。
CMAKE_CURRENT_LIST_LINE:当前正在处理的 CMakeLists.txt 的行号。
CMAKE_MODULE_PATH:一个用于指定额外的 CMake 模块(.cmake 文件)的搜索路径的列表。
CMAKE_INCLUDE_CURRENT_DIR:如果设置为 ON,则在构建过程中自动将当前处理的 CMakeLists.txt 所在的目录添加到包含路径中。
CMAKE_LIBRARY_OUTPUT_DIRECTORY:库文件的输出目录。
CMAKE_RUNTIME_OUTPUT_DIRECTORY:可执行文件的输出目录。
file
file(
GLOB SOURCES
${PROJECT_SOURCE_DIR}/*.c
)
获取目录下的所有cpp文件(不包括子目录),并赋值给SOURCES
set
set(变量 文件名/路径/...)
设置变量,给文件名/路径名或其他字符串起别名,用${变量}获取变量内容
add_definitions
add_definitions(-DFOO -DBAR ...)
添加编译选项FOO BAR
add_definitions定义宏,但是这种定义方式无法给宏具体值 等价C语言中的#define MG_ENABLE_OPENSSL
add_compile_definitions
add_compile_definitions(MG_ENABLE_OPENSSL=1)
add_compile_definitions定义宏,这种方式可以给宏具体值,但是这个指令只要高版本的cmake支持 等价C语言中 #define MG_ENABLE_OPENSSL 1
message
message(消息)
打印消息
add_subdirectory
add_subdirectory(子文件夹名称)
编译子文件夹的CMakeLists.txt
make命令
make是一条计算机指令,是在安装有GNU Make的计算机上的可执行指令。该指令是读入一个名为makefile 的文件,然后执行这个文件中指定的指令(编译和链接的之类的指令)。
make(选项)(参数)
选项
-f:指定“makefile”文件;
-i:忽略命令执行返回的出错信息;
-s:沉默模式,在执行之前不输出相应的命令行信息;
-r:禁止使用build-in规则;
-n:非执行模式,输出所有执行命令,但并不执行;
-t:更新目标文件;
-q:make操作将根据目标文件是否已经更新返回"0"或非"0"的状态信息;
-p:输出所有宏定义和目标文件描述;
-d:Debug模式,输出有关文件和检测时间的详细信息。
参数
目标:指定编译目标
makefile文件
它定义了模块间的依赖关系,指定文件的编译顺序,以及编译所使用的命令。
Makefile里主要包含了五个东西:显式规则、隐晦规则、变量定义、文件指示和注释。
- 显式规则
显式规则说明了,如何生成一个或多的的目标文件。这是由Makefile的书写者明显指出,要生成的文件,文件的依赖文件,生成的命令。
- 隐晦规则
由于我们的make有自动推导的功能,所以隐晦的规则可以让我们比较粗糙地简略地书写Makefile,这是由make所支持的。
- 变量的定义
在Makefile中我们要定义一系列的变量,变量一般都是字符串,这个有点你C语言中的宏,当Makefile被执行时,其中的变量都会被扩展到相应的引用位置上。
- 文件指示
其包括了三个部分,一个是在一个Makefile中引用另一个Makefile,就像C语言中的include一样;另一个是指根据某些情况指定Makefile中的有效部分,就像C语言中的预编译#if一样;还有就是定义一个多行的命令。有关这一部分的内容,我会在后续的部分中讲述。
- 注释
Makefile中只有行注释,和UNIX的Shell脚本一样,其注释是用“#”字符,这个就像C/C++中的“//”一样。如果你要在你的Makefile中使用“#”字符,可以用反斜框进行转义,如:“\#”。