软件工程通用makefile写法学习总结

工程通用makefile简单实现

最近学习了一下makefile,总结了一些经验,自己试着写了一套简单通用的软件工程makefile,总结下来以后可能会用到。

我的工程目录是这样的结构:

顶层目录是app/,app/include/存放公共的头文件,app/lib/存放公共的.a,app/obj/存放下层模块编译出的.a。

app层下面有三个模块分别是init,mod1,mod2。各模块编译出的.o放在obj下面,然后链接成.a文件放到上一级目录的obj下面。

app层通过链接lib和obj下面所有的.a来生成可执行文件。

模块目录下面的makefile:

app目录下面的makefile:

运行结果如下,达到了预期效果。

make all


make clean

需要注意的事项:

1.模块目录下面的DIR_INC需要手工指定需要包含的头文件路径。

2.模块目录下面的TARGET指定为需要输出的.a,设计上是每个模块单独生成一个.a。

3.原本想要实现的效果是,在每个模块目录下面单独执行makefile,可以生成.a,无需依赖上层,这样就需要.c中包含头文件时指定相对路径,或者DIR_INC指定清楚需要的头文件路径。

4.模块下面的makefile,用了一些定义的变量,表示如果上层没有传递该变量下来,则使用本定义来执行。这样可以减少对上层makefile的依赖。

遇到的几个问题:

1.模块层makefile编译时,提示找不到头文件:

原因是:定义头文件的变量有很多项时,需要每一项都指定-I参数,需要使用加头函数$(addprefix -I, $(INCLUDE)),这样编译时每一项都会加-I参数。宏定义同理,都要加-D。

2.在app层编译可执行程序时,链接所有.a,提示函数未定义:

原因是:链接器在链接.a时,由于链接的顺序问题,导致有些.a中的函数定义找不到。此时需要使用-Wl,–start-group  *.a   -Wl,–end-group,意思是链接时,在中间包含的所有.a中查找符 定义,直到找到为止。

可以优化的地方:

1.不知道这样可以不可以,在app层makefile中,指定INCLUDE=$(shell find ./ -name inc),这样上层就可以把所有头文件路径传给模块层使用,模块层无需再手工修改需要包含的路径了。

2.可以在app层上再指定一层project层,大型工程可能会编译出很多可执行程序,可以集中控制app层编译。

3.编译选项之类的,可以在app层指定一个compilier.mk文件,专门定义清楚。

可以使用的调试手段:

1.nm filename

[cl@localhost obj]$ nm libinit.a
main.o:
                 U App1Lib
                 U App1Mod1
                 U App1Mod2
0000000000000000 T main
                 U puts

2.readelf -a filename

解析文件的符 表。

3.ar -t

查看.a链接了哪些文件。

常用makefile命令

1.makefile中的几个符 含义: $@ 表示目标文件 $^   表示所有依赖的文件 $<  :="   "   +="  "> 2.makefile函数含义: wildcard:展开通配符。$(wildcard *.c) => 目录下的所有.c文件。 patsubst:模式字符串替换。$(patsubst %.c,%.o,a.c b.c) => 将a.c b.c替换为a.o b.o。 addprefix:加头。$(addprefix -I, a.h b.h) => 结果为-Ia.h -Ib.c notdir:去文件名。$(notdir xxx/a.c yyy/zzz/b.c) => 结果为a.c b.c

参考:

http://blog.csdn.net/haoel/article/details/2886/

http://www.cnblogs.com/Anker/p/3242207.html

声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2016年5月22日
下一篇 2016年5月22日

相关推荐