В §5.7 руководства GNU / Make говорится следующее:
5.7 Рекурсивное использование make
Рекурсивное использование make означает использование make в качестве команды в make-файле. Этот метод полезен, когда вам нужны отдельные make-файлы для разных подсистемы, составляющие большую систему. Например, предположим, что у вас есть подкаталог subdir, у которого есть собственный make-файл, и вы хотели бы make-файл содержащего каталога для запуска make в подкаталоге. Вы можете сделать это, написав следующее:
подсистема: cd subdir && $ (MAKE) или, что то же самое (см. Обзор параметров): подсистема: $ (СДЕЛАТЬ) -C подкаталог
Таким образом, в основном это означает, что cd subdir && $ (MAKE)
совпадает с $ (MAKE) -C subdir
.
Однако оказывается, что на самом деле это не эквивалент. При использовании параметра -C
путь к каталогу, если это символическая ссылка, всегда отменяется, поэтому нет способа получить «логический» (как в pwd -L
) имя каталога. Рассмотрим следующий пример. Имея следующий Makefile
в каталоге / tmp / b
, который является символической ссылкой на каталог / tmp / a /
:
foo:
@echo PWDL=$(shell pwd -L)
@echo PWDP=$(shell pwd -P)
@echo CURDIR=$(CURDIR)
Теперь давайте вызовем ] make
иначе:
$ pwd
/tmp
$ (cd b && make foo)
PWDL=/tmp/b
PWDP=/tmp/a
CURDIR=/tmp/a
$ make -C b foo
make: Entering directory `/tmp/a'
PWDL=/tmp/a
PWDP=/tmp/a
CURDIR=/tmp/a
make: Leaving directory `/tmp/a'
$ make --directory=b foo
make: Entering directory `/tmp/a'
PWDL=/tmp/a
PWDP=/tmp/a
CURDIR=/tmp/a
make: Leaving directory `/tmp/a'
$
Как видите, pwd -P
и $ (CURDIR)
всегда показывают символьную ссылку без ссылки.Но pwd -L
работает только при смене каталога перед запуском make
, что доказывает, что опция -C
для GNU / Make всегда отменяет ссылку на путь к каталогу. , без уважительной причины. Я пытался найти какое-либо объяснение этому поведению в документации, но не смог. Я также не могу придумать обходной путь для этой проблемы без изменения каталога с помощью cd
перед запуском make
(или без очень плохих ловушек через LD_PRELOAD
).
Вопрос в том, сталкивался ли кто-нибудь еще с этой проблемой раньше, имел ли объяснение или обходной путь? Спасибо!
ОБНОВЛЕНИЕ:
Пытаясь разобраться в этом, я загрузил исходный код для make
и не обнаружил никакой специальной обработки каталогов, только вызовы chdir
. Итак, я написал небольшую программу для проведения эксперимента, и вот что я нашел.
Когда вы находитесь в каталоге с символической ссылкой ( / tmp / b
) и пытаетесь изменить каталог на тот же, операция не имеет никакого эффекта, и текущий рабочий каталог продолжает указывать на символическую ссылку.
Когда вы вызываете chdir ()
и указываете полный или относительный путь, он отменяет ссылку перед сменой каталога. Вот доказательство:
$ cat cd.cpp
#include
#include
int main ()
{
chdir ("/tmp/b/");
printf ("Current dir: %s\n",
get_current_dir_name ()); /* Forgive my memory leak. */
}
$ gcc -o test ./cd.cpp
$ pwd
/tmp/b
$ ./test
Current dir: /tmp/b
$ cd ../
$ ./b/test
Current dir: /tmp/a
$ cd /
$ /tmp/b/test
Current dir: /tmp/a
$
Таким образом, похоже, что либо libc
, либо Linux играет со мной шутки, о которых я раньше не особо заботился. Кроме того, bash s
cd` работает как-то иначе.
Как ни странно, Linux chdir ()
страница руководства ничего не упоминает об этом, но есть примечание об этом в документации Borland Builder (! Sic), здесь . Поэтому мне интересно, что делает в этом отношении bash
.