Круговая зависимость Makefile с файлами ресурсов Windows - PullRequest
0 голосов
/ 24 марта 2019

Было несколько вопросов, касающихся циклических зависимостей , отбрасываемых при запуске Makefile ( здесь и здесь ), однако я все еще немного запутался, так как почему они происходят.

Например, я пытаюсь скомпилировать программу с графическим интерфейсом Win32, которая содержит файлы ресурсов ( из этого урока ). Эти файлы ресурсов компилируются в объектные файлы с помощью команды windres, поэтому они могут быть связаны с конечным исполняемым файлом (, как описано здесь ):

CC = gcc
CFLAGS = -mwindows
DEPS = resource.h
OBJ = menu_one.o $(patsubst %.rc,%.rc.o,$(wildcard *.rc))

all: menu_one

%.rc.o: %.rc
    windres $^ -o $@

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

menu_one: $(OBJ)
    $(CC) $^ -o $@ $(CFLAGS)

Команда $(patsubst %.rc,%.rc.o,$(wildcard *.rc)) берет все файлы ресурсов, заканчивающиеся на .rc, и добавляет к ним расширение .o (например, resource.rc.o).

Когда я запускаю это, кажется, все работает, и я получаю работающий исполняемый файл, однако, Make выводит следующее:

gcc -c menu_one.c -o menu_one.o -mwindows
make: Circular menu_one.rc <- menu_one.rc.o dependency dropped.
windres menu_one.rc -o menu_one.rc.o
gcc menu_one.o menu_one.rc.o -o menu_one -mwindows

Имеет ли это циклическая зависимость , потому что у меня есть два правила .o? Другими словами, как я могу исправить эту циклическую зависимость?


Редактировать 1:

Я пытался следовать тому, что сказал @ MadScientist , однако это все равно создавало циклическую зависимость с Make. После еще одного поиска в Google, я наткнулся на следующую страницу . В самом низу находится раздел под названием « Круговые зависимости файлов ». Это заставило меня задуматься о выводе из Make:

make: Circular menu_one.rc <- menu_one.rc.o dependency dropped.

Похоже, что суффикс rc создает эту зависимость - даже если он не является частью расширения файла выходного объекта (т.е. file.rc.o). Если я изменю суффикс выходного файла на .res.o, круговая зависимость полностью исчезнет:

...
RESOBJ = $(patsubst %.rc,%.res.o,$(wildcard *.rc))
OBJ = menu_one.o $(RESOBJ)
...
%.res.o: %.rc
    windres $^ -o $@
...

Это вызывает очень похожий вопрос: Если бы я хотел использовать предыдущий суффикс .rc.o, как бы вы этого достигли? Возможно ли это?

Редактировать 2:

Предложение

@ MadScientist об использовании правила match-any прекрасно сработало с исправлением проблемы. Теперь это позволяет мне использовать окончание суффикса .rc.o. См. Обновленный ответ @ MadScientist ниже.

1 Ответ

1 голос
/ 24 марта 2019

Один из способов - не называть ваши windres выходные файлы с расширением .o. Если вы выберете другое расширение, у вас не будет этой проблемы.

Другой способ заключается в использовании статических шаблонных правил для windres целей:

RCOBJ := $(patsubst %.rc,%.rc.o,$(wildcard *.rc))
OBJ = menu_one.o $(RCOBJ)

  ...
$(RCOBJ) : %.rc.o : %.rc
        windres $^ -o $@

Поскольку правила статических шаблонов являются сокращением для создания явных правил и не являются неявными правилами, они не участвуют в поиске, поэтому make не будет иметь циклическую зависимость.

ETA

ОК. Я создал ваш пример локально. Используя make -d, мы можем видеть, что происходит: make необходимо собрать menu_one.rc.o, и он находит наше правило с обязательным условием menu_one.rc. Затем он должен посмотреть, сможет ли он перестроить manu_one.rc, и найти общее шаблонное правило для сборки исполняемых файлов:

%: %.o ; ...

Сопоставление этого шаблона с целью menu_one.rc дает предварительное условие menu_one.rc.o, и у вас есть цикл.

Что вам нужно сделать, это уведомить make, что файлы *.rc являются исходными файлами, и make не должна пытаться их создавать. Вы можете сделать это, объявив терминальное правило . В руководстве по сборке GNU make содержится подробное обсуждение тонкостей работы с правилами с произвольным соответствием (правила с целью только %, которая соответствует любой цели).

Добавьте это, чтобы сообщить, что ваши .rc файлы являются терминальными (то есть они не могут быть построены из чего-то другого):

%.rc:
...