Sumber yang sama, semua itu, hanya menginginkan versi statis dan berbagi keduanya. Mudah untuk dilakukan?
Ya, ini cukup mudah. Cukup gunakan dua perintah "add_library":
add_library(MyLib SHARED source1.c source2.c)
add_library(MyLibStatic STATIC source1.c source2.c)
Meskipun Anda memiliki banyak file sumber, Anda akan menempatkan daftar sumber dalam variabel cmake, jadi masih mudah dilakukan.
Pada Windows Anda mungkin harus memberikan nama yang berbeda untuk setiap perpustakaan, karena ada file ".lib" untuk berbagi dan statis. Tetapi di Linux dan Mac Anda bahkan dapat memberi kedua pustaka nama yang sama (misalnya libMyLib.a
dan libMyLib.so
):
set_target_properties(MyLibStatic PROPERTIES OUTPUT_NAME MyLib)
Tapi saya tidak merekomendasikan memberikan versi statis dan dinamis dari pustaka nama yang sama. Saya lebih suka menggunakan nama yang berbeda karena itu membuatnya lebih mudah untuk memilih tautan statis vs. dinamis pada baris kompilasi untuk alat yang ditautkan ke perpustakaan. Biasanya saya memilih nama seperti libMyLib.so
(shared) dan libMyLib_static.a
(static). (Itu akan menjadi nama-nama di linux.)
-fPIC
), yang menambahkan sejumlah kecil overhead runtime saat library statis tersebut digunakan. Jadi untuk performa maksimal, jawaban ini tetap yang terbaik.Sejak CMake versi 2.8.8, Anda dapat menggunakan "perpustakaan objek" untuk menghindari kompilasi file objek yang digandakan . Menggunakan contoh pustaka Christopher Bruns dengan dua file sumber:
Dari dokumen CMake :
Sederhananya,
add_library(objlib OBJECT ${libsrc})
perintah menginstruksikan CMake untuk mengkompilasi file sumber ke*.o
file objek. Kumpulan*.o
file ini kemudian disebut sebagai$<TARGET_OBJECT:objlib>
duaadd_library(...)
perintah yang menjalankan perintah pembuatan perpustakaan yang sesuai yang membangun perpustakaan bersama dan statis dari kumpulan file objek yang sama . Jika Anda memiliki banyak file sumber, maka kompilasi*.o
file bisa memakan waktu cukup lama; dengan pustaka objek Anda mengkompilasinya hanya sekali.Harga yang Anda bayarkan adalah bahwa file objek harus dibuat sebagai kode yang tidak bergantung pada posisi karena library bersama memerlukan ini (library statis tidak peduli). Perhatikan bahwa kode yang tidak tergantung posisi mungkin kurang efisien, jadi jika Anda bertujuan untuk kinerja maksimal maka Anda akan menggunakan pustaka statis. Selain itu, lebih mudah untuk mendistribusikan file executable yang terhubung secara statis.
sumber
target_link_libraries()
panggilan berikutnya yang bergantung pada perpustakaan Anda tidak dapat menggunakan "perpustakaan objek" untuk ditautkan; mereka harus menargetkan pustaka bersama atau statis baru (dan mungkin digandakan). Tetapi bertentangan dengan pengalaman pemberi komentar pertama, ini cukup berguna, dan memungkinkan saya untuk menghapus semua target duplikat dan memotong semuaCMakeLists.txt
file saya hampir setengahnya.set_property
satu - satunya bekerja saat saya digunakanobjlib
dan tidak saat menggunakan${objlib}
. Jadi mungkin jawaban ini bisa diperbaiki?Biasanya tidak perlu menggandakan
ADD_LIBRARY
panggilan untuk tujuan Anda. Manfaatkan sajasaat membangun, pertama (dalam satu direktori di luar sumber) dengan
-DBUILD_SHARED_LIBS:BOOL=ON
, dan denganOFF
di direktori lainnya.sumber
Dimungkinkan untuk mengemas semuanya dalam nafas kompilasi yang sama, seperti yang disarankan dalam jawaban sebelumnya, tetapi saya akan menyarankan agar tidak melakukannya, karena pada akhirnya ini adalah peretasan yang hanya berfungsi untuk proyek-proyek sederhana. Misalnya, Anda mungkin memerlukan flag yang berbeda untuk versi library yang berbeda (khususnya pada Windows di mana flag biasanya digunakan untuk beralih antara mengekspor simbol atau tidak). Atau seperti yang disebutkan di atas, Anda mungkin ingin memasukkan
.lib
file ke direktori yang berbeda tergantung pada apakah mereka sesuai dengan pustaka statis atau bersama. Masing-masing rintangan itu membutuhkan peretasan baru.Mungkin sudah jelas, tetapi satu alternatif yang belum disebutkan sebelumnya adalah membuat tipe pustaka sebagai parameter:
Memiliki versi bersama dan statis pustaka dalam dua pohon biner berbeda membuatnya lebih mudah untuk menangani opsi kompilasi yang berbeda. Saya tidak melihat kekurangan serius dalam menjaga struktur kompilasi berbeda, terutama jika kompilasi Anda dilakukan secara otomatis.
Perhatikan bahwa meskipun Anda bermaksud untuk saling menguntungkan kompilasi menggunakan
OBJECT
pustaka perantara (dengan peringatan yang disebutkan di atas, jadi Anda memerlukan alasan kuat untuk melakukannya), Anda masih bisa memiliki pustaka akhir yang dimasukkan ke dalam dua proyek berbeda.sumber
Itu memang mungkin. Seperti yang dikatakan @Christopher Bruns dalam jawabannya, Anda perlu menambahkan dua versi perpustakaan:
Kemudian, seperti yang dijelaskan di sini , Anda perlu menentukan bahwa kedua target harus menggunakan nama keluaran yang sama dan tidak menimpa file satu sama lain:
Dengan cara ini, Anda akan mendapatkan libmylib.a dan libmylib.so (di Linux) atau mylib.lib dan mylib.dll (di Windows).
sumber