Рекурсивный make слишком много рекурсирует и требует фиктивного предварительного условия.

У меня есть очень простой Makefile, который не делает того, что я ожидал. Конечная цель состоит в том, что он должен вызывать себя рекурсивно, каждый раз включая соответствующий файл, что приводит к сборке, специфичной для того, что было включено (я создаю несколько проектов, которые используют одну и ту же кодовую базу, но используют разные комбинации исходных файлов). ). Я никогда не имел дело с рекурсивными вызовами, поэтому я должен упустить что-то очевидное. На данный момент у меня есть только один файл .mk в той же папке, что и мой Makefile. Это простая однострочная строка только для целей этого теста. В конечном итоге он будет содержать различные настройки для каждого проекта.

Макетфайл:

SHELL = /bin/sh

ifdef MYFILE
include $(MYFILE)
PROGRAM = $(basename $(MYFILE))
endif

all: $(wildcard *.mk)

dummy:
        @echo -- Entering dummy stub ... why do I need this?

%.mk: dummy
        @echo Calling $(MAKE) MYFILE=$@ $*
        $(MAKE) MYFILE=$@ $*

$(PROGRAM): objs
        @echo Time to link!

objs:
        @echo Building objs!

test.mk

SOMEVAR = SomeValue

У меня есть следующие две проблемы:

Проблема 1

Если я удаляю необходимое условие dummy из правила шаблона, правило шаблона никогда не вызывается (я получаю ужасную ошибку «Ничего не делать для всех»). Есть ли способ заставить рецепты по правилу %.mk работать без необходимости этого фиктивного предварительного условия?

Проблема 2

Учитывая два вышеупомянутых файла, я ожидаю, что make сделает следующее:

  1. make[1] запускается и выполняет правило all
  2. make[1] переходит к правилу шаблона %.mk
  3. make[1] вызывает себя рекурсивно (вызов будет выглядеть как make MYFILE=test.mk test)
  4. make[2] запускается, включает файл test.mk и устанавливает переменную PROGRAM
  5. make[2] переходит к правилу $(PROGRAM) (поскольку мы были явно вызваны с этой целью)
  6. make[2] переходит к правилу objs, запускает рецепты и возвращается вверх по цепочке

На самом деле make застревает на правиле шаблона %.mk и входит в бесконечный цикл. Я не понимаю, почему он настаивает на соблюдении правила шаблона, когда я явно сказал ему построить test в моем первом рекурсивном вызове (который должен соответствовать цели $(PROGRAM)). Что мне здесь не хватает?


person Jonah Bishop    schedule 04.05.2012    source источник
comment
Как вы думаете, во что будет расширена $(PROGRAM) при первом вызове make? Это имеет значение? Во-вторых, make делает два прохода через make-файл для разрешения/оценки всех переменных. Будут ли они содержать то, что вы ожидаете, когда попадете в рекурсивный вызов?   -  person HonkyTonk    schedule 04.05.2012
comment
Для меня не имеет значения, что $(PROGRAM) оценивает при первом вызове; это правило никогда не должно срабатывать, если оно явно не вызывается. Я считаю, что значения должны включать то, что я ожидаю при втором проходе, но есть ли простой способ проверить это?   -  person Jonah Bishop    schedule 04.05.2012


Ответы (1)


Проблема 0:
Это переработано. Здесь вам не нужно использовать рекурсивный Make.

Проблема 1:
Причина, по которой Make не пытается пересобрать test.mk (без фиктивного preq), заключается в том, что test.mk обновлен. Лучший подход — переключиться на правило статического шаблона и использовать PHONY:

MKS = $(wildcard *.mk)
.PHONY: $(MKS)

$(MKS): %.mk:
    @echo Calling $(MAKE) MYFILE=$@ $*
    $(MAKE) MYFILE=$@ $*

Еще лучший подход — не использовать имя реального файла в качестве цели правила, которое не перестраивает (или даже не трогает) этот файл.

Проблема 2:
В make[2] файл makefile включает test.mk. Если make-файл включает в себя другой файл, Make попытается пересобрать этот файл, прежде чем делать что-либо еще. Если для этого файла есть правило (которое есть) и если оно выполняется успешно (что и происходит), Make затем повторно вызывает себя.

Вы должны пересмотреть этот дизайн с нуля. Есть много способов получить поведение, которое вы ищете, в зависимости от специфики (сколько переменных будет определено в foo.mk? Вы действительно хотите управлять сборкой, перемещая эти файлы вручную? и так далее).

P.S. Вот один кладж, который приходит на ум. Подходит ли он для вашего случая, зависит от специфики:

make-файл:

# includes nothing

%.mk: dummy
        @echo Calling $(MAKE) MYFILE=$@ -f $@ $*
        $(MAKE) MYFILE=$@ -f $@ $*

тест.мк:

SOMEVAR = SomeValue
include makefile
person Beta    schedule 04.05.2012
comment
Спасибо за предложения. У меня был страх, что я пытался стать слишком фантазией. Я переделаю то, что пытаюсь сделать, и сделаю что-то более простое. - person Jonah Bishop; 04.05.2012
comment
Рад, что смог помочь. Если вам нужна дополнительная помощь/совет/предложения, не стесняйтесь спрашивать. - person Beta; 04.05.2012