Linux Makefile

程序的编译和链接

使用C、C++编写可执行程序,首先要把源文件编译成中间代码文件,Linux下是 .o 文件,即 Object File,这个动作叫做编译(compile)。然后再把大量的Object File合成执行文件,这个动作叫作链接(link)

编译时,编译器需要的是语法的正确,函数与变量的声明的正确。对于后者,通常是你需要告诉编译器头文件的所在位置(头文件中应该只是声明,而定义应该放在C/C++文件中),只要所有的语法正确,编译器就可以编译出中间目标文件。一般来说,每个源文件都应该对应于一个中间目标文件(O文件或是OBJ文件)。
链接时,主要是链接函数和全局变量,所以,可以使用这些中间目标文件(O文件或是OBJ文件)来链接应用程序。链接器并不管函数所在的源文件,只管函数的中间目标文件(Object File),在大多数时候,由于源文件太多,编译生成的中间目标文件太多,而在链接时需要明显地指出中间目标文件名,这对于编译很不方便,所以,我们要给中间目标文件打个包,在Windows下这种包叫“库文件”(Library File),也就是 .lib 文件,在UNIX下,是Archive File,也就是 .a 文件。

总结:
源文件首先会生成中间目标文件,再由中间目标文件生成执行文件。
在编译时,编译器只检测程序语法,和函数、变量是否被声明。如果函数未被声明,编译器会给出一个警告,但可以生成Object File。而在链接程序时,链接器会在所有的Object File中找寻函数的实现,如果找不到,那到就会报链接错误码(Linker Error),在VC下,这种错误一般是:Link 2001错误,意思说是说,链接器未能找到函数的实现。你需要指定函数的ObjectFile.

makefile菜鸟教程

Makefile

Makefile 确定整个工程的编译规则,只需要一个 make 命令,就可以实现“自动化编译”。
make 是一个解释 makefile 中指令的命令工具,一般来说,大多数的 IDE 都有这个命令,比如:Delphi的make,Visual C++ 的 nmake,Linux 下 GNU 的 make。

Makefile入门(超详细一文读懂)

Make 工作原理

通常在一个项目里,规则是:
1)如果这个工程没有编译过,那么所有C文件都要编译并被链接。
2)如果这个工程的某几个C文件被修改,那么只编译被修改的C文件,并链接目标程序。
3)如果这个工程的头文件被改变了,那么需要编译引用了这几个头文件的C文件,并链接目标程序。

语法规则

目标 ... : 依赖 ...
	命令1
	命令2
	. . .

Makefile 并不会关心命令是如何执行的,仅仅只是会去执行所有定义的命令,和我们平时直接输入命令行是一样的效果。

变量

$符号表示取变量的值,当变量名多于一个字符时,使用"( )"
$符的其他用法

$^ 表示所有的依赖文件
$@ 表示生成的目标文件
$< 代表第一个依赖文件

变量赋值

1."="是最普通的等号,在Makefile中容易搞错赋值等号,使用 “=”进行赋值,变量的值是整个Makefile中最后被指定的值。

VIR_A = A
VIR_B = $(VIR_A) B
VIR_A = AA

经过上面的赋值后,最后VIR_B的值是AA B,而不是A B,在make时,会把整个Makefile展开,来决定变量的值

2.“:=” 表示直接赋值,赋予当前位置的值。
3.“?=” 表示如果该变量没有被赋值,赋值予等号后面的值。
4."+="和平时写代码的理解是一样的,表示将符号后面的值添加到前面的变量上

Make 工作流程

1、make 会在当前目录下找名字叫“ Makefile” 或 “makefile” 的文件。
2、如果找到,它会找文件中的第一个目标文件(target),并把这个文件作为最终的目标文件。
3、如果目标文件不存在,或是目标文件所依赖的后面的 .o 文件的文件修改时间要比目标文件新,那么,他就会执行后面所定义的命令来生成这个目标文件。
4、如果目标文件所依赖的.o文件也不存在,那么make会在当前文件中找目标为.o文件的依赖性,如果找到则再根据那一个规则生成.o文件。(像不像堆栈过程?)
5、当然,我们的C文件和H文件都存在,于是make会生成 .o 文件,然后再用 .o 文件生命make的终极任务,也就是执行目标文件了。

伪目标 .PHONY

伪目标只是一个标签,clean是个伪目标没有依赖文件,只有用make来调用时才会执行
当目录下有与 make 命令 同名的文件时 执行 make 命令就会出现错误。
解决办法就是使用伪目标

SRC = $(wildcard *.c)
OBJ = $(patsubst %.c, %.o, $(SRC))
 
ALL: hello.out
 
hello.out: $(OBJ)
        gcc $< -o $@
 
$(OBJ): $(SRC)
        gcc -c $< -o $@
 
clean:
        rm -rf $(OBJ) hello.out
 
.PHONY: clean ALL

通常也会把 ALL 设置成伪目标

CMake

CMake 是一个强大的跨平台构建工具,它能够自动生成用于构建项目的Makefile、Visual Studio项目文件或其他构建系统所需的文件。使用CMake,可以更轻松地管理复杂的C语言项目,使它们易于维护和跨平台。

在 linux 平台下使用 CMake 生成 Makefile 并编译的流程如下: 1.编写 CMake 配置文件 CMakeLists.txt 。 2.执行命令 cmake PATH 生成 Makefile。其中, PATH 是 CMakeLists.txt 所在的目录。 3.使用 make 命令进行编译。

CMakeLists.txt

