2013-06-07 60 views
24

Tôi đang sử dụng CMake trong một dự án và tôi đang cố gắng liên kết tĩnh một số thư viện. Tôi đã đặt:CMake và Liên kết tĩnh

set(BUILD_SHARED_LIBS OFF) 
set(CMAKE_EXE_LINKER_FLAGS "-static-libgcc -static-libstdc++ -static") 
set_target_properties(icarus PROPERTIES LINK_SEARCH_END_STATIC 1) 

Và tôi đã chắc chắn khi tìm kiếm các thư viện thực mà tôi có phiên bản * .a của chúng.

Hiện nay nhập khẩu dự án:

libPocoNet.a 
libPocoUtil.a 
libPocoXML.a 
libPocoFoundation.a 
libmysqlclient.a 
libmysqlpp.a 
libcrypto++.a 
CUDA 

Tất cả các thư viện được tìm thấy, và khi thực hiện một/chia sẻ liên kết năng động, họ làm việc tốt. Tôi cũng đã cố gắng đặt cờ biên soạn:

set(GCC_CXX_FLAGS ${GCC_CXX_FLAGS} "-static-libgcc -static-libstdc++ -static") 

Nhưng vô ích. Trong khi tôi nhận được không có vấn đề khi biên dịch, liên kết được ném rất nhiều tài liệu tham khảo không xác định lỗi cho các cuộc gọi được tìm thấy trong các thư viện trên, tức là:

undefined reference to `mysql_thread_init' 
undefined reference to `mysql_real_query' 
undefined reference to `pthread_mutex_unlock' 
undefined reference to `Poco::ErrorHandler::handle()' 

Không theo thứ tự đặc biệt, và nhiều lỗi cho mỗi thư viện.

Nhìn vào dòng cuối cùng của GCC tôi thấy:

/usr/bin/c++ -g -g -static-libgcc -static-libstdc++ -static [list of *.cpp files] 
-o icarus -rdynamic /usr/local/lib/libPocoFoundation.a /usr/local/lib/libPocoNet.a 
/usr/local/lib/libPocoUtil.a /usr/local/lib/libPocoXML.a 
-Wl,-Bstatic -lmysqlclient -lmysqlpp -lcrypto++ 

Mà làm cho tôi ngạc nhiên:

  1. Tại sao Poco thư viện liên kết như -rdynamic, và không có cờ -Bstatic -Wl ? Như thể chúng bị bỏ qua/loại trừ khỏi liên kết tĩnh.
  2. mysqlclient, mysqlpp và crypto ++ dường như được thiết lập cho liên kết tĩnh, nhưng tôi vẫn nhận được lỗi

Vì vậy, có thể ai đó xin vui lòng giải thích cho tôi:

  1. Làm thế nào để thiết lập cho liên kết tĩnh một phần sử dụng CMake
  2. Chỉ CMAKE_EXE_LINKER_FLAGS tôi có cần thiết lập chỉ số CMAKE_EXE_LINKER_FLAGS?
  3. Tôi có nên buộc liên kết tĩnh cho các thư viện được đề cập nhưng không phải cho toàn bộ dự án không?

Hãy tha thứ cho tôi nếu những câu hỏi quá nhiều hoặc quá cục bộ, tôi chưa thử điều này trước đây và dường như tôi không tìm thấy nhiều thông tin trên mạng.

Trả lời

24

tôi đã quản lý để giải quyết vấn đề của tôi bằng cách sử dụng các mục sau:

#Dynamic/Shared Libs 
... 
#Static start 
set_target_properties(icarus PROPERTIES LINK_SEARCH_START_STATIC 1) 
set_target_properties(icarus PROPERTIES LINK_SEARCH_END_STATIC 1) 
set(CMAKE_FIND_LIBRARY_SUFFIXES ".a") 
#Static Libs 
... 
#Set Linker flags 
set(CMAKE_EXE_LINKER_FLAGS "-static-libgcc -static-libstdc++") 

Điều này hoạt động mà không cần đi qua -static tạo ra othe Các vấn đề lớn, và về cơ bản có thể trộn các thư viện tĩnh và động.

