从入门到制作编译多目录文件的makefile

makefile作用:用于管理编译文件。通常编译linux项目时,有长达几千个文件,在某次更改其中一个文件的话,若要将整个工程全部编译,太繁琐耗时。引入makefile,它依据文件更新的时间,从而只编译改动过的文件。

1 makefile名词解释:

目标:指编译后生成文件。

依赖:生成这个目标,所依赖的文件。(注意在执行这条规则时,makefile首先会去遍历这些依赖,如不存在,则会从这makefile文件中寻找依赖,并执行依赖所在的规则)。

eg:

test:a1.o  a2.o  
	gcc  a1.o  a2.o  –o test
a1.o:a1.c
	gcc –c a1.c
a2.o:a2.c
	gcc –c a2.c

命令:如何生成标。(命令行首格 按tab键,否则报错)

2 makefile基础规则

2.1赋值

A = 1  #普通赋值

B:= 2  #立即赋值,不管B之前有没有被赋值,立即被赋值为2

B?=3  #询问赋值,若B在之前没有被赋值,则赋值。若有,则不赋值

C =$A  #将变量A的值赋值给C  “$”在makefile中特别常用,用于变量的赋值

2.2 特殊符号

$@: 目标
$^:  全部依赖

$<: 第一个依赖

%:通配符

3 编写一个所有文件均在同一目录下的makefie

TGT = a.out
SRC = test.c  tst.c
OBJ := $(SRC:.c = .o)
CC = gcc

$(TGT):$(OBJ)
	$(CC) –o $@  $^
%.o : %.c
	$(CC) –o $@ –c $<
.PHONY:clean
clean:
	rm –rf $(SRC) $(OBJ) 

4上面那个makefile,头文件发生更改时,由于没有加入检测头文件更新的机制,在执行make的时候会忽略头文件的更改。下面完善检测头文件机制的makefile

%.d:%.c TGT=a.out
SRC=test.c tst.c
OBJ := $(SRC:.c = .o)
CROSS_COMPILER= #arm-linux-
CC=$(CROSS_COMPILER)gcc
CUR_DIR=$(shell pwd)
DIR=$(CUR_DIR)/head
CFLAGF=-I$(DIR)
$(TGT):$( OBJ )
        $(CC) $^  -o $@  $(CFLAGF)

%.o:%.c
        $(CC) $< -c -o $@
        $(CC) $< -MM > $@
-include $(SRC:.c=.d)
clean:
        rm -vf  $(TGT)  $( OBJ )  $(SRC:.c=.d)
.PHONY:clean

5 编写一个所有文件均在不同目录下的makefie

目录结构为:

book@www.100ask.org:~/makefile/04$ tree

.

├── head

│   └── head.h

├── head.h

├── main.c

├── makefile

├── test

│   ├── hello

│   │   ├── head.h

│   │   ├── hello.c

│   │   └── makefile

│   ├── makefile

│   └── test.c

└── tst

    ├── makefile

    └── tst.c

5.1在当前目录(主目录)makefile文件为

export CC = gcc 
export LD =ld 
SRC=main.c
TGT =a.out
SUB_DIR =test tst  
export SUB_TGT =build-in.o
TOP_DIR =$(shell pwd)
HEAD_DIR =$(TOP_DIR)/head
export CFLAGS=-I $(HEAD_DIR)
$(TGT):$(SUB_DIR) $(SRC:.c=.o)
        $(CC)  $(CFLAGS)  $(SUB_DIR:=/$(SUB_TGT)) $(SRC:.c=.o)

$(SUB_DIR):
        make -C $@
%.o:%.c
        $(CC) $(CFLAGS) -c  $<
%.d:%.c
        $(CC) $(CFLAGS) -MM $<  > $@
sinclude $(SRC:.c=.d)
clean:
        rm -vf $(TGT)
        rm -vf $(SRC:.c=.o)  $(SRC:.c=.d)
        for dir in $(SUB_DIR); do \  
