C/C++编译构建相关问题
名词辨析
GNU
- GNU's Not Unix!的递归缩写
- 一个自由的操作系统,起源于GNU计划,希望发展出一套完整的开放源代码操作系统来取代Unix
- 基本组成包括:
- GNU编译器套装(GCC)
- GNU的C库(glibc)
- GNU核心工具组(coreutils)
GCC
- GNU Compiler Collection, GNU编译器套装
- 有多种语言前端,可用于解析不同的编程语言、操作系统、计算机系统结构,是GNU计划的关键部分,也是GNU工具链的主要组成部分之一
- 可以编译C、C++、JAV、Fortran、Pascal、Object-C、Ada,Go等语言
gcc/g++/MinGW
- gcc: GCC中的GUN C Compiler(C 编译器)
- g++: GUN C++ Compiler(C++编译器)
- MinGW: Minimalist GNU for Windows,是将GCC编译器和GNU Binutils移植到Win32平台下的产物
但根据GCC的gcc和g++区别的说法,gcc和g++并不是编译器,它们只是一种驱动器[1],它们会根据参数中要编译的文件的类型,调用对应的GUN编译器。以编译C语言为例,包含以下过程。
Step1:Call a preprocessor, like cpp.
Step2:Call an actual compiler, like cc or cc1.
Step3:Call an assembler, like as.
Step4:Call a linker, like ld
因此gcc带参数个人理解就是去单独调用上面提及的一些工具,由此来说gcc更像是一种工具的封装,通过参数实现具体的工具调用
两者的联系和区别
对于 *.c文件,gcc当做c文件看待,g++当做cpp文件看待
虽然gcc和g++都可以编译*.c文件,但是二者会以不同的语言来对待c文件,而C++ 标准和 C 语言标准的语法要求是有区别的。
#include <stdio.h>
int main()
{
const char * a = "abc";
printStr(a);
return;
}
int printStr(const char* str)
{
printf(str);
}
以上代码使用gcc进行编译,其会看为c语言,编译结果为

以上代码使用g++进行编译,其会看为c++,编译结果为

由此可见,c++的语言要求会更高一些
对于 *.cpp文件,gcc当做cpp文件看待,g++当做cpp文件看待
虽然二者都会以cpp文件来对待,但是对于调用某些标准库中现有的函数或者类对象的c++程序,而单纯的 gcc 命令无法自动链接这些标准库文件,无法完成编译
MSVC
- Microsoft Visual C++,is a compiler for the C, C++ and C++/CX programming languages by Microsoft
LLVM
LLVM最初是指Low Level Virtual Machine,是类似但不同于jvm的一种虚拟机,现在来说,有很多理解方式,可以说LLVM是编译器的工具链的集合,Clang是使用LLVM的编译器;又或者说LLVM是一个优秀的编译器框架,它也采用经典的三段式设计
根据编译原理可以了解到,在GCC中前端和后端的分界并非明显,这就导致出现下面的情况,一种语言的前端对对应多个后端

而LLVM架构通过引入LLVM IR(Intermediate Representation)解决了这一问题,形成的LLVM架构如下图所示

clang/clang++
是LLVM项目中的一个子项目,是基于LLVM架构的轻量级编译器,属于整个LLVM架构中的编译器前端(由LLVM架构图可得知)
创造目的是为了替代GCC,提供更快的编译速度
make
make工具可以看成是一个智能的批处理工具,它本身并没有编译和链接的功能,而是用类似于批处理的方式—通过调用makefile文件中用户指定的命令利用gcc(或g++)来进行编译和链接。当程序只有一个源文件时,可以直接使用用gcc(或g++)命令进行编译。但当程序包含多个源文件时,逐文件去编译,编译顺序可能出现混乱同时工作量较大
cmake
makefile在一些简单的工程中可以人工书写,但当工程较大时,手写makefile较为麻烦,同时更换平台需要修改makefile,cmake工具可以根据CMakeLists.txt文件去生成makefile,过程如下图所示

