粗浅谈论makefile

主要参考:跟我一起写makefile  点击打开链接

Makefile简介:

简单的说,一个大的工程中的源文件不计其数,其按照不同的类型,功能,模块放在了不同的目录之中,makefile则是定义了一些规则来指定,哪些文件需要先编译,哪些需要后编译,哪些需要重新编译,而makefile带来的好处就是,一旦写好,之后一个make命令 就可以搞定,极大的提高了软件的开发。

简述编译链接:

无论选择什么语言c,c++都需要将源文件编译成为中间代码文件,在windows下面是.obj文件,而unix则是.o文件,这就是编译(compile),然后将.o文件链接(link操作)形成可执行文件。但由于源文件太多,编译生成的中间文件太多,不太方便,此时需要给中间目标文件打包,在windows下成为库文件.lib(library file),而在unix称为.a(archivefile)文件。

一个简单的makefile样例:

Edit(最终目标可执行文件):main.otest.o start.o xd.o(依赖文件)

Cc –o edit main.o test.o start.o xd.o

Main.o: main.c defs.h

Cc –c main.c

Test.o : test.c defs.h

Cc –c test.c

Start.o: start.c defs.h

Cc –c start.c

Xd.o: xd.c defs.h

Cc –c xd.c

Clean:(伪目标) 依赖文件不执行,退出时可以显示执行 make clean

Rm –r edit main.o test.o xd.o start.o

Gund make很强大,有自动推导的功能,一个.o文件 会自动推导.c文件,于此同时还可以使用变量 来代替目标文件(过多很复杂),新的makefile:

Objects = main.o test.o start.o xd.o

Cc –c edit $(objects)

Main.o:defs.h

Start.o:defs.h

Xd.o:defs.h

Test.o:defs.h

所有.c文件可以自动推导。

下面是一个makefile的小知识点:

Tips:

Makefile:

1)      如果make执行,遇到-I或者是includedir的时候,操作按照参数指定的路径去寻找

2)      如果/usr/local/bin 或者是/usr/include存在是话 make也会去寻找,到最后如果还是找不到的话,make会报告一个致命的信息,如果想让make忽略这些信息的话,寻找在include的前面加上一个-号: -include <filename>或者使用sinclude命令和-的作用是一致的。

3)      不建议使用环境变量:MAKEFILES(主要就是包含其他的makeifile文件)

Make的工作方式:

1)读入所有的makefiles

2)读入include的其他makefiles

3)初始化文件中的变量

4)推到隐晦规则,分析规则

5)创建依赖关系

6)根据依赖关系,决定哪些目标文见需要重新生成。

7)执行命令

在初始化变量的时候,只有在生成目标文件的时候,变量才会被展开使用,否则并不会立即进行展开。

第一条规则中第一个目标将会是最终的目标。

Make的命令需要以Tab开始

通配符的使用:

但是 当objects = *.o时 并不是代表着所有的.o文件,而是真正是*.o,要是需要所有的.o文件,可以使用
object := $(wildcard *.o)关键字wildcard(自动全部扩展开)

$?:自动化变量(上一次程序的退出码)

VPATH这个特殊的变量是指明了需找的路径,是在make在当前目录找不到的情况下会按照指定的目录去寻找文件

:VPATH= src:../headers(:是分隔)

与此同时还有一个vpath 关键字,不是一个变量是一个make关键字。

vpath %.h ../headers 表示在../headers目录下搜索以.h结尾是文件

伪目标不是一个文件,只是一个标签:(一般放在命令的最后,并且需要显示的调用 make clean)

.PHONY: clean

clean:

-rm *.o temp

静态模式

Objects = foo.obar.o

all:$(objects)

$(objects):%.o:%.c

$(cc) –c $(CFLAGS)$< -o [email protected]      /*$<:所有依赖目标集 [email protected]:目标集*/

自动寻找头文件和源文件:main.o: main.c defs.h

但是由于头文件过多的原因,需要自动寻找源文件和头文件,使用cc –M main.c

但是如果使用的是gnu的编译器,需要的是gcc –MM main.c 否则会将标准库的头文件一起包含进来。

Makefile的显示命令:

@echo xxxx 当make时会输出 echo xxxx 并不会执行命令

Make –n 或—just-print 只是显示命令 并不会执行