make -C $$dir clean; \
        done
.PHONY:clean $(SUB_DIR)

解析:在通过makefile编译的过程中,SUB_DIR指定了要去遍历的子目录,通过make -C $@

语句,执行各个子目录下的makefile文件,并生成一个叫build-in.o的文件,通过export SUB_TGT =build-in.o 指定。等待各个子目录都被编译完了,然后在返回主目录,连同build-in.o和main.o生成TGT。

5.2在test目录下的makefile文件为:

SRC =test.c
SUB_DIR=hello

$(SUB_TGT):$(SUB_DIR)  $(SRC:.c=.o) 
        $(LD)   $(SRC:.c=.o) $(SUB_DIR:=/$(SUB_TGT))  -r -o $@

%.o:%.c
        $(CC) $(CFLAGS) $< -c 

%.d:%.c
        $(CC)  $(CFLAGS) -MM $<  >  $@
$(SUB_DIR):
        make -C $@

sinclude $(SRC:.c=.d)

clean:
        rm -rvf $(SUB_TGT)
        rm -rvf $(SRC:.c=.d) $(SRC:.c=.o)
        for dir in $(SUB_DIR); do \
        make -C $$dir clean; \
        done
.PHONY:clean $(SUB_DIR)  

解析:通过主目录执行该子目录的makefile文件,该目录下有test.c文件和hello目录,大体执行与主目录相同。它先去hello目录执行该目录的makefile,并生成build-o,然后将build-o文件和该目录下的test.o一起打包生成build.o文件。

5.3 在hello目录下的makefile文件

SRC =hello.c
SUB_DIR=

$(SUB_TGT):$(SRC:.c=.o) $(SUB_DIR)
        $(LD)   $(SRC:.c=.o) $(SUB_DIR:=/$(SUB_TGT))  -r -o $@

%.o:%.c
        $(CC) $(CFLAGS) $< -c 

%.d:%.c
        $(CC)  $(CFLAGS) -MM $<  >  $@
$(SUB_DIR):
        make -C $@

sinclude $(SRC:.c=.d)

clean:
        rm -rvf $(SUB_TGT)
        rm -rvf $(SRC:.c=.d) $(SRC:.c=.o)
        for dir in $(SUB_DIR); do \
        make -C $$dir clean; \
        done
.PHONY:clean $(SUB_DIR)  

解析:该makefile 与上面基本相同,由于该目录下没有其他目录,所以SUB_DIR=

为空。

5.4 在tst目录下的makefile

SRC =tst.c
SUB_DIR=

$(SUB_TGT):$(SRC:.c=.o) $(SUB_DIR)
        $(LD)   $(SRC:.c=.o) $(SUB_DIR:=/$(SUB_TGT))  -r -o $@

%.o:%.c
        $(CC) $(CFLAGS) $< -c
        echo $(CFLAGS) 

%.d:%.c
        $(CC)  $(CFLAGS) -MM $<  >  $@
$(SUB_DIR):
        make -C $@

sinclude $(SRC:.c=.d)

clean:
        rm -rvf $(SUB_TGT)
        rm -rvf $(SRC:.c=.d) $(SRC:.c=.o)
        for dir in $(SUB_DIR); do \
        make -C $$dir clean; \
        done
.PHONY:clean $(SUB_DIR)

解析:同上

make之后的目录结构

book@www.100ask.org:~/makefile/04$ tree

.

├── a.out

├── head

│   └── head.h

├── head.h

├── main.c

├── main.d

├── main.o

├── makefile

├── test

│   ├── build-in.o

│   ├── hello

│   │   ├── build-in.o

│   │   ├── head.h

│   │   ├── hello.c

│   │   ├── hello.d

│   │   ├── hello.o

│   │   └── makefile

│   ├── makefile

│   ├── test.c

│   ├── test.d

│   └── test.o

└── tst

    ├── build-in.o

    ├── makefile

    ├── tst.c

    ├── tst.d

    └── tst.o

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值