单文件Makefile

test.c

#include <stdio.h>
int main() {
    printf("hello world\n");
    return 0;
}

编译一个C文件,并运行可执行文件的通常做法:

$ gcc test.c -o test
$ ls
test.c test
$ ./test
hello world

随着项目文件数量的增加,编译一个个单独的文件是不现实的,既费时又费力且容易出错

Makefile的基本格式:

target: dependencies
    command

以生成test为目标可执行文件的Makefile:

test: test.c
    gcc test.c -o test

在shell中执行 make 即可调用Makefile文件编译出可执行的目标文件:

$ make
gcc test.c -o test
$ ./test
hello world

多文件Makefile编写

多个源文件直接编译:

$ gcc foo.c bar.c tool.c -o main

如果源文件过多,命令会非常的长,而且最关键的问题是如果其中任意一个单文件有所改动,则需要重新输入冗长的编译命令完成编译

先将各个单独的文件编译为.o的obj文件,然后再将多个obj文件链接为最终的可执行文件

foo

以生成main为目标可执行文件的Makefile:

main: main.c foo.o bar.o tool.o
    gcc main.c foo.o bar.o tool.o -o main 
    
foo.o: foo.c
    gcc -c foo.c
    
bar.o: bar.c
    gcc -c bar.c

tool.o: tool.c
    gcc -c tool.c

clean:
    rm *.o main

在shell中执行 make 即可调用Makefile文件编译出可执行的目标文件:

$ make
gcc -c tool.c
gcc -c bar.c
gcc -c foo.c
gcc main.c foo.o bar.o tool.o -o main
$ ls
main
$ ./main

在shell中执行 make clean 即可调用Makefile文件编译出可执行的目标文件:

$ make clean
rm *.o main

进一步改进:

在多文件编译的Makefile编写中,每条command都以$gcc$开头,若后续需要更改为其他命令则需要一个个的更改,大大增加了后续维护的麻烦,因此引入变量解决此问题

CC = g++
CFLAGS = -lm -Wall -g

main: main.c foo.o bar.o tool.o
    $(CC) $(CFLAGS) main.c foo.o bar.o tool.o -o main 
    
foo.o: foo.c
    $(CC) $(CFLAGS) -c foo.c
    
bar.o: bar.c
    $(CC) $(CFLAGS) -c bar.c

tool.o: tool.c
    $(CC) $(CFLAGS) -c tool.c

clean:
    rm *.o main

多个可执行文件Makefile编写

CC = g++
CFLAGS = -lm -Wall -g

all: main_max main_min

main_max: main_max.c foo.o bar.o tool.o
    $(CC) $(CFLAGS) main_max.c foo.o bar.o tool.o -o main_max 
    
main_min: main_min.c foo.o bar.o tool.o
    $(CC) $(CFLAGS) main_min.c foo.o bar.o tool.o -o main_min 
    
foo.o: foo.c
    $(CC) $(CFLAGS) -c foo.c
    
bar.o: bar.c
    $(CC) $(CFLAGS) -c bar.c

tool.o: tool.c
    $(CC) $(CFLAGS) -c tool.c

clean:
    rm *.o main_max main_min