Linux编程之Makefile入门

嵌入式linux下Makefile入门

    • @[TOC](嵌入式linux下Makefile入门)
  • 1.概述
  • 2.“一个规则”
      • 基本原则:
  • 3."两个函数"(便于进行程序扩展)
  • 4.“三个自动变量”(便于进行程序扩展)
  • 5.模式规则
  • 6.附录
    • 总结
    • 万能makefile

1.概述

Makefile与Shell脚本类似,是一系列命令的集合。用于项目代码编译管理。其定义了一系列的规则来指定文件是否需要编译以及编译顺序,甚至进行更复杂的功能操作。

  • 优点:
    “自动化编译”
    节省编译时间
    一次编写,终身受益
  • 要点:
    “一个规则”
    “两个函数”
    “三个自动变量”

2.“一个规则”

目标:依赖条件
[Tab]命令     // 注:命令若另起一行,命令前必须为[Tab键]
目标:要生成的文件
依赖条件:
命令:

makefile1:

hello.o:hello.c
[一个Tab键]gcc -c hello.c -o hello.o

基本原则:

  1. 若想生成目标,检查规则中的依赖条件是否存在,如不存在,则寻找是否存在规则用来生成该依赖文件。
  2. 检查规则中的目标是否需要更新,必须先检查他的所有依赖,依赖中有任何一个被更新,则目标必须更新。

makefile2:

hello:hello.o
    gcc hello.o -o hello
hello.o:hello.c 
    gcc -c hello.c -o hello.o   

当存在多个文件联合编译生成一个可执行文件时,可对比出makefile1与makefile2的优劣。

makefile3 :直接将所有文件编译并链接

a.out:111.c 222.c 333.c
    gcc 111.c 222.c 333.c -o a.out

makefile4 :分别将每个文件编译,然后将每个 .o 文件进行链接

a.out:111.o 222.o 333.o
    gcc 111.o 222.o 333.o -o a.out
111.o:111.c
    gcc -c 111.c -o 111.o    
222.o:222.c
    gcc -c 222.c -o 222.o
333.o:333.c
    gcc -c 333.c -o 333.o  
  • 根据基本规则2,当多个文件只有一个或部分被修改,未被修改的文件并不需要被重新编译,当文件较多时makefile4会节省大量时间。
  • 通常我们称a.out为终极目标,makefile会将第一个目标作为默认终极目标,所以必须把终极目标作为第一个目标,为打破此项弊端,makefile存在一个默认命令all(ALL),用来指定终极目标。

makefile5 :此时,目标的顺序不再受限。

all:a.out

a.out:111.o 222.o 333.o
    gcc 111.o 222.o 333.o -o a.out
111.o:111.c
    gcc -c 111.c -o 111.o    
222.o:222.c
    gcc -c 222.c -o 222.o
333.o:333.c
    gcc -c 333.c -o 333.o  

3.“两个函数”(便于进行程序扩展)

  • src = $(wildcard *.c) ----- 找到当前目录下所有后缀为.c的文件,赋值给src。
  • obj = ( p a t s u b s t (patsubst %.c,%.o, (patsubst(src)) -----把src变量里所有后缀为.c的文件替换成.o;将参数3中,包含参数1的部分,替换为参数2。此时,makefile5便可进行升级:
    makefile6 :
src = $(wildcard *.c) 
obj = $(patsubst %.c,%.o,$(src))

all:a.out

a.out:$(obj)
    gcc $(obj) -o a.out
111.o:111.c
    gcc -c 111.c -o 111.o    
222.o:222.c
    gcc -c 222.c -o 222.o
333.o:333.c
    gcc -c 333.c -o 333.o 

我们生成了多个编译文件,Makefile存在一个清除目标文件的规则,规则如下:

clean:
    rm a.out

更为稳健的做法是:.PHONY表示clean是一个伪目标;“-”表示出错依然执行。不成文的规定“clean”规则一般放在文件最后。

.PHONY:clean
clean:
    -rm -rf a.out

makefile7 :

src = $(wildcard *.c) 
obj = $(patsubst %.c,%.o,$(src))

all:a.out

a.out:$(obj)
    gcc $(obj) -o a.out
111.o:111.c
    gcc -c 111.c -o 111.o    
222.o:222.c
    gcc -c 222.c -o 222.o
333.o:333.c
    gcc -c 333.c -o 333.o 
    
.PHONY:clean
clean:
    -rm -rf $(obj) a.out   

执行clean的命令为 “make clean”,以防万一,酿成大祸,建议先执行“make clean -n”,预执行一下,观察结果正确后,再执行“make clean”。

4.“三个自动变量”(便于进行程序扩展)

  • $@:表示规则命令中的目标
  • $^:表示规则中的所有依赖条件,组成一个列表,以空格隔开,如果该列表中存在重复项则消除重复项
  • $<:表示规则命令中的第一个依赖条件;如果将该变量应用在模式规则中,它可将依赖条件列表中的依赖依次取出,套用模式规则。

在makefile7的基础上,引入自动变量:
makefile8 :

src = $(wildcard *.c) 
obj = $(patsubst %.c,%.o,$(src))

all:a.out

a.out:$(obj)
    gcc $^ -o $@
111.o:111.c
    gcc -c $< -o $@    
222.o:222.c
    gcc -c $< -o $@
333.o:333.c
    gcc -c $< -o $@ 
    
.PHONY:clean
clean:
    -rm -rf $(obj) a.out   

5.模式规则

%.o:%.c
	gcc -c $< -o $@ 
src = $(wildcard *.c) 
obj = $(patsubst %.c,%.o,$(src))

all:a.out

a.out:$(obj)
    gcc $^ -o $@
    
%.o:%.c
    gcc -c $< -o $@    
    
.PHONY:clean    #强制执行
clean:
    -rm -rf $(obj) a.out   
静态模式规则:表示对哪一个依赖条件套用模式规则
$(obj)%.o:%.c
	gcc -c $< -o $@ 
src = $(wildcard *.c) 
obj = $(patsubst %.c,%.o,$(src))

all:a.out

a.out:$(obj)
    gcc $^ -o $@
    
$(obj)%.o:%.c
    gcc -c $< -o $@    

%.o:%.s
    gcc -S $< -o ...  
            
.PHONY:clean    #强制执行
clean:
    -rm -rf $(obj) a.out  
伪目标:.PHONY:clean   all      #强制执行
src = $(wildcard *.c) 
obj = $(patsubst %.c,%.o,$(src))

c_flags = -Wall -g 

all:a.out

a.out:$(obj)
    gcc $^ -o $@ $c_flags
    
$(obj)%.o:%.c
    gcc -c $< -o $@ $c_flags

%.o:%.s
    gcc -S $< -o ...  
            
.PHONY:clean    #强制执行
clean:
    -rm -rf $(obj) a.out 

6.附录

= 与 :=
  • “=” : make会将整个makefile展开后,再决定变量的值。也就是说,变量的值将会是整个makefile中最后被指定的值
  • “:=”:表示变量的值决定于它在makefile中的位置,而不是整个makefile展开后的最终值

总结

= 是最基本的赋值回
:= 是覆盖之前的值
?= 是如果答没有被赋值过就赋予等号后面的值
+= 是添加等号后面的值

万能makefile

万能makefile地址

你可能感兴趣的:(Linux相关,linux,makefile)