gcc系统生成程序makefile的结构分析

合集下载

c语言makefile编写实例

c语言makefile编写实例

c语言makefile编写实例Makefile是用来管理程序编译的工具,可以方便地管理程序的编译过程。

使用Makefile可以大大简化程序的编译过程,提高程序的可维护性。

Makefile的语法比较简单,主要由目标、依赖和命令三部分组成。

下面我们以一个简单的C程序为例,来介绍如何使用Makefile进行编译。

假设我们有一个名为hello.c的程序,代码如下:```c#include <stdio.h>int main(){printf("Hello, world!\n");return 0;}```我们需要使用gcc编译器将其编译成可执行文件。

下面是一个简单的Makefile:```makefilehello: hello.cgcc -o hello hello.c```这个Makefile很简单,它定义了一个名为hello的目标,该目标依赖于hello.c文件,并使用gcc命令将其编译成可执行文件。

如果我们在终端中输入make命令,Makefile会自动执行编译过程:```$ makegcc -o hello hello.c```Makefile还可以定义多个目标,每个目标可以有多个依赖和多个命令。

下面是一个稍微复杂一些的Makefile:```makefileCC=gccCFLAGS=-Wall -gall: hello goodbyehello: hello.o$(CC) $(CFLAGS) -o hello hello.ogoodbye: goodbye.o$(CC) $(CFLAGS) -o goodbye goodbye.ohello.o: hello.c$(CC) $(CFLAGS) -c hello.cgoodbye.o: goodbye.c$(CC) $(CFLAGS) -c goodbye.cclean:rm -f *.o hello goodbye```这个Makefile定义了两个目标:all和clean。

交叉编译makefile编写

交叉编译makefile编写

交叉编译makefile编写交叉编译Makefile编写在软件开发中,我们通常会遇到需要在不同平台上编译程序的情况。

当我们需要在一台主机上编译运行另一种架构的程序时,就需要进行交叉编译。

而Makefile作为一种构建工具,可以帮助我们自动化编译过程,提高开发效率。

本文将介绍如何编写适用于交叉编译的Makefile,以实现在不同平台上的程序构建。

一、了解交叉编译概念交叉编译是指在一台主机上编译生成另一种架构的可执行文件。

通常情况下,我们在本机上编写并编译程序,然后在本机上运行。

但是,当我们需要在不同的平台上运行程序时,由于不同平台的指令集、库文件等差异,我们就需要使用交叉编译来生成适用于目标平台的可执行文件。

二、Makefile的基本结构Makefile是一种用于描述程序构建过程的文件,它包含了一系列规则(rules),每个规则由一个或多个目标(target)和依赖项(dependencies)组成。

当某个目标的依赖项发生变化时,Make工具会根据规则自动更新目标文件。

一个基本的Makefile结构如下所示:```target: dependenciescommand```其中,target表示目标文件,dependencies表示目标文件的依赖项,command表示生成目标文件的命令。

三、交叉编译的Makefile编写在编写交叉编译的Makefile之前,我们需要了解目标平台的相关信息,如架构、编译器、库文件等。

以ARM架构为例,我们可以使用arm-linux-gnueabi-gcc作为交叉编译器。

我们需要定义一些变量,用于指定交叉编译工具链和相关参数:```CC = arm-linux-gnueabi-gccCFLAGS = -Wall -O2```其中,CC表示编译器,CFLAGS表示编译参数。

接下来,我们可以定义目标文件和依赖项:```TARGET = myprogramSRCS = main.c foo.c bar.cOBJS = $(SRCS:.c=.o)```其中,TARGET表示目标文件,SRCS表示源文件列表,OBJS表示目标文件列表。

Makefile 语法分析

Makefile 语法分析

Makefile 语法分析第一部分VERSION = 2# 给变量VERSION赋值PATCHLEVEL = 6# 给变量PATCHLEVEL赋值SUBLEVEL = 22# 给变量SUBLEVEL赋值EXTRAVERSION = .6# 给变量EXTRAVERSION赋值NAME = Holy Dancing Manatees, Batman!# 给变量NAME赋值# *DOCUMENTATION*# To see a list of typical targets execute "make help"# More info can be located in ./README# Comments in this file are targeted only to the developer, do not# expect to learn how to build the kernel reading this file.# Do not:# o use make's built-in rules and variables# (this increases performance and avoid hard-to-debug behavour);# o print "Entering directory ...";MAKEFLAGS += -rR --no-print-directory# 操作符“+=”的作用是给变量(“+=”前面的MAKEFLAGS)追加值。

# 如果变量(“+=”前面的MAKEFLAGS)之前没有定义过,那么,“+=”会自动变成“=”;# 如果前面有变量(“+=”前面的MAKEFLAGS)定义,那么“+=”会继承于前次操作的赋值符;# 如果前一次的是“:=”,那么“+=”会以“:=”作为其赋值符# 在执行make时的命令行选项参数被通过变量“MAKEFLAGS”传递给子目录下的make程序。

gcc链接g++编译生成的静态库和动态库的makefile示例

gcc链接g++编译生成的静态库和动态库的makefile示例

gcc链接g++编译⽣成的静态库和动态库的makefile⽰例使⽤c++开发程序或者库时,将库提供给其他⼈使⽤。

然⽽使⽤者是使⽤c开发的程序,链接g++编译⽣成的库时,于链接gcc⽣成的库,有所不同。

⾸先是静态库,以链接g++编译⽣成的libmylib.a为例⼦mylib依赖于pthread,rt,math库,链接时必须放在mylib之后。

同时-Wl,--no-as-needed -ldl添加在末尾是必须的。

arm和x86有些不同,就是arm的gcc不会⾃动链接数学库math,需要⼿动添加链接。

1 CC=arm-linux-gnueabihf-gcc -std=c992 CCLDFLAGS= -L. -lmylib -lstdc++ -pthread -lrt -lm -Wl,--no-as-needed -ldl3 #CC=gcc -m32 -std=c994 #CCLDFLAGS=-L. -lmylib -lstdc++ -pthread -lrt -Wl,--no-as-needed -ldl56 all:test78 test.o:test.c9 $(CC) -I../inc/ test.c -c -o test.o1011 test:test.o libmylib.a12 $(CC) test.o -o test $(CCLDFLAGS)1314 .PHONY: clean1516 clean:17 -rm test test.o -fgcc链接g++⽣成的动态库⽰例:libmylib.so库,使⽤g++编译时,静态链接了stdc++库(-static-libstdc++)。

1 CC=gcc -m32 -std=c992 #CC=arm-linux-gnueabihf-gcc -std=c993 CCLDFLAGS=-lstdc++ -L. -lmylib45 Root:root67 root.o:test.c8 $(CC) -I../inc/ test.c -c -o root.o910 root:root.o libmylib.so11 $(CC) root.o -o root $(CCLDFLAGS)121314 .PHONY: clean1516 clean:17 -rm root *.o。

MakeFile详解

MakeFile详解

引用其它的Makefile-实例



有这样几个Makefile:a.mk、b.mk、c.mk,还有 一个文件叫foo.make,以及一个变量$(bar),其 包含了e.mk和f.mk,那么,下面的语句: include foo.make *.mk $(bar) 等价于: include foo.make a.mk b.mk c.mk e.mk f.mk

在大多数时候,由于源文件太多,编译生成的中间目标文 件太多,而在链接时需要明显地指出中间目标文件名,这
对于编译很不方便,所以,通常要给中间目标文件打个包,
在Windows 下这种包叫“库文件”(Library File),也就 是 .lib 文件,在UNIX 下,是Archive File,也就是 .a 文件。
定义变量和引用变量
变量的定义和应用与Linux环境变量一样,变量名 要大写,变量一旦定义后,就可以通过将变量名 用圆括号括起来,并在前面加上“$”符号来进行 引用。 变量的主要作用: 1、保存文件名列表 2、保存可执行命令名,如编译器 3、保存编译器的参数 变量一般都在makefile的头部定义。按照惯例, 所有的makefile变量都应该是大写。
者,通常是你需要告诉编译器头文件的所在位置,只要所有的语法正
确,编译器就可以编译出中间目标文件。一般来说,每个源文件都应 该对应于一个中间目标文件(O 文件或是OBJ 文件)。
孙钦东
程序的编译和链接

链接时,主要是链接函数和全局变量。链接器并不管函数
所在的源文件,只管函数的中间目标文件(Object File)。



clean: -rm -f $(EXEC) *.elf *.gdb *.o

gccmakefile文件的编写精品PPT课件

