Make编译学习笔记(三)Makefile基本规则

来源:互联网 发布:nginx grpc 编辑:程序博客网 时间:2024/05/02 02:14

所有的规则都以目标、依赖、和命令组成,最最简单的规则就是前面提到的这种规则

main: main.o insert.o search.o    $(CC) -o main main.o insert.o search.o

Makefile 中规定了一些特殊目标,以 .PHONY 为例

main: main.o insert.o search.o    gcc -o $@ $^.PHONY: cleanclean:    rm *.o    rm main

.PHONY 目标的作用是表示其依赖作为伪目标使用,伪目标不代表真正的文件名,可以放着和实际的文件名冲突还能提高 make 编译的效率。
如同 .PHONY 这样的目标还有许多,GNU make 支持的如下表

目标 说明 .PHONY 其依赖作为伪目标使用,伪目标为目标的规则无论目标文件是否存在都会无条件执行 .SUFFIXES 其依赖作为新的后缀规则代替默认的后缀规则,.SUFFIXES 可以在一个 Makefile 中多次使用,每一次都将新的后缀规则加入以前的后缀规则中,如果 .SUFFIXES 的依赖为空,则设置后缀规则为空。 .DEFAULT 其命令用于没有依赖文件时执行,即某个文件作为目标的依赖时,但找不到这个文件或这个文件为目标的规则(无论显示规则还是隐式规则)时无法执行这条规则的命令,便执行.DEFAULT目标所在规则的命令 .PRECIOUS 其依赖在 make 编译时执行时中断后不会被删除,如果 .PRECIOUS 的依赖文件的依赖是中间文件则也不会被删除 .INTERMEDIATE 其依赖在 make 编译中作为中间过程文件被对待,如果其依赖为空则没意义 .SECONDARY 其依赖同样在 make 编译中作为中间过程文件被对待,但不会被自动删除,如果其依赖为空则表示所有文件都作为中间过程文件,且不删除任何文件 .DELETE_ON_ERROR 如果存在这个目标,则在 make 编译中自动删除规则命令执行错误的目标文件 .IGNORE 其依赖作为目标时的规则命令执行错误时,会自动忽略这些错误 .LOW_RESOLUTION_TIME 其依赖会自动认为是低分辨率时间戳文件 .SILENT 其依赖作为目标被创建是不会打印出执行的命令,如果没有依赖则表示在 make 执行中不打印任何命令 .EXPORT_ALL_VARIABLES 表示其后的所有变量将会传递给子 make 进程 .NOTPARALLEL 表所有命令以串行方式执行,但是在递归调用的 make 进程中命令可以并行执行

一个规则可以有个多目标,如果其依赖更新了那么所有的目标都会更新
通常使用静态模式规则可以更方便简单,例如

SOURCES := $(wildcard *.c)OBJECTS := $(patsubst %.c, %.o, $(SOURCES))main: $(OBJECTS)        gcc -o $@ $^$(OBJECTS): %.o: %.c        gcc -c $< -o $@.PHONY:cleanclean:        rm *.o        rm example

这个 Makefile 作用是编译工程文件夹中的所有 .c 文件

$(OBJECTS): %.o: %.c    gcc -c $< -o $@

是一条静态模式规则,其依赖是通过 %.o: %.c 对变量 $(OBJECTS) 进行替换,若该工程目录中有 foo.c bar.c 两个源文件则等价与如下规则

foo.o bar.o: foo.c bar.c    gcc -c $< -o $@

隐含规则是在 Makefile 中约定的一些规则,如果没有显示规则那么 make 编译时会自动使用隐含规则
常用的隐含规则如下

  1. 编译 C 程序时
    以 .o 的目标其依赖会自动推到为 .c 且其生成命令为 $(CC) –c $(CPPFLAGS) $(CFLAGS)
  2. 编译 C++ 程序时
    以 .o 的目标的依赖会自动推导为 .cc 或是 .C,并且其生成命令是 $(CXX) –c $(CPPFLAGS) $(CFLAGS)
  3. 编译 Pascal 程序时
    以.o 的目标的依赖目标会自动推导为 .p,并且其生成命令是 $(PC) –c $(PFLAGS)
  4. 编译 Fortran/Ratfor 程序时
    以 .o 的目标的依赖目标会自动推导为
    .r ,并且其生成命令为 $(FC) –c $(FFLAGS)
    或 .F,并且其生成命令为 $(FC) –c $(FFLAGS) $(CPPFLAGS)
    或 .f ,并且其生成命令为 $(FC) –c $(FFLAGS) $(RFLAGS)
  5. 预处理 Fortran/Ratfor 程序时
    以 .f 的目标的依赖会自动推导为
    .r ,并且其生成命令为 $(FC) –F $(CPPFLAGS) $(FFLAGS)
    或 .F,并且其生成命令为 $(FC) –F $(FFLAGS) $(RFLAGS)
    这个规则只是转换 Ratfor 或有预处理的 Fortran 程序到一个标准的 Fortran 程序
  6. 编译 Modula-2 程序时
    以 .sym 的目标的依赖会自动推导为 .def,并且其生成命令是 $(M2C) $(M2FLAGS) $(DEFFLAGS)
    以 .o 的目标的依赖会自动推导为 .mod,并且其生成命令是 $(M2C) $(M2FLAGS) $(MODFLAGS)
  7. 汇编和汇编预处理时
    以 .o 的目标的依赖会自动推导为 .s,默认使用编译器为 as,并且其生成命令是 $(AS) $(ASFLAGS)
    以 .s 的目标的依赖会自动推导为 .S,默认使用C预编译器 cpp,并且其生成命令是 $(AS) $(ASFLAGS)
  8. 链接 Object 文件时,目标依赖于 .o,通过运行 C 的编译器来运行链接程序生成,若目标文件名为 foo,其生成命令是 $(CC) $(LDFLAGS) foo.o $(LOADLIBES) $(LDLIBS),这个规则对于只有一个源文件的工程有效,同时也对多个 Object 文件(由不同的源文件生成)的也有效
  9. Yacc C程序时(“Yacc”是一个语法分析器)
    以 .c 为目标的依赖会自动推导为 .y(Yacc生成的文件),其生成命令是 $(YACC) $(YFALGS)
  10. Lex C程序时
    以 .c 为目标的依赖会自动推导为 .l(Lex生成的文件),其生成命令是 $(LEX) $(LFALGS)
  11. Lex Ratfor程序时
    以 .r 为目标的依赖会自动推导为 .l(Lex生成的文件),其生成命令是 $(LEX) $(LFALGS)
  12. 从C程序、Yacc文件或Lex文件创建Lint库时
    以 .ln(lint生成的文件)为目标的依赖会自动推导为 .c,其生成命令是 $(LINT) $(LINTFALGS) $(CPPFLAGS) -i。对于 .y 和 .l 同样适用
0 0