构建流程
1.配置项目:cmake -S . -B build 或 ctrl + shift + p > cmake configure
2.构建项目:cmake --build build 或 ctrl + shift + p > cmake build
// cmake最低版本
cmake_minimum_required(VERSION 3.0.0)
// 工程文件名
project(experiment2 VERSION 0.1.0)
// 寻找第三方库
// c++包管理工具vcpkg(类似pip,使用时再查找)
find_package(库名称 REQUIRED(库是必须的,未安装则报错))
// 匹配所有源文件添加到变量SRC_FILES中
file(GLOB SRC_FILES
"${PROJECT_SOURCE_DIR}/src/*.h"
"${PROJECT_SOURCE_DIR}/src/*.cpp"
"${PROJECT_SOURCE_DIR}/src/*.cc"
"${PROJECT_SOURCE_DIR}/src/*.c"
)
# 这里只是设置两个变量,并没有指定这个路径
set(INC_DIR include目录路径) # 设置include路径变量
set(LINK_DIR 库目录路径) # 设置library路径变量
# 指定include和lib路径
include_directories(${INC_DIR})
link_directories(${LINK_DIR})
# 链接静态库,在下一步构建可执行文件之前
# 需要理解的是上一步只是指示了头文件和库的路径,程序还需要显示包含
# 头文件往往都是在程序中再include,lib可以在程序中指明,但一般是直接在这里写上,程序中就不再添加代码了
link_libraries(库名称)
# 构建可执行文件
# ${CMAKE_PROJECT_NAME}:被替换为project指定的名称
# ${SRC_FILES}:file命令找到的所有源文件
add_executable(${CMAKE_PROJECT_NAME} ${SRC_FILES})
# 链接动态库(Link),需要在上一步构建可执行文件之后
target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE 库名称)
// 支持c++17
target_compile_features(${CMAKE_PROJECT_NAME} PRIVATE cxx_std_17)
// 自动化工作
// 需要使用再详细查找
add_custom_command(
TARGET ${CMAKE_PROJECT_NAME}
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory
"")
CMakeLists示例
此示例用于winPcap开发
cmake_minimum_required(VERSION 3.0.0)
project(experiment2 VERSION 0.1.0)
file(GLOB SRC_FILES
"${PROJECT_SOURCE_DIR}/*.cpp"
)
set(INC_DIR E:/useful/cmake_project/WpdPack/Include)
set(LINK_DIR E:/useful/cmake_project/WpdPack/Lib/x64)
include_directories(${INC_DIR})
link_directories(${LINK_DIR})
link_libraries(Packet wpcap)
add_executable(${CMAKE_PROJECT_NAME} ${SRC_FILES})
参考
- [1] GNU的发展史
- [2] GCC的gcc和g++区别
- [3] 编译器 cc、gcc、g++、CC 的区别
- [4] Linux环境中gcc和g++的区别详解
- [5] GCC、LLVM、Clang区别
- [6] 业界主流3大编译器
- [7] 区分gnu的gcc/g++, mingw/msvc, llvm的clang/clang++, make,cmake
- [8] LLVM架构(相关资料)
- [9] CMake入门
编译流程
以gcc为例

