Тот же источник, все это, просто хочет статическую и общую версию. Легко сделать?
Можно ли заставить CMake создавать статическую и общую версию одной и той же библиотеки?
Ответ 1
Да, это в меру легко. Просто используйте две команды 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.)
Ответ 2
Начиная с 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
может занять довольно много времени; с помощью библиотек объектов вы компилируете их только один раз.
Цена, которую вы платите, состоит в том, что объектные файлы должны создаваться как независимый от позиции код, потому что это требуется для разделяемых библиотек (статические библиотеки не заботятся). Обратите внимание, что позиционно-независимый код может быть менее эффективен, поэтому, если вы стремитесь к максимальной производительности, вам следует использовать статические библиотеки. Кроме того, легче распространять статически связанные исполняемые файлы.
Ответ 3
Как правило, нет необходимости дублировать вызовы 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 и с выключенным в другом
Ответ 4
Это действительно возможно. Как сказал в своем ответе @Кристофер Брунс, вам нужно добавить две версии библиотеки:
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).