Miễn là thứ tự của các thư viện tĩnh là chính xác, và miễn là phụ thuộc vào các thư viện tĩnh được thỏa mãn, tôi nhận được một ELF tải những gì là động (ví dụ: mysqlclient, libmysql ++) và tĩnh tất cả các phần còn lại (crypto ++, PocoNet, PocoUtil, PocoXML, PocoFoundation).

Hãy nhớ rằng các thư viện được liên kết tĩnh có các phụ thuộc riêng của chúng. Kiểm tra ứng dụng gỡ lỗi của tôi sử dụng ứng dụng readelf -d, tôi thấy:

Dynamic section at offset 0x508f88 contains 28 entries: 
    Tag  Type       Name/Value 
0x0000000000000001 (NEEDED)    Shared library: [libmysqlpp.so.3] 
0x0000000000000001 (NEEDED)    Shared library: [libmysqlclient.so.18] 
0x0000000000000001 (NEEDED)    Shared library: [libm.so.6] 
0x0000000000000001 (NEEDED)    Shared library: [libc.so.6] 
0x0000000000000001 (NEEDED)    Shared library: [ld-linux-x86-64.so.2] 
0x0000000000000001 (NEEDED)    Shared library: [libpthread.so.0] 

Tôi biết pthread được nhập khẩu bởi Poco :: Runnable, libm là cho các hoạt động toán học vv tôi vẫn không biết nếu điều này là đúng sự cách sử dụng CMake để liên kết tĩnh một phần.

Trong trường hợp các thư viện đóng gói Debian, chẳng hạn như crypto ++, mysql ++, mysqlclient, đơn giản là tìm thư viện * .a, nhưng trong trường hợp thư viện Poco, nó chỉ cho tôi đường dẫn đầy đủ và tên thư viện, không phải cờ, -Bdynamic chỉ có thể được tắt bằng cách sử dụng các dòng trên.

Lưu ý: Poco không thể được liên kết tĩnh, không -static-libstdc++

Tôi hy vọng điều này sẽ giúp mọi người bị mắc kẹt tại một cái gì đó tương tự.

+0

Tôi nhận được một "/ usr/bin/ld: không thể tìm thấy -lc" (xây dựng trên CentOS 7) –

+0

@MikeM Tôi thấy khó tin rằng thư viện C chưa được cài đặt. Có thể bạn cần xuất đường dẫn thư viện của mình? –

+0

Tôi đã kết thúc hardcoding đường dẫn đến .a tập tin thông qua add_library (..) và nó làm việc cho tôi (cho cả hai tiêu đề và thư viện tĩnh) –

11

Làm thế nào để thiết lập cho liên kết tĩnh nhờ sủ dụng CMake

Vâng ... bạn không :) Đó không phải là cách CMake hoạt động: trong CMake, trước tiên bạn tìm đường dẫn tuyệt đối của thư viện, sau đó liên kết với nó với target_link_libraries.

Vì vậy, nếu bạn muốn liên kết đến một thư viện tĩnh, bạn cần phải tìm kiếm cho rằng thư viện tĩnh:

find_library(SOMELIB libsomelib.a) 

thay vì:

find_library(SOMELIB somelib) 
+0

Xin chào một lần nữa! Đó là những gì tôi đã làm, tìm kiếm * .a và nhận chúng. Và đó là cách tôi vẫn gặp lỗi liên kết. Tôi có nên gửi đường dẫn tuyệt đối của mỗi thư viện tĩnh đến trình liên kết thay thế không? –

+0

Vâng, CMake hy vọng các đường dẫn tuyệt đối và đó là những gì find_library sẽ cung cấp cho bạn. – Guillaume

+0

Vâng đó là những gì tôi nhận được. Trong khi chạy cmake, tôi đang ghi tên thư viện và tôi có thể thấy đường dẫn đầy đủ và * .a thường là một liên kết tượng trưng đến lib tĩnh thực sự. Nó vẫn không giải thích được các lỗi không tham chiếu, đúng không? Những lỗi đó dường như đến từ bên trong các thư viện. Tôi có cần phải nhập khẩu các phụ thuộc của mỗi thư viện không? –

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