2011-01-25 23 views
9

Tôi đã cài đặt trong/usr/phiên bản phân phối của SQLite - phiên bản 3.4.2. Tôi đã cài đặt trong/usr/local/SQLite phiên bản 3.7.4.GCC tìm tiêu đề trong/usr/local/include khi biên dịch, nhưng không cho các thư viện trong/usr/local/lib khi liên kết. Tại sao?

/usr/include/sqlite3.h định nghĩa SQLITE_VERSION_NUMBER như 3.004.002
/usr/local/include/sqlite3.h định nghĩa SQLITE_VERSION_NUMBER như 3007004

Version 3.007.004 có chức năng sqlite3_initialize(), phiên bản 3.004.002 thì không.

$ nm -D /usr/local/lib/libsqlite3.so | grep sqlite3_initialize 
00018e20 T sqlite3_initialize 

Khi tôi biên dịch chương trình ví dụ sau:

#include <stdio.h> 
#include <sqlite3.h> 

// This should fail if including /usr/include/sqlite3.h 
#if SQLITE_VERSION_NUMBER != 3007004 
    #error "SQLite version is not 3.7.4" 
#endif 

int main() { 
    printf("%d\n", SQLITE_VERSION_NUMBER); 
    sqlite3_initialize(); 
    return 0; 
} 

Khi biên soạn và liên kết (với gcc 4.2.4) như thế này Preprocessor thấy tiêu đề sqlite3.h cho phiên bản 3.7.4 trong/usr/local/include /, nhưng linker không thành công vì nó tìm trong /usr/lib/libsqlite3.so cho các ký hiệu.

$ gcc -Wall test.c -o cpp -lsqlite3 
/tmp/cc4iSSN6.o: In function `main': 
test.c:(.text+0x26): undefined reference to `sqlite3_initialize' 
test.c:(.text+0x2b): undefined reference to `sqlite3_shutdown' 
collect2: ld returned 1 exit status 

Tất nhiên tôi có thể chỉ định thư mục lib và nó liên kết đúng phiên bản của thư viện.

$ gcc -Wall test.c -o cpp -L/usr/local/lib -lsqlite3 
$ ./cpp 
3007004 
$ 

Dường như gcc mặc định có dạng/usr/local/include/before/usr/include/cho tiêu đề, nhưng không cho thư viện khi liên kết. Tại sao?

Sửa 1: Theo đề nghị của Tim Post:

$ sudo ldconfig -n /usr/local/lib 
$ ldconfig -p | grep sqlite3 
    libsqlite3.so.0 (libc6) => /usr/local/lib/libsqlite3.so.0 
    libsqlite3.so.0 (libc6) => /usr/lib/libsqlite3.so.0 
    libsqlite3.so (libc6) => /usr/local/lib/libsqlite3.so 
    libsqlite3.so (libc6) => /usr/lib/libsqlite3.so 
$ gcc -Wall cpp.c -o cpp -lsqlite3 
/tmp/ccwPT9o0.o: In function `main': 
cpp.c:(.text+0x26): undefined reference to `sqlite3_initialize' 
cpp.c:(.text+0x2b): undefined reference to `sqlite3_shutdown' 
collect2: ld returned 1 exit status 

Trả lời

8

Các bao gồm tập tin đường dẫn tìm kiếm được xác định bởi gcc, nhưng đường dẫn tìm kiếm thư viện được mã hóa thành ld, mà là từ một dự án riêng biệt ; đây không nhất thiết phải đồng bộ.

Một điều bạn có thể làm là vá thông số thông số, nếu có, có thể tìm thấy trong cùng một thư mục với tên libgcc; bạn có thể lấy đường dẫn đến sau này sử dụng

gcc -print-libgcc-file-name 

Nếu không có số kỹ thuật tập tin đó, tạo một trang bằng

gcc -dumpspecs >specs 

và xác minh gcc được đọc nó, bằng cách gọi

gcc -v 

Tìm một dòng có chứa %{L*} và thêm -L/usr/local/lib đằng sau nó (ngăn cách bằng dấu cách). Sau đó, Gcc sẽ chuyển đối số này sau bất kỳ tùy chọn -L nào từ dòng lệnh đến ld khi liên kết.

Để khôi phục các giá trị mặc định, chỉ cần hoàn nguyên tệp thông số về trạng thái ban đầu của nó (nghĩa là xóa nó nếu nó không tồn tại trước đó).

+1

Đường dẫn thư viện được xác định rõ ràng trên dòng lệnh 'ld' bằng' gcc', không chỉ được mã hóa thành 'ld' (mặc dù chúng cũng có thể được mã hóa thành' ld'). Chỉ cần sử dụng 'strace' để xem. –

0

Đây có thể là triệu chứng của việc sử dụng trình liên kết vàng, không tìm kiếm /usr/local/lib, ít nhất trong một số phiên bản. Thử xóa gói binutils-gold.

+0

-1 bởi vì loại bỏ vàng, đó là một mối liên kết tốt hơn nhiều, không phải là gợi ý tốt nhất. –

+0

Sau đó, gợi ý tốt hơn là gì? Thêm một '-L/usr/local/lib' rõ ràng vào tất cả các dòng lệnh? Đối với các dự án nhỏ, về cơ bản không có sự khác biệt giữa 'vàng' và' ld' ngoại trừ vấn đề này. –

+0

-1 vì không có sự khác biệt giữa vàng và ld liên quan đến đường dẫn tìm kiếm. Đường dẫn tìm kiếm thư viện liên kết thời gian đến từ gcc. –

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