make 基本使用与 Makefile

在软件开发中,自动化构建过程是提高效率的关键。make 是一个在类Unix系统中广泛使用的构建自动化工具,它通过读取 Makefile 中的规则来自动化编译和链接程序。本节将介绍 make 的基本使用和 Makefile 的编写。

Makefile 基础

Makefile 是一个文本文件,它包含了一系列规则,每条规则定义了目标文件、依赖文件和生成目标文件的命令。

  • 规则格式:

    target: dependencies
            command
            ...
    
    • target:通常是需要生成的目标文件。
    • dependencies:生成目标文件所依赖的文件。
    • command:生成目标文件的命令。

基本 Makefile 示例

假设我们有一个简单的C语言项目,包含两个源文件 main.chello.c,以及一个头文件 hello.h。我们可以创建一个 Makefile 来编译这个项目。

  • Makefile 示例:

    # 定义变量
    CC = gcc
    CFLAGS = -Wall -g
    
    # 默认目标
    all: hello
    
    # 目标依赖和命令
    hello: main.o hello.o
            $(CC) $(CFLAGS) -o hello main.o hello.o
    
    # 编译规则
    main.o: main.c hello.h
            $(CC) $(CFLAGS) -c main.c
    
    hello.o: hello.c hello.h
            $(CC) $(CFLAGS) -c hello.c
    
    # 清理规则
    clean:
            rm -f hello *.o
    

make 命令的使用

make 命令不仅可以用来编译项目,还可以用来执行 Makefile 中定义的其他任务。

  • 指定目标

    make target
    

    这里的 targetMakefile 中定义的一个目标。如果不指定目标,make 会默认执行第一个目标(通常是 all)。

  • 递归 make: 在大型项目中,可能会有多个子目录,每个子目录都有自己的 Makefile。可以使用 make -C 命令来递归地调用子目录中的 make

    make -C subdir
    
  • 显示命令: 默认情况下,make 在执行命令时不会显示命令本身,只会显示输出。使用 -n--just-print 选项可以只显示命令而不执行。

    make -n
    
  • 忽略错误: 使用 -k--keep-going 选项可以让 make 在遇到错误时继续执行后续的命令。

    make -k
    

Makefile 的高级特性

Makefile 提供了许多高级特性,使得构建过程更加灵活和强大。

  • 自动变量make 提供了一些特殊的自动变量,如 $@(目标文件)、$<(第一个依赖文件)和 $^(所有依赖文件)。

    %.o: %.c
            $(CC) $(CFLAGS) -c $< -o $@
    
  • 伪目标: 伪目标不是真正的文件,而是代表一组操作。例如,clean 通常用来清理编译生成的文件。

    .PHONY: clean
    clean:
            rm -f hello *.o
    
  • 内置函数make 提供了许多内置函数,如 wildcardpatsubstsubst 等。

    SRCS := $(wildcard *.c)
    OBJS := $(patsubst %.c, %.o, $(SRCS))
    
  • 条件语句: 条件语句允许根据不同条件执行不同的命令。

    ifeq ($(OS), Windows_NT)
        RM := del
    else
        RM := rm -f
    endif
    
  • 宏定义: 宏定义允许在 Makefile 中定义复杂的表达式,并在需要时展开。

    MACRO = $(CC) $(CFLAGS) -c $< -o $@
    %.o: %.c
            $(MACRO)