2015-07-19 2 views
3

Я портирую проект AutoTools на CMake.CMake ссылка на общую библиотеку на статические библиотеки

Что Autotools делает:

  • создает некоторые статические библиотеки
  • сборках некоторые общие библиотеки и ссылки статическими в общий
  • создает исполняемый файл, связывает его с разделяемыми библиотеками

Что Мне удалось сделать с CMake:

  • построить некоторые статические библиотеки - add_library(staticfoo <src>)
  • сборки некоторые разделяемые библиотеки - add_library(sharedfoo SHARED <src>) и связать их - target_link_libraries(sharedfoo staticfoo)
  • построить исполняемый файл, связать его с разделяемыми библиотеками - target_link_libraries(exe sharedfoo), но тащили статические библиотеки снова, тоже.

Таким образом, результирующая ссылка для исполняемого файла имеет статические библиотеки в дополнение к общим. Это не соответствует команде, созданной проектом AutoTools.

Я пробовал target_link_libraries(sharedfoo PRIVATE staticfoo), но это не получает символы из статического lib в интерфейс общей библиотеки.

Как получить символы без этого «переходного» поведения?

(в платформо-независимом способе)

ответ

3

Как я знаю, CMake не позволяет смешивать статические и разделяемые библиотеки.

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

add_library(staticfoo OBJECT <src>) 

и использовать затем в качестве своего рода источников, когда строить другие библиотеки:

add_library(sharedfoo SHARED <src> $<TARGET_OBJECTS:staticfoo>) 

Для получения дополнительной информации см. documentation on add_library.

+0

CMake не волнует, какие библиотеки вы пытались связать со статическими/динамическими/смешанными ... это будет проблемой компоновщика на конкретной платформе. – zaufi

+0

В окнах компоновщик удаляет символы экспорта, связывая архивные объекты/статические библиотеки, но распаковываются объекты. Это одна из основных причин, по которой библиотеки объектов были добавлены в cmake. – Youka

+0

Действительно, это хороший способ конвертировать этот шаблон в проекты autotools. Для альтернатив и их проблем см. Этот подробный вопрос: http://stackoverflow.com/questions/5136184/linking-windows-dll-files-from-static-libraries-using-cmake-without-hand-craftin –

2

Чтобы решить этот случай вам нужно сделать несколько вещей:

  • первую очередь убедитесь, что вы скомпилированные статические библиотеки ж/-fPIC, так что они будут содержать перемещаемый код (который будет частью из общей библиотеки позже)
  • тогда вам необходимо контролировать видимость символов при компиляции всех библиотек, поэтому, будучи частью общей библиотеки, символы, полученные из статического, будут видны
  • и, наконец, да, вам нужно укажите PRIVATE <static libs> при связывании вашей общей библиотеки, поэтому в командной строке компоновщика для вашего execu таблица не будет иметь никакого статического LIBS
+0

Итак, как «контролировать видимость символов»? – Velkan

+0

Наиболее очевидным способом является использование опции '-fvisibility' [компилятор] (https://gcc.gnu.org/wiki/Visibility). CMake> = 3.x имеет ['CMAKE_ _VISIBILITY_PRESET'] (http://www.cmake.org/cmake/help/v3.0/variable/CMAKE_LANG_VISIBILITY_PRESET.html) переменную (и соответствующее [целевое свойство] (http: //www.cmake.org/cmake/help/v3.0/prop_tgt/LANG_VISIBILITY_PRESET.html)). Но, к сожалению, это не влияет на статические библиотеки. Это недостаток и будет зафиксирован в предстоящем выпуске [CMake 3.3] (http://www.kitware.com/blog/home/post/934). – zaufi

1

Я создал небольшой пример, который делает это правильный путь, здесь: https://github.com/CarloWood/cmaketest

Он показывает, как два «статическая» библиотека, один с двумя видимыми символами, как с по умолчанию скрытые символы, добавляются в общую библиотеку, которая затем используется для связывания исполняемого файла.

Используется метод @ Цыварев в сочетании с целевым свойством VISIBILITY, упомянутым @Zaufi.

Единственная неплатформная вещь (я думаю) - это макрос __EXPORT, который используется. Было бы неплохо исправить это, если кто-то знает, как это сделать.

0

См. Мой ответ here. В основном добавьте /WHOLEARCHIVE, -all_load, или --whole-archive к флагам компоновщика.

Смежные вопросы