gccmakefile文件的编写精品PPT课件
❖ 拷贝复制命令: (可视模式下) yy—拷贝一行到剪切板 p—粘贴剪切板的内容 在冒号命令方式下:yn,表示从当前光标处开始复制n行内容到 剪切板。将光标移到相应的位置,按p即可粘贴剪切板的内容。
常用的vim命令
❖ 编辑命令(可视模式下)
dd—删除整行命令 u—恢复前一次的删除动作
❖ 冒号命令方式命令 :q—退出命令 :w—存档 :wq—存档退出 :q!--放弃任何改动,强行退出
实例分析
❖ #The make for test. objects = main.o subr.o exec = prog all:$(objects) gcc –o $(exec) $(objects) main.o:test1.c gcc –c main.c subr.o:test2.c gcc –c subr.c clean: rm –r $(exec) $(objects)
vi的编辑状态
❖ 可视命令模式:一般当进入vi时,会首先进 入可视命令方式,这是Vi的启动默认模式。
❖ 冒号命令方式:所有命令都要以“:”开始, 所输入的字符系统均作命令来处理, 如输入 “:q”代表退出,“:w”表示存盘。
❖ 文本编辑模式:在可视命令模式下,输入”i” 即可进入编辑模式,进行编写、修改代码等 操作。
❖ $@ 扩展成当前规则的目的文件名, ❖ $< 扩展成依靠列表中的第 一个依靠文件 ❖ $^ 扩展成整个依靠的列表
gdb
❖ Linux 包含了一个叫gdb 的GNU 调试程序. gdb 是一个用来调试C 和C++ 程序的强力调 试器. 它使你能在程序运行时观察程序的内部 结构和内存的使用情况. Gdb 功能非常强大:
gcc规则
❖ gcc通过后缀来区别输入文件的类别,gcc所 遵循的部分约定规则如下:

简述Makefile文件的格式

简述Makefile文件的格式

简述Makefile文件的格式Makefile文件是一种常见的文本文件,用于描述一个项目中各个文件之间的依赖关系和编译规则。

Makefile文件通常由一系列规则组成,每个规则由一个目标、依赖关系和命令组成。

Makefile文件的格式如下:1. 目标(Target)目标是指需要生成的文件或者执行的操作。

在Makefile中,目标通常是一个可执行程序或者一个库文件。

目标的格式为:target: dependenciescommand其中,target表示目标名称,dependencies表示该目标所依赖的其他文件或者操作,command表示生成该目标所需要执行的命令。

2. 依赖关系(Dependencies)依赖关系指该目标所依赖的其他文件或者操作。

在Makefile中,可以通过在目标后面加上冒号(:)来定义该目标所依赖的其他文件或者操作。

多个依赖关系之间可以使用空格或者Tab键来进行分隔。

3. 命令(Command)命令是指生成该目标所需要执行的具体操作。

在Makefile中,可以通过在每个规则后面添加一行以Tab键开头的命令来定义具体操作。

4. 变量(Variables)变量是指用于存储各种编译参数和路径等信息的变量。

在Makefile中,可以通过使用$()符号来引用变量,并使用=符号来进行赋值操作。

例如:CFLAGS = -Wall -O2CC = gcctarget: dependencies$(CC) $(CFLAGS) -o target dependencies5. 注释(Comments)注释是指用于对Makefile中各个规则进行解释说明的文本。

在Makefile中,可以使用#符号来进行注释,#符号后面的内容将被忽略。

总之,Makefile文件是一个非常重要的工具,在项目开发过程中起到了至关重要的作用。

掌握Makefile文件的格式和编写方法,可以帮助我们更加高效地管理和组织项目代码,并提高项目开发效率。

makefile gcc编译

makefile gcc编译

makefile gcc编译
Makefile 是一个用来组织代码编译的工具,而 GCC 是一个常用的 C 和 C++ 编译器。

在 Makefile 中使用 GCC 进行编译可以通过以下步骤完成:
1. 创建一个名为 "Makefile" 的文本文件,并确保它位于你的项目根目录下。

2. 在 Makefile 中定义你的编译规则。

例如,假设你有一个名为 "main.c" 的源文件需要编译成可执行文件 "app",你可以这样编写 Makefile:
make.
app: main.c.
gcc -o app main.c.
在这个例子中,我们定义了一个名为 "app" 的目标,它依赖于"main.c" 这个源文件。

当你运行 "make" 命令时,Make 工具会根
据这个规则来执行编译。

3. 打开终端,进入到包含 Makefile 的项目目录下。

4. 运行命令 "make"。

Make 工具会读取 Makefile 文件,并执行其中定义的编译规则。

在这个例子中,它会使用 GCC 编译器来编译 "main.c" 并生成可执行文件 "app"。

需要注意的是,Makefile 可以包含更复杂的规则和变量定义,以及支持多个源文件的编译。

你可以根据你的项目需求来进一步扩展和定制 Makefile 文件。

总之,通过合理编写 Makefile 并结合使用 GCC 编译器,你可以高效地组织和管理你的代码编译过程。

makefile入门 PPT课件

