如何使GNU / Make停止取消引用目录的符号链接

时间:2011-12-05 19:08:54

标签: linux makefile build-process symlink gnu-make

GNU / Make手册§5.7声明如下:

  

5.7递归使用make

     

递归使用make意味着在makefile中使用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)目录名称。请考虑以下示例。在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之前更改目录时才有效,这证明GNU / Make的-C选项总是使它取消引用目录路径,这是没有充分理由的。我试图在文档中找到对此行为的任何解释但不能。在运行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)文档中有一个注释,here。所以我想知道bash在这方面做了什么。

1 个答案:

答案 0 :(得分:8)

ephemient的帮助下,我能够解决这个问题。所以很少有事情发生:

  1. Linux不支持将当前工作目录设置为符号链接。 chdir ()始终将其设置为真实目录。
  2. 根据惯例,有一个名为PWD的变量代表当前的工作目录。
  3. 部分功能/系统调用荣誉PWD变量,有些则不承担。
  4. Bash维护一个使用符号名称构建的“假”路径并相应地设置PWD变量。
  5. 它解释了gmake行为。当gmake调用sh时,PWD会在gmake进程执行之前更新。因此,PWD被设置为“符号”路径,并且履行它的功能继续正常工作。否则,gmake会调用chdir (),这会更改工作目录并设置PWD而无需耍花招。因此,包括尊重PWD的所有功能都开始返回“真实”路径。

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