Cùng một nguồn, tất cả điều đó, chỉ muốn có phiên bản tĩnh và được chia sẻ cả hai. Dễ làm sao?Có thể nhận CMake để xây dựng cả phiên bản tĩnh và chia sẻ của cùng một thư viện không?
Trả lời
Có, nó vừa phải dễ dàng. Chỉ cần sử dụng hai lệnh "add_library":
add_library(MyLib SHARED source1.c source2.c)
add_library(MyLibStatic STATIC source1.c source2.c)
Ngay cả khi bạn có nhiều tệp nguồn, bạn sẽ đặt danh sách nguồn vào biến cmake, vì vậy nó vẫn dễ thực hiện.
Trên Windows, bạn có thể đặt tên cho mỗi thư viện khác nhau, vì có tệp ".lib" cho cả tệp được chia sẻ và tĩnh. Nhưng trên Linux và Mac bạn thậm chí có thể cung cấp cho cả hai thư viện cùng tên (ví dụ libMyLib.a và libMyLib.so):
set_target_properties(MyLibStatic PROPERTIES OUTPUT_NAME MyLib)
Nhưng tôi không khuyên bạn nên cho cả hai phiên bản tĩnh và động của thư viện cùng Tên. Tôi thích sử dụng các tên khác nhau vì điều đó giúp dễ dàng chọn liên kết tĩnh và động trên đường biên dịch cho các công cụ liên kết đến thư viện. Thông thường tôi chọn các tên như libMyLib.so (được chia sẻ) và libMyLib_static.a (tĩnh). (Đó sẽ là tên trên Linux.)
Thường không cần lặp lại các cuộc gọi THÊM cho mục đích của bạn. Chỉ cần tận dụng
$> man cmake | grep -A6 '^ *BUILD_SHARED_LIBS$'
BUILD_SHARED_LIBS
Global flag to cause add_library to create shared libraries if on.
If present and true, this will cause all libraries to be built shared unless the library was
explicitly added as a static library. This variable is often added to projects as an OPTION
so that each user of a project can decide if they want to build the project using shared or
static libraries.
trong khi xây dựng đầu tiên (trong một out-of-nguồn thư mục) với -DBUILD_SHARED_LIBS: BOOL = ON và OFF với trong khác
Điều này dường như không xây dựng BOTH phiên bản tĩnh và chia sẻ, mà tôi nghĩ là những gì câu hỏi này là nhận được tại. –
Kể từ CMake phiên bản 2.8.8, bạn có thể sử dụng "thư viện đối tượng" để tránh việc biên dịch trùng lặp các tệp đối tượng. Sử dụng ví dụ về một thư viện Christopher Bruns' với hai tập tin nguồn:
# list of source files
set(libsrc source1.c source2.c)
# this is the "object library" target: compiles the sources only once
add_library(objlib OBJECT ${libsrc})
# shared libraries need PIC
set_property(TARGET ${objlib} PROPERTY POSITION_INDEPENDENT_CODE 1)
# shared and static libraries built from the same object files
add_library(MyLib_shared SHARED $<TARGET_OBJECTS:objlib>)
add_library(MyLib_static STATIC $<TARGET_OBJECTS:objlib>)
Từ CMake docs:
Một thư viện đối tượng biên dịch file nguồn nhưng không lưu trữ hoặc liên kết file đối tượng của họ thành một thư viện. Thay vào đó, các mục tiêu khác được tạo bởi add_library() hoặc add_executable() có thể tham chiếu các đối tượng sử dụng biểu thức của biểu mẫu $ dưới dạng nguồn, trong đó objlib là tên thư viện đối tượng.
Đơn giản chỉ cần đặt, lệnh add_library(objlib OBJECT ${libsrc})
hướng dẫn CMake biên dịch tệp nguồn thành *.o
tệp đối tượng. Bộ sưu tập này của *.o
tệp sau đó được gọi là $<TARGET_OBJECT:objlib>
trong hai lệnh add_library(...)
gọi lệnh tạo thư viện thích hợp để xây dựng thư viện được chia sẻ và tĩnh từ cùng một tập hợp của tệp đối tượng. Nếu bạn có nhiều tệp nguồn thì việc biên dịch các tệp *.o
có thể mất nhiều thời gian; với các thư viện đối tượng bạn chỉ biên dịch chúng một lần.
Giá bạn phải trả là các tệp đối tượng phải được tạo thành mã độc lập với vị trí vì các thư viện được chia sẻ cần điều này (các lib tĩnh không quan tâm). Lưu ý rằng mã độc lập vị trí có thể kém hiệu quả hơn, do đó, nếu bạn nhắm đến hiệu suất tối đa thì bạn sẽ đi cho các thư viện tĩnh. Hơn nữa, việc phân phối các tệp thực thi được liên kết tĩnh dễ dàng hơn.
Đúng, tôi thường thêm hậu tố _shared và _static. Câu trả lời đã chỉnh sửa ở trên, thx để chỉ ra câu trả lời. Tôi cũng đồng ý rằng đó là vấn đề sở thích cá nhân. Đối với trường hợp sử dụng của tôi obj libs làm việc khá tốt, YMMV. –
Điều này làm việc giống như một sự quyến rũ đối với tôi - cảnh báo duy nhất là các cuộc gọi 'target_link_libraries()' tiếp theo phụ thuộc vào thư viện của bạn không thể sử dụng “thư viện đối tượng” để liên kết; chúng phải nhắm mục tiêu các thư viện chia sẻ hoặc tĩnh mới (và có thể được nhân bản). Nhưng trái với trải nghiệm của người nhận xét đầu tiên, điều này khá hữu ích và cho phép tôi xóa tất cả các mục tiêu được sao chép và cắt tất cả các tệp 'CMakeLists.txt' của tôi gần một nửa. – fish2000
Bạn có cần phải "thoát" các obblib khi thiết lập các thuộc tính mục tiêu? tức là set_property (TARGET $ {objlib} THUỘC TÍNH ...) so với set_property (TARGET objlib PROPERTY ...) – gnac
Thực sự là có thể.Như @Christopher Bruns nói trong câu trả lời của mình, bạn cần phải thêm hai phiên bản của thư viện:
set(libsrc source1.c source2.c source3.c)
add_library(mylib-static STATIC ${libsrc})
add_library(mylib-shared SHARED ${libsrc})
Sau đó, như mô tả here, bạn cần phải xác định rằng cả hai chỉ tiêu nên sử dụng tên đầu ra giống nhau và không ghi đè lên nhau tệp:
SET_TARGET_PROPERTIES(mylib-static PROPERTIES OUTPUT_NAME mylib CLEAN_DIRECT_OUTPUT 1)
SET_TARGET_PROPERTIES(mylib-shared PROPERTIES OUTPUT_NAME mylib CLEAN_DIRECT_OUTPUT 1)
Bằng cách này, bạn sẽ nhận được cả libmylib.a và libmylib.so (trên Linux) hoặc mylib.lib và mylib.dll (trên Windows).
Điều này là không cần thiết khi sử dụng phiên bản CMake trên 2.8. [0?], Vì thuộc tính đã bị xóa vào năm 2009 và hành vi mà nó cung cấp giờ đây là mặc định. Điều này có thể hữu ích cho những người dưới 2,8 tuổi, nhưng nếu bạn vẫn đang sử dụng CMake <2,7, tôi yêu cầu bạn nâng cấp. https://github.com/Kitware/CMake/commit/430cc2b4b7a817be2fbc445d6803163f1695a533 – KymikoLoco
Đã hy vọng họ có cùng tên, nhưng tốt thôi. Một câu hỏi khác: Bạn có thể yêu cầu CMake liên kết các thư viện tĩnh vào thư viện được chia sẻ khi có thể không? –
Thông tin thêm về "cùng tên": Nếu bạn đang sử dụng Windows và muốn có cùng tên cho cả hai thư viện và bạn không cần tệp .lib được chia sẻ, bạn có thể tạo một tệp .lib tĩnh và một tệp .dll được chia sẻ. Nhưng bạn cần chia sẻ tập tin .lib nếu bạn đang sử dụng thư viện của bạn cho thời gian biên dịch thông thường liên kết. –
Tôi không chắc tôi hiểu câu hỏi của bạn về việc liên kết các thư viện tĩnh vào thư viện được chia sẻ. –