Makefile: почему не работает makefile с%? - PullRequest
1 голос
/ 16 мая 2019

% в моем make-файле не работает.

Я тестировал make-файл на Ubuntu 16.04 x64.

Мой код 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

запустите make, в терминале печатается сообщение:

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

Итак, запускается только последнее правило (main: main.o). Первый шаг - это автоматически полученный код (gcc -c -o main.o main.c). почему другие правила не работают 101

А потом я изменяю третьи правила, добавляю статический режим: Версия 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 $@ $^

Тогда все правила вступят в силу, отобразить сообщение:

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

(зачем запускать "rm main.i"?)

Я снова изменяю makefile: Версия 3

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

Может работать правильно. Распечатать сообщение:

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

Итак, почему версия 1 не может работать правильно?

Ответы [ 2 ]

6 голосов
/ 16 мая 2019

Это не работает, потому что make знает, как построить объектный файл (.o) из .c источника, является встроенным неявным правилом

Вы можете отключить неявные правила, если вы запускаете свою версию 1 с make -r, она должна работать должным образом.

Файл .i удален, поскольку является промежуточным файлом, по умолчанию make удаляет все промежуточные файлы, вы можете избежать этого, используя .PRECIOUS: some-file-name

% правила в make-файлах, именуемые stem , шаблонными правилами (не подстановочные знаки что другое)

Вы можете запустить make с аргументом --debug или --debug=all для подробного журнала или более подробного журнала

edit

У вас есть еще две опции, чтобы отключить встроенные правила и заставить работать версию 1:

  • переопределить определенное встроенное правило с пустым правилом, просто добавьте %.o: %.c
  • отключить все встроенные правила, добавив пустой список суффиксов .SUFFIXES:

Если вы измените суффикссписок, единственными предопределенными действующими правилами суффиксов будут те, которые названы одним или двумя суффиксами, которые указаны в указанном вами списке

edit

Anдополнительная опция для отключения встроенных правил, которые я использовал в прошлом:

MAKEFLAGS += --no-builtin-rules
1 голос
/ 17 мая 2019

Статический режим с явным объектом должен быть необходим, чтобы избежать вступления в силу неявных правил.Поэтому я переписываю makefile в статическом режиме.Он может работать правильно и не запускать "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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...