总体概括:

        cmakeList.txt ----->cmake工具---->makefile文件(包含gcc/g++命令)---->make工具---->编译连接源文件

编译器的工作流程:

         源码(source code)---->预处理器(preprocessor)---->编译器(compiler)---->汇编程序(assembler)---->目标代码(target code)---->链接器(linker)---->可执行程序(executable)

GCC:全称GNU Compiler Collection,是GNU编译器套装,最开始是编译c语言,后来可处理c++、java等语言

G++:是GCC对C++的升级版本

Make:是批处理工具,通过规则文件makefile调用GCC等实现编译

CMake:是跨平台编译工具,依赖规则文件CMakeList.txt生成makefile

GCC

理解linux编译工具 gcc、g++、cmake、make、makefile、makelist.txt 关系

  • 基本用法

语法: 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)

eg:(1)将hello.cpp 预编译 并链接到 hello.i

理解linux编译工具 gcc、g++、cmake、make、makefile、makelist.txt 关系

(2)编译hello.i 并链接到 hello.s

理解linux编译工具 gcc、g++、cmake、make、makefile、makelist.txt 关系

(3)编译和汇编 hello.s 并链接到 hello.o

理解linux编译工具 gcc、g++、cmake、make、makefile、makelist.txt 关系

(4)将hello.o链接到hello ,并执行

理解linux编译工具 gcc、g++、cmake、make、makefile、makelist.txt 关系

GCC 与 G++ 区别

  • 两者都可以编译 C 和 C++ 代码;对于 .c 文件,GCC 把它当做 C 程序,G++ 当做 C++ 程序;对于 .cpp 文件,二者都将其视为 C++ 程序
  • 编译阶段,G++ 会调用 GCC,对于 C++ 代码,两者等价;但 GCC 不能自动和 C++ 程序使用的库链接,因而,对于 C++ 程序,一般都使用 G++ 做编译和链接

 

Make/Makefile CMake/CMakeList.txt 

  • GCC/G++ 一般用于单个源文件的编译,当一个工程有多个源文件时,再用 GCC/G++ 逐个编译效率太低,所以出现 make 工具。
  • Make 相当于一个批处理命令,本身没有编译功能,通过 makefile 规则文件调用 GCC/G++ 或其他命令来编译和链接。当工程较大时,手写 makefile 比较麻烦;且在不同平台下编译时,需重新修改 makefile 文件,十分麻烦,因而 CMake 应运而生。
  • CMake 是一个跨平台的编译工具,通过规则文件 CMakeLists.txt 生成 Makefile 文件,CMakeLists.txt 文件需要自己去写.

逻辑图如下:

  • 理解linux编译工具 gcc、g++、cmake、make、makefile、makelist.txt 关系

MakeList.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)

 

eg:(1)编写 hello_world.cpp 源文件和 CMakeLists.txt 文件

理解linux编译工具 gcc、g++、cmake、make、makefile、makelist.txt 关系

(2)在当前路径下执行 cmake .  命令,可以发现生成了 CMakeFIles 文件夹和CMakeCache.txt, cmake_install.cmake, Makefie 文件

理解linux编译工具 gcc、g++、cmake、make、makefile、makelist.txt 关系

(3)在当前路径下执行 make 命令,生成了可执行文件

理解linux编译工具 gcc、g++、cmake、make、makefile、makelist.txt 关系

 

 

 

 

 

 

相关文章: