Makefile构建工程设计——工程构建与编写规则

本文介绍了Makefile在软件工程构建中的重要性,详细讲解了如何使用Makefile来管理源码,包括Makefile的目标、标签、变量、自动化变量、编译库文件等内容。通过实例展示了如何编译和清理目标文件,以及如何处理多个文件编译成一个目标文件的情况。还探讨了Makefile的标签依赖、执行语句、注释、变量和自动化变量的使用,以及头文件和源码的搜寻。最后讨论了Makefile的嵌套、传参和编译库文件的方法。
摘要由CSDN通过智能技术生成

文件版本说明

版本 颁布日期 修订章节 作者
0.1 2017.02.26 撰写草稿 钟鑫
0.2 2017.02.27 添加Makefile简单工程 钟鑫
0.3 2017.03.02 添加Makefile标签描述 钟鑫
0.4 2017.03.05 添加Makefile头文件搜寻 钟鑫
0.5 2017.03.09 添加Makefile源码搜寻 钟鑫
0.6 2017.03.12 添加Makefile函数调用 钟鑫
0.7 2017.03.20 添加Makefile字符串处理函数 钟鑫
0.8 2017.04.05 添加Makefile嵌套编译 钟鑫
0.9 2017.04.10 添加Makefile编译库文件 钟鑫
1.0 2017.04.12 整理文档结构 钟鑫
1.1 2017.04.16 编译静态库文件 钟鑫
1.2 2016.04.19 编译动态库文件 钟鑫
1.3 2016.04.23 整理库文件的引用 钟鑫
1.3 2016.04.29 添加Makefile传参 钟鑫
1.4 2016.05.03 整理Makefile自动化变量 钟鑫
1.5 2016.05.07 添加Makefile传参 钟鑫
1.6 2016.05.09 添加Makefile嵌套功能 钟鑫
1.7 2016.05.10 整理Makefile标准格式 钟鑫
1.8 2016.05.14 整理文档 钟鑫

工程构建

在软件开发中,按系统不同的功能模块来分,源码成百上千,文件之间的管理和编译需要由特定的规则来创建。假如其中一个文件改变,从而需要编译整个源码,浪费了时间和精力。虽然通过软件IDE如Keil能够仅仅编译改动的文件,但在软件工程构建中,没有看得到软件的整个系统架构是如何关联的。在Linux中,通过Makefile自己定义的规则管理软件工程,从而掌握整个软件架构的设计。
工程构建的目标就是将源码编译能够运行,有嵌入式的Linux,编译后烧录到单板上运行,也有桌面级的软件,通过编译安装后即可在x86上的Linux系统运行,在一些发型版本的Linux中,通过系统自带的命令可以一键安装软件,也可以通过下载源码,通过make install命令编译安装软件。

Makefile实现目标

假如在一个文件夹中包含了整个工程,里面有一个Makefile文件。只要输入一个make命令即可完成

1、  如果这个工程没有编译过,make之后系统会自动编译整个工程;
2、  如果对工程的某几个文件进行修改,make之后系统会只编译改动的文件以及关联的文件,其他文件不会编译;
3、  如果对工程的某几个头文件进行修改,make之后系统会自动编译这几个头文件关联的.c文件;
4、  如果工程添加了几个模块,在简单修改Makefile文件后,make之后系统会自动将新加的模块进行编译;
5、  清除系统编译出来的文件,make clean之后系统会自动清理编译出来的目标文件,仅仅保留源码。

Makefile文件里面总揽了整个工程的编译规则。
make命令下支持Makefile与makefile两个文件名,但推荐使用Makefile来命令,大写显示与其他文件区别。

最简单的Makefile工程文件

1、在文件夹test_Makfile中有一个源文件:main.c

#include <stdio.h>

int main(int argc,char *argv[])
{
    printf("test Makefile\n");
}

2、建立一个Makefile文件

命令:vim Makefile

输入以下内容:

all:
    gcc main.c -o main.o
clean:
    rm *.o

文件结构目录如下:

ghost@ghost-machine:~/workspace/testMakefile$ ls
Makefile  main.c

3、运行Makefile文件编译源码并运行目标文件

命令:make以及./ main.o
ghost@ghost-machine:~/workspace/testMakefile$ make
gcc main.c -o main.o
ghost@ghost-machine:~/workspace/testMakefile$ ls
Makefile  main.c  main.o
ghost@ghost-machine:~/workspace/testMakefile$ ./main.o 
test Makefile

4、清理编译出来的目标文件,保留源码

ghost@ghost-machine:~/workspace/testMakefile$ make clean
rm *.o
ghost@ghost-machine:~/workspace/testMakefile$ ls
Makefile  main.c

以上的步骤即包含了Makefile的主要功能:编译源码;以及最常用到的Makefile命令:make、make clean

Makefile标签

all:
clean:

以上两个为Makefile的标签,在Makefile文件中会标注出特殊的颜色,Makefile关键字一定要顶格写!而且关键字要独占一行,结尾以英文的“:”结束。下一行紧跟着的为Makefile的命令。
字面解释:

all     :下方的命令为make所执行的主体,为编译代码的功能;
clean   :下方命令为清除目标文件的主体,功能是清除编译过程
          中产生的目标文件以及机器二进制麻或者是镜像文件。

以上描述称之为为功能命令,如果将下方执行的命令调换过来,如下所示命令仍能执行,说明功能是认为定的编码规范,因此关键字只是个标签,具体功能由用户去定义。

修改功能的Makefile文件

all:
rm *.o
clean:
    gcc main.c -o main.o

执行