makefile入门 PPT课件
则以<replacement>替换。 – $(wildcard PATTERN...) :保持通配符有效。 功能:在规则中,通配符会被自动展开。但在变量的定义和函数引 用时,通配符将失效。这种情况下如果需要通配符有效,就需要使 用函数“wildcard”。
makefile:编译使用的文件二 • :=和=的区别:
Q&A
谢谢!
隐式规则 • 看如下的一个编译规则: %.o : %.c $(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $@ %.o(目标,target) : %.c(依赖, prerequisites ) 是表示把所有的[.c]文件都编译成[.o]文件; $< 是每次匹配到的那个依赖文件 $@ 是每次匹配到的那个目标文件
• 什么是makefile
• 分析一个简单的makefile
makefile的基本结构 helloworld的makefile
• Makefile中经常用到的知识 • 我们常用的makefile是如何组成的
• 什么是makefile • 分析一个简单的makefile
• Makefile中经常用到的知识
• 什么是makefile • 分析一个简单的makefile • Makefile中经常用到的知识
• 我们常用的makefile是如何组成的
m:通用库调用路径 makefile:编译使用的文件
m:通用库调用路径 • “-I” :定义了你自己的头文件的存储目录。 • “-L”:定义了你自己的库文件存放目录。 • Make中可以定义变量,直接赋值就可以了: ARPS_ROOT = /home/yedeng/arps • 引用变量使用$(APRS_ROOT),make会自动进行替 换。将$(APRS_ROOT)用“/home/yedeng/arps”来代 替。 实际看我们用的一个m:打开文件

makefile中的gcc -c -o语法

makefile中的gcc -c -o语法

文章标题:深度探讨makefile中的gcc -c -o语法在makefile中,gcc -c -o是一个非常重要的语法结构,用于编译源文件并生成目标文件。

在本文中,我将对这个语法进行深入探讨,帮助你更好地理解它的用途和功能,并运用到实际的项目中。

1. gcc -c -o的基本概念在makefile中,gcc -c -o用于将源文件编译成目标文件。

其中,-c表示编译但不信息,-o用于指定编译后生成的目标文件名。

这个语法结构在实际的项目中非常常见,尤其是在大型的软件开发过程中。

2. 深入理解gcc -c -o的作用通过gcc -c -o,我们可以将源文件编译成目标文件,然后再将多个目标文件信息起来,生成可执行文件。

这样的分步编译方式可以提高编译的效率,尤其是在一个项目中包含大量源文件的情况下。

另外,通过指定-o参数,我们可以自定义目标文件的生成规则和命名规范,让项目结构更加清晰和灵活。

3. 实际应用案例举一个实际的例子,比如我们有一个项目包含多个源文件,分别是main.c、function1.c和function2.c。

我们可以使用gcc -c -o将这些源文件分别编译成目标文件main.o、function1.o和function2.o,然后通过gcc将这些目标文件信息起来,生成可执行文件。

这样的分步编译方式可以提高项目的维护性和灵活性。

4. 对于gcc -c -o的个人观点和理解个人认为,gcc -c -o是一个非常实用的编译选项,尤其是在大型的软件开发项目中。

通过这个选项,我们可以更加灵活地管理项目的结构,提高编译效率,同时也让代码更加清晰和易于维护。

在实际的项目中,我经常使用这个选项来进行分步编译,以便更好地管理和组织代码。

5. 总结通过本文的深入探讨,相信你对makefile中的gcc -c -o语法有了更深入的理解。

这个语法不仅在软件开发中非常常见,而且也非常实用。

通过灵活运用这个选项,我们可以更好地管理和组织项目,提高代码的可维护性和开发效率。

Makefile使用总结

Makefile使用总结

Makefile使⽤总结1. Makefile 简介Makefile 是和 make 命令⼀起配合使⽤的.很多⼤型项⽬的编译都是通过 Makefile 来组织的, 如果没有 Makefile, 那很多项⽬中各种库和代码之间的依赖关系不知会多复杂. Makefile的组织流程的能⼒如此之强, 不仅可以⽤来编译项⽬, 还可以⽤来组织我们平时的⼀些⽇常操作. 这个需要⼤家发挥⾃⼰的想象⼒.本篇博客是基于⽽整理的, 有些删减, 追加了⼀些⽰例.⾮常感谢 gunguymadman_cu 提供如此详尽的Makefile介绍, 这正是我⼀直寻找的Makefile中⽂⽂档.1.1 Makefile 主要的 5个部分 (显⽰规则, 隐晦规则, 变量定义, ⽂件指⽰, 注释)Makefile基本格式如下:target ... : prerequisites ...command......其中,target - ⽬标⽂件, 可以是 Object File, 也可以是可执⾏⽂件prerequisites - ⽣成 target 所需要的⽂件或者⽬标command - make需要执⾏的命令 (任意的shell命令), Makefile中的命令必须以 [tab] 开头1. 显⽰规则 :: 说明如何⽣成⼀个或多个⽬标⽂件(包括⽣成的⽂件, ⽂件的依赖⽂件, ⽣成的命令)2. 隐晦规则 :: make的⾃动推导功能所执⾏的规则3. 变量定义 :: Makefile中定义的变量4. ⽂件指⽰ :: Makefile中引⽤其他Makefile; 指定Makefile中有效部分; 定义⼀个多⾏命令5. 注释 :: Makefile只有⾏注释 "#", 如果要使⽤或者输出"#"字符, 需要进⾏转义, "\#"1.2 GNU make 的⼯作⽅式1. 读⼊主Makefile (主Makefile中可以引⽤其他Makefile)2. 读⼊被include的其他Makefile3. 初始化⽂件中的变量4. 推导隐晦规则, 并分析所有规则5. 为所有的⽬标⽂件创建依赖关系链6. 根据依赖关系, 决定哪些⽬标要重新⽣成7. 执⾏⽣成命令2. Makefile 初级语法2.1 Makefile 规则2.1.1 规则语法规则主要有2部分: 依赖关系和⽣成⽬标的⽅法.语法有以下2种:target ... : prerequisites ...command...或者target ... : prerequisites ; commandcommand...*注* command太长, 可以⽤ "\" 作为换⾏符2.1.2 规则中的通配符* :: 表⽰任意⼀个或多个字符:: 表⽰任意⼀个字符[...] :: ex. [abcd] 表⽰a,b,c,d中任意⼀个字符, [^abcd]表⽰除a,b,c,d以外的字符, [0-9]表⽰ 0~9中任意⼀个数字~ :: 表⽰⽤户的home⽬录2.1.3 路径搜索当⼀个Makefile中涉及到⼤量源⽂件时(这些源⽂件和Makefile极有可能不在同⼀个⽬录中),这时, 最好将源⽂件的路径明确在Makefile中, 便于编译时查找. Makefile中有个特殊的变量VPATH就是完成这个功能的.指定了VPATH之后, 如果当前⽬录中没有找到相应⽂件或依赖的⽂件, Makefile 回到VPATH指定的路径中再去查找.. VPATH使⽤⽅法:vpath <directories> :: 当前⽬录中找不到⽂件时, 就从<directories>中搜索vpath <pattern> <directories> :: 符合<pattern>格式的⽂件, 就从<directories>中搜索vpath <pattern> :: 清除符合<pattern>格式的⽂件搜索路径vpath :: 清除所有已经设置好的⽂件路径# ⽰例1 - 当前⽬录中找不到⽂件时, 按顺序从 src⽬录 ../parent-dir⽬录中查找⽂件VPATH src:../parent-dir# ⽰例2 - .h结尾的⽂件都从 ./header ⽬录中查找VPATH %.h ./header# ⽰例3 - 清除⽰例2中设置的规则VPATH %.h# ⽰例4 - 清除所有VPATH的设置VPATH2.2 Makefile 中的变量2.2.1 变量定义 ( = or := )OBJS = programA.o programB.oOBJS-ADD = $(OBJS) programC.o# 或者OBJS := programA.o programB.oOBJS-ADD := $(OBJS) programC.o其中 = 和 := 的区别在于, := 只能使⽤前⾯定义好的变量, = 可以使⽤后⾯定义的变量测试 =# Makefile内容OBJS2 = $(OBJS1) programC.oOBJS1 = programA.o programB.oall:@echo $(OBJS2)# bash中执⾏make, 可以看出虽然 OBJS1 是在 OBJS2 之后定义的, 但在 OBJS2中可以提前使⽤$ makeprogramA.o programB.o programC.o测试 :=# Makefile内容OBJS2 := $(OBJS1) programC.oOBJS1 := programA.o programB.oall:@echo $(OBJS2)# bash中执⾏make, 可以看出 OBJS2 中的 $(OBJS1) 为空$ makeprogramC.o2.2.2 变量替换# Makefile内容SRCS := programA.c programB.c programC.cOBJS := $(SRCS:%.c=%.o)all:@echo "SRCS: " $(SRCS)@echo "OBJS: " $(OBJS)# bash中运⾏make$ makeSRCS: programA.c programB.c programC.cOBJS: programA.o programB.o programC.o2.2.3 变量追加值 +=# Makefile内容SRCS := programA.c programB.c programC.cSRCS += programD.call:@echo "SRCS: " $(SRCS)# bash中运⾏make$ makeSRCS: programA.c programB.c programC.c programD.c2.2.4 变量覆盖 override作⽤是使 Makefile中定义的变量能够覆盖 make 命令参数中指定的变量语法:override <variable> = <value>override <variable> := <value>override <variable> += <value>下⾯通过⼀个例⼦体会 override 的作⽤:# Makefile内容 (没有⽤override)SRCS := programA.c programB.c programC.call:@echo "SRCS: " $(SRCS)# bash中运⾏make$ make SRCS=nothingSRCS: nothing################################################## Makefile内容 (⽤override)override SRCS := programA.c programB.c programC.call:@echo "SRCS: " $(SRCS)# bash中运⾏make$ make SRCS=nothingSRCS: programA.c programB.c programC.c2.2.5 ⽬标变量作⽤是使变量的作⽤域仅限于这个⽬标(target), ⽽不像之前例⼦中定义的变量, 对整个Makefile都有效.语法:<target ...> :: <variable-assignment><target ...> :: override <variable-assignment> (override作⽤参见变量覆盖的介绍)⽰例:# Makefile 内容SRCS := programA.c programB.c programC.ctarget1: TARGET1-SRCS := programD.ctarget1:@echo "SRCS: " $(SRCS)@echo "SRCS: " $(TARGET1-SRCS)target2:@echo "SRCS: " $(SRCS)@echo "SRCS: " $(TARGET1-SRCS)# bash中执⾏make$ make target1SRCS: programA.c programB.c programC.cSRCS: programD.c$ make target2 <-- target2中显⽰不了 $(TARGET1-SRCS)SRCS: programA.c programB.c programC.cSRCS:2.3 Makefile 命令前缀Makefile 中书写shell命令时可以加2种前缀 @ 和 -, 或者不⽤前缀.3种格式的shell命令区别如下:不⽤前缀 :: 输出执⾏的命令以及命令执⾏的结果, 出错的话停⽌执⾏前缀 @ :: 只输出命令执⾏的结果, 出错的话停⽌执⾏前缀 - :: 命令执⾏有错的话, 忽略错误, 继续执⾏⽰例:# Makefile 内容 (不⽤前缀)all:echo"没有前缀"cat this_file_not_existecho"错误之后的命令" <-- 这条命令不会被执⾏# bash中执⾏make$ makeecho"没有前缀" <-- 命令本⾝显⽰出来没有前缀 <-- 命令执⾏结果显⽰出来cat this_file_not_existcat: this_file_not_exist: No such file or directorymake: *** [all] Error 1############################################################ Makefile 内容 (前缀 @)all:@echo "没有前缀"@cat this_file_not_exist@echo "错误之后的命令" <-- 这条命令不会被执⾏# bash中执⾏make$ make没有前缀 <-- 只有命令执⾏的结果, 不显⽰命令本⾝cat: this_file_not_exist: No such file or directorymake: *** [all] Error 1############################################################ Makefile 内容 (前缀 -)all:-echo"没有前缀"-cat this_file_not_exist-echo"错误之后的命令" <-- 这条命令会被执⾏# bash中执⾏make$ makeecho"没有前缀" <-- 命令本⾝显⽰出来没有前缀 <-- 命令执⾏结果显⽰出来cat this_file_not_existcat: this_file_not_exist: No such file or directorymake: [all] Error 1 (ignored)echo"错误之后的命令" <-- 出错之后的命令也会显⽰错误之后的命令 <-- 出错之后的命令也会执⾏2.4 伪⽬标伪⽬标并不是⼀个"⽬标(target)", 不像真正的⽬标那样会⽣成⼀个⽬标⽂件.典型的伪⽬标是 Makefile 中⽤来清理编译过程中中间⽂件的 clean 伪⽬标, ⼀般格式如下: .PHONY: clean <-- 这句没有也⾏, 但是最好加上clean:-rm -f *.o2.5 引⽤其他的 Makefile语法: include <filename> (filename 可以包含通配符和路径)⽰例:# Makefile 内容all:@echo "主 Makefile begin"@make other-all@echo "主 Makefile end"include ./other/Makefile# ./other/Makefile 内容other-all:@echo "other makefile begin"@echo "other makefile end"# bash中执⾏make$ lltotal 20K-rw-r--r-- 1 wangyubin wangyubin 125 Sep 2316:13 Makefile-rw-r--r-- 1 wangyubin wangyubin 11K Sep 2316:15 <-- 这个⽂件不⽤管drwxr-xr-x 2 wangyubin wangyubin 4.0K Sep 2316:11 other$ ll other/total 4.0K-rw-r--r-- 1 wangyubin wangyubin 71 Sep 2316:11 Makefile$ make主 Makefile beginmake[1]: Entering directory `/path/to/test/makefile'other makefile beginother makefile endmake[1]: Leaving directory `/path/to/test/makefile'主 Makefile end2.6 查看C⽂件的依赖关系写 Makefile 的时候, 需要确定每个⽬标的依赖关系.GNU提供⼀个机制可以查看C代码⽂件依赖那些⽂件, 这样我们在写 Makefile ⽬标的时候就不⽤打开C源码来看其依赖那些⽂件了.⽐如, 下⾯命令显⽰内核源码中 virt/kvm/kvm_main.c 中的依赖关系$ cd virt/kvm/$ gcc -MM kvm_main.ckvm_main.o: kvm_main.c iodev.h coalesced_mmio.h async_pf.h <-- 这句就可以加到 Makefile 中作为编译 kvm_main.o 的依赖关系2.7 make 退出码Makefile的退出码有以下3种:0 :: 表⽰成功执⾏1 :: 表⽰make命令出现了错误2 :: 使⽤了 "-q" 选项, 并且make使得⼀些⽬标不需要更新2.8 指定 Makefile,指定特定⽬标默认执⾏ make 命令时, GNU make在当前⽬录下依次搜索下⾯3个⽂件 "GNUmakefile", "makefile", "Makefile",找到对应⽂件之后, 就开始执⾏此⽂件中的第⼀个⽬标(target). 如果找不到这3个⽂件就报错.⾮默认情况下, 可以在 make 命令中指定特定的 Makefile 和特定的⽬标.⽰例:# Makefile⽂件名改为 MyMake, 内容target1:@echo "target [1] begin"@echo "target [1] end"target2:@echo "target [2] begin"@echo "target [2] end"# bash 中执⾏make$ lsMakefile$ mv Makefile MyMake$ lsMyMake$ make <-- 找不到默认的 Makefilemake: *** No targets specified and no makefile found. Stop.$ make -f MyMake <-- 指定特定的Makefiletarget [1] begintarget [1] end$ make -f MyMake target2 <-- 指定特定的⽬标(target)target [2] begintarget [2] end2.9 make 参数介绍make 的参数有很多, 可以通过 make -h 去查看, 下⾯只介绍⼏个我认为⽐较有⽤的.参数含义--debug[=<options>]输出make的调试信息, options 可以是 a, b, v-j --jobs同时运⾏的命令的个数, 也就是多线程执⾏ Makefile-r --no-builtin-rules禁⽌使⽤任何隐含规则-R --no-builtin-variabes禁⽌使⽤任何作⽤于变量上的隐含规则-B --always-make假设所有⽬标都有更新, 即强制重编译2.10 Makefile 隐含规则这⾥只列⼀个和编译C相关的.编译C时,<n>.o 的⽬标会⾃动推导为 <n>.c# Makefile 中main : main.ogcc -o main main.o#会⾃动变为:main : main.ogcc -o main main.omain.o: main.c <-- main.o 这个⽬标是隐含⽣成的gcc -c main.c2.11 隐含规则中的命令变量和命令参数变量2.11.1 命令变量, 书写Makefile可以直接写 shell时⽤这些变量.下⾯只列出⼀些C相关的变量名含义RM rm -fAR arCC ccCXX g++⽰例:# Makefile 内容all:@echo $(RM)@echo $(AR)@echo $(CC)@echo $(CXX)# bash 中执⾏make, 显⽰各个变量的值$ makerm -farccg++2.11.2 命令参数变量变量名含义ARFLAGS AR命令的参数CFLAGS C语⾔编译器的参数CXXFLAGS C++语⾔编译器的参数⽰例: 下⾯以 CFLAGS 为例演⽰# test.c 内容#include <stdio.h>int main(int argc, char *argv[]){printf ("Hello Makefile\n");return 0;}# Makefile 内容test: test.o$(CC) -o test test.o# bash 中⽤make来测试$ lltotal 24K-rw-r--r-- 1 wangyubin wangyubin 69 Sep 2317:31 Makefile-rw-r--r-- 1 wangyubin wangyubin 14K Sep 2319:51 <-- 请忽略这个⽂件-rw-r--r-- 1 wangyubin wangyubin 392 Sep 2317:31 test.c$ makecc -c -o test.o test.ccc -o test test.o <-- 这个是⾃动推导的$ rm -f test test.o$ make CFLAGS=-Wall <-- 命令中加的编译器参数⾃动追加⼊下⾯的编译中了cc -Wall -c -o test.o test.ccc -o test test.o2.12 ⾃动变量Makefile 中很多时候通过⾃动变量来简化书写, 各个⾃动变量的含义如下:⾃动变量含义$@⽬标集合$%当⽬标是函数库⽂件时, 表⽰其中的⽬标⽂件名$<第⼀个依赖⽬标. 如果依赖⽬标是多个, 逐个表⽰依赖⽬标$?⽐⽬标新的依赖⽬标的集合$^所有依赖⽬标的集合, 会去除重复的依赖⽬标$+所有依赖⽬标的集合, 不会去除重复的依赖⽬标$*这个是GNU make特有的, 其它的make不⼀定⽀持3. Makefile ⾼级语法3.1 嵌套Makefile在 Makefile 初级语法中已经提到过引⽤其它 Makefile的⽅法. 这⾥有另⼀种写法, 并且可以向引⽤的其它 Makefile 传递参数.⽰例: (不传递参数, 只是调⽤⼦⽂件夹 other 中的Makefile)# Makefile 内容all:@echo "主 Makefile begin"@cd ./other && make@echo "主 Makefile end"# ./other/Makefile 内容other-all:@echo "other makefile begin"@echo "other makefile end"# bash中执⾏make$ lltotal 28K-rw-r--r-- 1 wangyubin wangyubin 104 Sep 2320:43 Makefile-rw-r--r-- 1 wangyubin wangyubin 17K Sep 2320:44 <-- 这个⽂件不⽤管drwxr-xr-x 2 wangyubin wangyubin 4.0K Sep 2320:42 other$ ll other/total 4.0K-rw-r--r-- 1 wangyubin wangyubin 71 Sep 2316:11 Makefile$ make主 Makefile beginmake[1]: Entering directory `/path/to/test/makefile/other'other makefile beginother makefile endmake[1]: Leaving directory `/path/to/test/makefile/other'主 Makefile end⽰例: (⽤export传递参数)# Makefile 内容export VALUE1 := export.c <-- ⽤了 export, 此变量能够传递到 ./other/Makefile 中VALUE2 := no-export.c <-- 此变量不能传递到 ./other/Makefile 中all:@echo "主 Makefile begin"@cd ./other && make@echo "主 Makefile end"# ./other/Makefile 内容other-all:@echo "other makefile begin"@echo "VALUE1: " $(VALUE1)@echo "VALUE2: " $(VALUE2)@echo "other makefile end"# bash中执⾏make$ make主 Makefile beginmake[1]: Entering directory `/path/to/test/makefile/other'other makefile beginVALUE1: export.c <-- VALUE1 传递成功VALUE2: <-- VALUE2 传递失败other makefile endmake[1]: Leaving directory `/path/to/test/makefile/other'主 Makefile end*补充* export 语法格式如下:export variable = valueexport variable := valueexport variable += value3.2 定义命令包命令包有点像是个函数, 将连续的相同的命令合成⼀条, 减少 Makefile 中的代码量, 便于以后维护.语法:define <command-name>command...endef⽰例:# Makefile 内容define run-hello-makefile@echo -n "Hello"@echo " Makefile!"@echo "这⾥可以执⾏多条 Shell 命令!"endefall:$(run-hello-makefile)# bash 中运⾏make$ makeHello Makefile!这⾥可以执⾏多条 Shell 命令!3.3 条件判断条件判断的关键字主要有 ifeq ifneq ifdef ifndef语法:<conditional-directive><text-if-true>endif# 或者<conditional-directive><text-if-true>else<text-if-false>endif⽰例: ifeq的例⼦, ifneq和ifeq的使⽤⽅法类似, 就是取反# Makefile 内容all:ifeq ("aa", "bb")@echo "equal"else@echo "not equal"endif# bash 中执⾏make$ makenot equal⽰例: ifdef的例⼦, ifndef和ifdef的使⽤⽅法类似, 就是取反# Makefile 内容SRCS := program.call:ifdef SRCS@echo $(SRCS)else@echo "no SRCS"# bash 中执⾏make$ makeprogram.c3.4 Makefile 中的函数Makefile 中⾃带了⼀些函数, 利⽤这些函数可以简化 Makefile 的编写.函数调⽤语法如下:$(<function> <arguments>)# 或者${<function> <arguments>}<function> 是函数名<arguments> 是函数参数3.4.1 字符串函数字符串替换函数: $(subst <from>,<to>,<text>)功能: 把字符串<text> 中的 <from> 替换为 <to>返回: 替换过的字符串# Makefile 内容all:@echo $(subst t,e,maktfilt) <-- 将t替换为e# bash 中执⾏make$ makemakefile模式字符串替换函数: $(patsubst <pattern>,<replacement>,<text>)功能: 查找<text>中的单词(单词以"空格", "tab", "换⾏"来分割) 是否符合 <pattern>, 符合的话, ⽤ <replacement> 替代.返回: 替换过的字符串# Makefile 内容all:@echo $(patsubst %.c,%.o,programA.c programB.c)# bash 中执⾏make$ makeprogramA.o programB.o去空格函数: $(strip <string>)功能: 去掉 <string> 字符串中开头和结尾的空字符返回: 被去掉空格的字符串值# Makefile 内容VAL := " aa bb cc "all:@echo "去除空格前: " $(VAL)@echo "去除空格后: " $(strip $(VAL))# bash 中执⾏make去除空格前: aa bb cc去除空格后: aa bb cc查找字符串函数: $(findstring <find>,<in>)功能: 在字符串 <in> 中查找 <find> 字符串返回: 如果找到, 返回 <find> 字符串, 否则返回空字符串# Makefile 内容VAL := " aa bb cc "all:@echo $(findstring aa,$(VAL))@echo $(findstring ab,$(VAL))# bash 中执⾏make$ makeaa过滤函数: $(filter <pattern...>,<text>)功能: 以 <pattern> 模式过滤字符串 <text>, *保留* 符合模式 <pattern> 的单词, 可以有多个模式返回: 符合模式 <pattern> 的字符串# Makefile 内容all:@echo $(filter %.o %.a,program.c program.o program.a)# bash 中执⾏make$ makeprogram.o program.a反过滤函数: $(filter-out <pattern...>,<text>)功能: 以 <pattern> 模式过滤字符串 <text>, *去除* 符合模式 <pattern> 的单词, 可以有多个模式返回: 不符合模式 <pattern> 的字符串# Makefile 内容all:@echo $(filter-out %.o %.a,program.c program.o program.a)# bash 中执⾏make$ makeprogram.c排序函数: $(sort <list>)功能: 给字符串 <list> 中的单词排序 (升序)返回: 排序后的字符串# Makefile 内容all:@echo $(sort bac abc acb cab)# bash 中执⾏make$ makeabc acb bac cab取单词函数: $(word <n>,<text>)功能: 取字符串 <text> 中的第<n>个单词 (n从1开始)返回: <text> 中的第<n>个单词, 如果<n> ⽐ <text> 中单词个数要⼤, 则返回空字符串# Makefile 内容all:@echo $(word 1,aa bb cc dd)@echo $(word 5,aa bb cc dd)@echo $(word 4,aa bb cc dd)# bash 中执⾏make$ makeaadd取单词串函数: $(wordlist <s>,<e>,<text>)功能: 从字符串<text>中取从<s>开始到<e>的单词串. <s>和<e>是⼀个数字.返回: 从<s>到<e>的字符串# Makefile 内容all:@echo $(wordlist 1,3,aa bb cc dd)@echo $(word 5,6,aa bb cc dd)@echo $(word 2,5,aa bb cc dd)# bash 中执⾏make$ makeaa bb ccbb单词个数统计函数: $(words <text>)功能: 统计字符串 <text> 中单词的个数返回: 单词个数# Makefile 内容all:@echo $(words aa bb cc dd)@echo $(words aabbccdd)@echo $(words )# bash 中执⾏make$ make41⾸单词函数: $(firstword <text>)功能: 取字符串 <text> 中的第⼀个单词返回: 字符串 <text> 中的第⼀个单词# Makefile 内容all:@echo $(firstword aa bb cc dd)@echo $(firstword aabbccdd)@echo $(firstword )# bash 中执⾏make$ makeaaaabbccdd3.4.2 ⽂件名函数取⽬录函数: $(dir <names...>)功能: 从⽂件名序列 <names> 中取出⽬录部分返回: ⽂件名序列 <names> 中的⽬录部分# Makefile 内容all:@echo $(dir /home/a.c ./bb.c ../c.c d.c)# bash 中执⾏make$ make/home/ ./ ../ ./取⽂件函数: $(notdir <names...>)功能: 从⽂件名序列 <names> 中取出⾮⽬录部分返回: ⽂件名序列 <names> 中的⾮⽬录部分# Makefile 内容all:@echo $(notdir /home/a.c ./bb.c ../c.c d.c)# bash 中执⾏make$ makea.c bb.cc.cd.c取后缀函数: $(suffix <names...>)功能: 从⽂件名序列 <names> 中取出各个⽂件名的后缀返回: ⽂件名序列 <names> 中各个⽂件名的后缀, 没有后缀则返回空字符串# Makefile 内容all:@echo $(suffix /home/a.c ./b.o ../c.a d)# bash 中执⾏make$ make.c .o .a取前缀函数: $(basename <names...>)功能: 从⽂件名序列 <names> 中取出各个⽂件名的前缀返回: ⽂件名序列 <names> 中各个⽂件名的前缀, 没有前缀则返回空字符串# Makefile 内容all:@echo $(basename /home/a.c ./b.o ../c.a /home/.d .e)# bash 中执⾏make$ make/home/a ./b ../c /home/加后缀函数: $(addsuffix <suffix>,<names...>)功能: 把后缀 <suffix> 加到 <names> 中的每个单词后⾯返回: 加过后缀的⽂件名序列# Makefile 内容all:@echo $(addsuffix .c,/home/a b ./c.o ../d.c)# bash 中执⾏make$ make/home/a.c b.c ./c.o.c ../d.c.c加前缀函数: $(addprefix <prefix>,<names...>)功能: 把前缀 <prefix> 加到 <names> 中的每个单词前⾯返回: 加过前缀的⽂件名序列# Makefile 内容all:@echo $(addprefix test_,/home/a.c b.c ./d.c)# bash 中执⾏make$ maketest_/home/a.c test_b.c test_./d.c连接函数: $(join <list1>,<list2>)功能: <list2> 中对应的单词加到 <list1> 后⾯返回: 连接后的字符串# Makefile 内容all:@echo $(join a b c d,1234)@echo $(join a b c d,12345)@echo $(join a b c d e,1234)# bash 中执⾏make$ makea1 b2 c3 d4a1 b2 c3 d4 5a1 b2 c3 d4 e3.4.3 foreach语法:$(foreach <var>,<list>,<text>)⽰例:# Makefile 内容targets := a b c dobjects := $(foreach i,$(targets),$(i).o)all:@echo $(targets)@echo $(objects)# bash 中执⾏make$ makea b c da.ob.oc.od.o3.4.4 if这⾥的if是个函数, 和前⾯的条件判断不⼀样, 前⾯的条件判断属于Makefile的关键字语法:$(if <condition>,<then-part>)$(if <condition>,<then-part>,<else-part>)⽰例:# Makefile 内容val := aobjects := $(if $(val),$(val).o,nothing)no-objects := $(if $(no-val),$(val).o,nothing)all:@echo $(objects)@echo $(no-objects)# bash 中执⾏make$ makea.onothing3.4.5 call - 创建新的参数化函数语法:$(call <expression>,<parm1>,<parm2>,<parm3>...)⽰例:# Makefile 内容log = "====debug====" $(1) "====end===="all:@echo $(call log,"正在 Make")# bash 中执⾏make$ make====debug==== 正在 Make ====end====3.4.6 origin - 判断变量的来源语法:$(origin <variable>)返回值有如下类型:类型含义undefined<variable> 没有定义过default<variable> 是个默认的定义, ⽐如 CC 变量environment<variable> 是个环境变量, 并且 make时没有使⽤ -e 参数file<variable> 定义在Makefile中command line<variable> 定义在命令⾏中override<variable> 被 override 重新定义过automatic<variable> 是⾃动化变量⽰例:# Makefile 内容val-in-file := test-fileoverride val-override := test-overrideall:@echo $(origin not-define) # not-define 没有定义@echo $(origin CC) # CC 是Makefile默认定义的变量@echo $(origin PATH) # PATH 是 bash 环境变量@echo $(origin val-in-file) # 此Makefile中定义的变量@echo $(origin val-in-cmd) # 这个变量会加在make的参数中@echo $(origin val-override) # 此Makefile中定义的override变量@echo $(origin @) # ⾃动变量, 具体前⾯的介绍# bash 中执⾏make$ make val-in-cmd=val-cmdundefineddefaultenvironmentfilecommand lineoverrideautomatic3.4.7 shell语法:$(shell <shell command>)它的作⽤就是执⾏⼀个shell命令, 并将shell命令的结果作为函数的返回.作⽤和 `<shell command>` ⼀样, ` 是反引号3.4.8 make 控制函数产⽣⼀个致命错误: $(error <text ...>)功能: 输出错误信息, 停⽌Makefile的运⾏# Makefile 内容all:$(error there is an error!)@echo "这⾥不会执⾏!"# bash 中执⾏make$ makeMakefile:2: *** there is an error!. Stop.输出警告: $(warning <text ...>)功能: 输出警告信息, Makefile继续运⾏# Makefile 内容all:$(warning there is an warning!)@echo "这⾥会执⾏!"# bash 中执⾏make$ makeMakefile:2: there is an warning!这⾥会执⾏!3.5 Makefile中⼀些GNU约定俗成的伪⽬标如果有过在Linux上, 从源码安装软件的经历的话, 就会对 make clean, make install ⽐较熟悉.像 clean, install 这些伪⽬标, ⼴为⼈知, 不⽤解释就⼤家知道是什么意思了.下⾯列举⼀些常⽤的伪⽬标, 如果在⾃⼰项⽬的Makefile合理使⽤这些伪⽬标的话, 可以让我们⾃⼰的Makefile看起来更专业, 呵呵 :)伪⽬标含义all所有⽬标的⽬标,其功能⼀般是编译所有的⽬标clean删除所有被make创建的⽂件install安装已编译好的程序,其实就是把⽬标可执⾏⽂件拷贝到指定的⽬录中去print列出改变过的源⽂件tar把源程序打包备份. 也就是⼀个tar⽂件dist创建⼀个压缩⽂件, ⼀般是把tar⽂件压成Z⽂件. 或是gz⽂件TAGS更新所有的⽬标, 以备完整地重编译使⽤check 或 test⼀般⽤来测试makefile的流程。

makefile 命令行参数

makefile 命令行参数
2. -C选项
-C选项可以指定Makefile所在的路径。如果我们在当前路径下执行make命令,但是Makefile文件不在当前路径下,那么就需要使用-C选项来指定Makefile所在的路径。例如:
make -C /path/to/Makefile
3. -f选项
-f选项可以指定要使用的Makefile文件名。如果我们有多个Makefile文件,那么就可以使用-f选项来指定要使用哪个Makefile文件。例如:
makefile 命令行参数
Makefile是一种用来管理代码编译的工具,它可以自动化执行编译任务,帮助程序员更高效地管理代码。在Makefile中,可以定义一系列规则来指定如何编译代码。在使用Makefile时,我们可以通过命令行参数来控制编译过程的行为。本文将详细介绍makefile命令行参数的使用方法。项
-j选项可以指定并行编译时所使用的线程数。如果我们有多个CPU核心,并且要编译大型项目,那么就可以使用-j选项来加速编译过程。例如:
make -j4
5. --dry-run选项
--dry-run选项可以模拟执行make命令,并输出将要执行的命令列表,但是并不会真正地执行这些命令。这个功能非常实用,因为我们可以预先查看将要执行的命令,确保它们是正确的。例如:
这样做的好处是,我们可以在不修改Makefile的情况下,通过命令行参数来控制编译过程的行为。
四、总结
本文介绍了Makefile命令行参数的用法,包括make命令、-C选项、-f选项、-j选项、--dry-run选项和--print-data-base选项。同时,本文还介绍了一些Makefile常用技巧,包括使用变量来存储编译选项、使用通配符来自动生成目标文件列表和使用命令行参数来控制编译过程。希望本文能够对大家理解和学习Makefile有所帮助。

Makefile

Makefile

makefile自动化工具
CMake
跨平台的安装(编译)工具, 能够输出各种各样的makefile或者 project文件,能测试编译器所支持的C++特性,类似于automake。 Cmake不再使你在构建项目时郁闷地想自杀了。 一位KDE开发者
GNU Autotools应用
GNU
பைடு நூலகம்
Autotools指的就是下面的六个工具: 1. aclocal 2. autoscan 3. autoconf 4. autoheader 5. automake 6. libtool
GNU Autotools应用
Autotools的使用流程:
·手工编写Makefile.am这个文件。 ·在源代码目录树的最高层运行autoscan。然后手动修改 configure.scan文件,并改名为configure.in。 ·运行aclocal,它会根据configure.in的内容生成 aclocal.m4文件。 ·运行autoconf,它根据configure.in和aclocal.m4的内容生 成configure这个配置脚本文件。 ·运行automake --add-missing,它根据Makefile.am的内容 生成Makefile.in。 ·运行configure,它会根据Makefile.in的内容生成Makefile 这个文件。 获得Makefile文件后,就可以使用make程序来管理我们的工程。
1.关于可执行文件和各程序模块间的相互关系。
2.文件的修改日期
Makefile依赖关系描述
一般的语法规则为: target:dependency command

例如,对于之前的例程1,其
Makefile 可书写如上:

makefile 生成依赖关系

makefile 生成依赖关系

一、概述在软件开发过程中,源文件之间的依赖关系是非常重要的。

当一个文件发生变化时,其依赖文件可能也会受到影响,因此需要一个工具来管理这些依赖关系,确保在编译过程中能够正确地处理依赖关系。

makefile就是一个非常强大的工具,能够自动生成依赖关系,本文将详细介绍makefile生成依赖关系的方法。

二、什么是makefilemakefile是一个包含规则和命令的文本文件,用来描述软件项目的编译过程。

它告诉make工具,如何去利用源文件生成目标文件。

makefile通常包含了以下内容:1. 目标(target):表示要生成的文件,可以是可执行文件、中间文件或其他类型的文件。

2. 依赖(dependencies):表示目标文件所依赖的源文件或其他文件。

3. 命令mands):表示生成目标文件的具体操作,通常是编译、信息等。

三、makefile生成依赖关系的原理在编译过程中,一个源文件可能会依赖于其他源文件或头文件,当这些依赖关系发生变化时,我们需要重新编译相关的文件。

makefile 生成依赖关系的原理就是通过分析源文件中的#include语句,自动识别出文件之间的依赖关系,并生成相应的规则。

1. 使用gcc的-M选项gcc是一个非常流行的编译器,在编译过程中,它提供了-M选项来生成依赖关系。

例如:```make.o: .cgcc -c $< -o $ -MMD -MF $*.d```这里,-MMD选项表示生成依赖关系文件,-MF选项指定了依赖关系文件的名称。

通过这样的makefile规则,gcc能够自动生成每个源文件的依赖关系。

2. 使用自定义脚本除了使用gcc的-M选项外,我们也可以编写一个自定义的脚本来生成依赖关系。

这样能够更加灵活地控制依赖关系的生成过程。

五、makefile生成依赖关系的优势1. 自动化:makefile能够自动分析源文件之间的依赖关系,不需要手动维护依赖关系。

2. 灵活性:makefile生成依赖关系的方法非常灵活,可以根据实际需要选择不同的生成方式。

makefile的工作原理

makefile的工作原理

makefile的工作原理Makefile是软件开发中常用的构建工具,它可以根据项目中的依赖关系和规则来自动化构建和管理项目。

