makefile就像一个Bash脚本,其中也可以执行操作系统的命令。makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。

例子源码

sin_value.c

1
2
3
4
5
6
7
8
9
10
11
#include <stdio.h>
#include <math.h>
#define pi 3.14159
float angle;

void sin_value(void)
{
float value;
value = sin ( angle / 180. * pi );
printf ("\nThe Sin is: %5.2f\n",value);
}

cos_value.c

1
2
3
4
5
6
7
8
9
10
11
#include <stdio.h>
#include <math.h>
#define pi 3.14159
float angle;

void cos_value(void)
{
float value;
value = cos ( angle / 180. * pi );
printf ("The Cos is: %5.2f\n",value);
}

haha.c

1
2
3
4
5
#include <stdio.h>
int haha(char name[15])
{
printf ("\n\nHi, Dear %s, nice to meet you.", name);
}

main.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>
#define pi 3.14159
char name[15];
float angle;

int main(void)
{
printf ("\n\nPlease input your name: ");
scanf ("%s", &name );
printf ("\nPlease enter the degree angle (ex> 90): " );
scanf ("%f", &angle );
haha( name );
sin_value( angle );
cos_value( angle );
}

分析4个源文件,main.c需要使用另外3个文件中的函数,并且函数文件又用到了math库。

手动逐一操作

下面先用gcc进行编译链接执行:

  1. 编译4个.c源文件,生成对应的.o目标文件。
1
gcc -c main.c haha.c sin_value.c cos_value.c
  1. 再进行链接,注意添加库目录。
1
gcc -o main main.o haha.o sin_value.o cos_value.o -lm -L/usr/lib -L/lib
  1. 测试。
1
./main
1
2
3
4
5
Please input your name: xxpcb
Please enter the degree angle (ex> 90): 30
Hi, Dear xxpcb, nice to meet you.
The Sin is: 0.50
The Cos is: 0.87

使用makefile

创建一个makefile

vim makefile,文件并编辑如下:

1
2
3
main: main.o haha.o sin_value.o cos_value.o
gcc -o main main.o haha.o sin_value.o cos_value.o -lm

注意:第2行的开头的空格是键。

使用编解的makefile进行自动编译

编译器前先清除之前生成的文件,再使用make命令编译:

1
2
3
rm -f main *.o
make

此时已经生成生成完毕了。

尝试再次使用make编译

查看效果:

1
2
make

1
2
make: 'main' is up to date.

可以看到,由于程序没有修改过,因而没有重新编译,只是进行更新操作。

完善makefile

添加clean功能

1
2
3
4
5
main: main.o haha.o sin_value.o cos_value.o
gcc -o main main.o haha.o sin_value.o cos_value.o -lm
clean:
rm -f main main.o haha.o sin_value.o cos_value.o

此时,makefile里有两个目标:mainclean,使用make clean命令即可自动清除之前生成的文件,使用make mainmake命令即可重新编译,也可以连起来使用make clean main命令实现先清除再编译。

1
2
make clean main

1
2
3
4
5
6
7
rm -f main main.o haha.o sin_value.o cos_value.o
cc -c -o main.o main.c
cc -c -o haha.o haha.c
cc -c -o sin_value.o sin_value.c
cc -c -o cos_value.o cos_value.c
gcc -o main main.o haha.o sin_value.o cos_value.o -lm

使用变量简化makefile

1
2
3
4
5
6
7
LIBS = -lm
OBJS = main.o haha.o sin_value.o cos_value.o
main: ${OBJS}
gcc -o $@ ${OBJS} ${LIBS}
clean:
rm -f main ${OBJS}

注意:makefile中的变量与bash中的变量,语法稍有不同,makefile变量的基本语法为:

  • 变量之间用 = 隔开,且 = 两侧可以有空格
  • 变量左边不可以键空格
  • 习惯上变量以大写字母
  • 引用变量使用大括号或括号,如**${变量}$(变量)**
  • **$@**表示当前的目标

关于CFLAGS

  • 命令行时输入

例如:

1
2
CFLAGS="-Wall" make clean main

  • makefile文件中添加’
1
2
3
4
5
6
7
8
LIBS = -lm
OBJS = main.o haha.o sin_value.o cos_value.o
CFLAGS="-Wall"
main: ${OBJS}
gcc -o $@ ${OBJS} ${LIBS}
clean:
rm -f main ${OBJS}

  • 使用shell默认的环境变量

命令行中指定的CFLAGS优先级最高,然后是makefile文件中指明的CFLAGS,如果前两种都未指明CFLAGS,则使用shell默认的环境变量。

参考:《鸟哥的Linux私房菜 (基础学习篇 第三版)》