Можно ли заставить CMake собрать как статическую, так и совместно используемую версию одной и той же библиотеки? - PullRequest
121 голосов
/ 28 января 2010

Тот же источник, все это, просто хочу статическую и совместно используемую версию. Легко сделать?

Ответы [ 4 ]

113 голосов
/ 28 января 2010

Да, это в меру легко. Просто используйте две команды add_library:

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

Даже если у вас много исходных файлов, вы бы поместили список источников в переменную cmake, так что это все еще легко сделать.

В Windows вы, вероятно, должны дать каждой библиотеке свое имя, так как существует файл ".lib" для общих и статических файлов. Но в Linux и Mac вы можете даже дать обеим библиотекам одинаковые имена (например, libMyLib.a и libMyLib.so):

set_target_properties(MyLibStatic PROPERTIES OUTPUT_NAME MyLib)

Но я не рекомендую давать статической и динамической версиям библиотеки одно и то же имя. Я предпочитаю использовать разные имена, потому что это облегчает выбор статической и динамической связи в строке компиляции для инструментов, которые ссылаются на библиотеку. Обычно я выбираю такие имена, как libMyLib.so (общая) и libMyLib_static.a (статическая). (Это будут имена в Linux.)

72 голосов
/ 23 апреля 2015

Начиная с CMake версии 2.8.8, вы можете использовать «библиотеки объектов» , чтобы избежать дублирования компиляции объектных файлов . Используя пример библиотеки Кристофера Брунса с двумя исходными файлами:

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

Из CMake документов :

Библиотека объектов компилирует исходные файлы, но не архивирует и не связывает их объектные файлы в библиотеку. Вместо других целей, созданных add_library() или add_executable() могут ссылаться на объекты, используя выражение вида $<TARGET_OBJECTS:objlib> как источника, где objlib - это имя библиотеки объектов.

Проще говоря, команда add_library(objlib OBJECT ${libsrc}) указывает CMake скомпилировать исходные файлы в *.o объектные файлы. Эта коллекция файлов *.o затем упоминается как $<TARGET_OBJECT:objlib> в двух командах add_library(...), которые вызывают соответствующие команды создания библиотеки, которые создают общие и статические библиотеки из одного и того же набора объектных файлов. Если у вас много исходных файлов, то компиляция файлов *.o может занять довольно много времени; с помощью библиотек объектов вы компилируете их только один раз.

Цена, которую вы платите, состоит в том, что объектные файлы должны создаваться как позиционно-независимый код, потому что это требуется для разделяемых библиотек (статические библиотеки не заботятся). Обратите внимание, что позиционно-независимый код может быть менее эффективен, поэтому, если вы стремитесь к максимальной производительности, вам следует использовать статические библиотеки. Кроме того, легче распространять статически связанные исполняемые файлы.

23 голосов
/ 31 августа 2013

Обычно нет необходимости дублировать вызовы ADD_LIBRARY для ваших целей. Просто используйте

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

при первом построении (в одном каталоге вне источника) с -DBUILD_SHARED_LIBS: BOOL = ON и с OFF в другом

0 голосов
/ 11 января 2017

Это действительно возможно.Как сказал @Christopher Bruns в своем ответе, вам необходимо добавить две версии библиотеки:

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

Затем, как описано здесь , необходимо указать, что обе цели должны использоватьто же имя и не перезаписывать файлы друг друга:

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)

Таким образом, вы получите и libmylib.a и libmylib.so (в Linux), или mylib.lib и mylib.dll (в Windows).

...