下面是Makefile的工作原理的详细解释,分为以下步骤:1. 读取Makefile:Makefile是一个文本文件,记录了项目中的目标、依赖关系和构建规则。

在使用make命令时,系统会读取当前目录下的Makefile文件。

2. 解析目标和依赖关系:Makefile中的每一行都由目标和依赖关系组成。

解析器会解析这些目标和依赖关系,并将它们保存在内部数据结构中,以便后续使用。

3. 检查目标是否需要重新构建:构建过程中,Makefile会检查目标文件和依赖文件的时间戳,来确定是否需要重新构建。

如果目标文件不存在、依赖文件的时间戳比目标文件新,或者依赖文件有更新,则需要重新构建目标。

4. 构建目标:如果目标需要重新构建,Makefile会执行相关的构建规则。

构建规则由一系列命令组成,用于编译源代码、链接目标文件等。

Makefile会按照规则中定义的顺序依次执行这些命令,完成目标的构建。

5. 更新目标的时间戳:构建完成后,Makefile会更新目标文件的时间戳,以便下一次构建时进行比较。

6. 检查下游目标:构建完成一个目标后,Makefile会检查该目标是否是其他目标的依赖。

如果是,则会重复步骤3-5,以构建下游目标。

7. 构建完成:当所有目标都构建完成后,Makefile会退出。

