2010-01-28 9 views

Antwort

96

Ja, es ist mäßig einfach. Nur zwei „add_library“-Befehle verwenden:

add_library(MyLib SHARED source1.c source2.c) 
add_library(MyLibStatic STATIC source1.c source2.c) 

Auch wenn Sie viele Quelldateien haben, würden Sie die Liste der Quellen in einer Cmake Variablen halten, so ist es immer noch einfach zu tun.

Unter Windows sollten Sie wahrscheinlich jeder Bibliothek einen anderen Namen geben, da es eine ".lib" -Datei für freigegebene und statische Dateien gibt. Aber auf Linux und Mac können Sie sogar beide Bibliotheken geben den gleichen Namen (zB libMyLib.a und libMyLib.so):

set_target_properties(MyLibStatic PROPERTIES OUTPUT_NAME MyLib) 

Aber ich nicht empfehlen, sowohl die statischen und dynamischen Versionen der Bibliothek gibt dem gleichen Name. Ich bevorzuge es, andere Namen zu verwenden, da dies die Auswahl von statischen und dynamischen Verknüpfungen in der Kompilierzeile für Werkzeuge vereinfacht, die mit der Bibliothek verknüpft sind. Normalerweise wähle ich Namen wie libMyLib.so (shared) und libMyLib_static.a (statisch). (Das wären die Namen unter Linux.)

+0

Hatte für sie den gleichen Namen, aber na ja. Eine andere Frage: Kannst du CMake anweisen, statische Bibliotheken wenn möglich in die gemeinsame Bibliothek einzubinden? –

+0

Weitere Informationen zu "gleicher Name": Wenn Sie Windows verwenden und für beide Bibliotheken denselben Namen verwenden möchten und die gemeinsam genutzte .lib-Datei nicht benötigen, können Sie eine statische .lib-Datei und eine freigegebene .dll-Datei erstellen. Sie benötigen diese freigegebene LIB-Datei jedoch, wenn Sie Ihre Bibliothek für die normale Kompilierungszeitverknüpfung verwenden. –

+1

Ich bin mir nicht sicher, ob ich Ihre Frage zum Verknüpfen von statischen Bibliotheken in der gemeinsam genutzten Bibliothek verstehe. –

23

Es ist im Allgemeinen nicht notwendig, ADD_LIBRARY-Aufrufe für Ihren Zweck zu duplizieren. So stellen Sie die Verwendung von

$> 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. 

, während der ersten Gebäude (in einer Out-of-Source-Verzeichnis) mit -DBUILD_SHARED_LIBS: BOOL = ON und OFF mit in den anderen

+17

Dies scheint nicht BEIDE statische und geteilte Versionen zu bauen, was ich denke, was diese Frage ist. –

36

Da CMake 2.8.8 Version, können Sie Verwenden Sie "Objektbibliotheken" , um die doppelte Kompilierung der Objektdateien zu vermeiden. Mit Christopher Bruns' Beispiel für eine Bibliothek mit zwei Quelldateien:

# 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>) 

Vom CMake docs:

Eine Objektbibliothek Quelldateien kompiliert, sondern archiviert werden nicht oder Link ihre Objektdateien in eine Bibliothek. Stattdessen können andere Ziele, die durch add_library() oder add_executable() erstellt wurden, auf die Objekte verweisen, indem ein Ausdruck der Form $ als Quelle verwendet wird, wobei objlib der Objektbibliotheksname ist.

Einfach gesagt, die add_library(objlib OBJECT ${libsrc}) Befehl weist CMake die Quelldateien *.o Objektdateien zu kompilieren. Diese Sammlung von *.o Dateien wird dann als $<TARGET_OBJECT:objlib> in den beiden add_library(...)-Befehlen bezeichnet, die die entsprechenden Bibliothekserstellungsbefehle aufrufen, die die freigegebenen und statischen Bibliotheken aus dem gleichen Satz der Objektdateien erstellen. Wenn Sie viele Quelldateien haben, kann das Kompilieren der *.o Dateien ziemlich lange dauern; Mit Objektbibliotheken kompilieren Sie sie nur einmal.

Der Preis, den Sie zahlen, ist, dass die Objektdateien als positionsunabhängiger Code erstellt werden müssen, da gemeinsame Bibliotheken dies benötigen (statische Bibliotheken sind nicht wichtig). Beachten Sie, dass positionsunabhängiger Code möglicherweise weniger effizient ist. Wenn Sie also maximale Leistung anstreben, sollten Sie statische Bibliotheken verwenden. Außerdem ist es einfacher, statisch verknüpfte ausführbare Dateien zu verteilen.

+1

Wahr, normalerweise füge ich _shared und _static Suffixe hinzu. Beantwortete Antwort oben, danke für das Aufzeigen. Ich stimme auch zu, dass es eine Frage der persönlichen Präferenz ist. Für meine Anwendungsfälle funktionierte obj libs ziemlich gut, YMMV. –

+1

Das funktionierte wie ein Zauber für mich - der einzige Vorbehalt waren nachfolgende 'target_link_libraries()' Aufrufe, die von Ihrer Bibliothek abhängen, können nicht die "Objektbibliothek" verwenden, um dagegen zu verlinken; Diese müssen auf die neuen freigegebenen oder statischen Bibliotheken abzielen (und möglicherweise dupliziert werden). Aber im Gegensatz zu den Erfahrungen der ersten Kommentatoren war dies sehr nützlich und erlaubte mir, alle duplizierten Ziele zu entfernen und alle meine 'CMakeLists.txt' Dateien um fast die Hälfte zu schneiden. – fish2000

+1

Müssen Sie das Obblib beim Festlegen der Zieleigenschaften "flüchten"? d. h. set_property (TARGET $ {objlib} PROPERTY ...) und set_property (TARGET objlib PROPERTY ...) – gnac

-1

Es ist in der Tat möglich.Als @Christopher Bruns in seiner Antwort sagte, müssen Sie zwei Versionen der Bibliothek hinzuzufügen:

set(libsrc source1.c source2.c source3.c) 
add_library(mylib-static STATIC ${libsrc}) 
add_library(mylib-shared SHARED ${libsrc}) 

Dann wird, wie here beschrieben, müssen Sie angeben, dass beide Ziele die gleichen Ausgabenamen verwenden sollten, und nicht gegenseitig überschreiben Dateien:

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) 

auf diese Weise werden Sie sowohl libmylib.a und libmylib.so (unter Linux) oder mylib.lib und MYLIB.DLL (unter Windows) erhalten.

+3

Dies ist unnötig, wenn CMake-Versionen über 2.8. [0?] Verwendet werden, da die Eigenschaft 2009 entfernt wurde und das von ihr bereitgestellte Verhalten jetzt der Standardwert ist. Dies kann nützlich sein für Leute unter 2.8, aber wenn du CMake <2.7 verwendest, bitte ich dich um ein Upgrade. https://github.com/Kitware/CMake/commit/430cc2b4b7a817be2fbc445d6803163f1695a533 – KymikoLoco