#cmake
Вопрос:
Не удалось настроить следующий проект повторного создания. Цель состоит в том, чтобы создать общую библиотеку, которая внутренне состоит из пары статических библиотек. Я хочу, чтобы внутренние символы, включая пути и т. Д., Были экспортированы из общей библиотеки. Для этого я делаю внутренние библиотеки ОБЩЕДОСТУПНЫМИ библиотеками ссылок. Но затем cmake говорит мне, что мне нужно экспортировать свою цель. Я не хочу «загрязнять» конфигурацию моего пакета кучей внутренних целей. Нет ли способа «объединить» внутренние целевые объекты (статические библиотеки) в общедоступную экспортируемую целевую (общую библиотеку) или скрыть ее в файле целевых объектов конфигурации?
Импортированный целевой объект SystemC::systemc не отображается в моем целевом файле и также не создает никаких ошибок. Я предполагаю, что это связано с тем, что этот целевой объект уже экспортирован в своем собственном пакете? Если да, значит ли это, что мне нужно создать свои внутренние пакеты библиотек и таким образом импортировать целевые объекты, чтобы они исчезли из моего списка экспортированных целевых объектов?
cmake_minimum_required(VERSION 3.16)
project(mylib)
find_package(SystemCLanguage 2.3.3 CONFIG REQUIRED)
add_library(mysublib STATIC mysublib.cpp)
add_library(mylib SHARED mylib.cpp)
target_link_libraries(mylib
PUBLIC SystemC::systemc
PUBLIC mysublib
)
export(
TARGETS mylib
NAMESPACE MyLib::
FILE MyLibTargets.cmake
)
Ошибка, сгенерированная при настройке
CMake Error in CMakeLists.txt:
export called with target "mylib" which requires target "mysublib" that is
not in any export set.
Ответ №1:
Цель состоит в том, чтобы создать общую библиотеку, которая внутренне состоит из пары статических библиотек. Я хочу, чтобы внутренние символы, включая пути и т. Д., Были экспортированы из общей библиотеки. Для этого я делаю внутренние библиотеки ОБЩЕДОСТУПНЫМИ библиотеками ссылок.
Итак, во-первых, я отмечу, что PUBLIC
это не имеет никакого отношения к видимости символов. В вашем примере mysublib
нет никаких INTERFACE
свойств, поэтому вы могли бы сделать это PRIVATE
mylib
и избежать необходимости экспорта mysublib
.
Однако, если вам действительно нужно mysublib
в INTERFACE
оф mylib
, то вам действительно нужно его экспортировать, и точка. Как вы говорите, невозможно «объединить» внутренние целевые объекты […] в общедоступную экспортируемую цель […] или скрыть ее в файле целевых объектов конфигурации». Но это тоже не настоящая проблема.
Если вы беспокоитесь о людях , на которых полагаетесь mysublib
, то вы можете установить EXPORT_NAME
свойству of mysublib
значение, указывающее, что оно не предназначено для использования, например _private_mysublib
:
set_target_properties(mysublib PROPERTIES EXPORT_NAME _private_mysublib)
Если вы хотите быть действительно агрессивным по этому поводу, вы можете даже сделать имя случайным:
string(RANDOM LENGTH 12 mysublib_export)
set_target_properties(mysublib PROPERTIES EXPORT_NAME "x${mysublib_export}")
Добавление an x
гарантирует, что оно не начинается с числа. Существует также небольшая вероятность столкновения, если вы будете делать это часто. Если вы хотите быть в абсолютной безопасности, вам следует написать функцию, которая записывает имена, которые она уже вернула, в глобальное свойство и повторяет попытку, если она выберет столкновение.
Импортированный целевой объект SystemC::systemc не отображается в моем целевом файле и также не создает никаких ошибок. Я предполагаю, что это связано с тем, что этот целевой объект уже экспортирован в своем собственном пакете? Если да, значит ли это, что мне нужно создать свои внутренние пакеты библиотек и таким образом импортировать целевые объекты, чтобы они исчезли из моего списка экспортированных целевых объектов?
Вы правы: поскольку SystemC::systemc
он импортирован, его не нужно (и фактически не может быть) реэкспортировать. Ожидается, что вы вызовете find_dependency(SystemCLanguage 2.3.3)
свой MyLibConfig.cmake
файл как в дереве сборки ( export
), так и после установки ( install(EXPORT)
).
Если вы хотите , чтобы это поведение применялось mysublib
, тогда да, вам нужно будет разделить свои проекты на части. Однако я не вижу веской причины для этого. Либо сделайте mysublib
PRIVATE
, либо просто смиритесь с тем, что он будет переименован в вашей конфигурации пакета. Цели не являются драгоценными, и они расположены в пространстве имен, так что нет никаких реальных причин для беспокойства.
Комментарии:
1. Я привык делать файлы более прямыми, делай это, получай то. Я предполагаю, что cmake попытается доказать это в будущем, если я, например, изменю mysublib для СОВМЕСТНОГО ИСПОЛЬЗОВАНИЯ. Теперь мне просто нужно выяснить, как получить зависимости (dll) в целевую папку сборки (exe), чтобы ctest мог запускать созданные целевые объекты…
2. Попробуй
CMAKE_RUNTIME_OUTPUT_DIRECTORY