[转]Make的使用与Makefile的写法结构

转自:Make的使用与Makefile的写法结构_漏洞百出的博客-CSDN博客

Make:
工程管理器,也叫“自动编译管理器”,
“自动”的意思是指它能够根据文件更改的时间自动发现更新过的文件而减少编译的工作量,
同时,它通过读入Makefile文件的内容来执行大量的编译工作

Makefile基本结构
是Make读入的唯一配置文件
由make工具创建的目标体(target),通常是目标文件或可执行文件
要创建的目标体所依赖的文件(dependency_file)
创建每个目标体时需要运行的命令(command)
注意:命令行前面必须是一个”TAB键”,否则编译错误为:*** missing separator.Stop.

makefile基本格式: 

target:dependency_files
<TAB> command
例如:
hello.o :hello.c hello.h
gcc –c hello.c –o hello.o

makefile变量

main:led.o pwm.o
	gcc led.o pwm.o -o main
kang.o : pwm.c pwm.h
	gcc –Wall –O -g –c pwm.c -o pwm.o
led.o : led.c led.h
	gcc - Wall –O -g –c led.c -o led.o
.PHONY: clean       伪目标,防止出现与clean同名的文件
clean:
	rm  *.o test	  删除.o文件和test文件
-Wall:编译时发出所有有用的信息
-c:只是编译不链接,生成目标文件  .o  
-o file :把输出文件输出到file里(man手册查看更多)

创建和使用变量:
创建变量的目的:

用来代替一个文本字符串:    
1.系列文件的名字
2.传递给编译器的参数
3.需要运行的程序
4.需要查找源代码的目录
5.你需要输出信息的目录
6.你想做的其它事情

---------定义变量的方式:----------
OBJS = led.o pwm.o
CC = gcc
CFLAGS = -Wall -O -g
main: $(OBJS)
    $(CC) $(OBJS) -o main
kang.o : pwm.c pwm.h
    $(CC) $(CFLAGES) pwm.c -o pwm.o
led.o : led.c led.h
    $(CC) $(CFLAGES) led.c -o led.o
    
---------递归展开方式:----------
    foo = $(bar)
    bar = $(ugh)
    ugh = Huh?
    优点:可以向后引用变量
    缺点:不能对该变量进行任何扩展:CFLAGES = $(CFLAGES) -这个会一直死循环
---------简单方式:---------------
    VAR:=var
    m := mm
    x := $(m)
    y := $(x) bar
    x := later
    echo $(x) $(y)
        这种方式定义的变量,会在变量的定义点,按照被引用的变量的当前值进行展开
        这种定义变量的方式更适合在大的编程项目中使用,因为它更像我们一般的编程语言
-------------------------------------
------用 ?= 定义变量-----------
    dir := /foo/bar
    FOO ?= bar   查看FOO是否被定义过,没有则定义为bar,否则什么都不做
    FOO是?
-------为变量添加值---------------
使用   +=   为已知的变量添加新的值
    Main = demo1.o demo2.o
    Main += demo3.o    相当于Main = demo1.o demo2.o demo3.o

 

预定义变量

AR        库文件维护程序的名称,默认值为ar。AS汇编程序的名称,默认值为as。
CC       C编译器的名称,默认值为cc。
CPP         C预编译器的名称,值为$(CC) –E。
CXX     C++编译器的名称,默认值为g++
FC         FORTRAN 编译器的名称,默认值为 f77
RM        文件删除程序的名称,默认值为 rm -f
------------------例如:----------------------
Main = led.c led.h
    $(CC) -o Main led.c
clean:
    $(RM)Main
-----------------------------------
ARFLAGS        库文件维护程序的选项,无默认值。        
ASFLAGS         汇编程序的选项,无默认值。
CFLAGS          C编译器的选项,无默认值。
CPPFLAGS        C预编译的选项,无默认值。
CXXFLAGS        C++编译器的选项,无默认值。
FFLAGS            FORTRAN编译器的选项,无默认值。
-----------------------例如-----------------------------
OBJS = led.o pwm.o
CC = gcc
CFLAGS = -Wall -O -g
main: $(OBJS)
    $(CC) $(OBJS) -o main
kang.o : pwm.c pwm.h
    $(CC) $(CFLAGES) pwm.c -o pwm.o
led.o : led.c led.h
    $(CC) $(CFLAGES) led.c -o led.o
--------------------------------------------------------    

自动变量

$*                不包含扩展名的目标文件名称
$+            所有的依赖文件,以空格分开,并以出现的先后为序,可能包含重复的依赖文件
$<            第一个依赖文件的名称
$?            所有时间戳比目标文件晚的依赖文件,并以空格分开
$@            目标文件的完整名称
$^            所有不重复的目标依赖文件,以空格分开
$%            如果目标是归档成员,则该变量表示目标的归档成员名称
------------------例子--------------------
OBJS = led.o pwm.o
CC = gcc
CFLAGS = -Wall -O -g
main: $(OBJS)
    $(CC) $^ -o $@
kang.o : pwm.c pwm.h
    $(CC) $(CFLAGES) -c $< -o $@
led.o : led.c led.h
    $(CC) $(CFLAGES) -c $< -o $@
------------------------------------------------    

环境变量

    make在启动时会自动读取系统当前已经定义了的环境变量,并且会创建与之具有相同名称和数值的变量
    如果用户在Makefile中定义了相同名称的变量,那么用户自定义变量将会覆盖同名的环境变量

