2008-09-27 15 views
7

Tôi gặp sự cố với trình biên dịch của mình cho tôi biết có một tham chiếu không xác định đối với hàm tôi muốn sử dụng trong thư viện. Tôi xin chia sẻ một số thông tin về các vấn đề:tai ương liên kết - tham chiếu không xác định

  • Tôi biên dịch chéo với gcc cho C.
  • tôi kêu gọi một hàm thư viện được truy cập thông qua một tiêu đề bao gồm trong đó bao gồm một tiêu đề, trong đó có nguyên mẫu .
  • Tôi đã bao gồm thư mục tiêu đề bằng -I và tôi chắc chắn rằng nó đang được tìm thấy.
  • Lần đầu tiên tôi tạo các tệp .o rồi liên kết chúng trong một lệnh riêng biệt.

Vì vậy, suy nghĩ của tôi là nó có thể là thứ tự mà tôi bao gồm các tệp thư viện, nhưng tôi không chắc chắn cách chính xác để đặt hàng chúng là gì. Tôi đã thử với bao gồm cả thư mục tiêu đề cả trước và sau tệp .o.

Một số gợi ý sẽ tuyệt vời và có thể cũng như giải thích cách trình liên kết thực hiện điều đó.

Cảm ơn!


Response to câu trả lời

  • không có tập tin thư viện .a, chỉ .h và .c trong thư viện, vì vậy -l không phải là thích hợp
  • sự hiểu biết của tôi về một tập tin thư viện là nó chỉ là một tập hợp các tập tin tiêu đề và nguồn, nhưng có lẽ đó là một tập hợp các tệp .o được tạo từ nguồn ?!
  • không có tệp đối tượng thư viện nào được tạo, có thể phải có ?? Có vẻ như tôi không hiểu sự khác biệt giữa bao gồm và thư viện ... tôi sẽ làm việc với điều đó :-)

Cảm ơn mọi phản hồi! Tôi đã học được rất nhiều về thư viện. Tôi muốn đặt tất cả các câu trả lời là câu trả lời được chấp nhận :-)

Trả lời

5

Có vẻ như bạn không biên soạn tệp .c trong thư viện để tạo tệp .o. Trình liên kết sẽ tìm cách triển khai mẫu thử nghiệm trong tệp .o được tạo bằng cách biên soạn thư viện

Quy trình xây dựng của bạn có biên dịch tệp .c thư viện không?

Tại sao bạn gọi nó là "thư viện" nếu đó thực sự chỉ là mã nguồn?

0

Tôi đoán bạn phải thêm đường dẫn nơi trình liên kết có thể tìm thấy cây bút. Trong gcc/ld bạn có thể làm điều này với -L và libraray với -l.

-Ldir, --library-path = dir

mục Tìm kiếm dir trước thư mục tìm kiếm chuẩn (tùy chọn này phải trước tùy chọn -l để tìm kiếm thư mục đó).

-larch, --library = lưu trữ

Bao gồm các kiến ​​trúc tập tin lưu trữ trong danh sách các tập tin liên kết.


Response to câu trả lời - không có tập tin thư viện .a, chỉ .h và .c trong thư viện, vì vậy -l không phải là approriate

Sau đó, bạn có thể có để tạo ra libraray trước?

gcc -c mylib.c -o mylib.o 
ar rcs libmylib.a  mylib.o 
4

Tiêu đề cung cấp các khai báo chức năng và định nghĩa chức năng. Để cho phép trình liên kết tìm thấy việc thực thi hàm (và loại bỏ tham chiếu không xác định), bạn cần yêu cầu trình điều khiển trình biên dịch (gcc) liên kết thư viện cụ thể nơi hàm cư trú bằng cờ -l. Ví dụ, -lm sẽ liên kết thư viện toán học. Trang hướng dẫn của hàm thường chỉ định thư viện nào, nếu có, phải được chỉ định để tìm hàm.

Nếu trình liên kết không thể tìm thấy thư viện được chỉ định, bạn có thể thêm đường dẫn tìm kiếm thư viện bằng cách sử dụng công tắc -L (ví dụ: -L/usr/local/lib). Bạn cũng có thể ảnh hưởng vĩnh viễn đến đường dẫn thư viện thông qua biến môi trường LIBRARY_PATH.

