简体   繁体   English

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

[英]How to make GNU/Make stop de-referencing symbolic links to directories

GNU/Make manual §5.7 states the following: GNU / Make手册§5.7声明如下:

5.7 Recursive Use of make 5.7递归使用make

Recursive use of make means using make as a command in a makefile. 递归使用make意味着使用make作为makefile中的命令。 This technique is useful when you want separate makefiles for various subsystems that compose a larger system. 当您需要为构成更大系统的各种子系统创建单独的makefile时,此技术非常有用。 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. 例如,假设您有一个子目录subdir,它有自己的makefile,并且您希望包含目录的makefile在子目录上运行make。 You can do it by writing this: 你可以这样写:

  subsystem: cd subdir && $(MAKE) or, equivalently, this (see Summary of Options): subsystem: $(MAKE) -C subdir 

So, basically it implies that cd subdir && $(MAKE) is the same as $(MAKE) -C subdir . 因此,基本上它暗示cd subdir && $(MAKE)$(MAKE) -C subdir

However, it turns out that it is not really an equivalent. 然而,事实证明它并不是真正的等价物。 When using -C option, the directory path, if it is a symlink, is always de-referenced, so there is no way to get "logical" (as in pwd -L ) directory name. 使用-C选项时,目录路径(如果是符号链接)始终是取消引用的,因此无法获得“逻辑”(如在pwd -L )目录名称。 Consider the following example. 请考虑以下示例。 Having the following Makefile in /tmp/b directory, which is a symlink to /tmp/a/ directory: /tmp/b目录中有以下Makefile ,它是/tmp/a/目录的符号链接:

foo:
    @echo PWDL=$(shell pwd -L)
    @echo PWDP=$(shell pwd -P)
    @echo CURDIR=$(CURDIR)

Now, let's invoke make differently: 现在,让我们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 you can see, pwd -P and $(CURDIR) are always showing de-referenced symbolic link. 如您所见, pwd -P$(CURDIR)始终显示取消引用的符号链接。 But pwd -L works only when changing directory before running make , which proves that -C option to GNU/Make always makes it de-reference the directory path, for no good reason. 但是pwd -L只有在运行make之前更改目录时才有效,这证明GNU / Make的-C选项总是使它取消引用目录路径,这是没有充分理由的。 I was trying to find any explanation for this behavior in the documentation but couldn't. 我试图在文档中找到对此行为的任何解释但不能。 Neither I can come up with a workaround for this problem without changing directory using cd before running make (or w/o very bad hooks trough LD_PRELOAD ). 在运行make (或通过LD_PRELOAD非常糟糕的挂钩)之前,我无法在不使用cd更改目录的情况下为此问题找到解决方法。

The question is - did anyone else run into this problem before, have an explanation or a workaround? 问题是 - 之前有没有其他人遇到过这个问题,有解释或解决方法吗? Thanks! 谢谢!

UPDATE: 更新:

Trying to get to the bottom of it, I have downloaded source code for make and did not find any special processing of directories, only calls to chdir . 试图找到它的底部,我已下载make源代码,并没有找到任何特殊的目录处理,只调用chdir So I wrote a little program to conduct an experiment, and here is what I found. 所以我写了一个小程序来进行实验,这就是我发现的。

When you are in a symlinked directory ( /tmp/b ) and trying to change directory to the same, the operation has no effect and current working directory continues to point to the symbolic link. 当您处于符号链接目录( /tmp/b )并尝试将目录更改为相同时,该操作无效,并且当前工作目录继续指向符号链接。

When you call chdir () and specify either full or relative path, it de-references it before changing directory. 当您调用chdir ()并指定完整路径或相对路径时,它会在更改目录之前取消引用它。 Here is a prove: 这是一个证明:

$ 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
$ 

So it seems like either libc or Linux is playing tricks on me that I didn't really care about before. 因此,看起来libc或Linux正在玩弄我以前并不真正关心的技巧。 And on top of that, bash s cd` is working somehow different. 最重要的是,bash s cd`的工作方式有所不同。

Strangely enough, Linux chdir () man page doesn't mention anything about it, but there is a note on it in Borland Builder (!sic) documentation, here . 奇怪的是, Linux的chdir ()手册页并没有提及任何关于它,但有一张纸条上它在Borland的生成器(!原文如此)的文件, 在这里 So I wonder what bash does in this regard. 所以我想知道bash在这方面做了什么。

With ephemient 's help I was able to figure this one out. epippient的帮助下,我能够把这一点弄清楚。 So there are few things that are going on: 所以很少有事情发生:

  1. Linux does not support having current working directory set to a symlink. Linux不支持将当前工作目录设置为符号链接。 chdir () always sets it to the real directory. chdir ()总是将它设置为真实目录。
  2. There is a variable called PWD that represents a current working directory, by convention. 根据惯例,有一个名为PWD的变量代表当前工作目录。
  3. Some of the function/system calls honor PWD variable and some do not. 一些函数/系统调用会使用PWD变量,而PWD一些则不会。
  4. Bash maintains a "fake" path built using symbolic names and sets PWD variable accordingly. Bash维护一个使用符号名称构建的“假”路径,并相应地设置PWD变量。

It explains gmake behavior. 它解释了gmake行为。 When gmake is invoked by sh , PWD is updated before gmake process is executed. sh调用gmake ,在执行gmake进程之前更新PWD Thus, PWD is set to "symbolic" path and functions honoring it continue to work fine. 因此, PWD被设置为“符号”路径并且功能尊重它继续正常工作。 Otherwise, gmake calls chdir () , which changes working directory and sets PWD without sh's tricks. 否则, gmake调用chdir () ,它会更改工作目录并设置PWD而不需要使用sh的技巧。 Thus, all functions including those honoring PWD start to return "real" path. 因此,包括那些尊重PWD所有功能开始返回“真实”路径。

All in all, I'd say that depending on symbolic path name is a bad idea and things can easily fall apart. 总而言之,我会说取决于符号路径名称是一个坏主意,事情很容易崩溃。 For example, because getcwd () system call doesn't care about PWD . 例如,因为getcwd ()系统调用不关心PWD Invoking cd before running make works as a short term solution though. 在运行make之前调用cd可以作为短期解决方案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM