45

Tôi muốn kiểm soát loại thư viện được tìm thấy/liên kết với các tệp nhị phân của tôi trong CMake. Mục tiêu cuối cùng là, để tạo các tệp nhị phân "càng tĩnh càng tốt" là liên kết tĩnh với mọi thư viện có sẵn phiên bản tĩnh. Điều này rất quan trọng vì sẽ cho phép tính di động của các tệp nhị phân trên các hệ thống khác nhau trong khi thử nghiệm.CMake: cách tạo các tệp nhị phân "tĩnh nhất có thể"

ATM này có vẻ khá khó khăn để đạt được như các gói FindXXX.cmake, hoặc chính xác hơn lệnh find_library luôn luôn chọn lên các thư viện động bất cứ khi nào cả tĩnh và động có sẵn.

Mẹo về cách triển khai chức năng này - tốt nhất là theo cách thanh lịch - sẽ rất được hoan nghênh!

+0

Không hẳn là một sự lừa dối của: http://stackoverflow.com/questions/2113231/making-cmake-choose-static -linkage-when-possible, đặc biệt là GCC. –

+0

Trong thực tế, không chỉ là gcc cụ thể, đó là một giải pháp bất tiện. Xem bình luận của tôi ở câu hỏi khác. – pszilard

+0

@pszilard Bạn cuối cùng đã tìm được giải pháp chưa? Tôi đang cố gắng làm tương tự với g ++. – augustin

Trả lời

14

Một tệp FindXXX.cmake được làm tốt sẽ bao gồm một cái gì đó cho việc này. Nếu bạn tìm trong FindBoost.cmake, bạn có thể đặt biến Boost_USE_STATIC_LIBS để kiểm soát xem nó có tìm thấy các thư viện tĩnh hoặc chia sẻ hay không. Thật không may, phần lớn các gói không thực hiện điều này.

Nếu một mô-đun sử dụng lệnh find_library (phần lớn làm), thì bạn có thể thay đổi hành vi của CMake thông qua biến số CMAKE_FIND_LIBRARY_SUFFIXES. Dưới đây là đoạn code CMake có liên quan từ FindBoost.cmake sử dụng này:

IF(WIN32) 
    SET(CMAKE_FIND_LIBRARY_SUFFIXES .lib .a ${CMAKE_FIND_LIBRARY_SUFFIXES}) 
ELSE(WIN32) 
    SET(CMAKE_FIND_LIBRARY_SUFFIXES .a ${CMAKE_FIND_LIBRARY_SUFFIXES}) 
ENDIF(WIN32) 

Bạn có thể đặt này trước khi gọi find_package, hoặc, tốt hơn, bạn có thể thay đổi .cmake tập tin bản thân và đóng góp lại cho cộng đồng.

Đối với các tệp .cmake tôi sử dụng trong dự án của mình, tôi giữ tất cả chúng trong thư mục riêng của chúng trong kiểm soát nguồn. Tôi đã làm điều này bởi vì tôi thấy rằng có tệp .cmake đúng cho một số thư viện không nhất quán và giữ bản sao của riêng tôi cho phép tôi sửa đổi và đảm bảo rằng tất cả những người đã kiểm tra mã sẽ có cùng tệp hệ thống xây dựng.

+0

Cảm ơn nhận xét, tôi đã thực sự đi đến kết luận trong khi đó ở trên là giải pháp khả thi duy nhất để có được phiên bản tĩnh của các thư viện bên ngoài được phát hiện. Tuy nhiên, đây là một cách khá bẩn, tôi không muốn phải xác định hậu tố. Thật không may, dựa trên các cuộc thảo luận về danh sách gửi thư của CMake có vẻ như là Windows có một thư viện khá khó hiểu đặt tên không có kế hoạch để thực hiện nó đúng cách. Điều này sẽ làm việc trên hầu hết * hệ thống NIX, mặc dù. – pszilard

+0

Lưu ý rằng nếu bạn muốn * chỉ * các thư viện tĩnh được phát hiện (và do đó có thể cấu hình thất bại, thì các lệnh trên không nên thêm tên tệp thư viện tĩnh vào CMAKE_FIND_LIBRARY_SUFFIXES, mà thay vào đó đặt biến đó cho các tên tệp đó. *() chức năng từ bao giờ chọn lên thư viện chia sẻ với hậu tố thông thường – mabraham

+1

Lưu ý rằng không quan trọng như thế nào "cũng được thực hiện" gói FindXXXX.cmake là nếu thư viện được tìm thấy trong một thư mục liên kết tiềm ẩn, ví dụ như đường dẫn hệ thống. chuyển đổi thành -lXXXX để cho phép trình liên kết sử dụng độ phân giải bình thường trong trường hợp đó - xem http://public.kitware.com/pipermail/cmake/2015-January/059702.html – mabraham

26

Tôi đã thực hiện một số điều tra và mặc dù tôi không thể tìm thấy giải pháp thỏa mãn cho vấn đề này nhưng tôi đã tìm được giải pháp một nửa.

Các vấn đề của tĩnh xây dựng sôi xuống 3 điều:

  1. Xây dựng và liên kết các thư viện nội bộ của dự án.

    Khá đơn giản, chỉ cần lật công tắc BUILD_SHARED_LIBSOFF.

  2. Tìm phiên bản tĩnh của thư viện bên ngoài.

    Cách duy nhất có vẻ là thiết lập CMAKE_FIND_LIBRARY_SUFFIXES để chứa hậu tố tệp mong muốn (đó là danh sách ưu tiên).

    Giải pháp này khá là "bẩn" và rất nhiều so với nguyện vọng đa nền tảng của CMake. IMHO này nên được xử lý đằng sau hậu trường bởi CMake, nhưng theo như tôi hiểu, vì sự nhầm lẫn ".lib" trên Windows, có vẻ như các nhà phát triển CMake thích việc thực hiện hiện tại.

  3. Liên kết tĩnh với thư viện hệ thống.

CMake cung cấp tùy chọn LINK_SEARCH_END_STATIC dựa trên tài liệu: "Kết thúc một đường liên kết sao cho các thư viện hệ thống tĩnh được sử dụng." Người ta sẽ nghĩ, đây là nó, vấn đề được giải quyết. Tuy nhiên, có vẻ như việc thực hiện hiện tại không phải là nhiệm vụ. Nếu tùy chọn được bật, CMake tạo ra một cuộc gọi liên kết ngầm với một danh sách đối số kết thúc bằng các tùy chọn được chuyển đến trình liên kết, bao gồm -Wl,-Bstatic. Tuy nhiên, điều này là không đủ. Chỉ hướng dẫn liên kết để liên kết các kết quả tĩnh trong một lỗi, trong trường hợp của tôi: /usr/bin/ld: cannot find -lgcc_s. Đối số -statickhông phải là được tạo ra cho cuộc gọi liên kết của CMake. Tôi nghĩ rằng đây là lỗi nhưng tôi chưa quản lý để nhận được xác nhận từ các nhà phát triển.

Cuối cùng, tôi nghĩ rằng tất cả điều này có thể và nên được thực hiện bởi CMake đằng sau hậu trường, sau khi tất cả nó không phải là quá phức tạp, ngoại trừ việc nó không thể trên Windows - nếu tính đó phức tạp ...

+1

Bạn không nên đặt 'BUILD_SHARED_LIBS' thành tắt (vì vậy nó * sẽ không * xây dựng thư viện được chia sẻ)? – Nooble

+0

Hahha, trong gần năm năm bạn là người đầu tiên lưu ý sai lầm đó. – pszilard

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