假设一个 C 语言项目中存在几个文件:main.c、func1.h、func2.h、func1.c、func2.c。
文件 main.c 内容如下:
#include <stdio.h>
#include <stdlib.h>
#include "func1.h"
#include "func2.h"
int main() {
func1();
func2();
exit(0);
}
文件 func1.h 内容如下:
#ifndef FUNC1_H__
#define FUNC1_H__
void func1(void);
#endif
文件 func2.h 内容如下:
#ifndef FUNC2_H__
#define FUNC2_H__
void func2(void);
#endif
文件 func1.c 内容如下:
#include <stdio.h>
#include "func1.h"
void func1(void){
printf("func1() run.\n");
}
文件 func2.c 内容如下:
#include <stdio.h>
#include "func2.h"
void func2(void){
printf("func2() run.\n");
}
根据平时的做法,可能会使用如下命令进行编译:
这样,得到的将是一个名为 a.out 的可执行文件,运行效果如下:
func1() run.
func2() run.
比较好的做法是写一个 Makefile 文件,使用 make 命令进行编译。虽然绝大多数软件包发行时,使用的是首字母大写的 Makefile 文件,但是 make 命令在执行时,优先使用的是文件名全部小写的 makefile 文件。之所以采用首字母大写的 Makefile 文件,是为了让用户能够自定义自己的 makefile 文件,当同时存在 Makefile 和 makefile 文件时,以 makefile 文件为主进行编译。
这里编写一个 Makefile 文件,内容如下:
myfunc:main.o func1.o func2.o
gcc main.o func1.o func2.o -o myfunc
main.o:main.c
gcc main.c -c -Wall -g -o main.o
func1.o:func1.c
gcc func1.c -c -Wall -g -o func1.o
func2.o:func2.c
gcc func2.c -c -Wall -g -o func2.o
clean:
rm *.o myfunc -rf
其中,第一行 myfunc 表示要生成的文件名,冒号后面跟的 main.o、func1.o、func2.o 表示要生成 myfunc,需要依赖的几个文件名。
第二行表示要执行的命令。
由于 main.o、func1.o、func2.o 不存在,需要生成 main.o、func1.o、func2.o。同理,依照前两行进行相关命令的编写。其中,-c 参数表示只编译不链接,即只生成 .o 文件,但不生成可执行文件。-g 参数是加入调试信息。-Wall 参数是生成所有警告信息。
最后两行表示在执行 make clean 命令时,删除所有的 .o 文件以及 myfunc 可执行文件。
以下是执行过程及效果:
gcc main.c -c -Wall -g -o main.o
gcc func1.c -c -Wall -g -o func1.o
gcc func2.c -c -Wall -g -o func2.o
gcc main.o func1.o func2.o -o myfunc
root@RicenOS:~# ./myfunc
func1() run.
func2() run.
root@RicenOS:~# make clean
rm *.o myfunc -rf
接下来,使用变量的方式对 Makefile 文件里的重复内容进行替换,修改后的 Makefile 文件内容如下:
OBJS=main.o func1.o func2.o
CC=gcc
CFLAGS+=-c -Wall -g
myfunc:$(OBJS)
$(CC) $(OBJS) -o myfunc
main.o:main.c
$(CC) main.c $(CFLAGS) -o main.o
func1.o:func1.c
$(CC) func1.c $(CFLAGS) -o func1.o
func2.o:func2.c
$(CC) func2.c $(CFLAGS) -o func2.o
clean:
$(RM) *.o myfunc -r
前三行定义了三个变量,后面使用$()来引用前三行定义的变量,而最后一行的变量 RM 相当于 rm -f。
以下是执行过程及效果:
gcc main.c -c -Wall -g -o main.o
gcc func1.c -c -Wall -g -o func1.o
gcc func2.c -c -Wall -g -o func2.o
gcc main.o func1.o func2.o -o myfunc
root@RicenOS:~# ./myfunc
func1() run.
func2() run.
root@RicenOS:~# make clean
rm -f *.o myfunc -r
继续简化 Makefile 文件,内容如下:
OBJS=main.o func1.o func2.o
CC=gcc
CFLAGS+=-c -Wall -g
myfunc:$(OBJS)
$(CC) $^ -o $@
%.o:%.c
$(CC) $^ $(CFLAGS) -o $@
clean:
$(RM) *.o myfunc -r
其中,$^ 表示上一级依赖关系中被依赖的所有文件,$@ 表示上一级的目标文件,% 相当于一个通配符,在同一句话中,表示同一个名字。
以下是执行过程及效果:
gcc main.c -c -Wall -g -o main.o
gcc func1.c -c -Wall -g -o func1.o
gcc func2.c -c -Wall -g -o func2.o
gcc main.o func1.o func2.o -o myfunc
root@RicenOS:~# ./myfunc
func1() run.
func2() run.
root@RicenOS:~# make clean
rm -f *.o myfunc -r
Copyright © 2005-2023 by www.ricensoftwares.com.cn All Rights Reserved.