简体   繁体   English

Makefile:为什么带有%的makefile不起作用?

[英]Makefile: why makefile with % does not work?

% in my makefile didn't work. 我的Makefile中的%无效。

I've tested the makefile on ubuntu 16.04 x64. 我已经在Ubuntu 16.04 x64上测试了makefile。

My makefile code is that: Version 1 我的makefile代码是:版本1

CC=gcc
OBJ=main.o
TARGET:=main
.PHONY: clean
all : main
# ${OBJ}:%.o:%.c

%.i : %.c
        $(info Preprocess: build main.i)
        ${CC} -E -o $@ $<

%.s : %.i
        $(info Compile: build main.s)
        ${CC} -S -o $@ $<

%.o : %.s
        $(info Assemble: build main.o)
        ${CC} -c -o $@ $<

main : main.o
        $(info Link: build main.o)
        ${CC} -o $@ $^

clean:
        rm -f *.o *.out *.s *.i *.asm *.map ${OBJ} main

run make, the terminal print message: 运行make,终端显示以下消息:

gcc    -c -o main.o main.c
Link: build main.o
gcc -o main main.o

So only the last rule(main: main.o) run . 因此,只有最后一条规则(main:main.o)运行。 fist step is autoderived code (gcc -c -o main.o main.c). 第一个步骤是自动派生的代码(gcc -c -o main.o main.c)。 why other rules didn't run? 为什么其他规则没有执行?

And then I modify 3rd rules, add static mode: Version 2 然后修改第三条规则,添加静态模式:版本2

...
%.i : %.c
        $(info Preprocess: build main.i)
        ${CC} -E -o $@ $<

%.s : %.i
        $(info Compile: build main.s)
        ${CC} -S -o $@ $<

main.o : %.o : %.s
        $(info Assemble: build main.o)
        ${CC} -c -o $@ $<

%: %.o
        $(info Link: build main.o)
        ${CC} -o $@ $^

Then all rules take effect, display message : 然后所有规则生效,显示消息:

Preprocess: build main.i
gcc -E -o main.i main.c
Compile: build main.s
gcc -S -o main.s main.i
Assemble: build main.o
gcc -c -o main.o main.s
Link: build main.o
gcc -o main main.o
rm main.i

(why run "rm main.i"?) (为什么运行“ rm main.i”?)

I modify makefile again: Version 3 我再次修改makefile:版本3

%.o:%.c
        $(info build main.o)
        ${CC} -c -o $@ $<
main : main.o
        $(info Link: build main.o)
        ${CC} -o $@ $^

It can be run correctly. 它可以正确运行。 Print message: 列印讯息:

build main.o
gcc -c -o main.o main.c
Link: build main.o
gcc -o main main.o

So, why version 1 can't work correctly? 那么,为什么版本1无法正常工作?

It doesn't work because make knows how to build an object file ( .o ) from a .c source, is a built-in implicit rule 它不起作用,因为make知道如何从.c源构建目标文件( .o ),这是内置的隐式规则

You can disable implicit rules, if you run your version 1 with make -r it should run as expected. 您可以禁用隐式规则,如果使用make -r运行版本1,则应按预期运行。

The .i file is removed because is an intermediate file, by default make remove all intermediate files, you can avoid that by using .PRECIOUS: some-file-name .i文件被删除,因为它是一个中间文件,默认情况下, make删除所有中间文件,可以通过使用.PRECIOUS: some-file-name来避免这种.PRECIOUS: some-file-name

% rules in makefiles are referred as stem , pattern rules (not wildcards which are another thing) Makefile中的%规则称为stempattern规则 (不是通配符 ,这是另一回事)

You can run make with the argument --debug or --debug=all for a verbose log or a more verbose log 您可以使用--debug--debug=all参数运行make以获得详细日志或更详细的日志

edit 编辑

You have two more options to disable built-in rules and get version 1 working: 您还有两个选项可以禁用内置规则并使版本1正常运行:

  • override a specific built-in rule with an empty rule, just add %.o: %.c 用空规则覆盖特定的内置规则,只需添加%.o: %.c
  • disable all built-in rules adding an empty suffixes list .SUFFIXES: 禁用所有内置规则,添加空后缀列表。后缀.SUFFIXES:

If you modify the suffix list, the only predefined suffix rules in effect will be those named by one or two of the suffixes that are on the list you specify 如果您修改后缀列表,则唯一有效的预定义后缀规则将是由您指定的列表中的一个或两个后缀命名的规则

edit 编辑

An additional option to disable built-in rules that I used in the past: 禁用我过去使用的内置规则的其他选项:

MAKEFLAGS += --no-builtin-rules

Static mode with explicit object should be needed for avoiding implicit rules take effect. 为了避免隐式规则生效,应该使用带有显式对象的静态模式。 So i rewrite makefile with static mode. 所以我用静态模式重写了makefile。 It can work correctly and don't run "rm main.i". 它可以正常工作,并且不运行“ rm main.i”。

CC:=gcc
SRCS:=          $(wildcard *.c)
OBJ:=           $(patsubst %.c, %.o, ${SRCS})
PREFILE:=       $(patsubst %.o, %.i, ${OBJ})
ASMFILE:=       $(patsubst %.o, %.s, ${OBJ})
TARGET:=main
all: ${TARGET}
.PHONY: clean distclean

$(PREFILE):%.i:%.c
        $(info Preprocess: build main.i)
        $(CC) -E -o $@ $<

$(ASMFILE):%.s:%.i
        $(info Compile: build main.s)
        $(CC) -S -o $@ $<

$(OBJ):%.o:%.s
        $(info Assemble: build main.o)
        $(CC) -c -o $@ $<
        @objdump -DrwC -Mintel $@ > $(patsubst %.o,%.o.asm,$@)

$(TARGET):$(OBJ)
        $(info Link: build main)
        $(CC) -o $@ $^ -Wl,-Map=gcc.map
        @objdump -D $@ > $(patsubst %,%.asm,$@)

clean:
        rm -f *.o *.out *.s *.i *.asm *.map ${OBJ} ${TARGET}

distclean : clean
        rm -f *.d

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM