多文件目录Makefile写法
1、前言
linux下程序开发,涉及到多个文件,多个目录,这时候编译文件的任务量比较大,需要写Makefile
2、简单测试
测试程序在同一个文件中,共有func.h、func.c、main.c三个文件,Makefile写法如下所示:
代码语言:javascript复制1 CC = gcc
2 CFLAGS = -g -Wall
3
4 main:main.o func.o
5 $(CC) main.o func.o -o main
6 main.o:main.c
7 $(CC) $(CFLAGS) -c main.c -o main.o
8 func.o:func.c
9 $(CC) $(CFLAGS) -c func.c -o func.o
10 clean:
11 rm -rf *.o
执行过程如下图所示:
3、通用模板
实际当中程序文件比较大,这时候对文件进行分类,分为头文件、源文件、目标文件、可执行文件。也就是说通常将文件按照文件类型放在不同的目录当中,这个时候的Makefile需要统一管理这些文件,将生产的目标文件放在目标目录下,可执行文件放到可执行目录下。测试程序如下图所示:
完整的Makefile如下所示:
代码语言:javascript复制1 DIR_INC = ./include
2 DIR_SRC = ./src
3 DIR_OBJ = ./obj
4 DIR_BIN = ./bin
5
6 SRC = $(wildcard ${DIR_SRC}/*.c)
7 OBJ = $(patsubst %.c,${DIR_OBJ}/%.o,$(notdir ${SRC}))
8
9 TARGET = main
10
11 BIN_TARGET = ${DIR_BIN}/${TARGET}
12
13 CC = gcc
14 CFLAGS = -g -Wall -I${DIR_INC}
15
16 ${BIN_TARGET}:${OBJ}
17 $(CC) $(OBJ) -o $@
18
19 ${DIR_OBJ}/%.o:${DIR_SRC}/%.c
20 $(CC) $(CFLAGS) -c $< -o $@
21 .PHONY:clean
22 clean:
23 find ${DIR_OBJ} -name *.o -exec rm -rf {}
解释如下:
(1)Makefile中的 符号 @, ^, < 的意思: ^ 表示所有的依赖文件 < 表示第一个依赖文件
(2)wildcard、notdir、patsubst的意思:
wildcard : 扩展通配符 notdir : 去除路径 patsubst :替换通配符
例如下图例子所示:
输出结果如下所示:
SRC = $(wildcard *.c)
等于指定编译当前目录下所有.c文件,如果还有子目录,比如子目录为inc,则再增加一个wildcard函数,象这样:
SRC = (wildcard *.c) (wildcard inc/*.c)
(3)gcc -I -L -l的区别:
gcc -o hello hello.c -I /home/hello/include -L /home/hello/lib -lworld
上面这句表示在编译hello.c时-I /home/hello/include表示将/home/hello/include目录作为第一个寻找头文件的目录,
寻找的顺序是:/home/hello/include-->/usr/include-->/usr/local/include
-L /home/hello/lib表示将/home/hello/lib目录作为第一个寻找库文件的目录,
寻找的顺序是:/home/hello/lib-->/lib-->/usr/lib-->/usr/local/lib
-lworld表示在上面的lib的路径中寻找libworld.so动态库文件(如果gcc编译选项中加入了“-static”表示寻找libworld.a静态库文件)
参考:
http://www.groad.net/bbs/read.php?tid-2920-page-e.html
http://blog.csdn.net/liangkaiming/article/details/6267357
http://blog.csdn.net/zqt520/article/details/7727051
http://blog.csdn.net/haoel/article/details/2886/
最后一行应为 find ${DIR_OBJ} -name *.o -exec rm -rf {} ; 少了一个反斜杠和; 注:-exec command ; Execute command; true if 0 status is returned. All following arguments to find are taken to be arguments to the command until an argument consisting of ';' is encountered. The string '{}' is replaced by the current file name being processed everywhere it occurs in the arguments to the command, not just in arguments where it is alone, as in some versions of find. Both of these constructions might need to be escaped (with a '') or quoted to protect them from expansion by the shell. See the EXAMPLES sec-tion for examples of the use of the '-exec' option. The speci-fied command is run once for each matched file. The command is executed in the starting directory. There are unavoidable security problems surrounding use of the -exec option; you should use the -execdir option instead.
附:我的makefile:
######################################## #makefile ######################################## #编译指定子目录 SUBDIRS := .\lib\NC_Com .\lib\NC_FileSys .\lib\NC_BlkFile .\lib\NC_Card\NC_Card_Lib .\lib\NC_UPCash\NC_UPCash_Lib define make_subdir @ for subdir in $(SUBDIRS) ; do ( cd $$subdir && make $1) done; endef #编译主程序 BINARY := ./bin/bus OBJ_DIR := ./obj/ CC= gcc LD= ld CFLAGS= -std=c99 -Wall -g LDSCRIPT= -lmycom -lws2_32 -liconv -lmyfile -lmycard -lmyup -lmycalc -lmyblkfile LDFLAGS= -Llib SRC = $(wildcard *.c) DIR = $(notdir $(SRC)) OBJS = $(patsubst %.c,$(OBJ_DIR)%.o,$(DIR)) #OBJS= main.o myutils.o inirw.o cmdpboc.o cputest.o bustcp.o ansrec.o m1cmd.o m1api.o m1test.o upcash.o myother.o getsys.o #CFLAGS=-std=c99 #@echo Building lib... #$(call make_subdir) .PHONY: clean all: prebuild $(BINARY).exe prebuild:
@echo Building lib... $(call make_subdir) @echo Building app... $(BINARY).exe : $(OBJS) @echo Generating ... $(CC) -o $(BINARY).exe $(OBJS) $(LDFLAGS) $(LDSCRIPT) @echo OK! $(OBJ_DIR)%.o : %.c $(CC) -c $(CFLAGS) $< -o $@ clean: rm -f $(OBJ_DIR)*.o @echo Removed!