Почему make ведет себя по-разному, если ему дан абсолютный путь по сравнению с локальным путем для опции -C? - PullRequest
0 голосов
/ 16 апреля 2019

Я пишу файл make для компиляции кода в исходном дереве. В моем файле make у меня есть следующее:

MK = make
CC = g++
PWD = $(shell pwd)
CFLAGS = -std=c++11 -g -Wall
SRCDIR = $(PWD)/src
TSTDIR = $(PWD)/tests


export MK CC SRCDIR TSTDIR CFLAGS

tests:
    $(MK) -C $(TSTDIR)

затем в каталоге TSTDIR есть еще один make-файл:

OBJS = $(notdir $(shell find $(SRCDIR) | grep .o))
IFLAGS = -I$(SRCDIR)

all: ts_tst

%: %.cc $(OBJS)
    $(CC) $(CFLAGS) $(IFLAGS) $(LFLAGS) -o $@ $^

Вывод, который я получаю при запуске:

make  -C <pwd>/tests
make[1]: Entering directory `<pwd>/tests'
g++     ts_tst.cc   -o ts_tst
ts_tst.cc:8:31: fatal error: packets/ts_packet.h: No such file or directory
 #include "packets/ts_packet.h"
                               ^
compilation terminated.
make[1]: *** [ts_tst] Error 1
make[1]: Leaving directory `<pwd>/tests'
make: *** [tests] Error 2

Обратите внимание, что команда g ++ не соответствует моему шаблону в файле make. Теперь, если я удалю $(PWD)/ из переменных SRCDIR и TSTDIR, я получу это вместо ...

make  -C tests
find: ‘src’: No such file or directory
make[1]: Entering directory `<pwd>/tests'
g++ -std=c++11 -g -Wall -Isrc  -o ts_tst ts_tst.cc 
ts_tst.cc:8:31: fatal error: packets/ts_packet.h: No such file or directory
 #include "packets/ts_packet.h"
                               ^
compilation terminated.
make[1]: *** [ts_tst] Error 1
make[1]: Leaving directory `<pwd>/tests'
make: *** [tests] Error 2

Как видите, поиск в исходном dir, очевидно, не удался, потому что путь теперь локальный и поэтому его не существует, однако команда g ++ теперь соответствует моему шаблону ... Кто-нибудь знает, почему это происходит и как я могу это сделать? исправить это?

1 Ответ

0 голосов
/ 16 апреля 2019

Учтите это:

OBJS = $(notdir $(shell find $(SRCDIR) | grep .o))

%: %.cc $(OBJS)
        $(CC) $(CFLAGS) $(IFLAGS) $(LFLAGS) -o $@ $^

Когда установлен SRCDIR, он может найти некоторые объектные файлы (кстати, я не знаю, почему вы используете grep здесь вместо простого добавления -name \*.o к команде find: grep глючит, так как он также будет соответствовать файлам, таким как foo.ohno.

Предположим, он находит объектный файл /my/path/to/src/foo.o. notdir выполняется на этом, а OBJS установлен на foo.o.

Это означает, что шаблон становится:

%: %.cc foo.o
        $(CC) $(CFLAGS) $(IFLAGS) $(LFLAGS) -o $@ $^

Теперь make хочет найти шаблонное правило, которое будет соответствовать. Это правило не будет соответствовать этому правилу, поскольку, хотя шаблоны % и %.cc совпадают, другой предпосылки foo.o не существует (ее нет в локальном каталоге). В результате этот шаблон игнорируется, и make будет продолжать искать другой шаблон. Он найдет встроенный шаблон, который соответствует, и именно поэтому вы получите результат, который вы делаете.

В случае, когда объектные файлы не найдены (неправильная команда find), переменная OBJS пуста, поэтому правило шаблона соответствует.

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

Другие примечания:

  • Вы всегда должны явно использовать $(MAKE) или ${MAKE} при вызове рекурсивного make, и никогда не make или какую-либо другую переменную.
  • Как правило, вы должны использовать := при вызове shell или других более медленных функций.
  • Возможно, было бы проще понять, что происходит, если вы использовали явное правило, а не шаблонное правило для построения тестовой программы: тогда вы получите ошибку типа no rule для сборки foo.o
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...