Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux 如何使GNU/make stop取消引用指向目录的符号链接_Linux_Makefile_Build Process_Symlink_Gnu Make - Fatal编程技术网

Linux 如何使GNU/make stop取消引用指向目录的符号链接

Linux 如何使GNU/make stop取消引用指向目录的符号链接,linux,makefile,build-process,symlink,gnu-make,Linux,Makefile,Build Process,Symlink,Gnu Make,GNU/Make手册§5.7规定如下: 5.7循环使用make 递归使用make意味着在makefile中使用make作为命令。 当您希望为不同的应用程序创建单独的makefile时,此技术非常有用 组成更大系统的子系统。例如,假设您有 一个子目录subdr,它有自己的makefile,您希望 要在子目录上运行make的包含目录的makefile。 您可以这样做: subsystem: cd subdir && $(MAKE) or, equivalently

GNU/Make手册§5.7规定如下:

5.7循环使用make

递归使用make意味着在makefile中使用make作为命令。 当您希望为不同的应用程序创建单独的makefile时,此技术非常有用 组成更大系统的子系统。例如,假设您有 一个子目录subdr,它有自己的makefile,您希望 要在子目录上运行make的包含目录的makefile。 您可以这样做:

 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
(或通过
LD\u PRELOAD
)之前,如果不使用
cd
更改目录,我都无法想出解决此问题的方法

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

更新:

为了弄清真相,我下载了
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
$ 
$cat cd.cpp
#包括
#包括
int main()
{
chdir(“/tmp/b/”);
printf(“当前目录:%s\n”,
获取当前目录名称();/*请原谅我的内存泄漏*/
}
$gcc-o测试。/cd.cpp
$pwd
/tmp/b
美元/测试
当前目录:/tmp/b
$cd/
美元/桶/测试
当前目录:/tmp/a
$cd/
$/tmp/b/测试
当前目录:/tmp/a
$ 
所以,看起来不是libc就是Linux在捉弄我,我以前根本不在乎。最重要的是,bash
s
cd`的工作方式有所不同

奇怪的是,没有提到任何关于它的内容,但是在Borland Builder(!sic)文档中有一个关于它的注释。因此,我想知道bash在这方面做了什么。

在他的帮助下,我能够理解这一点。因此,发生的事情很少:

  • Linux不支持将当前工作目录设置为符号链接
    chdir()
    始终将其设置为实际目录
  • 根据惯例,有一个名为
    PWD
    的变量表示当前工作目录
  • 有些函数/系统调用变量
    PWD
    ,有些则不调用
  • Bash维护一个使用符号名构建的“假”路径,并相应地设置
    PWD
    变量
  • 它解释了gmake的行为。当
    gmake
    sh
    调用时,
    PWD
    在执行
    gmake
    过程之前更新。因此,
    PWD
    被设置为“符号”路径,表示该路径的函数继续正常工作。否则,
    gmake
    调用
    chdir()
    ,这将更改工作目录并设置
    PWD
    ,而不使用sh的技巧。因此,所有函数,包括那些遵守
    PWD
    的函数,都开始返回“真实”路径


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

    实际上,这是我期望make的行为。“逻辑”目录纯粹是shell的发明,它做了额外的工作来维持这种错觉。@ephemient:我以为它在做类似的事情,但奇怪的是,当执行
    cd
    并调用调用
    getcwd()
    的进程时,
    getcwd()
    返回一个指向符号链接的路径,而不是真正的目录。我尝试使用symlink的完整路径调用
    chdir()
    ,但无法获得相同的效果。我想知道到底发生了什么。
    bash
    将工作目录缓存在
    $PWD
    中<代码>光盘在shell中更新
    $PWD
    <如果shell中的code>pwd与实际工作目录匹配,则返回
    $pwd
    。使用
    cd&&$(MAKE)
    时,将为递归调用设置变量;当您使用
    $(MAKE)-C时,它不是,并且
    pwd
    会返回到未缓存的物理路径。@ephemient:整个过程会一直工作到。。。。我要草拟一个关于这件事的小答案。一团糟。顺便说一句:Glibc的
    get\u current\u dir\u name
    检查
    getenv(“PWD”)
    <但是,code>make
    bash
    只需使用
    getcwd
    。显然,这些都是具体实现的细节。