Makefile的工作原理基于依赖关系和规则,通过检查目标和依赖文件的时间戳来确定是否需要重新构建。

这种方式可以提高软件开发的效率,避免不必要的重复构建。

同时,Makefile还可以支持并行构建,提高构建速度。

make的用法和原理

make的用法和原理

make的用法和原理"make" 是一个流行的构建工具,用于自动化构建和管理软件项目。

它的原理是基于 Makefile 文件中定义的规则和依赖关系来确定构建过程中需要执行的操作。

首先,让我们来了解一下 Makefile 文件的基本结构。

一个简单的 Makefile 包含一系列的规则,每个规则由一个目标(target)和一组依赖(dependencies)组成。

目标是构建过程中的一个中间或最终的产物,而依赖是构建目标所需要的文件或其他目标。

每个规则还包含一组命令(commands),用于描述如何生成目标。

当执行 make 命令时,它会读取当前目录下的 Makefile 文件,并根据规则和依赖关系来确定需要执行哪些命令。

make 会首先检查目标和依赖的时间戳,如果目标不存在或者依赖的时间戳较新,则需要执行相应的命令来生成目标。

Makefile 文件中的规则可以定义编译、链接、拷贝文件等操作。

例如,一个简单的 C 语言项目的 Makefile 可能包含以下规则:target: dependency1 dependency2。

command1。

command2。

在这个例子中,"target" 是目标文件,"dependency1" 和"dependency2" 是构建目标所需要的文件。

"command1" 和"command2" 是生成目标的命令。

Makefile 还支持变量的定义和使用,可以方便地管理和重用代码片段。

变量可以用来存储文件名、编译选项等信息。

例如:CC = gcc.CFLAGS = -Wall -O2。

target: dependency.$(CC) $(CFLAGS) -o target dependency.在这个例子中,"CC" 和 "CFLAGS" 是变量,分别表示编译器和编译选项。

Makefile及GCC编译选项培训

Makefile及GCC编译选项培训
据文件名后缀选择一个缺省值)。此选项影响后面的所有输入文件 ,一直到下一个 –x 选项。
language可取的值为:
c c-header cpp-output c++ c++-cpp-output objective-c objc-cpp-output assembler assembler-with-cpp ada f77 f77-cpp-input ratfor java
Makefile及GCC编译选项培训
Makefile中变量的使用:
objects = main.o kbd.o command.o display.o \ insert.o search.o files.o utils.o
edit : $(objects) cc -o edit $(objects)
Makefile及GCC编译选项培训
-ansi
支持所有ANSI标准的C程序。 这个开关不支持那些GNU C中与ANSI C 不兼容的特性,如关键词asm,inline和typeof,以及标明所用系统类型的预 定义宏,如unix和vax。它同时支持不受欢迎而且很少使用的ANSI三字母词 特性,不允许“$”作为标识符的一部分,不识别C++风格的“//”注释。
一般情况下GCC会采用特殊代码更高效地实现特定的内置函数。比如 调用alloca会变成若干直接调整堆栈的单一指令,而调用memcpy 会变成直 接插入的复制循环。这样产生的代码更小更快,而由于代码中没有了函数 调用,无法在这些调用中设置断点,也不能通过连接不同的库来改变这些 函数的功能。
-ansi 开关禁止函数alloca和ffs成为内置函数,因为它们没有ANSI标准 下的意义。
上下文中时,虽然没有用引号括起来,其数值被字符串化)。预处理器 认为字符串常量以新行为结束。