- 预处理(预编译):头文件包含,条件编译,宏替换,删除注释
- 编译:词法,语法,语义分析,生成汇编代码
- 汇编:将汇编语言转化为相应的机器语言(二进制目标文件)
- 链接[2]:将多个可重定位目标文件和标准库函数合并为可执行目标文件
关于驱动器的说法,目前只在gcc/g++链接选项一文中看到相关说法 ︎
C/C++编译构建相关问题的更多相关文章
- pbuilder编译构建工具分析
1. 简介 pbuilder(personal Debian package builder)是ubuntu环境下维护debian包的专业工具,能够为每个deb包创建纯净的编译构建环境,自动解析和安装 ...
- kubernetes下jenkins实战maven项目编译构建
关于kubernetes环境的jenkins集群 在kubernetes环境部署的jenkins集群,执行任务时会新建pod,任务完成后pod被销毁,架构如下所示: 在kubernetes搭建jenk ...
- Nginx编译安装相关参数
Nginx编译安装相关参数 Nginx插件安装 ------------------pcre------------------ cd /usr/local/source wget http://ww ...
- wxWidgets的安装编译、相关配置、问题分析处理
wxWidgets的安装编译.相关配置.问题分析处理 一.介绍部分 (win7 下的 GUI 效果图见 本篇文章的最后部分截图2张) wxWidgets是一个开源的跨平台的C++构架库(framewo ...
- 纯干货!华为软件开发云编译构建之Maven
一.Maven介绍 Maven是一个项目管理和整合的工具.Maven为开发者提供了一套完整的构建生命周期框架.开发团队基本不用花多少时间就能自动完成工程的基础构建配置,因为Maven使用了一个标准的目 ...
- 《Linux操作系统编译构建指南》
在线阅读地址:http://www.doc88.com/p-5126905896771.html Linux编译构建定制qq群: 521902245 文件夹...0 前言...3 第零章 绪论...5 ...
- 如何在Idea中编译构建Spring Framework 5.x
如何在Idea中编译构建Spring Framework 5.x 安装配置Gradle(略) 下载源码:git clone https://github.com/spring-projects/spr ...
- 【计算机视觉】关于OpenCV中GPU配置编译的相关事项
[计算机视觉]关于OpenCV中GPU配置编译的相关事项 标签(空格分隔): [计算机视觉] 前一段发现了OpenCV中关于GPU以及opencl的相关知识,打算升级一下对OpenCV的使用,但是发现 ...
- Qt 编译配置相关总结
MinGW 与 MSVC 编译的区别 我们可以从 Qt 下载页面看到两种版本编译器,如下图: 我们来对比一下这两个编译器的区别: MSVC 是指微软的 VC 编译器. MinGW 是 Minimali ...
- 踩坑经验总结之go web开源库第一次编译构建
前言:记录一个go新手第一次构建复杂开源库的经历.go虽然是新手,但是编程上还是有多年的经验,除了c/c++,用过IDEA能进行简单的java编程.甚至scala编程.所以最开始还是有点信心的.所以也 ...
随机推荐
- 简体Windows系统登录玩新枫之谷方法
2022-2-23 游戏更新后Locale.Emulato失效,64位游戏使用新的工具Locale_Remulator,请自行到GitHub上搜索下载,使用方法与Locale.Emulato类似. ...
- CPU密集型和IO密集型与线程池的配置
CPU密集型任务应配置尽可能小的线程,如配置CPU数目+1个线程的线程池.由于IO密集型任务线程并不是一直在执行任务,则应配置尽可能多的线程,如2*CPU数目.
- Java中Math类常用方法
在编写程序时,可能需要计算一个数的平方根.绝对值或获取一个随机数等.java.lang包中的Math类包含许多用来进行科学计算的static方法,这些方法可以直接通过类名调用.另外,Math类还有两 ...
- DER编码
1. Attribute Type编码 对于标识串,采用低标识编码方式,只需1个字节.OBJECT IDENTIFIER的 tag为Ox06;class选择universal,则位8和位7为0,O ...
- MQTT服务器搭建——Liunx安装mosquitto,并设置用户密码
一.安装 1.下载mosquitto安装包 地址:http://mosquitto.org/files/source/ 2.安装依赖包 yum install gcc gcc-c++ libstdc+ ...
- 虚拟机VMware15的CentOS7.3的docker下安装Oracle11g
1.拉取镜像docker pull registry.cn-hangzhou.aliyuncs.com/helowin/oracle_11g 2.安装容器:docker run -d --name o ...
- mysql_记录操作
在MySQL管理软件中,可以通过SQL语句中的DML语言来实现数据的操作,包括 使用INSERT实现数据的插入 UPDATE实现数据的更新 使用DELETE实现数据的删除 使用SELECT查询数据以及 ...
- 如何跳出forEach循环
for(let ii in this.listData){ console.log("提交前数据",ii) try{ this.listData[ii].forEach((el,i ...
- maven远程debug
1.修改tomcat服务器配置 打开tomcat/bin/catalina.sh 添加参数 CATALINA_OPTS="-Xdebug -Xrunjdwp:transport=dt_soc ...
- Spring校验:@Validated和@Valid区别
结论: Spring validation验证框架对入参实体进行嵌套验证必须在相应属性(字段)加上@Valid而不是@Validated Spring Validation验证框架对参数的验证机制提供 ...