Make –s 或者是–slient 全面禁止命令的显示

嵌套执行make

在一些比较大的工程之中,我们会把不同模块或是不同功能的源文件放在不同的目录里面,可以在每个目录下面都写一个makefile文件,这样还会很简洁,但是也存在着缺陷,就是难以维护,嵌套执行make语句就体现出了很强大的好处。例如:

subsystem:

cd subdir&& $(make) – 意思是先进入subdir文件,之后执行make命令,这个是总控的makefile文件,总控文件里面的变量可以传递到下一级的makefile文件中,但是不会覆盖下一级makefile的变量,除非使用指定参数-e

传递变量:export variable = value

如果要是想传入所有的变量。只使用一个export即可。例外shell ,makeflags 变量都是需要传入下一级的变量。

变量的使用,使用$来表示变量,但是要想使用单独的$时候,需要使用$$来表示。

变量的使用,可以使用变量的变量,变量的值可以是后续变量的值:foo = $(bar)

bar = xd;

但是这样同时也会存在着弊端,就是递归定义,形成类似于死循环的样式。

解决

使用:= 来限制,是前面的变量不可以使用后面的变量的值,只可以使用前面已经定义好的变量的值

y := $(x) bar

x := foo

其中y的值就是 bar ,而不是 foo bar

空格的定义:(先定义一个空的变量,在将这个空的变量在等号的右边使用)

nullstring :=

space :=$(nullstring)

?= 是否存在的意思

替换

Foo := a.o b.o

Bar := $(foo: .o =.c)

Bar = a.c b.c

追加变量值 使用 += (好比java的那个字符串的拼接)

Makefile的函数使用:

subst替换函数

$(subst ee,EE,geet ont the feet)

patsubst:模式字符串替换函数

$(patsubst %.c,%.o,x.c.c bar.c)=>x.c.obar.o

strip: 去空格函数(去掉开头和结尾的空格)

findstring:$(findstring <find> ,<in>)在<in>查找<find>

$(findstring a, a b c)=>a

$(findstring a, b c)=>“”

filter: 按照条件过滤(过滤掉不符合条件的)

filter-out :反过滤函数

sort:给单词排序(升序)并且去掉相同的单词

word:取出单词

$(word <n> ,<text>)取出text中的第n个单词

wordlist:取单词串的函数

$(wordlist 2,3,<text>)取出text中的第2-3个单词

words:统计单词个数

firstword:取首个单词

文件名的操作函数:

dir:取目录函数 目录部分是/之前的 没有/ 返回“./”

$(dir src/foo.c hacks)=>src/./

notdir:取文件函数

$(notdir src/foo.c hacks)=>foo.c hacks

suffix:取后缀函数

basename:取前缀函数

addsuffix:添加后缀函数

addprefix:添加前缀函数

join:连接函数(对应链接)

$(join aaa bbb, 111 222 333)=>aaa111bbb222 333

foreach:用于循环的使用

$(foreach<var>,<list>,<text>)

name:= a b c d

files:= $(foreachn,$(name),$(n).o)就是将临时局部变量每次赋予一个值,之后转化为.o文件 临时变量出了函数 将会无效,类似于c++for函数中的i。

if函数:

$(if<condition>,<then-part>,<else-part>)

call:创建一个新参数化的函数

origin:主要是返回这个变量是从什么地方来的

$(origin <variable>) 返回值:

undefined:

default:

file

command line

override

automatic

控制make的函数:

Error:

$(error <text>) text是出错信息

Warning

$(warning <text>) text是警告信息

Make的退出码

0---表示成功执行

1---出现任何错误,返回1

2--- 一些目标不需要更新

Makefile伪目标:

all:

所有的目标

clean:

删除所被make创建的文件

install:

安装已经编译好的程序,就是将目标执行文件拷贝到制定的目标中去

print:

列出改变过的源文件

tar:

将源文件打包备份

dist:

创建一个压缩文件

TAGS:

更新所有目标

check和test:

测试makefile的流程

时间: 2024-08-02 11:03:48

粗浅谈论makefile的相关文章

u-boot的Makefile语法教程分析

