一个项目/工程不可能只有一个.c文件,那么如何将众多.c文件,甚至是汇编.S等不同源文件编译链接?
有的IDE可以帮你做到,但作为一名合格的嵌入式Linux程序员,make是必学的,也就是要学习Makefile,注意:只需要学到能基本看懂,稍微能改改改就行,实际工作中,基本上不会让你从0开始写。
更多嵌入式/单片机内容与参考资料,大叔的嵌入式小站:
make是一个命令工具,它解释Makefile 中的指令。Makefile 文件描述了整个工程的编译、连接等规则。
接下来讲解Makefile的基本结构,用例子掌握Makefile的基本内容。
基本结构
target... : prerequisites ...
command #注意前面是一个TAB
target也就是一个目标文件,可以是Object File,也可以是执行文件。还可以是一个标签(Label),对于标签这种特性,在后续的“伪目标”文章中会有叙述。
prerequisites就是,要生成那个target所需要的文件或是目标。
command也就是make需要执行的命令。(任意的Shell命令)
注意:命令前必须是一个“TAB键”,否则编译错误为:*** missing separator. Stop.
也可以这样
targets : prerequisites ; command
command
command,如果其不与“target:prerequisites”在一行,那么,必须以[Tab键]开头,如果和prerequisites在一行,那么可以用分号做为分隔
例子:
hello.o:hello.c hello.h
gcc -c hello.c -o hello.o
在定义好依赖关系后,后续的那一行定义了如何生成目标文件的操作系统命令,一定要以一个Tab键作为开头。记住,make并不管命令是怎么工作的,他只管执行所定义的命令。make会比较targets文件和prerequisites文件的修改日期,如果prerequisites文件的日期要比targets文件的日期要新,或者target不存在的话,那么,make就会执行后续定义的命令。
基本使用实例
新建f1.c、f2.c、main.c、head.h四个文件,并输入一下内容:
f1.c内容如下:
#include <stdio.h>
void print1()
{
printf("Message:f1.c\n");
}
f2.c内容如下:
#include <stdio.h>
void print2()
{
printf("Message:f2.c\n");
}
head.h内容如下:
void print1();
void print2();
main.c内容如下:
#include <stdio.h>
#include "head.h"//调用自己写的头文件用引号
int main()
{
print1();
print2();
printf("end main\n");
return 0;
}
在没有编写makefile之前可以使用命令gcc *.c -Wall查看当前代码是否有语法错误。检查没有语法错误以后可以编写makefile文件。
新建makefile文件并输入以下内容:
test:f1.o f2.o main.o
gcc f1.o f2.o main.o -o test
f2.o:f2.c
gcc -c -Wall f2.c -o f2.o# -Wall允许发出gcc所有有用的报警信息
f1.o:f1.c
gcc -c -Wall f1.c -o f1.o#-c表示只编译不链接,生成目标文件“.o”
main.o:main.c
gcc -c -Wall main.c -o main.o#-o file表示把输出文件输入到file里
clean:
rm *.o test#删除.o和执行文件
执行makefile文件:
make #默认生成第一个文件
make '目标名'#选择性的编译
例如输入make生成的是test,输入make clean执行makefile中clean:的命令
当工程中的文件名和makefile中的目标重名时,就会有伪目标。执行make命令时会发现提示目标文件已经是最新的了,将不被执行!
如果我想让makefile中某个命令永远被执行。可以在makefile目标前加上.PHONY:'目标名'