初探makefile

嵌入式软件开发少不了使用makefile进行软件编译,写好一个makefile,让其完成所有程序代码的自动化编译链接,可以提高软件开发效率。make是一个命令工具,用于解释并执行makefile中的指令。大多数IDE都有这个命令工具,如Visual C++nmakeLinuxGNUmake。本文以一个简单例子说明makefile文件的书写规范和执行过程。

创建待编译的文件

mkdir mkfiles
vim add.h add.c main.h main.c

然后逐个编辑头文件和源文件,实现一个简单的加法运算。

add.h

加法函数放于add.c中,对应头文件为add.h,用于存放函数声明。

#ifndef __ADD_H_
#define __ADD_H_

// declaration functions
int add(int a,int b);

#endif // __ADD_H_

add.c

add.c中实现加法函数。

#include "add.h"

int add(int a, int b)
{
  return a+b;
}

main.h

在主函数对应的头文件main.h中添加依赖的头文件。

#ifndef __MAIN_H_
#define __MAIN_H_

#include <math.h>

#endif // __MAIN_H_

main.c

main.c中实现主函数,打印出一个加法运算结果。

#include <stdio.h>
#include "main.h"
#include "add.h"

int main(void)
{
  int a = 10;
  int b = 1;
  int c = add(a,b);
  printf("%d + %d = %d\n",a,b,c);
  return 0;
}

创建 makefile

makefile 规则

target ... : prerequisites ...
<tab>   command

...
...

target: 目标文件,可以是.o(object file)文件,也可以是最终的可执行文件
prerequisites : 生成目标文件所需的文件或是目标(*.h, *.c, *.o, ...)
command: make需要执行的编译、链接等指令(所有指令前都以TAB键开头)

makefile 基础写法

test : main.o add.o
cc -o test main.o add.o

main.o : main.c main.h add.h
cc -c main.c

add.o : add.c add.h
cc -c add.c

# make clean : use to clean all the object files

.PHONY : clean
clean :
rm test main.o add.o

其中,test, main.o, add.o均是目标文件target;所有源文件及头文件均为prerequisites

cc : 编译器,与gcc相似,-c代表编译,执行后产生对象文件,即".o"文件;-o代表链接,用于链接".o"文件并生成可执行文件;

.PHONY : 用于声明后面跟着的都是伪目标(类似于C语言中的标签(Label));

clean : 一个伪目标,只有在外部执行make clean时方才执行相应的执行,此次用于删除生成的所有目标文件。

makefile 简化版1

makefile中可以通过$符号引用变量,简化文件。变量定义以等号连接,类似于宏定义,将需要多处使用的字符串存入变量中可以方便修改和管理,如本例,可定义以下变量:

objs = main.o add.o  # 引用方法 $(objs)

简化后的makefile如下:

objs = main.o add.o
test : $(objs)
cc -o test $(objs)

main.o : main.c main.h add.h
cc -c main.c

add.o : add.c add.h
cc -c add.c

# make clean : use to clean all the object files

.PHONY : clean
clean :
rm test (objs)

当项目文件很多时,合理使用变量可以大大简化makefile的编写和修改。

makefile 简化版2

要知道,make非常强大,具有自动推导的功能,可以自动推导".o"目标文件下面的指令。如果目标文件为"main.o",那么指令必然为"cc -c main.c",依赖于make指令的推导功能,makefile可以省略该指令的编写。

此外,每个".o"目标文件的依赖文件必然包含一个文件名相同的".c"文件,该文件可以通过自动推导得出,所以在makefile中同样可以省略。

根据以上规则可以对makefile进一步简化:

objs = main.o add.o
test : $(objs)
cc -o test $(objs)

main.o : main.h add.h
add.o : add.h

# make clean : use to clean all the object files

.PHONY : clean
clean :
rm test (objs)

make

编写好makefile文件后,便可以使用make指令进行编译链接并生成可执行文件了。

$ make  # 生成可执行文件
cc -c main.c
cc -c add.c
cc -o test main.o add.o
$ ls
add.c  add.h  add.o  main.c  main.h  main.o  makefile  test
$ ./test  # 执行可执行文件
10 + 1 = 11
$ make clean  # 清除所有目标文件
rm test main.o add.o
$ ls
add.c  add.h  main.c  main.h  makefile

至此,一个简单的makefile编写过程及执行过程便结束了。