Make的使用

    直接输入make 
    后面可跟选项
    -C         dir读入指定目录下的Makefile
    -f            file读入当前目录下的file文件作为 Makefile
    -i            忽略所有的命令执行错误,比如很多文件一起编译,全部走一遍看具体哪些文件有错
    -I            dir指定被包含的Makefile 所在目录
    -n            只打印要执行的命令,但不执行这些命令
    -p            显示make变量数据库和隐含规则
    -s            在执行命令时不显示命令
    -w        如果make在执行过程中改变目录,打印当前目录名

Makefile的隐含规则 

编译C程序的隐含规则:
name.o 的目标的依赖目标会自动推到 name.o  ,并且其生成命令是 
$(CC) -c $(CFLAGES) $(CFLAGES)

链接文件的隐含规则:
name 目标依赖于 name.o  ,通过运行C的编译器来运行链接程序生成(一般是ld),
其生成命令是:$(CC) $(LDFLAGES) name.o $(LOADLIBES) $(LDLIBS) . 这个规则对于
只有一个源文件的工程有效,同时也对多个Object 文件(由多个不同的源文件生
成)也    有效
-----------------例如----------------------
x : x.o y.o z.o
–并且“x.c”、“y.c”和“z.c”都存在时,隐含规则将执行如下命令:
–cc -c x.c -o x.o
–cc -c y.c -o y.o
–cc -c z.c -o z.o
–cc x.o y.o z.o -o x
–如果没有一个源文件(如上例中的x.c)和你的目标名字
(如上例中的x)相关联,那么你最好写出自己的生成规则,不然,隐含规
则会报错的。

 

Makefile的VPATH:虚路径

在一些大的工程中,有大量的源文件,我们通常的做法是把这许多的
源文件分类,并存放在不同的目录中。所以,当make需要去找寻文
件的依赖关系时,你可以在文件前加上路径,但最好的方法是把一个
路径告诉make,让make在自动去找。
所以特殊变量VPATH 就是完成这个功能的,如果没有指明路径,
make会在当前路径下起找依赖文件和目标文件,如果定义了这个变量
make就会从当前路径再到指定的路径的查找

写法:
VPATH = src:../header     指当前目录的src  和上一级目录的header
上面的定义指定两个目录,src  和   ../header  make会按照这个顺序进
行搜索,目录由冒号分隔  

 

Makefile的嵌套

@echo $(SUBDIRS) 打印信息,但不提示
@(RM)  删除
make -C $@   读入指定目录下的Makefile开始编译生成目
标的完整名称
export CC OBJS BIN OBJS_DIR BIN_DIR  把这些变量传递
给子目录

 

Makefile模板:

CC = gcc    定义gcc
SUBDIR = f1 \          定义所有文件路径
                f2 \
                main \
                obj
OBJS = f1.o f2.o main.o        定义所有 .o  文件变量
BIN = myapp                        定义bin名字
OBJS_DIR = obj                   定义obj目录
BIN_DIR = bin                      定义bin目录
export CC OBjS BIN OBJS_DIR BIN_DIR          传递变量
all:CHECK_DIR $(SUBDIRS)               
CHECK_DIR:                      
    mkdir -p $(BIN_DIR)             创建bin文件夹       
$(SIBDIR):ECHO
    make -C $@                    开始去各个目录编译
ECHO:                              打印
    @echo $(SUBDIRS)           打印SUBDIR但不提示,加上@就是不提示
    @echo begin compile         打印begin compile
clean:
    @$(RM) $(OBJS_DIR)/*.o       删除OBJS_DIR目录下的  .o  文件
    @rm -rf $(BIN_DIR)            删除bin文件夹

 

f1的Makefile

../$(OBJS_DIR)/fi.o    : fi.c        把f1.c生成的.o 文件放到上一级目录的 OBJS_DIR 下,也就是obj文件夹
    $(CC) -c $(^) -o $@           gcc 编译所有目标文件生成目标文件完整名称的 .o 文件

main的Makefile

../$(OBJS_DIR)/main.o : main.c
    $(CC) -c $^ -o $@

 

obj链接文件的Makefile(把.o文件链接起来放入bin文件夹下)

 ../$(BIN_DIR)/$(BIN):func1.o func2.o func.o
    $(CC) func1.o func2.o func.o -o ../$(BIN_DIR)/$(BIN)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
makefile是一种用于自动化构建和编译程序的脚本文件。makefile的基本写法包括目标、依赖、规则和命令这三个要素。 1. 目标:目标是指需要生成的文件或执行的任务。在makefile中,目标通常是一个可执行文件或一个文件的对象文件。可以有多个目标,每个目标占据一行,并以冒号(:)结尾。 2. 依赖:依赖是指目标生成所依赖的文件或任务。在makefile中,依赖通常是源文件或其他目标。依赖也可以有多个,每个依赖之间用空格分隔,放在目标的后面。 3. 规则:规则是指定义了目标和依赖之间关系的部分。在makefile中,规则以目标为开头,后面是一个冒号(:),然后是依赖。规则可以有多行,每行以一个Tab键开头,表示规则所对应的命令。 例如,下面是一个简单的makefile示例: ``` target: dependency command ``` 其中,`target`是目标,`dependency`是依赖,`command`是需要执行的命令。 通过这样的规则,当依赖发生变化时,可以使用make命令来自动更新目标。make工具会自动识别目标和依赖之间的关系,并执行相应的命令来生成目标。 需要注意的是,makefile中的命令必须以Tab键开头,否则make工具无法正确解析。 这只是makefile的一种简单写法,实际上,makefile可以包含更复杂的规则和命令,以满足具体项目的需求。可以通过学习更多的makefile语法和使用方法来进一步掌握makefile写法。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [手把手教你makefile](https://blog.csdn.net/weixin_43574962/article/details/104108641)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值