cmake的核心就是CMakeLists.txt文件,(注意:CMakeLists.txt文件名严格区分大小写,确保文件名准确无误)告诉CMake如何构建项目。通过CMakeLists.txt可以决定工程文件生成二进制文件,动态库,静态库文件,以及链接各种库文件。

不一定每个目录里都要有CMakeLists.txt文件,只要CMakeLists.txt里的各个路径引用正确即可

cmake_minimum_required(VERSION 3.16)
PROJECT (MyCProject)
# 设置编译选项,加入-g可以gdb调试
SET(CMAKE_CXX_FLAGS "-g")
SET(CMAKE_C_FLAGS "-g")
# 添加源文件
file(GLOB SOURCES "src/*.c")
# 添加头文件目录
#INCLUDE_DIRECTORIES(../include)
# 生成可执行文件
add_executable(src ${SOURCES})

以上的CMakeLists.txt文件做了以下事情:

CMakeLists.txt不区分函数名字母大小写,一般一个函数都用大写或者都用小写
**#**号用于注释语句
cmake_minimum_required( )指定CMake的最低版本。
PROJECT( ) 定义项目名称。
SET(CMAKE_CXX_FLAGS “-g”)设置C语言标准,此外set(A B)函数还用于赋值将B赋予A。
使用file()函数将所有在src/目录下的.c文件赋给变量SOURCES
使用include_directories()函数添加头文件目录。
链接库文件路径LINK_LIBRARIES(xxxx.a xxxx.so)
链接库文件LINK_DIRECTORIES(. ./lib/ . ./build/xxx.a . ./build/xxx.so)
最后,使用add_executable()函数生成可执行文件,将源文件${SOURCES}执行生成src可执行程序。
生成静态库文件 ADD_LIBRARY(xxx STATIC ${SRC_LIST})生成静态库文件xxx.a
生成动态库 ADD_LIBRARY(xxx SHARED ${SRC_LIST})生成动态库文件xxx.so

构建 build

内部构建:直接在项目目录下进行cmakemake ,这会导致出现很多临时文件,很不友好和美观;
外部构建:在项目根目录 新建build文件 在此文件中进行cmake . .make,隐藏不不要的临时文件,便于其他操作。

Makefile与CMake的差异总结

CMakeLists.txt 与 Makefile 都用于管理和自动化项目的构建过程

1.语法和语言:
CMakeLists.txt 使用 CMake 的自定义语言,其语法更加清晰和可读,具有更高的抽象层次,使得配置和生成过程更加简单。
Makefile 使用 Make 构建系统的自定义语言,其语法较为低级,需要手动编写规则和依赖关系。

2.跨平台性:
CMake 是一个跨平台的构建工具,可以生成适用于不同操作系统和编译器的构建文件。这意味着 CMakeLists.txt 可以用于多种不同的平台,并支持跨平台的项目构建。
Makefile 通常是为特定平台和编译器编写的,因此在不同平台上可能需要不同的 Makefile。

3.可扩展性:
CMake 提供了许多内置模块和函数,可以用于搜索依赖项、配置项目、生成文档等。它还支持自定义函数和宏的创建,以便进行更高级的构建操作。
Makefile 的可扩展性较差,需要手动编写复杂的规则和脚本。

4.维护和可读性:
CMakeLists.txt 通常比较容易维护,因为它的语法更加清晰,模块化,允许更容易地组织项目结构。
Makefile 的语法相对较低级,可能需要更多的维护工作,并且更容易出现错误。
CMakeLists.txt 更适合管理大型、复杂和跨平台的项目,而 Makefile 通常更适合小型项目或特定于某个平台的项目。
选择使用哪种工具通常取决于项目的需求和团队的偏好。在实际项目中,有时会将 CMake 与 Makefile 结合使用,以实现更高级的构建和依赖关系管理。

相同功能的对比:
cmake:

#Cmake version requirement
cmake_minimum_required(VERSION 3.16)

#program information
project(HelloSpeak)

#specifiy object
add_executable(CmakeHelloSpeak speak.cpp hellospeak.cpp)

makefile:

hello_demo: hellospeak.o speak.o
	gcc -o hello_demo hellospeak.o speak.o -lstdc++

hellospeak.o: hellospeak.cpp speak.h
	gcc -c hellospeak.cpp -lstdc++
speak.o: speak.cpp  speak.h
	gcc -c speak.cpp -lstdc++
clean:
	rm hello_demo speak.o  hellospeak.o

https://www.bilibili.com/read/cv29251791/

相关推荐

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-04-23 02:58:03       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-04-23 02:58:03       106 阅读
  3. 在Django里面运行非项目文件

    2024-04-23 02:58:03       87 阅读
  4. Python语言-面向对象

    2024-04-23 02:58:03       96 阅读

热门阅读

  1. 富格林:扫清虚假套路实现安全

    2024-04-23 02:58:03       43 阅读
  2. 用户态和内核态的区别

    2024-04-23 02:58:03       31 阅读
  3. C语言C++面试题 (包答案)

    2024-04-23 02:58:03       77 阅读
  4. 信息收集的方式与工具

    2024-04-23 02:58:03       108 阅读
  5. rst文件是什么?如何阅读rst文件

    2024-04-23 02:58:03       98 阅读
  6. 第十四届蓝桥杯 子串简写 | 树状数组解法

    2024-04-23 02:58:03       31 阅读
  7. AI时代,智能体成下一个爆点

    2024-04-23 02:58:03       144 阅读
  8. 网络通信 mac表 tcp连接

    2024-04-23 02:58:03       188 阅读