第五课 Makefile文件的制作(补充)
序言:
前面的几节课讲解Makefile的一些基本知识也做了一些小例子实践了几下,那么到现在普通的练习则是没有问题。但是如果做项目文件较多又分层次等等还是会碰上好多问题的,这节课补充一些知识。
知识点:
1.makefile的内嵌函数;
2.二级目录Makefile的编写;
3.多级目录Makefile的编写;
原理:
GNU make还提供了相关的函数来帮助我们编写此文件,使得我们在编写makefile文件时更加灵活健壮。提供的函数大致分为有:处理文件名、文本内容、变量、命令四种;在这节中不会讲太多的函数甚至连最基本的去空格、排序、过滤功能函数也不会,只需要几个就可以了。有了这些函数就能帮我们很好的处理具有二级多级目录文件的编译工作。
make函数接下来讲解几个常用的函数。
实践:
1.内嵌函数
1.1 函数的调用格式类似于变量的引用用$开始,具体如下:
$(FUNCTION ARGUMENTS) #也可以是如下: ${FUNCTION ARGUMENTS}
这里需要注意下:FUNCTION则是make内嵌的函数名称,如果是用户自己的需要用call间接调用;ARGUMENTS则是函数的参数多个使用都好分隔,所以参数中不能有都好分隔否则出错。
1.2 常见的几个
1.2.1 $(wildcard PATTERN):列出当前目录下匹配的文件、文件夹;例如列出当前目录下的所有目标.o文件:src=$(wildcard *.o)。
1.2.2 $(patsubst PATTERN,REPLACEMENT,TEXT):在TEXT文本中符合PATTERN模式的讲替换成REPLACEMENT,例如把推导出calc.o,calcmain.o其calc.c和calcmain.c:
OBJECTS=calc.o calcmain.o $(patsubst %.o,%.c,$(OBJECTS)) #(OBJECTS:.o=.c)也可以用
1.2.3 $(shell 命令):执行shell命令,例如执行列出当前目录的所有文件夹:
$(shell ls -d */)
1.2.4 $(findstring FIND,IN):在IN字符串里面查找FIND字符,如果存在则返回FIND,否则返回为空;
$(findstring a,abcd) #存在返回a
2. Makefile文件支持二级目录
2.1 先建立环境,看如下代码:
mkdir gcc04 cd gcc04 mkdir ui #界面代码库 mkdir dal #数据访问库 mkdir bll #业务逻辑库 cd ui touch ui.c ui.h cd ../dal touch dal.c dal.h cd ../bll touch bll.c bll.h
在对ui、dal、bll模块下编写一些简单的测试代码:
#ui.c文件 #include <stdio.h> #include "ui.h" void print_UI(const char* str) { printf(str); } #ui.h文件 #ifndef _UI_H #define _UI_H void print_UI(const char* str); #endif #dal.c文件 #include <stdio.h> #include "dal.h" void print_DAL(const char* str) { printf(str); } #dal.h文件 #ifndef _DAL_H #define _DAL_H void print_DAL(const char* str); #endif #bll.c文件 #include <stdio.h> #include "bll.h" void print_BLL(const char* str) { printf(str); } #bll.h文件 #ifndef _BLL_H #define _BLL_H void print_BLL(const char* str); #endif
下面看下Makefile文件:
CC=gcc CFLAGS=-Wall -g BIN=main SUBDIR=$(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) -c $< -o $@ clean: rm -f $(BIN) $(ROOTOBJ) $(SUBOBJ)
上面通过几个函数跟推导写出来的Makefile文件,至于其意思前面也有相对应的解析了,这个
SUBDIR变量也注意下它是当前目录下目录的集合后面通过find命令查找出这些对于目录下的.c文件;
上面的代码只能支持到二级目录,代码是由SUBDIR决定了它只找到了二级目录的文件!现在想想如果是二级目录下还有目录即是多级目录Makefile编写(也可以是Makefile生成多个可执行文件)那怎么办呢,有什么办法了解决呢?这里就需要用到一个命令:make bll/ TARGET=all ;其中all是可执行文件或是伪目标。下面看看二级目录的Makefile文件的编写:
SUBDIRS=test #定义二级目录 .PHONY:default all clean $(SUBDIRS) #定义多个伪目标 default:all #这个相当于每月作用后面没命令 all clean: #all 或是 clean 就执行下面命令,但是是没有依赖文件,也就是直接执行命令 $(make) $(SUBDIRS) TARGET=$@ #这句相当于:make test TARGET=all $(SUBDIRS) # $(make) -C $@ $(TARGET) #进入文件夹传递all调用Makefile,命令其实就是:make -C test/Makefile all
test目录下的Makefile文件:
CC=gcc BIN=test OBJS=test.o CFLAGS=-Wall -g .PHONE: all clean print #传递all all:print $(BIN) #目的是打印信息 print: @echo "make in $(BIN)......" $(BIN):$(OBJS) $(CC) $(OBJS) -o $@ .o:.c $(CC) -c $< clean: @echo "rm......" rm -f $(BIN) #(OBJS)
相信这个代码都能明白了,下面的就不注释比较简单跟之前的一样。这个在进入跟退出文件夹时会有输出这样在看起来高大上哦!!!