海思makefile结构解析

海思makefile结构解析

海思makefile结构解析全文共四篇示例,供读者参考第一篇示例:海思芯片是一家领先的半导体公司,在国际市场上拥有广泛的市场份额。

海思芯片的产品广泛应用在手机、网络通信、物联网、智能家居等领域,其芯片性能卓越,在同行业内享有很高的声誉。

在海思芯片的开发中,makefile是一个非常重要的工具,它负责管理整个项目的编译、链接和部署过程,帮助开发人员更高效地完成工作。

makefile是一个用于自动化编译的脚本文件,通过编写makefile 文件,可以告诉计算机如何编译源代码,生成可执行文件。

海思makefile结构解析主要包括以下几个部分:1. 定义变量:在makefile中定义变量是非常重要的,可以方便地管理项目的路径、编译参数等信息。

海思makefile中通常会定义一些常用的变量,比如CC表示编译器的路径,CXX表示C++编译器的路径,CFLAGS表示编译参数等。

通过定义这些变量,可以在整个makefile中直接引用,减少了代码的冗余,提高了代码的可维护性。

2. 设置编译规则:在makefile中,通常会定义一些编译规则,告诉make工具如何编译源文件和生成可执行文件。

海思makefile中的编译规则通常使用模式匹配的方式,比如"%.c:%.o"表示将所有的.c文件编译为.o文件,而"%.o:%.c"则表示将所有的.o文件根据对应的.c文件进行重新编译。

通过这些编译规则,make工具可以根据需要自动化地完成整个项目的编译过程。

3. 定义目标:在makefile中通常会定义一些目标,这些目标可以是编译生成可执行文件的命令,也可以是清理生成的临时文件的命令。

海思makefile中的目标通常包括all、clean、install等,通过定义这些目标,可以方便地管理整个项目的编译和部署过程。

4. 调用外部工具:在海思makefile中,通常会调用一些外部工具来完成一些特定的任务,比如编译器、链接器、打包工具等。

cmake生成makefile流程

cmake生成makefile流程

文章标题:深入剖析CMake生成Makefile的流程与原理1. CMake介绍CMake是一个跨评台的自动化构建工具,可用于管理软件构建过程中的编译、信息、测试和安装等任务。

它采用了一种称为“CMakeLists.txt”的文本配置文件来描述项目的构建过程,然后根据这些描述生成不同评台下的构建脚本,如Makefile。

2. CMake生成Makefile的流程(1)项目目录结构:需要在项目目录下创建一个CMakeLists.txt文件,描述项目的组织结构和构建过程。

(2)配置CMake:运行cmake命令,指定项目的路径和生成的构建系统,如Unix的Makefile、Windows的Visual Studio项目等。

(3)生成Makefile:CMake解析CMakeLists.txt文件,生成相应的Makefile文件。

(4)编译项目:运行生成的Makefile文件,执行编译、信息等操作。

3. CMake生成Makefile的原理(1) CMakeLists.txt文件:该文件描述了项目的结构、依赖关系、编译选项等信息,CMake根据这些信息生成Makefile。

(2) CMake内部算法:CMake利用内部的算法来解析CMakeLists.txt文件,生成对应评台的构建脚本。

4. 个人观点和理解CMake的优势在于其跨评台性和灵活性,能够简化项目的构建过程,提高开发效率。

而CMake生成Makefile的过程则是其核心功能之一,可以帮助开发人员快速、高效地进行项目构建和管理。

总结与回顾本文深入剖析了CMake生成Makefile的流程与原理,介绍了CMake的基本概念和使用方法。

通过本文的阐述,读者可以更全面地了解CMake在软件构建中的作用和重要性,以及其生成Makefile的内部工作机制,希望能对读者有所帮助。

通过本文的了解,你是否对CMake生成Makefile的流程有了更深入的认识呢?让我们一起来探索和学习吧!CMake作为一个跨评台的自动化构建工具,其生成Makefile的流程和原理是非常重要的,了解这些内容有助于开发人员更好地使用和理解CMake,提高项目构建的效率和质量。

makefilePPT课件

makefilePPT课件
5、注释。和UNIX的Shell脚本一样Makefile中只有行注释, 其注释是用“#”字符,这个就像C/C++中的“//”或者 “ /*”。 在Makefile中的命令,必须要以[Tab]键开始!!!
2021/2/10
Makefile的默认文件名为GNUmakefile、 makefile或Makefile,多数Linux程序员使用 第三种。
gcc –o test prog.o code.o prog.o:prog.c prog.h code.h
gcc –c prog.c –o prog.o code.o:code.c code.h
gcc –c code.c –o code.o clean:
rm –f *.o
2021/2/10
上面的Makefile文件中共定义了四个目标: test、prog.o、code.o和clean。目标从每行的最左 边开始写,后面跟一个冒号(:),如果有与这 个目标有依赖性的其他目标或文件,把它们列在 冒号后面,并以空格隔开。然后另起一行开始写 实现这个目标的一组命令。在Makefile中,可使 用续行号(\)将一个单独的命令行延续成几行。 但要注意在续行号(\)后面不能跟任何字符 (包括空格和键)。
2021/2/10
但是,在检查文件prog.o和code.o的时间戳之前, make会在下面的行中寻找以prog.o和code.o为目标的 规则,在第三行中找到了关于prog.o的规则,该文件 的依赖文件是prog.c、prog.h和code.h。同样,make 会在后面的规则行中继续查找这些依赖文件的规则, 如果找不到,则开始检查这些依赖文件的时间戳,如 果这些文件中任何一个的时间戳比prog.o的新,make 将执行“gcc –c prog.c –o prog.o”命令,更新prog.o文 件。
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

主页 /mara@引用请注明出处GCC系统生成程序Makefile的结构分析玛瑞 1996/11 系统生成程序M akefile命令行参数的定义 (2)2 系统生成程序M akefile的工作流程 (4)2.1 A. all.internal (4)2.1.1 宏定义 (4)2.1.2 执行目标a ll (转向执行a ll.internal) (5)2.1.3 检察配置状态 (5)2.1.4 预处理程序的生成(cpp) (5)2.1.5 c编译子系统的生成(cc1) (5)2.1.6 链接程序的生成(ld) (6)2.1.7 驱动程序的生成(xgcc) (6)2.1.8 spec文件的生成 (6)2.1.9 libgcc1.a的生成 (6)2.1.10 生成x limit.h (7)2.1.11 c++驱动程序的生成(g++) (7)2.1.12 头文件的获得 (7)2.1.13 执行f ixproto (9)2.1.14 目标a ll(all.internal)结束 (9)2.1.15 退出m ake (9)2.2 B. install (9)2.2.1 宏定义 (9)2.2.2 执行目标i nstall (10)2.2.3 安装生成的系统文件 (10)2.2.4 安装头文件 (11)2.2.5 安装库文件 (11)2.2.6 安装帮助手册 (12)2.2.7 安装系统信息手册 (12)2.2.8 目标i nstall结束 (12)2.2.9 退出m ake (12)1系统生成程序Makefile命令行参数的定义1. 限制语言的安装:"LANGUAGES=c c++ Objective-c proto的子集"其中,proto是生成程序protoize和unprotoize的目标名。

protoize支持ANSI函数原型格式的说明。

注: 在xgcc生成之前,只有c的说明有效。

2. 重定义编译程序"CC=编译程序名 CFLAGS=使用此编译程序所带的参数表"缺省的CC是本机配带的cc编译程序,其CFLAGS为" -g "3. 目标名GCC的提供以下外部目标名:1> all : 是第一个目标名,故当make命令行不指明目标时,系统分析从all开始。

all的执行动作取决于configure文件是否在Makefile.in中插入了文件${srcdir}/cross-make的内容。

若是交叉编译,此文件被插入,则all实际执行目标all.cross;否则,all实际执行目标all.internal。

所以,all.cross是交叉编译的驱动目标名,all.internal是一般系统生成的驱动目标名(它们是内部目标名)。

