Можно ли заставить CMake создавать как статическую, так и общую версию одной и той же библиотеки?
тот же источник, все это, просто хочу статическую и общую версию обоих. Легко сделать?
4 ответа:
Да, это в меру легко. Просто используйте две "команды add_library":
add_library(MyLib SHARED source1.c source2.c) add_library(MyLibStatic STATIC source1.c source2.c)
даже если у вас много исходных файлов, вы разместите список источников в переменной cmake, так что это все еще легко сделать.
в Windows вы, вероятно, должны дать каждой библиотеке другое имя, так как есть ".lib " файл для общего и статического. Но на Linux и Mac вы даже можете дать обеим библиотекам одно и то же имя (например, libMyLib.а и libMyLib.so):
set_target_properties(MyLibStatic PROPERTIES OUTPUT_NAME MyLib)
Но Я не рекомендуется давать статической и динамической версиям библиотеки одинаковое имя. Я предпочитаю использовать разные имена, потому что это упрощает выбор статической и динамической связи в строке компиляции для инструментов, которые ссылаются на библиотеку. Обычно я выбираю такие имена, как libMyLib.so (shared) и libMyLib_static.статика.) (Это были бы имена в linux.)
начиная с версии 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 docs:
библиотека объектов компилирует исходные файлы, но не архивирует и не связывает их их объектные файлы в библиотеку. Вместо этого другие цели, созданные add_library() или add_executable() может ссылаться на объекты, используя выражение вида $ как источник, где objlib-это имя библиотеки объектов.
проще говоря,
add_library(objlib OBJECT ${libsrc})
команда дает команду CMake скомпилировать исходные файлы в*.o
объектные файлы. Эта коллекция*.o
файлы называется$<TARGET_OBJECT:objlib>
в дваadd_library(...)
команды, вызывающие соответствующие команды создания библиотек, которые создают общие и статические библиотеки из тот же набор of объектный файл. Если у вас есть много исходных файлов, то компиляция*.o
файлы могут занимать довольно много времени; с библиотеками объектов вы компилируете их только один раз.цена, которую вы платите, заключается в том, что объектные файлы должны быть построены как независимый от позиции код, потому что общие библиотеки нуждаются в этом (статические библиотеки не заботятся). Обратите внимание, что позиционно-независимый код может быть менее эффективным, поэтому, если вы стремитесь к максимальной производительности, вы бы выбрали статические библиотеки. Кроме того, его легче распространять статически связанные исполняемые файлы.
обычно нет необходимости дублировать вызовы 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=ВКЛ и ВЫКЛ в другом
Это действительно возможно. Как сказал @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.а и libmylib.so (на Linux) или mylib.Либ и милиб.dll (на Windows).