2011-12-05 27 views
10

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

+1

Đâ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

+0

@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. –

+0

'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

Trả lời

7

Với sự giúp đỡ của ephemient Tôi đã có thể tìm ra điều này. Vì vậy, có một vài điều đang diễn ra:

  1. Linux không hỗ trợ thư mục làm việc hiện tại được đặt thành liên kết tượng trưng. chdir() luôn đặt nó vào thư mục thực.
  2. Có một biến gọi là PWD đại diện cho một thư mục làm việc hiện tại, theo quy ước.
  3. Một số chức năng/cuộc gọi hệ thống tôn vinh PWD biến và một số thì không.
  4. Bash duy trì đường dẫn "giả" được tạo bằng cách sử dụng tên và bộ ký hiệu PWD biến cho phù hợp.

Nó giải thích hành vi gmake. Khi gmake được gọi bởi sh, PWD được cập nhật trước khi quá trình gmake được thực hiện. Do đó, PWD được đặt thành đường dẫn "biểu tượng" và các chức năng tôn vinh nó tiếp tục hoạt động tốt. Nếu không, gmake gọi chdir(), thay đổi thư mục làm việc và bộ PWD mà không có thủ thuật của sh. Vì vậy, tất cả các chức năng bao gồm cả những người tôn vinh PWD bắt đầu quay trở lại đường dẫn "thực".

Tất cả trong tất cả, tôi muốn nói rằng tùy thuộc vào tên đường dẫn tượng trưng là một ý tưởng tồi và mọi thứ có thể dễ dàng bị xé rời. Ví dụ: bởi vì getcwd(), cuộc gọi hệ thống không quan tâm đến PWD. Tuy nhiên, yêu cầu cd trước khi chạy make hoạt động như một giải pháp ngắn hạn.

Các vấn đề liên quan