Dưới đây là một số chi tiết bổ sung để giúp bạn gỡ lỗi sự cố của mình. Theo quy ước, tên của các tệp thư viện có tiền tố là lib và (trong dạng tĩnh của chúng) có đuôi .a. Do đó, phiên bản được liên kết tĩnh của thư viện toán mặc định của hệ thống (thư viện bạn liên kết với -lm) thường nằm trong /usr/lib/libm.a. Để xem những ký hiệu nào mà một thư viện nhất định định nghĩa bạn có thể chạy nm - chỉ được định nghĩa trên tệp thư viện. Trên hệ thống của tôi, chạy lệnh trên libm.a cho tôi kết quả như sau.

e_atan2.o: 
00000000 T atan2 

e_asinf.o: 
00000000 T asinf 

e_asin.o: 
00000000 T asin 

Để xem đường dẫn thư viện mà trình biên dịch của bạn sử dụng và thư viện nào tải theo mặc định, bạn có thể gọi gcc bằng tùy chọn -v. Một lần nữa trên hệ thống của tôi điều này cho đầu ra sau.

GNU assembler version 2.15 [FreeBSD] 2004-05-23 (i386-obrien-freebsd) 
using BFD version 2.15 [FreeBSD] 2004-05-23 
/usr/bin/ld -V -dynamic-linker /libexec/ld-elf.so.1 /usr/lib/crt1.o 
/usr/lib/crti.o /usr/lib/crtbegin.o -L/usr/lib /var/tmp//ccIxJczl.o -lgcc -lc 
-lgcc /usr/lib/crtend.o /usr/lib/crtn.o 
+0

Tệp tiêu đề ('.h' theo mặc định) _can_ chứa bất kỳ loại nguồn C nào, nhưng _strongly_ không được khuyến khích đặt bất kỳ thứ gì ngoài định nghĩa macro và _declarations_ trong đó. – vonbrand

1

Tôi sợ bạn đã trộn lẫn các khái niệm thư viện và tiêu đề. Giả sử bạn có thư viện libmylib.a chứa hàm myfunc() và tiêu đề tương ứng mylib.h xác định nguyên mẫu của nó. Trong tệp nguồn của bạn myapp.c bạn bao gồm tiêu đề, trực tiếp hoặc bao gồm một tiêu đề khác bao gồm tiêu đề đó. Ví dụ:

/* myapp.h 
** Here I will include and define my stuff 
*/ 
... 
#include "mylib.h" 
... 

tệp nguồn của bạn trông giống như:

/* myapp.c 
** Here is my real code 
*/ 
... 
#include "myapp.h" 
... 
/* Here I can use the function */ 
myfunc(3,"XYZ"); 

Bây giờ bạn có thể biên dịch nó để có được myapp.o:

gcc -c -I../mylib/includes myapp.c 

Lưu ý rằng -Tôi chỉ nói với gcc nơi các tiêu đề các tệp là, chúng không có gì để làm với chính thư viện đó!

Bây giờ bạn có thể liên kết ứng dụng của bạn với thư viện thực:

gcc -o myapp -L../mylib/libs myapp.o -lmylib 

Lưu ý rằng -L switch kể gcc nơi thư viện là, và -l nói với nó để liên kết mã của bạn vào thư viện.

Nếu bạn không thực hiện bước cuối cùng này, bạn có thể gặp phải sự cố bạn đã mô tả.

Có thể có các trường hợp phức tạp hơn nhưng từ câu hỏi của bạn, tôi hy vọng điều này sẽ đủ để giải quyết vấn đề của bạn.

1

Đăng tệp makefile của bạn và chức năng thư viện bạn đang cố gắng gọi. makefiles gcc thậm chí đơn giản thường có một dòng như thế này:

LIBFLAGS = -lc -lpthread -lrt -lstdC++ -lShared -L ../ chia sẻ

Trong trường hợp này, nó có nghĩa là liên kết các thư viện C chuẩn, trong số những người khác

0

Tôi đã gặp sự cố này khi xây dựng một chương trình với phiên bản gcc mới. Vấn đề đã được khắc phục bằng cách gọi gcc với tùy chọn -std = gnu89. Rõ ràng đây là do khai báo hàm nội tuyến. Tôi đã tìm thấy giải pháp này tại https://gcc.gnu.org/gcc-5/porting_to.html