Как сделать так, чтобы цель зависела от конкретного имени файла? - PullRequest
0 голосов
/ 04 февраля 2019

Я пытаюсь использовать Makefile для управления несколькими задачами вокруг моего проекта (например, для упаковки его для распространения).Однако я не могу найти способ зависеть от конкретного имени файла вместо некоторого авто-магии.Смотрите пример:

+   $ cat Makefile
dist: ctl
        echo "package it here"

+   $ tree
.
├── ctl
└── Makefile

0 directories, 2 files

+   $ make
echo "package it here"
package it here

Как видите, все работает отлично.Но он перестает работать в тот момент, когда я создаю файлы ctl.h и ctl.c:

+   $ touch ctl.{h,c}

+   $ make
cc     ctl.c   -o ctl
/usr/bin/ld: /usr/lib/gcc/x86_64-pc-linux-gnu/8.2.1/../../../../lib/Scrt1.o: in function `_start':
(.text+0x24): undefined reference to `main'
collect2: error: ld returned 1 exit status
make: *** [<builtin>: ctl] Error 1

+   $ tree
.
├── ctl.c
├── ctl.h
└── Makefile

0 directories, 3 files

Я предполагаю, что make пытается быть умным и считает ctl программой, скомпилированной из ctl.c.Который не такой случай.Как я могу подавить это поведение?

Ответы [ 3 ]

0 голосов
/ 04 февраля 2019

Make поставляется с набором шаблонных правил, которые он очень старается использовать.Один из них говорит, как создать исполняемый файл foo из foo.c.Это то, что происходит с вами.

Лично я очень не люблю эти правила и обычно отключаю их, используя параметр -R.

$ ls
ctl  ctl.c  Makefile

$ make -R
echo "package it here"
package it here

$ make
cc     ctl.c   -o ctl
/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/crt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
collect2: error: ld returned 1 exit status
make: *** [ctl] Error 1

Теперь не хочется требовать от ваших пользователейдолжны использовать определенный параметр.Один из способов продвижения вперед - просто отменить все неявные правила.Вы можете уничтожить список расширений файлов, которые make рассматривает в качестве кандидатов для применения шаблонного правила.Простое SUFFIXES: подойдет.

$ ls
ctl  ctl.c  Makefile

$ cat Makefile
.SUFFIXES:
dist: ctl
       echo "package it here"

$ make
echo "package it here"
package it here
0 голосов
/ 04 февраля 2019

Обычно make предполагает, что все цели создадут файл с одинаковым именем.Если в вашем примере не указана зависимость, как для ctl, make пытается угадать зависимость, например, если у вас есть файл ctl.c, он предполагает, что он может построить ctl из ctl.c с использованием стандартных правил.

Предполагая, что ваши цели dist и ctl никогда не должны быть построены как файлы, вы можете объявить их как фальшивые цели, добавив строку

.PHONY: dist ctl

см. https://www.gnu.org/software/make/manual/html_node/Phony-Targets.html

0 голосов
/ 04 февраля 2019

«Неявное правило» для создания ctl из ctl.c используется только в том случае, если явно не указано правило для создания ctl.Например, если ctl должен быть скомпилирован из исходных файлов ctlcmd.c и common.c, то напишите:

ctl: ctlcmd.o common.o
        $(CC) $(CFLAGS) -o $@ $^

(файлы .o будут созданы из файлов .c с использованиемдругое неявное правило.)

Если ctl вообще не нужно создавать заново (например, это рукописный скрипт), тогда вы можете написать для него фиктивное правило, например:

# `ctl` is a hand-written file, don't try to recreate it from anything
ctl:
        touch ctl

Вы должны также написать несколько правил, чтобы сказать Make, что он должен делать с ctl.c.

...