U-BOOT是一个LINUX下的工程,在编译之前必须已经安装对应体系结构的交叉编译环境,这里只针对ARM,编译器系列软件为arm-linux-*. U-BOOT的下载地址: http://sourceforge.net/projects/u-boot我下载的是1.1.6版本,一开始在FTP上下载了一个次新版,结果编译失败.1.1.6是没问题的. u-boot源码结构    解压就可以得到全部u-boot源程序.在顶层目录下有18个子目录,分别存放和管理不同的源程序.这些目录中所要存放的文件有其规

关于makefile中变量的多次赋值以及override指令

1 基本原则如下 1.1 原则1 变量的普通赋值是有先后顺序的,后面的赋值会覆盖掉前面的赋值. 1.2 原则2 使用的时候,用的是其前面最后的赋值,就算其后面有使用了override指令的赋值也不会影响这条原则. 1.3 原则3 当使用了override指令定义赋值了变量后,其后对该变量的所有的赋值都是无效的.但是override之前的所有的赋值都是有效的.使用的时候是往前最近原则. 2 override变量.命令行参数和普通变量之间的屏蔽关系 override变量会屏蔽命令行参数,除非用+=:

使用Makefile去管理程序

前言:在gcc中如何使用分屏操作  : 在命令行中使用    : sp + filename     vim  Makefile  编辑make工程   第一行使用 # 进行注释   说明是什么make  内容格式:  目标文件:  依赖文件 ·  ·  ·  但是一定要注意如果要使用编译指令一定要用table键 不能使用几个空格代替 另外  max.h 和min.h 的内容就是函数声明 下面说下这样make的好处吧:  在大型程序中能很好帮我们管理我们的代码和项目,程序的任何部分分工都很明确,

Contiki 2.7 Makefile 文件(三)

2.第二部分 这里的usage,targets,savetarget,savedefines都是伪目标. 和all不同,这些伪目标不会被执行,除非显式指定这些目标. 这里有两个目标savetarget,savedefines前边我们提过. 通过命令 make TARGET=esb savetarget可以保存默认的TARGET到Makefile.target中. 通过命令 make TARGET=esb DEFINES=MYTRACE,MYVALUE=4711 savedefines 可以保存默

My first makefile to compile multiple C files

I have three files to compile: main.c, func.c,  func.h The steps: 1   main.c   to   main.o 2   func.c    to   func.o 3    link main.o func.o to main(file that can execute) So, u need to run at least three commands without a Makefile.Then if u have 10

liunx中ctags 与makefile的使用

ctags 是vim下可以帮助阅读代码的一个的工具,它可以很方便的看到程序的源代码 使用ctags可以有两种方法:(1).可以在任意目录下建立文件,然后使用 ctags *.c,这个命令的意思是把当前目录下的所有文件生成标签文件(vim可以通过标签,跳转到标签文件处)例如: vim ctag.h vim ctag.c vim main.c 在main.c中把光标移至fun函数处,按Ctrl+[就会跳转到fun函数定义的地方,即ctag.c处,Ctrl+T回转到main.c函数 (2).输入cta

linux中make命令的简单使用以及Makefile文件的书写

Makefile 会不会写makele,从一个侧面说明了一个是否具备完成大型工程的能力. 一个工程中的源件不计数,其按类型.功能.模块分别放在若干个目录中,makele定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为makele就像一个Shell脚本一样,其中也可以执行操作系统的命令.makele带来的好处就是"自动化编译",一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率. ma

makefile编译文件介绍

通常在C语言程序开发中,尤其是大型项目的构建,我们不可能一个文件一个文件去编译,通常会编写Makefile文件使用make命令完成项目的编译构建: 如下:math项目是简单的计算那个数字大,哪个数字小,以及两个数字和的小程序.由max.c,min.c , sum.c 和main.c构成,分别如下: max.c #include <stdio.h> int max(int a,int b) {     if(a>b){         return a;      }else{      

通用多目录makefile的写法

我的项目文件层次是:项目名称/include.output.src src/admin.stu.tch.common 最外层的Makefile: DEBUG = yMYDEBUG = DEBUGifeq ($(DEBUG),y)DEBFLAGS = -O -g -D$(MYDEBUG)elseDEBFLAGS =endif PRJ_HOME := $(shell pwd)SOURCES := $(wildcard *.c)OBJECTS := ${SOURCES:%.c=%.o}INCPATH