如何使GNU/ make停止去引用指向目录的符号链接



GNU/Make manual§5.7声明如下:

5.7 make 的递归使用

递归使用make意味着在make文件中使用make作为命令。当您想要为不同的组件单独创建makefile时,此技术非常有用组成一个更大系统的子系统。例如,假设您有子目录subdir,它有自己的makefile,你可以包含目录的makefile,以便在子目录上运行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)目录名。考虑下面的例子。在/tmp/b目录中有以下Makefile,这是到/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之前更改目录时起作用,这证明了GNU/Make的-C选项总是让它去引用目录路径,没有什么好理由。我试图在文档中找到这种行为的任何解释,但不能。在运行make之前,如果不使用cd更改目录(或者通过LD_PRELOAD没有非常糟糕的钩子),我也不能想出一个解决这个问题的方法。

问题是——其他人以前遇到过这个问题吗,有解释或解决方法吗?谢谢!

更新:

试图得到它的底部,我已经下载了make的源代码,并没有发现任何特殊的处理目录,只有调用chdir。所以我写了一个小程序来做一个实验,下面是我的发现。

当你在一个符号链接目录(/tmp/b)中,并试图将目录更改为相同的目录时,操作无效,当前工作目录继续指向符号链接。

当您调用chdir ()并指定完整路径或相对路径时,它会在更改目录之前取消引用它。下面是一个证明:

$ cat cd.cpp 
#include <stdio.h>
#include <unistd.h>
int main ()
{
    chdir ("/tmp/b/");
    printf ("Current dir: %sn",
        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文档中有一个注释,在这里。所以我想知道bash在这方面做了什么。

在ephemient的帮助下,我能够弄清楚这个问题。所以有一些事情正在发生:

  1. Linux不支持将当前工作目录设置为符号链接。chdir ()总是将其设置为实际目录。
  2. 有一个叫做PWD的变量,它代表当前的工作目录。
  3. 有些函数/系统调用支持PWD变量,有些不支持。
  4. Bash维护一个使用符号名构建的"假"路径,并相应地设置PWD变量。

它解释了gmake的行为。当gmakesh调用时,PWDgmake进程执行之前被更新。因此,PWD被设置为"符号"路径,并且尊重它的函数继续正常工作。否则,gmake调用chdir (),后者将更改工作目录并设置PWD,而不需要sh的技巧。因此,所有函数,包括那些遵循PWD的函数,都开始返回"真实"路径。

总而言之,我想说依赖符号路径名是一个坏主意,事情很容易崩溃。例如,因为getcwd ()系统调用不关心PWD。在运行make之前调用cd可以作为短期解决方案。

最新更新