Dieselbe Quelle möchte nur eine statische und eine gemeinsam genutzte Version. Leicht zu schaffen?
Ja, es ist mäßig einfach. Verwenden Sie einfach zwei "add_library" -Befehle:
add_library(MyLib SHARED source1.c source2.c)
add_library(MyLibStatic STATIC source1.c source2.c)
Selbst wenn Sie viele Quelldateien haben, würden Sie die Liste der Quellen in eine cmake-Variable einfügen, sodass dies immer noch einfach ist.
Unter Windows sollten Sie wahrscheinlich jeder Bibliothek einen anderen Namen geben, da es eine ".lib" -Datei für gemeinsam genutzte und statische Dateien gibt. Unter Linux und Mac können Sie beiden Bibliotheken sogar den gleichen Namen geben (z. B. libMyLib.a
und libMyLib.so
):
set_target_properties(MyLibStatic PROPERTIES OUTPUT_NAME MyLib)
Ich empfehle jedoch nicht, sowohl der statischen als auch der dynamischen Version der Bibliothek den gleichen Namen zu geben. Ich bevorzuge die Verwendung unterschiedlicher Namen, da dies die Auswahl einer statischen oder dynamischen Verknüpfung in der Kompilierungszeile für Tools erleichtert, die mit der Bibliothek verknüpft sind. Normalerweise wähle ich Namen wie libMyLib.so
(geteilt) und libMyLib_static.a
(statisch). (Das wären die Namen unter Linux.)
-fPIC
) erstellt werden, wodurch bei Verwendung dieser statischen Bibliotheken ein geringer Laufzeitaufwand entsteht. Für maximale Leistung ist diese Antwort immer noch die beste.Seit CMake Version 2.8.8 können Sie "Objektbibliotheken" verwenden , um die doppelte Kompilierung der Objektdateien zu vermeiden . Am Beispiel von Christopher Bruns für eine Bibliothek mit zwei Quelldateien:
Aus den CMake-Dokumenten :
Einfach ausgedrückt, weist der
add_library(objlib OBJECT ${libsrc})
Befehl CMake an, die Quelldateien zu*.o
Objektdateien zu kompilieren . Diese Sammlung von*.o
Dateien wird dann als$<TARGET_OBJECT:objlib>
in den beidenadd_library(...)
Befehlen bezeichnet, die die entsprechenden Befehle zum Erstellen von Bibliotheken aufrufen, mit denen die gemeinsam genutzten und statischen Bibliotheken aus demselben Satz von Objektdateien erstellt werden. Wenn Sie viele Quelldateien haben,*.o
kann das Kompilieren der Dateien ziemlich lange dauern. Mit Objektbibliotheken kompilieren Sie diese nur einmal.Der Preis, den Sie zahlen, ist, dass die Objektdateien als positionsunabhängiger Code erstellt werden müssen, da gemeinsam genutzte Bibliotheken dies benötigen (statische Bibliotheken kümmern sich nicht darum). Beachten Sie, dass positionsunabhängiger Code möglicherweise weniger effizient ist. Wenn Sie also maximale Leistung anstreben, sollten Sie sich für statische Bibliotheken entscheiden. Darüber hinaus ist es einfacher, statisch verknüpfte ausführbare Dateien zu verteilen.
quelle
target_link_libraries()
Aufrufe, die von Ihrer Bibliothek abhängen. Sie können die "Objektbibliothek" nicht zum Verknüpfen verwenden. Diese müssen auf die neuen gemeinsam genutzten oder statischen Bibliotheken abzielen (und können dupliziert werden). Aber im Gegensatz zu den Erfahrungen der ersten Kommentatoren war dies sehr nützlich und erlaubte mir, alle doppelten Ziele zu entfernen und alle meineCMakeLists.txt
Dateien um fast die Hälfte zu schneiden .set_property
funktionierte das nur, wenn ich es benutzteobjlib
und nicht, wenn ich es benutzte${objlib}
. Vielleicht könnte diese Antwort korrigiert werden?Es ist im Allgemeinen nicht erforderlich,
ADD_LIBRARY
Anrufe für Ihren Zweck zu duplizieren . Nutzen Sie einfachbeim Erstellen zuerst (in einem Out-of-Source-Verzeichnis) mit
-DBUILD_SHARED_LIBS:BOOL=ON
und mitOFF
im anderen.quelle
Es ist möglich, alles in den gleichen Zusammenstellungsatem zu packen, wie in den vorherigen Antworten vorgeschlagen, aber ich würde davon abraten, weil es am Ende ein Hack ist, der nur für einfache Projekte funktioniert. Beispielsweise benötigen Sie möglicherweise irgendwann unterschiedliche Flags für verschiedene Versionen der Bibliothek (insbesondere unter Windows, wo Flags normalerweise zum Umschalten zwischen dem Exportieren von Symbolen verwendet werden oder nicht). Wie oben erwähnt, möchten Sie möglicherweise
.lib
Dateien in verschiedenen Verzeichnissen ablegen, je nachdem, ob sie statischen oder gemeinsam genutzten Bibliotheken entsprechen. Jede dieser Hürden erfordert einen neuen Hack.Es mag offensichtlich sein, aber eine Alternative, die zuvor nicht erwähnt wurde, besteht darin, den Typ der Bibliothek zu einem Parameter zu machen:
Gemeinsame und statische Versionen der Bibliothek in zwei verschiedenen Binärbäumen erleichtern die Handhabung verschiedener Kompilierungsoptionen. Ich sehe keinen ernsthaften Nachteil darin, Kompilierungsbäume voneinander zu unterscheiden, insbesondere wenn Ihre Kompilierungen automatisiert sind.
Beachten Sie, dass selbst wenn Sie beabsichtigen, Kompilierungen mithilfe einer Zwischenbibliothek zu verinnerlichen
OBJECT
(mit den oben genannten Einschränkungen, sodass Sie einen zwingenden Grund dafür benötigen), Endbibliotheken in zwei verschiedene Projekte eingefügt werden können.quelle
Es ist in der Tat möglich. Wie @Christopher Bruns in seiner Antwort sagte, müssen Sie zwei Versionen der Bibliothek hinzufügen:
Dann müssen Sie, wie hier beschrieben , angeben, dass beide Ziele denselben Ausgabenamen verwenden und die Dateien des anderen nicht überschreiben sollen:
Auf diese Weise erhalten Sie sowohl libmylib.a als auch libmylib.so (unter Linux) oder mylib.lib und mylib.dll (unter Windows).
quelle