ghost@ghost-machine:~/workspace/testMakefile$ make clean
gcc main.c -o main.o
ghost@ghost-machine:~/workspace/testMakefile$ ./test.o 
test Makefile
ghost@ghost-machine:~/workspace/testMakefile$ make
rm *.o

Makefile执行语句

在Makefile中执行的语句,必须要以[Tab]键开始。

    gcc main.c -o main.o

    rm *.o

以上即为Makefile所执行的命令,由用户设定,简单的Makefile命令与shell脚本的命令是一样的。

注释、隐藏显示与输出文字描述

Makefile的注释一般前面带“#”来注释,隐藏显示则在命令前面带“@”

将make clean执行的信息隐藏,在执行make clean的时候这条被隐藏的命令就不会显示出来。

all:
    gcc main.c -o main.o
clean:
    @rm *.o

结果

ghost@ghost-machine:~/workspace/testMakefile$ make
gcc main.c -o main.o
ghost@ghost-machine:~/workspace/testMakefile$ make clean
ghost@ghost-machine:~/workspace/testMakefile$

多个文件编译成一个目标文件

通常的代码为多个文件(若干个功能模块函数和一个main),需要将这些源码编译成一个目标文件,可以采用以下方法

all:
    gcc main.c module_func.c -o main.o

clean:
    rm *.o

Makefile标签

在执行make时,执行make 和 make clean会分别执行不同的命令,那将这两个用其他命令替代效果如下。

project1:
    gcc main.c module_func.c -o main.o
project2:
    rm *.o

执行结果如下

ghost@ghost-machine:~/workspace/testMakefile$ make
gcc main.c module_func.c -o main.o
ghost@ghost-machine:~/workspace/testMakefile$ ./main.o 
test Makefile
file=module_func.c,func=test_func1 is called.
ghost@ghost-machine:~/workspace/testMakefile$ make project2
rm *.o
ghost@ghost-machine:~/workspace/testMakefile$ make project1
gcc main.c module_func.c -o main.o
ghost@ghost-machine:~/workspace/testMakefile$

说明all和clean为人们约定俗成的标签,和本身功能无关,这样可以利用标签进行条件编译,通过执行make命令时传入不同的参数,来决定执行什么编译动作,编译那些文件。

标签的依赖

标签可以依赖标签,像条件编译一样,在目标标签中嵌入其他标签,达到条件联合编译的目的
书写格式,在标签“:”后面加上依赖标签,多标签以空格隔开
Makefile文件

all:project1 project2
    @echo "this is all project"

project1:
    gcc main.c module_func.c -o main.o

project2:project3
    gcc test.c -o test.o

project3:
    @echo "make project3"

clean:
    rm *.o

执行结果

host@ghost-machine:~/workspace/testMakefile$ make
gcc main.c module_func.c -o main.o
make project3
gcc test.c -o test.o
this is all project
ghost@ghost-machine:~/workspace/testMakefile$

Makefile的编译顺序:先执行标签所依赖的标签文件,再执行该标签自身的命令。

Makefile的标签也可以称做Makefile中的伪目标,和目标变量用法一样,那这样就好引起名称冲突的问题,如果源码需要生成一个clean的目标文件,但这个又和标签冲突,因为这两个的写法是一样的。为了区分make标签中的clean功能和伪目标变量的clean文件,Makefile用前置.PHONY来限定clean的功能,这样目标文件就不会与Makefile标签冲突。

all:project1 project2
    @echo "this is all project"

project1:
    gcc main.c module_func.c -o main.o

project2:
    gcc test.c -o test.o

.PHONY:chean
clean:
    rm *.o

特殊标签

1、.c.o:
2、.cpp.o:
3、%o:%c
4、%o:%cpp

该类特殊标签就是将该Makefile文件下的所有源码文件(.c、.cpp)编译成目标文件(.o),使用该特殊标签时需要上一层的依赖,特殊标签在自动化变量$<有详细说明。

Makefile变量

变量的基本书写

基本的变量可以自定义命名,然后通过符号$(varname)来使用这个变量

例如:

source = main.c module_func.c

all:
    gcc $(source) -o main.o
clean:
    rm *.o

其中$(source)代表了test.c这个变量

变量里面的内容除了可以直接加在变量的后面外,还可以通过符号“+=”来添加新的内容

source = main.c

source += module_func.c

all:
    gcc $(source) -o main.o
clean:
    rm *.o

执行结果

ghost@ghost-machine:~/workspace/testMakefile$ make
gcc main.c module_func.c -o main.o
ghost@ghost-machine:~/workspace/testMakefile$ ./main.o 
test Makefile
file=module_func.c,func=test_func1 is called.
ghost@ghost-machine:~/workspace/testMakefile$ make clean
rm *.o
ghost@ghost-machine:~/workspace/testMakefile$

另外一种比较少用,因为符号“+=”更加简洁,执行的结果是一样的

source = main.c

source := $(source) module_func.c

all:
    gcc $(source) -o main.o
clean:
    rm *.o

自动化变量

自动化变量尽量少用,因为有可能不兼容其他版本的MakEFile。

目标文件名集合:$@

目标文件名,将编译出来的目标文件(.o文件)按照目标的名称命名,如果是多个目标,那么该符号“$@”则为多个目标中的集合,以下的目标文件名为project1

source = main.c

source += module_func.c

all:project1
    @echo "this is all project"

project1:
    gcc $(source) -o $@

clean:
    rm *.o

执行结果

ghost@ghost-machine:~/workspace/testMakefile$ make
gcc main.c module_func.c -o project1
this is all project
ghost@ghost-machine:~/workspace/testMakefile$ 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值