2014-12-02 13 views
5

Vấn đề: Tôi đang xây dựng một dự án bên ngoài trong CMake. Dự án có một Makefile mà cuối cùng tạo ra một đối tượng được chia sẻ. Tôi muốn liên kết và cài đặt đối tượng này trong dự án siêu của tôi, giống như thể nó là một trong các thư viện trong dự án. Vấn đề là lib ExternalProject được liên kết vào các ứng dụng và thư viện của tôi với một đường dẫn tương đối, không phải là đường dẫn tuyệt đối gây ra vấn đề khi chạy từ bất kỳ thư mục nào ngoài CMake đặt nó.CMake: Liên kết đối tượng chia sẻ C++ từ ExternalProject tạo ra các tệp nhị phân với đường dẫn tương đối, không tuyệt đối

Tôi có created a sample SSCCE example project để minh họa thiết lập tổng thể của tôi. Vui lòng đọc và biên dịch nếu cần (git clone https://github.com/calebwherry/cmake-SO-question-main --recursive && cd cmake-SO-question-main && mkdir build && cd build && cmake .. && make && cd src/app/testApp && ldd testApp).

Bất cứ khi nào tôi chạy ldd trên thực thi và libs, tôi nhận được kết quả như thế này:

linux-vdso.so.1 => (0x00007fff8b5a2000) 
    libTestLib.so => /home/jwherry3/repos/cmake-superprj-main-test/build/src/lib/TestLib/libTestLib.so (0x00007f592da57000) 
    ../../lib/libExtLib.so (0x00007f592d855000) 
    libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f592d539000) 
    libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f592d2b7000) 
    libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f592d0a0000) 
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f592cd14000) 
    /lib64/ld-linux-x86-64.so.2 (0x00007f592dc5a000) 

Tôi đã thử tất cả mọi thứ đối phó với RPATHS nhưng không thể có được ExtLib để liên kết đúng. Các lib là địa phương cho các dự án (libTestLib.so) liên kết tốt.

Tôi cũng đã cố gắng đặt LD_LIBRARY_PATH để ghi đè đường dẫn tương đối khi tôi chạy ứng dụng nhưng ngay cả khi tôi làm điều đó, nó vẫn không tìm thấy thư viện. Tôi cho rằng vì nó là tương đối nó không theo thứ tự liên kết bình thường? Kết quả là nhị phân sẽ không chạy trừ khi tôi nằm trong thư mục chứa nó.

Tôi cảm thấy như tôi đang làm điều gì đó thực sự câm khi tạo phụ thuộc với ExternalProject và đó là vấn đề của tôi nhưng tôi đã đánh bại đầu của tôi trong 3 ngày và đã không đưa ra bất cứ điều gì.

Thiết lập hệ thống: Debian Wheezy 64 bit, CMake 3.0.2, g ++ - 4.9.2.

+0

Vẫn không có lần truy cập, phải không? Whelp, tôi đã tạm thời 'cố định' vấn đề bằng cách có dự án bên ngoài cũng xây dựng một lib tĩnh và liên kết mà thay vì lib được chia sẻ. Không phải là một giải pháp lâu dài nhưng một trong đó ít nhất được điều này để chạy một cách chính xác. Tôi đã cập nhật repo để có tùy chọn này cho người khác nhưng bạn phải tự thay đổi nó trong ext/CMakeLists.txt để bật nó lên. – Caleb

+0

xin lỗi, không nhận thấy câu trả lời – Slava

Trả lời

1

Mất một thời gian nhưng cuối cùng tôi đã có câu trả lời với sự trợ giúp từ danh sách Người dùng CMake, cụ thể là @ brad-king.

Vấn đề chính là tôi không biên dịch chính xác đối tượng được chia sẻ trong dự án bên ngoài của mình. Câu trả lời của Brad cho câu hỏi của tôi:

Cảm ơn ví dụ hoàn chỉnh/đơn giản. Vấn đề là tệp libExtLib.so được xây dựng bởi dự án bên ngoài không có DT_SONAME được thiết lập bởi trình liên kết. Khi một liên kết được cấp một đường dẫn vào tệp thư viện được chia sẻ không có soname thì đường dẫn được sao chép vào trường DT_NEEDED của người tiêu dùng vì nó không có soname để sử dụng cho điều đó.

Có hai giải pháp:

  1. Hãy chắc chắn rằng DT_SONAME được thiết lập đúng cách xây dựng hệ thống bên ngoài.

  2. Nói CMake rằng các tập tin thư viện nhập khẩu không có soname:

    set_Property (MỤC TIÊU ExtLib HỮU IMPORTED_NO_SONAME 1)

    sau đó CMake sẽ liên kết nó qua -lExtLib và mối liên kết sẽ không cửa hàng đường dẫn đến tệp trong DT_NEEDED nhưng chỉ có tên tệp.

Một trong hai cách này sẽ giải quyết được vấn đề. Số 1 sạch hơn.

Kể từ khi tôi có thể kiểm soát các tập tin thực hiện trong các thư viện bên ngoài, tôi đã lựa chọn giải pháp đầu tiên sạch bằng cách biên dịch các đối tượng chia sẻ như vậy:

$(SHARED_TARGET): $(OBJECTS) $(CXX) $(CXXFLAGS) $(OBJECTS) -o [email protected] $(LDFLAGS) -Wl,-soname,[email protected]

Tôi đã sửa đổi ví dụ ban đầu của tôi và làm cho nó đơn giản hơn rất nhiều: https://github.com/calebwherry/cmake-SO-question-main. Tôi sẽ để nó như là một tài liệu tham khảo cho bất cứ ai ngại trên bài đăng này vào một ngày sau đó.

P.S.

Có một bản sửa lỗi khác là tối ưu phụ. Nếu tôi đã không thực hiện bất kỳ điều nào ở trên, tôi có thể đã chỉ cho target_link_library đường dẫn đầy đủ đến thư viện mà tôi đã liên kết và không sử dụng mục tiêu thư viện đã nhập. Tôi đã lưu ý điều này trong tập tin CMake trong repo và nhận xét nó. Không phải là một giải pháp tuyệt vời nhưng giải quyết vấn đề theo cách khác.

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