Один и тот же источник, все это, просто нужна как статическая, так и общая версия. Легко сделать?
Да, в меру легко. Просто используйте две команды 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.)
-fPIC
), что добавляет небольшие накладные расходы времени выполнения при использовании этих статических библиотек. Так что для максимальной производительности этот ответ по-прежнему лучший.Начиная с версии CMake 2.8.8, вы можете использовать «объектные библиотеки», чтобы избежать дублирования компиляции объектных файлов . Используя пример Кристофера Брунса библиотеки с двумя исходными файлами:
Из документов CMake :
Проще говоря,
add_library(objlib OBJECT ${libsrc})
команда инструктирует CMake скомпилировать исходные файлы в*.o
объектные файлы. Этот набор*.o
файлов затем упоминается как$<TARGET_OBJECT:objlib>
в двухadd_library(...)
командах, которые вызывают соответствующие команды создания библиотеки, которые строят общие и статические библиотеки из одного и того же набора объектных файлов. Если у вас много исходных файлов, то компиляция*.o
файлов может занять довольно много времени; с библиотеками объектов вы компилируете их только один раз.Цена, которую вы платите, состоит в том, что объектные файлы должны быть построены как позиционно-независимый код, потому что это необходимо разделяемым библиотекам (статические библиотеки не заботятся). Обратите внимание, что позиционно-независимый код может быть менее эффективным, поэтому, если вы стремитесь к максимальной производительности, вы должны использовать статические библиотеки. Кроме того, легче распространять статически связанные исполняемые файлы.
источник
target_link_libraries()
вызовы, которые зависят от вашей библиотеки, не могут использовать «библиотеку объектов» для компоновки; они должны быть нацелены на новые общие или статические библиотеки (и могут дублироваться). Но вопреки опыту первых комментаторов это было весьма полезно и позволило мне удалить все повторяющиеся цели и сократить все моиCMakeLists.txt
файлы почти наполовину.set_property
сработало только при использовании,objlib
а не при использовании${objlib}
. Так, может быть, этот ответ можно исправить?Как правило, нет необходимости дублировать
ADD_LIBRARY
звонки для ваших целей. Просто используйтепри сборке сначала (в одном каталоге вне исходного кода) с помощью
-DBUILD_SHARED_LIBS:BOOL=ON
, аOFF
в другом.источник
Можно упаковать все в одном дыхании компиляции, как предлагалось в предыдущих ответах, но я бы не советовал этого, потому что, в конце концов, это хак, который работает только для простых проектов. Например, в какой-то момент вам могут понадобиться разные флаги для разных версий библиотеки (особенно в Windows, где флаги обычно используются для переключения между экспортируемыми символами или нет). Или, как упоминалось выше, вы можете поместить
.lib
файлы в разные каталоги в зависимости от того, соответствуют ли они статическим или разделяемым библиотекам. Каждое из этих препятствий потребует нового взлома.Это может быть очевидным, но одна альтернатива, о которой ранее не упоминалось, - это сделать тип библиотеки параметром:
Наличие общих и статических версий библиотеки в двух разных двоичных деревьях упрощает обработку различных параметров компиляции. Я не вижу серьезных недостатков в разделении деревьев компиляции, особенно если ваши компиляции автоматизированы.
Обратите внимание, что даже если вы намереваетесь взаимно объединять компиляции с использованием промежуточной
OBJECT
библиотеки (с оговорками, упомянутыми выше, поэтому вам нужна веская причина для этого), вы все равно можете поместить конечные библиотеки в два разных проекта.источник
Это действительно возможно. Как сказал @Christopher Bruns в своем ответе, вам нужно добавить две версии библиотеки:
Затем, как описано здесь , вам необходимо указать, что обе цели должны использовать одно и то же имя вывода и не перезаписывать файлы друг друга:
Таким образом вы получите как libmylib.a, так и libmylib.so (в Linux) или mylib.lib и mylib.dll (в Windows).
источник