Руководство по GNU / Make §5.7 гласит следующее:
5.7 Рекурсивное использование make
Рекурсивное использование make-средств с использованием make в качестве команды в make-файле.Этот метод полезен, когда вам нужны отдельные make-файлы для различных подсистем, составляющих большую систему.Например, предположим, что у вас есть подкаталог subdir, который имеет свой собственный make-файл, и вы хотите, чтобы make-файл содержащего каталога запускал make в подкаталоге.Вы можете сделать это, написав это:
subsystem:
cd subdir && $(MAKE) or, equivalently, this (see Summary of Options):
subsystem:
$(MAKE) -C subdir
Таким образом, в основном это означает, что 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'
$
AsВы можете видеть, что pwd -P
и $(CURDIR)
всегда показывают разыменованную символическую ссылку.Но pwd -L
работает только при смене каталога перед запуском make
, что доказывает, что опция -C
для GNU / Make всегда отменяет ссылку на путь к каталогу без веской причины.Я пытался найти какое-либо объяснение этого поведения в документации, но не смог.Также я не могу найти обходной путь для этой проблемы, не меняя каталог с помощью cd
перед запуском make
(или без очень плохих перехватов через LD_PRELOAD
).
Вопрос - кто-нибудь ещестолкнуться с этой проблемой раньше, есть объяснение или обходной путь?Спасибо!
ОБНОВЛЕНИЕ:
Пытаясь докопаться до сути, я скачал исходный код для make
и не нашел какой-либо специальной обработки каталогов,только звонки на chdir
.Поэтому я написал небольшую программу для проведения эксперимента, и вот что я нашел.
Когда вы находитесь в каталоге с символическими ссылками (/tmp/b
) и пытаетесь сменить каталог на тот же, эта операция не имеет никакого эффектаи текущий рабочий каталог продолжает указывать на символическую ссылку.
Когда вы вызываете chdir ()
и указываете полный или относительный путь, он отменяет ссылку на него перед изменением каталога.Вот доказательство:
$ cat cd.cpp
#include <stdio.h>
#include <unistd.h>
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 ()
man page ничего об этом не упоминает, но естьобратите внимание на это в документации Borland Builder (! sic), здесь .Поэтому мне интересно, что bash
делает в этом отношении.