Ладно, разобрался: это намного больнее, чем должно быть. До недавнего времени люди в Kitware не понимали, зачем кому-то вообще захочется создавать DLL из статических библиотек. Их аргумент состоит в том, что всегда должны быть исходные файлы в основном (например, top_project в моем случае) каталоге, потому что это, по сути, собственный проект. Я вижу вещи по-другому, и мне нужно разбить top_project на более мелкие подпроекты, которые не должны существовать независимо (т.е. нет смысла создавать для них полноценный проект и добавлять их с помощью ExternalProject_Add). Кроме того, когда я отправляю свою общую библиотеку (для использования, например, с собственным интерфейсом Java), я не хочу отправлять десятки общих библиотек, потому что это будет означать раскрытие внутренней структуры моего проекта. В любом случае, как мне кажется, обосновав необходимость создания разделяемой библиотеки из статических библиотек, я перейду к техническим деталям.
В CMakeLists.txt для subproject1 и subproject2 вы должны создать свою цель с помощью функции библиотеки OBJECT (представленной в CMake 2.8.8):
add_library(${PROJECT_NAME} OBJECT ${SRC})
где SRC обозначает список исходных файлов (обратите внимание, что они должны быть явно установлены в файле CMakeLists.txt, поскольку он позволяет make повторно запустить CMake при обнаружении модификации CMakeLists.txt, например, при добавлении или удалении файла)
В top_project добавьте подпроекты, используя:
add_subdirectory(subproject1)
add_subdirectory(subproject2)
Чтобы увидеть символы из статической библиотеки, используйте:
set(CMAKE_SHARED_LINKER_FLAGS "-Wl,--export-all-symbols")
Затем вы можете создать общую библиотеку, используя:
add_library(${PROJECT_NAME} SHARED $<TARGET_OBJECTS:subproject1>
$<TARGET_OBJECTS:subproject2>)
Я обнаружил, что любую «обычную» библиотеку (т.е. не объект) нужно добавить в отдельную команду add_library, иначе она просто игнорируется.
Для исполняемых файлов вы можете использовать:
add_executable(name_of_executable $<TARGET_OBJECTS:subproject1>
$<TARGET_OBJECTS:subproject2>)
set(LINK_FLAGS ${LINK_FLAGS} "-Wl,-whole-archive")
target_link_libraries(name_of_executable ${PROJECT_NAME}
Я повторяю, что это работает только с версией CMake 2.8.8. Точно так же CMake очень хорошо управляет зависимостями и является кроссплатформенным, потому что это не намного менее болезненно, чем простые старые файлы Makefile, и, конечно, менее гибко.
person
Deimos
schedule
12.07.2012