Как заставить GNU / Make прекратить разыменование символических ссылок на каталоги

В §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 .

12
задан 5 December 2011 в 19:37
поделиться