Linux 编译工具 gcc/g++、Make/Makefile、CMake/CMakeLists.txt、qmake
前言
编译器的主要工作流程:
源码(Source Code)>> 预处理器(Preprocessor)>> 编译器(Compiler)>> 汇编程序(Assembler)>> 目标代码(Target Code)>> 链接器(Linker)>> 可执行程序(Executables)
- GCC,全称 GNU Compiler Collection,是 GNU 编译器套装,最开始编译 C 语言,后来可以处理 C++ 以及 Fortran, Java, Go 等其他语言;
- G++ 是 GCC 对 C++ 的升级版本,两者区别见后文;
- Make 是批处理工具,通过规则文件 Makefile 调用 GCC 等实现编译;
- CMake 是跨平台编译工具,依据规则文件 CMakeLists.txt 生成 Makefile
- qmake 是 Qt 专用编译工具,也是生成 Makefile 文件
一. GCC / G++
- 基本用法
语法: gcc/g++ [options] file...
gcc [-E | -S | -c] [-std=standrad]
[-g] [-Idir] [-Ldir]
[-o outfile]
基本选项
-E Preprocess only; do not compile, assemble or link 预处理
-S Compile only; do not assemble or link 编译,生成 .s 汇编代码
-c Compile and assemble, but do not link 编译和汇编,生成 .o 的 obj 文件
-o <file> Place the output into <file> 链接,将 .o 链接到指定的可执行文件,若不指定可执行文件的名称,默认为 a.out目录选项
-Idir 指定头文件的搜索目录
-Ldir 指定库文件的搜索目录
-llibraray 指定编译时使用的库
链接方式选项
-static 编译为静态库
-shared 编译为动态库
-dPIC 编译器就输出位置无关目标代码,使用于生成动态链接库(DLL - Dynamic Linking Library)
- 举例

- GCC 与 G++ 区别
- 两者都可以编译 C 和 C++ 代码;对于 .c 文件,GCC 把它当做 C 程序,G++ 当做 C++ 程序;对于 .cpp 文件,二者都将其视为 C++ 程序
- 编译阶段,G++ 会调用 GCC,对于 C++ 代码,两者等价;但 GCC 不能自动和 C++ 程序使用的库链接,因而,对于 C++ 程序,一般都使用 G++ 做编译和链接
二. Make / Makefile、CMake / CMakeLists.txt、qmake
- GCC/G++ 一般用于单个源文件的编译,当一个工程有多个源文件时,再用 GCC/G++ 逐个编译效率太低,所以出现 make 工具。
- Make 相当于一个批处理命令,本身没有编译功能,通过 makefile 规则文件调用 GCC/G++ 或其他命令来编译和链接。当工程较大时,手写 makefile 比较麻烦;且在不同平台下编译时,需重新修改 makefile 文件,十分麻烦,因而 CMake 应运而生。
- CMake 是一个跨平台的编译工具,通过规则文件 CMakeLists.txt 生成 Makefile 文件,CMakeLists.txt 文件需要自己去写。
- qmake 是为 Qt 量身打造的编译工具,Qt 是跨平台 C++ 图形用户界面应用程序开发框架。qmake 根据 Qt 工程文件(.pro)生成跨平台的 makefile 文件。
整个逻辑如下图所示(参考知乎问题:make makefile cmake qmake都是什么,有什么区别?):

