linux c编程之Makefile使用

来源:互联网 发布:ipad软件商店不动 编辑:程序博客网 时间:2024/06/08 11:45

make工具通过一个称为Makefile的文件来完成并自动维护编译工作。
Makefile文件描述了整个工程的编译、链接等规则。

Target… : DEPENDENCIES…
COMMAND

目标:程序产生的文件,如可执行文件和目标文件;目标也可以是可执行的动作,如clean,也称作伪目标。
依赖:是用来产生目标的输入文件列表,一个目标通常依赖于多个文件。
命令:是make执行的动作(命令是shell命令或是可在shell下执行的程序)。注意:每个命令行的起始字符必须为TAB字符!
如果依赖文件列表DEPENDENCIES中有一个或多个文件更新的话,COMMAND就要执行,这就是Makefile最核心内容。

例子

假设当前目录下有main.c add.c sub.c add.h sub.h等文件,欲生成main可执行文件,则Makefile可以这么写:
注意命令行起始必须是TAB字符!!!

第一版

main:main.o add.o sub.o gcc -Wall -g main.o add.o sub.o -o mainmain.o:main.c gcc -Wall -g -c main.c -o main.oadd.o:add.c add.h gcc -Wall -g -c add.c -o add.osub.o:sub.c sub.h gcc -Wall -g -c sub.c -o sub.oclean: rm -rf main main.o add.o sub.o

第一版存在的主要问题在于如果当前目录下有名称为clean的文件,则make clean时就会出现问题。

第二版

第二版就是为了改进第一版存在的问题(显式指定伪目标)

.PHONY:cleanmain:main.o add.o sub.o gcc -Wall -g main.o add.o sub.o -o mainmain.o:main.c gcc -Wall -g -c main.c -o main.oadd.o:add.c add.h gcc -Wall -g -c add.c -o add.osub.o:sub.c sub.h gcc -Wall -g -c sub.c -o sub.oclean: rm -rf main main.o add.o sub.o

如果不想在编译时显示编译命令,则在command前加入@符号

Makefile的自动化变量

  • $@:规则的目标文件名
  • $<:规则的第一个依赖文件名
  • $^:规则的所有依赖文件列表

第三版

第三版主要是为了定义一些变量,让这个Makefile更为通用,少敲一些代码。ps:在Makefile中变量引用使用$(变量)这种方式。

.PHONY:cleanOBJECTS=main.o add.o sub.omain:$(OBJECTS) gcc -Wall -g $^ -o $@main.o:main.c gcc -Wall -g -c $< -o $@add.o:add.c add.h gcc -Wall -g -c $< -o $@sub.o:sub.c sub.h gcc -Wall -g -c $< -o $@clean: rm -rf main $(OBJECTS)

如何在当前目录下生成多个可执行文件

模式规则
%.o:%.c
后缀规则
.c.o:
(当前文件夹下.o文件对应着.c文件)

第一版

.PHONY:clean allBIN=01test 02testall:$(BIN)#%.o:%.c #gcc -Wall -g -c $< -o $@.c.o: gcc -Wall -g -c $< -o $@01test:01test.o gcc -Wall -g  $^ -o $@02test:02test.o gcc -Wall -g  $^ -o $@clean: rm -rf *.o $(BIN)

生成过程:生成all->生成BIN->生成01test和02test

第二版

.PHONY:clean allCC=gccCFLAGS=-Wall -gBIN=01test 02testall:$(BIN)#%.o:%.c(当前文件夹下.o文件对应着.c文件) #$(CC) $(CFLAGS) -c $< -o $@.c.o: $(CC) $(CFLAGS) -c $< -o $@01test:01test.o $(CC) $(CFLAGS)  $^ -o $@02test:02test.o $(CC) $(CFLAGS)  $^ -o $@clean: rm -rf *.o $(BIN)

第三版

增加一个可执行文件03test,其依赖项03test.o abc.o

.PHONY:clean allCC=gccCFLAGS=-Wall -gBIN=01test 02test 03testall:$(BIN)#%.o:%.c(当前文件夹下.o文件对应着.c文件) #$(CC) $(CFLAGS) -c $< -o $@.c.o: $(CC) $(CFLAGS) -c $< -o $@01test:01test.o $(CC) $(CFLAGS)  $^ -o $@02test:02test.o $(CC) $(CFLAGS)  $^ -o $@03test:03test.o abc.o $(CC) $(CFLAGS)  $^ -o $@clean: rm -rf *.o $(BIN)

再增加一个可执行文件04test

.PHONY:clean allCC=gccCFLAGS=-Wall -gBIN=01test 02test 03test 04testall:$(BIN)#%.o:%.c(当前文件夹下.o文件对应着.c文件) #$(CC) $(CFLAGS) -c $< -o $@.c.o: $(CC) $(CFLAGS) -c $< -o $@01test:01test.o $(CC) $(CFLAGS)  $^ -o $@02test:02test.o $(CC) $(CFLAGS)  $^ -o $@03test:03test.o pub.o $(CC) $(CFLAGS)  $^ -o $@clean: rm -rf *.o $(BIN)>

make常用内嵌函数

函数调用

$(function arguments)

$(Wildcard PATTERN)

当前目录下匹配模式的文件
src=$(wildcard *.c)

$(patsubst PATTREN,REPLACEMENT,TEXT)

模式替换函数
(patsubstsrc)/将src里的.c后缀文件替换为.o/
等价于$(src:.c=.o)

shell函数

执行shell命令
$(shell ls -d */)

多级目录的Makefile

所有目录只有一个可执行文件

**以下的Makefile适合当前目录存放main.c,子目录add/和sub/分别存放了main.c里用到的add和sub函数声明及定义add.c add.h sub.c sub.h
这种情况**

CC=gccCFLAGS=-Wall -gCINCLUDES=-I./add -I./subBIN=mainSUBDIR=$(shell ls -d */)ROOTSRC=$(wildcard *.c)ROOTOBJ=$(ROOTSRC:%.c=%.o)SUBSRC=$(shell find $(SUBDIR) -name '*.c')SUBOBJ=$(SUBSRC:%.c=%.o)$(BIN):$(ROOTOBJ) $(SUBOBJ) $(CC) $(CFLAGS) -o $(BIN) $(ROOTOBJ) $(SUBOBJ).c.o: $(CC) $(CFLAGS) $(CINCLUDES) -c $< -o $@clean: rm -rf $(BIN) $(ROOTOBJ) $(SUBOBJ)

每个目录都可生成可执行文件

前提是想生成可执行文件的目录下有对应的Makefile

当前目录

SUBDIRS=test1 test2.PHONY:default all clean $(SUBDIRS)default:allall clean: $(MAKE) $(SUBDIRS) TARGET=$@     $(SUBDIRS): $(MAKE) -C $@ $(TARGET)

$(MAKE) ==make

子目录

test1子目录下Makefile

CC=gccBIN=test1OBJS=test1.o.PHONY:all clean printall:print $(BIN)print: @echo "---make all in $(PWD)---"$(BIN):$(OBJS) $(CC) $(OBJS) -o $@.c.o: $(CC) -c $<clean: @echo "---make clean in $(PWD)---" rm -rf $(BIN) $(OBJS)

test2子目录下Makefile

CC=gccBIN=test2OBJS=test2.o.PHONY:all clean printall:print $(BIN)print: @echo "---make all in $(PWD)---"$(BIN):$(OBJS) $(CC) $(OBJS) -o $@.c.o: $(CC) -c $<clean: @echo "---make clean in $(PWD)---" rm -rf $(BIN) $(OBJS)>
0 0
原创粉丝点击