2> doc : 生成系统信息手册3> proto : 生成程序protoize,unprotoize4> install : 安装已生成的GCC编译系统到适当的目录下5> install-cross : (未定义,需安装者自己设计各步)6> install-cross-rest : 在目标系统上完成安装交叉编译系统的后期工作7> uninstall : 将被安装的文件删除8> TAGS : 更新c-parse.c , objc-parse.c , cexp.c的内容(执行etags使*.y和*.h重新生成*.c)9> mostlyclean : 删除由编译生成的大多数文件;不删除libgcc.a及其组成10> clean : 删除由编译生成的所有文件(及目录)11> distclean : 删除由安装生成的所有文件(及目录)12> realclean : 删除可以自动(由别的程序)生成的所有文件(及目录)(这四级删除是后一级包含前一级)[13|14|15|16]> stage[1234] : 将安装阶段[1234]生成的目标文件(*.o)拷贝到子目录stage[1234]下(各语言子目录下的*.o拷贝到stage[1234]相应的子目录下)2系统生成程序Makefile的工作流程限于篇幅,以下只分析目标 : all.internal和install假设在mips-sgi-irix5.2上安装 :2.1 A. all.internal假设已做过distclean,并执行过configure; 命令行为 :" sgi% make LANGUAGES=c"2.1.1宏定义(略)2.1.2执行目标all (转向执行all.internal)2.1.3检察配置状态若config.status不存在,则错误退出2.1.4预处理程序的生成(cpp)生成cppp.o , cexp.o , version.o , cpp-->cppp注 : 大多数的" *.c-->*.o"由以下命令完成 :" cc -c -DIN_GCC -g -I. -I. -I./config c源文件名"2.1.5c编译子系统的生成(cc1)1. 生成C_OBJS,它们是特定于c的目标文件,包括 :c-parse.o c-lang.o c-lex.o c-pragma.o c-decl.oc-typeck.o c-convert.o c-aux-info.o c-common.oc-iterate.o2. 生成OBJS,它们是各种语言的公共目标文件,包括 :toplev.o version.o tree.o print-tree.o stor-layout.o fold-const.o function.o stmt.o expr.o calls.o expmed.o explow.o optabs.o varasm.ortl.o print-rtl.o rtlanal.o emit.o real.o dbxout.o sdbout.o dwarfout.oxcoffout.o integrate.o jump.o cse.o loop.o unroll.o flow.o stupid.ocombine.o regclass.o local-alloc.o global.o reload.o reload1.o caller-save.o insn-peep.o reorg.osched.o final.o recog.o reg-stack.o insn-opinit.o insn-recog.o insn-extract.o insn-output.o insn-emit.o insn-attrtabs.o aux-output.o getpwd.oconvert.o(还可包括${EXTRA_OBJS}中的目标文件)注 : 文件insn-*是程序gen*读取md中目标系统的机器描述生成的,即 :" gen* md > insn-* "故不同的目标系统有不同的一套insn-*3. 生成BC_OBJS,它们是c的interpreter bytecode compiler,包括 :bc-emit.o bc-optab.o4. 生成cc12.1.6链接程序的生成(ld)(这一步是否做取决于目标系统的配置参数)生成collect2.o , ld-->collect22.1.7驱动程序的生成(xgcc)生成multilib.h , gcc.o , xgcc2.1.8spec文件的生成2.1.9libgcc1.a的生成1. libgcc.a有两部分构成 :1> libgcc1.a ,它包括${LIB1FUNCS},即 :_mulsi3 _udivsi3 _divsi3 _imodsi3 _modsi3 _lshrsi3 _lshlsi3 _ashrsi3_ashlsi3_divdf3_muldf3_negdf2_adddf3_subdf3_fixdfsi_fixsfsi_floatsidf_floatsisf_truncdfsf2_extendsfdf2_addsf3 _negsf2 _subsf3 _mulsf3 _divsf3 _eqdf2 _nedf2 _gtdf2_gedf2 _ltdf2-ledf2 _eqsf2 _nesf2 _gtsf2 _gesf2 _ltsf2 _lesf2它必须由GCC以外的编译器来生成 (这些功能对各目标系统可选)2> libgcc2.a ,它包括${LIB2FUNCS},即 :_muldi3 _divdi3 _moddi3 _udivdi3 _umoddi3 _negdi2 _lshrdi3_lshldi3_ashldi3_ashrdi3_ffsdi2_udiv_w_sdic_udivmoddi4_cmpdi2_ucmpdi2_floatdidi_floatdisf_fixunsdfsi_fixunssfsi_fixunsdfdi _fixdfdi _fixunssfdi _fixsfdi _fixxfdi _fixunsxfdi _floatdixf_fixunsxfsi_fixtfdi_fixunstfdi_flostditf__gcc_bcmp_varargs_epintf _op_new _op_vnew _new_handler _op_delete _op_vdel _bb_shtab _clear_cathe _trampoline __main _exit _ctors它必须由GCC的编译器(xgcc)来生成2. configure文件可能在Makefile.in中插入目标系统的tmake_file文件,其中可有对LIBGCC1的定义。

若系统不需要libgcc1.a中的功能,则生成的是libgcc1.null(空文档),而非libgcc1.a(如本目标系统mips-sgi-irix5.2)2.1.10生成xlimit.h2.1.11c++驱动程序的生成(g++)2.1.12头文件的获得(目标名为stmp-headers) (安装在临时目录./include中)1. 系统头文件的安装(目标名为stmp-fixinc)对${local_prefix}(即/usr/include)中的名子目录执行${srcdir}/${FIXINCLUDES}程序(本系统上是Makefile.in),在./include目录下建立目标系统头文件的硬拷贝2. objc头文件的安装(目标名为objc-fixinc)将${srcdir}/objc下的头文件拷贝至./include/objc下(执行${srcdir}/objc/Makefile copy-header)3. 将USE_H中的头文件拷贝至./include下,它们是GCC使用的头文件,包括 :${srcdir}/ginclude/stdarg.h ${srcdir}/ginclude/stddef.h${srcdir}/ginclude/varargs.h ${srcdir}/ginclude/va-alpha.h${srcdir}/ginclude/va-h8300.h ${srcdir}/ginclude/va-i860.h${srcdir}/ginclude/va-i960.h ${srcdir/ginclude/va-mips.h${srcdir}/ginclude/va-m88k.h ${srcdir/ginclude/va-pa.h${srcdir}/ginclude/va-pyr.h ${srcdir}/ginclude/va-sparc.h${srcdir}/ginclude/va-clipper.h ${srcdir}/ginclude/va-spur.h${srcdir}/ginclude/proto.h(还可包括${EXTRA_HEADERS}中的内容)4. 将xlimits.h拷贝成./include/limit.h5. 将${srcdir}/README-fixinc拷贝成./include/README6. libgcc.a的生成1> 生成libgcc2.a2> 将libgcc1.a(或libgcc1.null)与libgcc2.a合并成libgcc.a7. float.h的生成1> 生成enquire2> 执行enquire,生成gfloat.h3> 将gfloat.h拷贝成./include/float.h2.1.13执行fixproto(${STMP_FIXPROTO}决定是否执行这一步) (目标名为stmp-fixproto)1. 生成与fixproto相关的文件deduced.h scan.o xsys-proto(由gen-proto生成)fix-headers.o scan-decl.o2. 生成fix-headers程序3. 若./include/fixed不存在,则执行"${srcdir}/fixproto include include ${SYSTEM_HEADER_DIR}"对./include/*和${SYSTEM_HEADER_DIR}(通常为/usr/include)中的ANSI/POSIX标准系统文件改造,使之更符合ANSI/POSIX,并更适于c++2.1.14目标all(all.internal)结束2.1.15退出make2.2 B. install假设在上一步的基础上输入命令行 :"sgi% make install LANGUAGES=c "2.2.1宏定义(略)2.2.2执行目标install2.2.3安装生成的系统文件(目标名为install-common)1. 检查配置状态若config.status不存在,则退出2. 生成安装子目录若子目录已存在,则不生成3. 检查编译系统文件的状态若xgcc不存在,则生成之4. 检查c++子系统状态若生成了cc1plus(c++子系统编译成功),则若生成g++-cross 则将g++-cross安装成${bindir}/${target-g++},并建立${bindir}/${target-g++}与${bindir}/${target-c++}的逻辑链接( bindir=${exec_prefix}/bin )否则将g++安装成${bindir/g++},并建立${bindir}/g++与${bindir}/c++的逻辑链接5. 将${COMPILERS}(即cc1 cc1objc cc1plus)移至${libsubdir}下( libsubdir=${libdir}/gcc-lib}/${target}libdir=${exec_prefix}/lib )6. 将生成的ld和spec移至${libsubdir}下(系统特有的${EXTRA_PASSES}${EXTRA_PROGRAMS} ${EXTRA_PARTS}也移至此目录下)7. 若生成gcc-cross,则移至${exec_prefix}/bin下,改名为${target-gcc};且移至${exec_prefix}/${target}/bin下,改名为gcc8. 若生成xgcc,则移至${exec_prefix}/bin下,改名为gcc;并有逻辑名${target-gcc}9. 若生成protoize,unprotoize,SYSCALLS.c.X,则移至${exec_prefix}/bin下10. 将cpp移至${libsubdir}下2.2.4安装头文件(目标名为install-headers)1. 建立${libsubdir}/include2. 用${INSTALL_HEADERS_DIR}方式(tar或cpio)将./include中的内容安装在${libsubdir}/include中(安装过程另建一个子进程)3. 用${INSTALL}方式将${srcdir}/assert.h安装成${assertdir}/assert.h(assertdir=${tooldir}/includetooldir=${exec-prefix}/${target})2.2.5安装库文件若libgcc.a已生成,则1>用${INSTALL}的方式将它安装在${libsubdir}下2>若定义了${RANLIB-TEST},则用相应的目录(/usr/bin或cross-make中定义为${tooldir}/bin)下的ranlib来构造libgcc.a的符号表2.2.6安装帮助手册以${IJNSTALL}方式将${srcdir}/gcc.1、${srcdir}/cccp.1、${srcdir}/cp/g++.1安装成$(mandir)/gcc.1${mandir}cccp.1${mandir}g++.1(mandir=${prefix}/man/man1)2.2.7安装系统信息手册1. 在${srcdir}下执行makeinfo程序,由cpp.texi生成*,由gcc.texi(还需extend.texi install.texi invoke.texi md.texi rtl.texi tm.texi)生成*2. 用${INSTALL}方式将${srcdir}下*,*安装在${infodir}下(infodir=${prefix}/info)2.2.8目标install结束2.2.9退出make。

相关文档
最新文档