全部学习汇总: GreyZhang/g_makefile: Learn makefile from all kinds of tutorials on the web. Happy hacking and let's find an common way so we may don't need to touch makefile code any more! (github.com)
前阵子实现了一个CodeWarrior嵌入式开发环境的自动编译环境,用的基本上是Python。说起来,我觉得那个环境还是很实用的。虽说还有很多可以改进的地方,但是总觉得能用就好了,不想去做那么多的补丁。
虽说自己从事的是汽车电子嵌入式开发,但是很多时候各种代码正确或者错误的测试我都是借助于gcc,编译一下直接打印出执行结果。虽说方法很烂,但是通常这么简单的一个功能已经足以让我去定位绝大多数的问题。不过,有时候文件多的时候确实也需要自己写个简单的makefile,一来二去,厌烦了重复劳作的我有了写个简单小工具的想法。参考之前的CodeWarrior实现,只是这次改成了Perl,因为我接触的计算机环境中Perl更为普遍适用一些。
本次实现的功能很不完整,实用功能是最主要的指标,其他的功能能省则省。makefile的生成也只完成了文件的编译和链接功能,但是我觉得这已经足以覆盖90%以上的需求。make工具使用了gmake,从MATLAB的安装目录中找到的,gcc是安装草莓Perl时打包安装的。中间用到了一点点DOS CMD命令,测试的平台为Windows10 HB。
我的最小工程demo如下:
一个main.c文件,两个以文件夹划分的模块。设计的时候把所有的object文件生成在同一个文件夹,名为objects,最终可执行程序的名称在Perl程序中指定。
原始工程目录树如下:
makefile构建功能在make.pl中实现,具体的代码如下(使用截图是为了有更好的格式与语法显示,路过感兴趣的可以自己抄一遍或者跟我联系索取,联系方式在文章开头已经提供):
为了能够让工程更完善一些,我把gmake加入到了环境变量,而make与clean则全都用Windows的批处理简单实现了一下。具体的测试结果如下:
1. 运行Perl程序,生成makefile
生成的makefile内容如下:
CC = gcc
test_project : main.o test1.o test2.o
gcc -o D:\workspace\Perl\maketools\test_project main.o test1.o test2.o
main.o: D:\workspace\Perl\maketools\main.c C:/Strawberry/c/i686-w64-mingw32/include/stdio.h \
C:/Strawberry/c/i686-w64-mingw32/include/crtdefs.h \
C:/Strawberry/c/i686-w64-mingw32/include/_mingw.h \
C:/Strawberry/c/i686-w64-mingw32/include/_mingw_mac.h \
C:/Strawberry/c/i686-w64-mingw32/include/_mingw_secapi.h \
C:/Strawberry/c/i686-w64-mingw32/include/vadefs.h \
C:/Strawberry/c/i686-w64-mingw32/include/sdks/_mingw_directx.h \
C:/Strawberry/c/i686-w64-mingw32/include/sdks/_mingw_ddk.h \
C:/Strawberry/c/i686-w64-mingw32/include/_mingw_print_push.h \
C:/Strawberry/c/i686-w64-mingw32/include/_mingw_off_t.h \
C:/Strawberry/c/i686-w64-mingw32/include/swprintf.inl \
C:/Strawberry/c/i686-w64-mingw32/include/sec_api/stdio_s.h \
C:/Strawberry/c/i686-w64-mingw32/include/_mingw_print_pop.h \
D:\workspace\Perl\maketools\test1/test1.h \
D:\workspace\Perl\maketools\test2/test2.h
$(CC) -c -o $@ $< -I D:\workspace\Perl\maketools -I D:\workspace\Perl\maketools\objects -I D:\workspace\Perl\maketools\test1 -I D:\workspace\Perl\maketools\test2
test1.o: D:\workspace\Perl\maketools/test1\test1.c C:/Strawberry/c/i686-w64-mingw32/include/stdio.h \
C:/Strawberry/c/i686-w64-mingw32/include/crtdefs.h \
C:/Strawberry/c/i686-w64-mingw32/include/_mingw.h \
C:/Strawberry/c/i686-w64-mingw32/include/_mingw_mac.h \
C:/Strawberry/c/i686-w64-mingw32/include/_mingw_secapi.h \
C:/Strawberry/c/i686-w64-mingw32/include/vadefs.h \
C:/Strawberry/c/i686-w64-mingw32/include/sdks/_mingw_directx.h \
C:/Strawberry/c/i686-w64-mingw32/include/sdks/_mingw_ddk.h \
C:/Strawberry/c/i686-w64-mingw32/include/_mingw_print_push.h \
C:/Strawberry/c/i686-w64-mingw32/include/_mingw_off_t.h \
C:/Strawberry/c/i686-w64-mingw32/include/swprintf.inl \
C:/Strawberry/c/i686-w64-mingw32/include/sec_api/stdio_s.h \
C:/Strawberry/c/i686-w64-mingw32/include/_mingw_print_pop.h
$(CC) -c -o $@ $< -I D:\workspace\Perl\maketools -I D:\workspace\Perl\maketools\objects -I D:\workspace\Perl\maketools\test1 -I D:\workspace\Perl\maketools\test2
test2.o: D:\workspace\Perl\maketools/test2\test2.c C:/Strawberry/c/i686-w64-mingw32/include/stdio.h \
C:/Strawberry/c/i686-w64-mingw32/include/crtdefs.h \
C:/Strawberry/c/i686-w64-mingw32/include/_mingw.h \
C:/Strawberry/c/i686-w64-mingw32/include/_mingw_mac.h \
C:/Strawberry/c/i686-w64-mingw32/include/_mingw_secapi.h \
C:/Strawberry/c/i686-w64-mingw32/include/vadefs.h \
C:/Strawberry/c/i686-w64-mingw32/include/sdks/_mingw_directx.h \
C:/Strawberry/c/i686-w64-mingw32/include/sdks/_mingw_ddk.h \
C:/Strawberry/c/i686-w64-mingw32/include/_mingw_print_push.h \
C:/Strawberry/c/i686-w64-mingw32/include/_mingw_off_t.h \
C:/Strawberry/c/i686-w64-mingw32/include/swprintf.inl \
C:/Strawberry/c/i686-w64-mingw32/include/sec_api/stdio_s.h \
C:/Strawberry/c/i686-w64-mingw32/include/_mingw_print_pop.h
$(CC) -c -o $@ $< -I D:\workspace\Perl\maketools -I D:\workspace\Perl\maketools\objects -I D:\workspace\Perl\maketools\test1 -I D:\workspace\Perl\maketools\test2
虽说这种makefile比较冗长难维护,但是其实我们的工具本来就是解决这样的问题的,只要编译能够顺利执行,我们并不需要特别在意makefile的具体内容。
2. 进行编译功能的测试
这样,简单的编译功能已经实现。
3. 编译结果执行
到此,一个简单可以用于日常代码测试的工具已经实现。值得注意的是,中间固定死了主函数所在的文件名以及位置。至于目录层级,其实这个工具支持还算是良好。