Makefile 使用

0.前言

    从学习C语言开始就慢慢开始接触makefile,查阅了很多的makefile的资料但总感觉没有真正掌握makefile,如果自己动手写一个makefile总觉得非常吃力。所以特意借助博客总结makefile的相关知识,通过例子说明makefile的具体用法。

    例说makefile分为以下几个部分,更多内容请参考【例说makefile索引博文

    1.只有单个C文件   

    2.含有多个C文件    

    3.需要包括头文件路径

    4.增加宏定义

    5.增加系统共享库

    6.增加自定义共享库

    7.一个实际的例子

    【代码仓库】——makefile-example

    代码仓库位于bitbucket,可借助TortoiseHg(GUI工具)克隆代码或者在网页中直接下载zip包。

1.复习gcc指令

    一个非常简单的C文件——test.c

    【test.c】

 
  1. #include <stdio.h>

  2. int main(void)

  3. {

  4. int a = 3;

  5. int b = 2;

  6.  
  7. printf("a=%d\n",a);

  8. printf("b=%d\n",b);

  9. return 0;

  10. }

    【最简单方法】

    gcc test.c -o test

    最终生成可执行文件test。

    【执行test】

    ./test

    【输出结果】

    a=3

    b=5

    

    【不正确的写法】

    请注意以下写法并不正确。

    gcc -c test.c -o test

    【详细步骤分解】编译——链接

    无论gcc指令的参数如何变化,从源文件变为可执行文件只需要两步,第一步源文件编译为目标文件,第二步从目标文件链接为可执行文件。在最简单的指令——gcc test.c -o test中使用了一处GCC的隐含规则,所有编译和链接这两个关键步骤展现的不明显。那么下面通过指令让“不明显”变得“明显”。

【1】由c文件编译为目标文件

    【写法1】

    gcc -c test.c -o test.o

    【写法2】——顺序可以颠倒

    gcc -o test.o -c test.c

    【写法3】——适当简写

    可以适当简写,充分利用GCC的默认规则,*.o文件由同名的*.c文件编译得到。

    gcc -c test.c

    【写法4】——有点奇怪

    还可以这样写,虽然看起来有点奇怪,但只执行结果却是一样的。makefile文件似乎更喜欢这种方式。

    gcc -c -o test.o test.c

【2】把目标文件链接为可执行文件

    【写法1】

    gcc test.o -o test

    【写法2】——顺序可以颠倒

    顺序可以颠倒,makefile文件似乎更喜欢这种方式。

    gcc -o test test.o

2.编写makefile文件

    【makefile】

    请替换其中的[tab],并以代码仓库中的makefile文件为主。

 
  1. # 可执行文件

  2. TARGET = test

  3. # 依赖目标

  4. OBJS = test.o

  5.  
  6. # 指令编译器和选项

  7. CC=gcc

  8. CFLAGS=-Wall -std=gnu99

  9.  
  10. $(TARGET):$(OBJS)

  11. # @echo TARGET:$@

  12. # @echo OBJECTS:$^

  13. [tab]$(CC) -o $@ $^

  14.  
  15. clean:

  16. [tab]rm -rf $(TARGET) $(OBJS)

    【具体说明】

    【1】TARGET=test test为最后可执行文件,linux中的可执行文件就是windows中的exe文件

    【2】OBJS = test.o test.o对应test.c,利用makefile的隐含规则,test.o由test.c编译得到。

    【3】CC=gcc 指定编译器为gcc

    【4】CFLAGS=-Wall -std=gnu99 使能所有警告,指定编译器标准为gnu99

    【5】 $(CC) -o $@ $^ 

            $@和$^为自动化变量,$@指目标文件,此处为可执行文件test,$^指去除重复的依赖文件,此处为test.o

            $(CC) -o $@ $^ 最终变化为 gcc -o test test.o。gcc -o test test.o和【详细步骤】链接部分的指令完全相同。那么makefile和gcc指令便建立了联系。

            可以通过@echo指令在makefile执行过程中打印自动化变量,通过这种方式调试makefile加速错误修正。

    【编译】

    make clean && make

    先执行make clean再执行make生成可执行文件

    【控制台输出】

gcc -Wall -std=gnu99 -c -o test.o test.c

gcc -o test test.o

    【分析】

    若去除-Wall -std=gnu99,那么以上两句简化为

gcc -c -o test.o test.c 和编译过程方法【4】相同

gcc -o test test.o       和执行过程方法【2】相同  

    那么makefile和gcc指令便建立了关系,理解起来也方便多了。          

3.再完善一些

    【makefile】

    请替换其中的[tab],并以代码仓库中的makefile文件为主

 
  1. # 可执行文件

  2. TARGET=test

  3. # C文件

  4. SRCS = test.c

  5. # 目标文件

  6. OBJS = $(SRCS:.c=.o)

  7.  
  8. # 指令编译器和选项

  9. CC=gcc

  10. CFLAGS=-Wall -std=gnu99

  11.  
  12. $(TARGET):$(OBJS)

  13. # @echo TARGET:$@

  14. # @echo OBJECTS:$^

  15. [tab]$(CC) -o $@ $^

  16.  
  17. clean:

  18. [tab]rm -rf $(TARGET) $(OBJS)

  19.  
  20. %.o:%.c

  21. [tab]$(CC) $(CFLAGS) -o $@ -c $<

    【变化说明】

    【1】OBJS = $(SRCS:.c=.o) 变量替换函数,把所有的*.c文件替换为*.o文件。该函数和

            OBJS = $(patsubst %.c,%.o,$(SRCS))具有相同效果。

    【2】$<为自动化变量,指第一个对象文件,此处为test.c

            替换变量和自动化变量之后:

            test.o:test.c

            [tab]gcc -Wall -std=gnu99 -o test.o -c test.c

4.总结

    【1】gcc指令执行顺序——先编译目标文件,后链接成可执行文件

    【2】自动化变量

            $@ 当前规则的目标文件

            $< 第一个依赖文件

            $^ 去除重复的所有依赖文件

猜你喜欢

转载自blog.csdn.net/guoke312/article/details/81092112
今日推荐