~欢迎你!第 AmazingCounters.com 位造访者

makefile 学习笔记


之前学习导师给的代码并且在linux环境下编译的时候,第一次见到makefile文件,对于makefile文件,我只知道这是一个可以编译.c文件的工具,今天我就到网上找了一些有关makefile的资料进行了学习和知识整理。
下面参照的代码是节选了一个makefile文件的几个代码。

/*
makefile是一个能自动判断一个大型程序的哪些源代码需要重新编译的工具 并且能够根据判断结果自动调用编译器编译源代码,按照一点的顺序将编译结果整合成可执行程序 编译:gcc -c file.c 链接:gcc <file.o><file2.o>-o<output> 会解决掉.o文件中的交叉引用解决掉 <c> <汇编> <目标> <可执行> .c => .s => .o => a.out .h If median.c is edited - gcc -c median.c - gcc median.o main.o sort.o -o top ***********************************************************************/

# # 用libtool工具编译目标系统 # 以 STEST.c
==>生成STEST.so /** 使用 GNU Libtool 可以容易的在不同的系统中建立动态链接库。 它通过一个称为 Libtool 库的抽象,隐藏了不同系统之间的差异,给开发人员提供了一致的的接口。 对于大部分情况,开发人员甚至不用去查看相应的系统手册,只需要掌握 GNU Libtool 的用法就可以了。 并且,使用 Libtool 的 Makefile 也只需要编写一次就可以在多个系统上使用。 Libtool 库可以是一个静态链接库,可以是一个动态链接库,也可以同时包含两者。 **/ //Libtool库资料网站 https://www.cnblogs.com/xmphoenix/p/4065950.html /**************************************************************************** 引用其他的makefile文件 语法: include <filename> (filename 可以包含通配符和路径) */ include ${HOME}/src/etc/makefile.${PLATFORM} /**************************************************************************** Makefile中的变量*/ DATE =`date +"%Y%m%d%H%M"` BUILDDATETIME =$(DATE) RELEASE_VERSION =1.0.0 LIBDIR =${HOME}/lib -L${HOME}/sqlite/lib SHLIBDIR =${HOME}/shlib BINDIR =${HOME}/bin LIBINCL =${HOME}/libincl INCLUDE =${HOME}/incl -I${HOME}/sqlite/include CC =cc ${OS_CCFLAG} /* Makefile 中的变量 变量定义 ( = or := ) OBJS = programA.o programB.o OBJS-ADD = $(OBJS) programC.o # 或者 OBJS := programA.o programB.o OBJS-ADD := $(OBJS) programC.o *****************************************************************************/ /****************************************************************************** makfile规则中的通配符 * :: 表示任意一个或多个字符 ? :: 表示任意一个字符 [...] :: ex. [abcd] 表示a,b,c,d中任意一个字符, [^abcd]表示除a,b,c,d以外的字符, [0-9]表示 0~9中任意一个数字 ~ :: 表示用户的home目录 ******************************************************************************/ /****************************************************************************** 源文件的路径*/ VPATH=.libs /* 指定了 VPATH 之后, 如果当前目录中没有找到相应文件或依赖的文件, Makefile 回到 VPATH 指定的路径中再去查找. VPATH 使用方法: vpath <directories> :: 当前目录中找不到文件时, 就从<directories>中搜索 vpath <pattern> <directories> :: 符合<pattern>格式的文件, 就从<directories>中搜索 vpath <pattern> :: 清除符合<pattern>格式的文件搜索路径 vpath :: 清除所有已经设置好的文件路径 ******************************************************************************/ /* 从上往下第一个目标就是最终目标 ,top图,从下往上 (依赖树) 先查询目标文件是否存在,若存在则结束 若不存在,查找依赖文件是否存在; 依赖文件存在则直接使用,若不存在则继续向下找 以依赖文件为目标文件的依赖图 查找是否重新编译的规则,看修改目标文件和依赖文件的编辑时间 若依赖文件修改时间比目标文件的编辑时间晚,则重新编译 */ /** all: 此目标动作是编译整个软件包。all是整个软件的终极目标 **/ all:STEST.so /** 第一行取消掉makefile的可识别后缀表 第二行重新制定可识别后缀 **/ .SUFFIXES: .SUFFIXES: .c .lo .c.lo: libtool --mode=compile --tag=CC ${CC} -g -O $(DEBUG) $(CCFLAG) -I$(LIBINCL) -I$(INCLUDE) -c $< /** install: 此目标动作为完成程序的编译并且将最终的可执行程序、库文件等拷贝到安装的目录 如果只是验证这些程序是否可被正确安装,它的动作应该是一个测试安装动作 **/ install: install-shlib.sh STEST.la ${SHLIBDIR} /** uninstall: 删除所有的已安装文件——由install创建的所有的文件拷贝。 规则定义的命令 不能修改编译目录下面的文件,仅仅是删除安装目录下的文件。 **/ uninstall: libtool --mode=uninstall /bin/rm ${SHLIBDIR}/STEST.so ${SHLIBDIR}/STEST-*.so /**************************************************************************** 目标文件:需要源文件 target:dependencies <tab>rule like as: main.o:main.c median.h //dependencies 依赖 <tab>gcc -c main //rule 规则 tab必须要有,而且必须是tab,否则makefile不认为这是一条规则命令,同一条规则命令不换行 */ STEST.so: STEST.lo libtool --mode=link --tag=CC ${CC} ${LDFLAG} ${LDFLAG} -g -O -o $(@:.so=.la) $? -rpath ${SHLIBDIR} -release 1.0.0 -L${LIBDIR}/****************************************************************************/ /** chean: 清除当前目录下变异生成的所有文件,这些文件在make过程中产生。 注意:clean命令不能删除软件包的配置文件,同时也不能删除build时创建的那些文件。 **/ clean: @rm -f lib*.a *~ *core *.lo *.o *.la @rm -rf .libs /** 隐含规则:makefile自己定义的规则 Compiling C Program 'n.o' is made automatically from 'n.c' with a command of the from '$(CC) -c $(CPPFLAGS) $(CFLAGS)' Compiling C++ Program 'n.o' is made automatically from 'n.cc','n.cpp'or'n.C' with a command of the from '$(CXX) -c $(CPPFLAGS) $(CFLAGS)' We encourage you ti use the suffix '.cc' for C++ source file instead of '.C' 用户也可以自己定义隐含规则,用户自己定义的规则称为模式规则 格式 模式规则和普通规则相似; 模式规则的目标有且只有一个"%","%"可以匹配任意的非空字符串 '%.o:%.c' //表示把任意一个.c文件编译成.o文件 %.o:%.c $(CC) -c $(CPPFLAGS) $(CFLAGS) $< -o $@ 自动变量 $@ 表示规则中的目标名字 $< 表示规则中的源文件(依赖)的名字 $? The name of all the prerequisties that are newer than the traget, with spacee\s between them. $^ The name of all the prerequisites, with spaces between them. 任意匹配模式规则 %:%.c touch $@ "任意匹配"模式规则可以匹配任意一个target的规则 when a pattern rule's target is just '%' , it matches any file name whatever. 问题: 会寻找不存在的依赖,例如 file.c.c file.o.o 解决方案: 只有当其他的所有规则都无法使用才使用任意匹配模式规则 %::%.c touch $@ 采用双冒号的任意匹配规则叫做terminal规则 这种规则 对依赖进行限制,只有依赖确实存在,才会使用这种规则 取消隐含规则 1、如果自己定义的模式规则的目标依赖和make内部的规则相同将会替换 2、%.o:%.s {no command} 省略掉command即可取消掉隐含规则 一个源文件可能会依赖很多个头文件,这些头文件再依赖其他的头文件... 现代编译器可以提供源文件依赖的所有头文件 cc -M main.c main.o:main.c defs.h 对于每一个源文件'name.c'编译器会产生一个'name.d'的文件,这个文件中'name.o'所依赖的所以文件 这个文件的本质是一个规则 **/ //学习参考源于makefile中文操作手册 //参考视频:https://www.bilibili.com/video/av21042581

 

posted @ 2018-07-30 15:16  ~HDMaxfun  阅读(486)  评论(0编辑  收藏  举报