2012-02-23 37 views
16

Tôi đang viết một chương trình C nhỏ sử dụng librt. Tôi khá ngạc nhiên rằng chương trình sẽ không biên dịch nếu tôi đặt cờ liên kết vào đầu thay vì ở cuối:Tại sao cờ liên kết thư viện đôi khi phải đi vào cuối bằng GCC?

Tại thời điểm này, để biên dịch chương trình tôi làm:

gcc -o prog prog.c -lrt -std=gnu99

Nếu tôi được làm những điều sau đây, nó sẽ thất bại trong việc tìm ra các chức năng trong librt:

gcc -std=gnu99 -lrt -o prog prog.c

Tuy nhiên, điều này làm việc với các thư viện khác. Tôi đã tìm thấy sự cố khi cố gắng sử dụng Makefile đơn giản. thực hiện prog.c thực sự biên dịch mà không thích đầu tiên (sử dụng cờ c) và sau đó đã làm các liên kết.

Đây là Makefile:

CC = gcc 

CFLAGS = -std=gnu99 

LIBS= -lrt 

LDFLAGS := -lrt 


prog: prog.o 

     $(CC) -o prog prog.c -lrt -std=gnu99 

Sản lượng tôi sẽ nhận được khi gõ làm sẽ là:

gcc -std=gnu99 -c -o prog.o prog.c 
gcc -lrt prog.o -o prog 
prog.o: In function `main': 
prog.c:(.text+0xe6): undefined reference to `clock_gettime' 
prog.c:(.text+0x2fc): undefined reference to `clock_gettime' 
collect2: ld returned 1 exit status 
make: *** [buff] Error 1 

Bây giờ tôi đã soạn thảo một Makefile mà đặt các liên kết ở phần cuối của gcc dòng, tuy nhiên tôi đang bối rối tại sao nó không hoạt động nếu cờ liên kết là lúc bắt đầu.

Tôi sẽ đánh giá cao nếu có ai có thể giải thích điều này với tôi. Cảm ơn.

+1

Tôi không phải là 100% về điều này, nhưng tôi nghĩ rằng các mối liên kết có thể được xem xét librt và quyết định nó không cần bất cứ điều gì trong đó, vì vậy chỉ cần ném nó đi. Librt là một thư viện tĩnh? – spencercw

+0

Xem câu trả lời cho câu hỏi này để giải thích tại sao liên kết tĩnh phụ thuộc vào đơn đặt hàng: http: //stackoverflow.com/questions/45135/linker-order-gcc –

+2

Có thể liên quan đến tùy chọn * khi cần thiết * của liên kết đang được sử dụng theo mặc định. Bạn có thể thử 'gcc -std = gnu99 -Wl, -no-as-needed -lrt -o prog.c' –

Trả lời

19

Khi trình liên kết xử lý từng mô-đun (có thể là thư viện hoặc tệp đối tượng), nó cố gắng giải quyết từng biểu tượng không xác định trong khi có khả năng thêm vào danh sách biểu tượng không xác định. Khi nó được vào danh sách các mô-đun, nó hoặc là đã giải quyết tất cả các biểu tượng không xác định và là thành công hoặc nó báo cáo các biểu tượng không xác định.

Trong trường hợp của bạn, khi nó xử lý librt, nó không có biểu tượng không xác định. Việc xử lý proc dẫn đến clock_gettime là biểu tượng không xác định. gcc sẽ không quay trở lại và tìm trong librt cho các ký hiệu không xác định.

Vì lý do đó, bạn nên luôn có mã của mình trước, sau đó là thư viện của bạn, tiếp theo là thư viện được cung cấp nền tảng.

Hy vọng điều này sẽ hữu ích.

+1

Ghi chú nhỏ: thứ tự của các tệp đối tượng không quan trọng; một tệp đối tượng tham chiếu đến một biểu tượng trong một tệp đối tượng khác không nhất thiết phải xuất hiện trước nó trên dòng lệnh. Điều này có ý nghĩa, tất nhiên, nếu bạn xem xét tất cả các biểu tượng từ một tệp đối tượng được đưa vào hình ảnh cuối cùng, ngay cả khi chưa có tham chiếu chưa được xác định, và do đó được thêm vào danh sách các ký hiệu đã xác định, do đó tham khảo sau trong một tệp đối tượng khác sẽ không dẫn đến biểu tượng không xác định. – eriktous

+0

@eriktous Cảm ơn bạn đã sửa. – Lou

11

Từ ld (linker GNU) tài liệu (http://sourceware.org/binutils/docs/ld/Options.html#Options):

Các mối liên kết sẽ tìm kiếm một kho lưu trữ duy nhất một lần, tại địa điểm nơi nó được chỉ định trên dòng lệnh. Nếu kho lưu trữ định nghĩa một biểu tượng không xác định trong một số đối tượng xuất hiện trước khi lưu trữ trên dòng lệnh, trình liên kết sẽ bao gồm (các) tệp thích hợp từ tệp lưu trữ. Tuy nhiên, một biểu tượng không xác định trong một đối tượng xuất hiện sau này trên dòng lệnh sẽ không làm cho trình liên kết tìm kiếm kho lưu trữ một lần nữa.

Vì vậy, nếu bạn chỉ định thư viện quá sớm, trình liên kết sẽ quét nó, nhưng không tìm thấy bất kỳ điều gì bạn quan tâm. Sau đó, trình liên kết chuyển sang tệp đối tượng được trình biên dịch tạo ra và tìm các tham chiếu cần được giải quyết, nhưng nó đã quét thư viện và sẽ không bận tâm tìm kiếm ở đó nữa.

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