三. CMakeLists.txt
- 基本指令
0. 基本语法规则
- 变量使用 ${} 取值,IF控制语句中直接使用变量名
- 指令(参数1 参数2 ...)
- 参数之间用
- 指令大小写无关,参数和变量大小写相关,但推荐全部使用大写
1. 指定 cmake 最小版本
CMAKE_MINIMUM_REQUIRED(VERSION 3.5.1)此命令是可选的,一般不需要写这句话,但当使用了高版本的 cmake,则需要提醒用户需要升级 cmake
2. 设置项目名称
PROJECT(hello)自动引入两个变量 hello_BINARY_DIR 和 hello_SOURCE_DIR
3. 生成可执行文件
ADD_EXECUTABLE(hello hello_world.cpp)4. 设置编译类型
1. ADD_LIBRARY(hello hello.cpp) # 默认生成静态库
2. ADD_LIBRARY(hello STATIC hello.cpp) # 指定为静态库
3. ADD_LIBRARY(helloshared SHARED hello.cpp) # 指定为共享库假设 hello.cpp 文件中没有 main 函数,意味着这个库中没有可执行文件。添加上述命令,cmake 后会依次生成下面几个文件:
libhello.a libhello.a libhello_shared.so
静态库以 .a 为后缀名,共享库以 .so 为后缀名,所有库都是一些函数打包后的集合,静态库每次被调用都会生成一个副本,而共享库则只有一个副本,更省空间。
库文件是一个压缩包,里面有编译好的二进制函数,仅有 .a 或 .so 库文件,别人并不知道里面的函数是什么样的,或如何调用;这就需要提供一个头文件,有了库文件和头文件,就可以调用这个库。
5. 设置变量
(1)set 直接设置变量的值
SET(SRC_LIST a.cpp b.cpp)
ADD_EXECTUABLE(demo ${SRC_LIST})(2)set 追加设置变量的值
SET(SRC_LIST a.cpp)
SET(SRC_LIST ${SRC_LIST} b.cpp)
ADD_EXECTUABLE(demo ${SRC_LIST})(3)LIST 追加或删除变量的值
SET(SRC_LIST a.cpp)
LIST(APPEND SRC_LIST b.cpp)
LIST(REMOVE_ITEM SRC_LIST b.cpp)
ADD_EXECTUABLE(demo ${SRC_LIST})6. 指定源文件
(1)明确指定(用空格或分号隔开)
ADD_LIBRARY(hello hello.cpp a.cpp b.cpp)(2)所有源文件
AUX_SOURCE_DIRECTORY(dir VAR) 发现一个目录下所有的源代码文件并将列表存储在一个变量中。AUX_SOURCE_DIRECTORY(. SRC_LIST) # 搜索当前目录下的所有.cpp文件ADD_LIBRARY(hello ${SRC_LIST})7. 查找指定的库文件
FIND_LIBRARY(VAR name path)查找到指定的预编译库,并将它的路径存储在变量中。默认的搜索路径为 cmake 包含的系统库。
类似的命令还有 find_file()、find_path()、find_program()、find_package()等。
8. 设置包含的目录
INCLUDE_DIRECTORIES(
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/include或
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -I${CMAKE_CURRENT_SOURCE_DIR}")9. 设置链接库搜索目录
LINK_DIRECTORIES(
${CMAKE_CURRENT_SOURCE_DIR}/libs
)或
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -L${CMAKE_CURRENT_SOURCE_DIR}/libs")10. 设置 Target 需要链接的库
TARGET_LINK_LIBRARIES(target_lib link_lib_path)(1)指定链接静态库或共享库
TARGET_LINK_LIBRARIES(hello libhello.a)TARGET_LINK_LIBRARIES(hello libhello_shared.so)(2)设置全路径
TARGET_LINK_LIBRARIES(hello ${CMAKE_CURRENT_SOURCE_DIR}/libs/libhello.a)TARGET_LINK_LIBRARIES(hello ${CMAKE_CURRENT_SOURCE_DIR}/libs/libhello_shared.so)
- 示例:hello_world
(1)编写 hello_world.cpp 源文件和 CMakeLists.txt 文件
(2)在当前路径下执行 cmake . 命令,可以发现生成了 CMakeFIles 文件夹和CMakeCache.txt, cmake_install.cmake, Makefie 文件
(3)在当前路径下执行 make 命令,生成了可执行文件

参考:
[1]. 《视觉 SLAM 十四讲》高翔
[2]. 博客:https://blog.csdn.net/afei__/article/details/81201039
Linux 编译工具 gcc/g++、Make/Makefile、CMake/CMakeLists.txt、qmake的更多相关文章
- [转]Linux下用gcc/g++生成静态库和动态库(Z)
Linux下用gcc/g++生成静态库和动态库(Z) 2012-07-24 16:45:10| 分类: linux | 标签:链接库 linux g++ gcc |举报|字号 订阅 ...
- 解决安装编译工具gcc后无法连接mysql
在安装编译工具gcc后: yum -y install make gcc g++ gcc-c++ libtool autoconf automake imake mysql-devel libxml2 ...
- make Makefile 与 cmake CMakeLists.txt
make Makefile 与 cmake CMakeLists.txt 大家都知道,写程序大体步骤为: 1.用编辑器编写源代码,如.c文件. 2.用编译器编译代码生成目标文件,如.o. 3.用链接器 ...
- Linux编译工具:gcc入门
1. 什么是gcc gcc的全称是GNU Compiler Collection,它是一个能够编译多种语言的编译器.最开始gcc是作为C语言的编译器(GNU C Compiler),现在除了c语言,还 ...
- linux下使用gcc/g++编译代码时gets函数有错误
今天在linux中使用个g++编译一个名为myfirst.cpp的代码的时候,出现如下错误 myfirst.cpp: In function ‘int main()’:myfirst.cpp:11:2 ...
- gcc,g++,make,cmake的区别
首先介绍一下GCC:GNU Compiler Collection(GNU 编译器集合),在为Linux开发应用程序时,绝大多数情况下使用的都是C语言,因此几乎每一位Linux程序员面临的首要问题都是 ...
- Linux 之 编译器 gcc/g++参数详解
2016年12月9日16:48:53 ----------------------------- 内容目录: [介绍] gcc and g++分别是gnu的c & c++编译器 gcc/g++ ...
- [forward] cmake, CMakeLists.txt梳理
cmake intro 原文请见 cmake使用总结(转)-工程主目录CMakeList文件编写 在 Linux 下进行开发很多人选择编写 makefile 文件进行项目环境搭建,而makefile ...
- Makefile 和 CMakeLists.txt
Makefile Makefile 的格式 target: prerequisites [tab]command 例子 #Makefile all:chap1 chap2 chap1: - - - : ...
随机推荐
- PostgreSQL中的onflict
PostgreSQL 9.5 引入了一项新功能,UPSERT(insert on conflict do),当插入遇到约束错误时,直接返回,或者改为执行UPDATE. 1.不存在则插入,存在则更新 i ...
- 初级模拟电路:4-1 BJT交流分析概述
回到目录 BJT晶体管的交流分析(也叫小信号分析)是模拟电路中的一个难点,也可以说是模电中的一个分水岭.如果你能够把BJT交流分析的原理全都搞懂,那之后的学习就是一马平川了.后面的大部分内容,诸如:场 ...
- ReactNative: 使用导航栏组件-NavigatorIOS组件和Navigator组件
一.简言 在软件开发中,不论是Web还是App,它们的应用程序都是由很多的功能视图组成的.对于这些组合的视图,如何实现页面间平滑地过渡,应用都有统一的一套跳转机制,这个功能就是路由或者叫导航.应用程序 ...
- Java实现网络聊天中使用的socket API与Linux socket API之间的关系
尝试着用Java编写一个网络聊天程序,发现总不如网上写的好,所以就直接引用了网上大神的优秀代码.代码如下: package project1; import java.awt.*; import ja ...
- 2019年全国高校计算机能力挑战赛初赛C语言解答
http://www.ncccu.org.cn 2019年全国高校计算机能力挑战赛分设大数据算法赛,人工智能算法赛,Office高级应用赛,程序设计赛4大赛项 C语言初赛解答 1:编程1 16.现有一 ...
- ArrayList和LinkedList介绍
java.util.ArrayList集合的数据存储结构是数组,且是多线程,元素增删慢,查找快, 由于日常使用开发大多数为查询数据,遍历数据,所以ArrayList是最常用的集合.上一节已写了. ja ...
- 手把手教你搭建织女星开发板RISC-V开发环境
前言 Windows环境下搭建基于Eclipse + RISC-V gcc编译器的RISC-V开发环境,配合openocd调试软件,可以实现RISC-V内核程序的编译.下载和调试. 准备工作 工欲善其 ...
- js 对 只包含简单类型数据的对象 为元素 组成的数组 进行去重
/** * 对于由简单类型数据组成的对象为元素组成的数组进行去重操作 * @params {Array} 需要去重的对象数组 * @returns {Array} 去重后的对象数组 */ functi ...
- (转)Skyline timeseries异常判定算法
原文链接:https://jiroujuan.wordpress.com/2013/10/09/skyline-anomalous-detect-algorithms/ Skyline内部提供了9个预 ...
- mac pro下iterm快捷键(转)
标签 新建标签:command + t 关闭标签:command + w 切换标签:command + 数字 command + 左右方向键 切换全屏:command + enter 查找:comma ...