GNU/Make 手册 §5.7 规定如下:
5.7 Recursive Use of make
Recursive use of make means using make as a command in a makefile. This technique is useful when you want separate makefiles for various subsystems that compose a larger system. For example, suppose you have a subdirectory subdir which has its own makefile, and you would like the containing directory's makefile to run make on the subdirectory. You can do it by writing this:
subsystem: cd subdir && $(MAKE) or, equivalently, this (see Summary of Options): subsystem: $(MAKE) -C subdir
所以,基本上它意味着 cd subdir && $(MAKE)
与 $(MAKE) -C subdir
相同。
然而,事实证明它并不是真正的等价物。使用 -C
选项时,目录路径(如果它是符号链接(symbolic link))总是被取消引用,因此无法获得“逻辑”(如 pwd -L
) 目录名。考虑以下示例。在 /tmp/b
目录中有以下 Makefile
,这是到 /tmp/a/
目录的符号链接(symbolic link):
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)
始终显示取消引用的符号链接(symbolic link)。但 pwd -L
仅在运行 make
之前更改目录时有效,这证明 GNU/Make 的 -C
选项总是使它取消引用目录路径,没有充分的理由。我试图在文档中找到对此行为的任何解释,但找不到。如果在运行 make
之前使用 cd
更改目录(或者没有通过 LD_PRELOAD
的非常糟糕的钩子(Hook)),我也无法想出解决这个问题的方法).
问题是 - 之前有没有其他人遇到过这个问题,有解释或解决方法吗?谢谢!
更新:
为了追根究底,我下载了make
的源代码,并没有发现对目录有任何特殊处理,只是调用了chdir
。所以我写了一个小程序来进行实验,这就是我的发现。
当您在符号链接(symbolic link)目录 (/tmp/b
) 中并尝试将目录更改为相同目录时,该操作无效,当前工作目录继续指向符号链接(symbolic link)。
当您调用 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 正在对我开玩笑,我以前并不真正关心。最重要的是,bashs
cd` 的工作方式有所不同。
奇怪的是,Linux chdir ()
man page没有提及任何相关内容,但在 Borland Builder (!sic) 文档中有关于它的注释,here .所以我想知道 bash
在这方面做了什么。
最佳答案
与 ephemient的帮助我能够弄清楚这一点。所以发生的事情很少:
- Linux 不支持将当前工作目录设置为符号链接(symbolic link)。
chdir ()
始终将其设置为真实目录。 - 按照惯例,有一个名为
PWD
的变量代表当前工作目录。 - 有些函数/系统调用支持
PWD
变量,有些则不然。 - Bash 维护一个使用符号名称构建的“假”路径,并相应地设置
PWD
变量。
它解释了 gmake
行为。当sh
调用gmake
时,PWD
在执行gmake
进程之前更新。因此,PWD
被设置为“符号”路径并且支持它的函数继续正常工作。否则,gmake
会调用 chdir ()
,它会更改工作目录并设置 PWD
,而无需使用 sh 的技巧。因此,包括那些尊重 PWD
的函数在内的所有函数都开始返回“真实”路径。
总而言之,我认为依赖于符号路径名是个坏主意,事情很容易崩溃。例如,因为getcwd()
系统调用不关心PWD
。不过,在运行 make
之前调用 cd
是一种短期解决方案。
关于linux - 如何使 GNU/Make 停止取消对目录的符号链接(symbolic link)的引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8390502/