GNU/Làm thủ §5.7 khẳng định như sau:Làm thế nào để làm cho GNU/Hãy dừng de-tham khảo liên kết tượng trưng đến thư mục
5,7 Sử dụng đệ quy của làm
sử dụng đệ quy thực hiện nghĩa sử dụng làm như một lệnh trong một makefile. Kỹ thuật này rất hữu ích khi bạn muốn các makefiles riêng biệt cho các hệ thống con khác nhau soạn một hệ thống lớn hơn. Ví dụ: giả sử bạn có thư mục con thư mục con có tệp makefile riêng và bạn muốn makefile của thư mục chứa để chạy thực hiện trên thư mục con. Bạn có thể làm điều đó bằng cách viết này:
subsystem: cd subdir && $(MAKE) or, equivalently, this (see Summary of Options): subsystem: $(MAKE) -C subdir
Vì vậy, về cơ bản nó ngụ ý rằng cd subdir && $(MAKE)
cũng giống như $(MAKE) -C subdir
.
Tuy nhiên, nó chỉ ra rằng nó không thực sự là tương đương. Khi sử dụng tùy chọn -C
, đường dẫn thư mục, nếu đó là một liên kết tượng trưng, luôn bị hủy tham chiếu, do đó không có cách nào để nhận tên thư mục "hợp lý" (như trong pwd -L
). Hãy xem xét ví dụ sau. Có những điều sau Makefile
trong /tmp/b
thư mục, mà là một liên kết tượng trưng đến /tmp/a/
thư mục:
foo:
@echo PWDL=$(shell pwd -L)
@echo PWDP=$(shell pwd -P)
@echo CURDIR=$(CURDIR)
Bây giờ, chúng ta hãy gọi make
cách khác nhau:
$ 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'
$
Như bạn thấy, pwd -P
và $(CURDIR)
luôn thấy de- liên kết tượng trưng được tham chiếu. Nhưng pwd -L
chỉ hoạt động khi thay đổi thư mục trước khi chạy make
, điều này chứng minh rằng tùy chọn -C
đối với GNU/Make luôn làm cho nó không tham chiếu đường dẫn thư mục, vì không có lý do chính đáng. Tôi đã cố gắng tìm bất kỳ lời giải thích cho hành vi này trong tài liệu nhưng không thể. Tôi không thể tìm ra giải pháp cho vấn đề này mà không thay đổi thư mục bằng cách sử dụng cd
trước khi chạy make
(hoặc w/o móc rất xấu máng LD_PRELOAD
).
Câu hỏi đặt ra là - có ai khác đã gặp sự cố này trước đây, có giải thích hoặc giải pháp khác không? Cảm ơn!
UPDATE:
Đang cố gắng để có được để dưới cùng của nó, tôi đã tải về mã nguồn cho make
và không tìm thấy bất kỳ chế biến đặc biệt của danh bạ, cuộc gọi chỉ để chdir
. Vì vậy, tôi đã viết một chương trình nhỏ để thực hiện một thử nghiệm, và đây là những gì tôi tìm thấy.
Khi bạn đang ở trong một thư mục được liên kết tượng trưng (/tmp/b
) và cố gắng thay đổi thư mục giống nhau, thao tác không có hiệu lực và thư mục làm việc hiện tại tiếp tục trỏ đến liên kết tượng trưng.
Khi bạn gọi chdir()
và chỉ định đường dẫn đầy đủ hoặc tương đối, nó sẽ không tham chiếu đến nó trước khi thay đổi thư mục. Đây là một chứng minh:
$ 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
$
Vì vậy, nó có vẻ như một trong hai libc
hoặc Linux đang chơi thủ đoạn trên với tôi rằng tôi không thực sự quan tâm về trước.Và trên hết, bash s
cd` đang hoạt động khác biệt.
Kỳ lạ đủ, Linux chdir()
man page không đề cập đến bất kỳ điều gì về nó, nhưng có một lưu ý về nó trong tài liệu Borland Builder (! Sic), here. Vì vậy, tôi tự hỏi những gì bash
hiện trong lĩnh vực này.
Đây là hành vi tôi mong đợi từ thực tế. Thư mục "hợp lý" hoàn toàn là một phát minh của vỏ, mà làm thêm công việc để duy trì ảo ảnh. – ephemient
@ephemient: Tôi nghĩ rằng nó đang làm một cái gì đó như thế, nhưng kỳ lạ, khi làm 'cd' và gọi một quá trình gọi' getcwd() ',' getcwd() 'trả về một đường dẫn đến symlink, chứ không phải là thư mục thực. Tôi đã cố gắng gọi 'chdir()' với đường dẫn đầy đủ đến symlink và không thể có được hiệu ứng tương tự. Tôi tự hỏi chính xác những gì đang xảy ra. –
'bash' lưu trữ thư mục làm việc trong' $ PWD'. 'cd' trong bản cập nhật shell' $ PWD'. 'pwd' trong shell trả về' $ PWD' nếu nó khớp với thư mục làm việc thực. Khi bạn sử dụng 'cd && $ (MAKE)', biến được đặt cho lời gọi đệ quy; khi bạn sử dụng '$ (MAKE) -C', nó không phải, và' pwd' rơi trở lại đường dẫn vật lý không bị luồn lách. – ephemient