GNU Make: обеспечить наличие обязательных компонентов и отключить неявный поиск правил - PullRequest
0 голосов
/ 13 января 2019

Вопрос:

Как отключить неявный поиск правил для предварительного условия, при этом гарантируя, что предварительное условие действительно существует?

Справочная информация:

Рассмотрим следующую начальную Makefile:

b: a
    @echo MAKING B
    cp a b

a - файл, необходимый для создания b. Если файл a существует, make b успешно выполняется. Если его не существует, мы получаем следующую ошибку:

make: *** No rule to make target `a', needed by `b'.  Stop.` 

Это именно то, что мы и ожидали, однако, проверяя вывод make --debug=a b, мы видим, что даже когда существует a, make выполняет поиск по предопределенным неявным правилам, подходящим a, чтобы выяснить, это можно сделать заново. Например, если файл a.c действительно существует, то make попытается скомпилировать a.c для создания файла a. Чтобы предотвратить это, мы определяем явное правило для a с пустым рецептом. Это дает нам обновленный Makefile:

a: ;

b: a
    @echo MAKING B
    cp a b

Проблема в том, что рецепт для make b работает, даже если a не существует, что приводит к сбою. Есть ли другой способ указать, что a должен существовать, не ища неявные правила для сборки a? Я хотел бы сделать это, не давая рецепт для a, который проверяет его существование.

1 Ответ

0 голосов
/ 14 января 2019

Я постараюсь подвести итоги нашего обсуждения. Возможно, кто-то все еще всплывает с другим / лучшим пониманием.

Помимо опции, также упомянутой в самом вопросе (см. Пояснение по последней итерации для этого подхода):

a:
        $(error missing file "$@")
b: a
        @echo MAKING B
        cp a b

Теоретически должна быть возможность полностью отключить неявное правило шаблонов или для конкретного (набора) целей, либо , определяя правило цели без рецепта (% : %.c) или , определяя a правило статического шаблона (a: % : %.c). Тем не менее, результирующее поведение в случае наличия файла a.c выглядит так же, как и с пустым правилом для a:. То есть make b просто продолжается без файла a (и мы позже не сможем получить к нему доступ).

Поскольку, по крайней мере, некоторые из неявных правил, по-видимому, реализованы в виде суффиксных правил , можно отключить учет таких входных данных, как a.c, путем очистки списка достаточных значений по умолчанию:

.SUFFIXES:

Или вообще запретите использование неявных встроенных правил, вызвав make с опцией -r (или --no-builtin-rules). Однако они довольно жесткие, поскольку они влияют на обработку всех правил в Makefile.


Работать с комментариями в:

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

% : %.c
% : %.o

В результате a.c присутствует, а a нет make: *** No rule to make target 'a', needed by 'b'. Stop.

Однако (как -r) это довольно навязчиво, так как это повлияет на все другие цели, на которые полагается неявное правило. Хотя в то же время это не так далеко, потому что он не охватывает другие случаи, такие как a.C, a.cpp, a,v, ...

Статическое правило должно быть в состоянии заменить шаблонные правила, где это применимо (более точное правило применяется к более общему правилу при сопоставлении). Но на самом деле ограничение его одной целью в действительности ставит его в один ряд с определенным правилом a:.

На самом деле я не уверен, как выглядит остальная часть дерева и какие могут быть все возможные этапы сборки. При существующем понимании я все же стремился бы к явной цели с проверкой существования файла, если файлы со встречными именами могут быть проблемой.


Пояснение для последней версии простого ошибочного правила:

Когда @ Stein продолжил тему, он на самом деле очень услужливо указал: простое (всегда) несоблюдение правила для "сборки" a вполне достаточно. Если файл с таким именем (a) существует, правило для цели a никогда не запускает свой рецепт. В случае, если файла нет, у нас может быть просто рецепт, который завершается ошибкой с сообщением об ошибке.

...