Использование protobuf с различными конфигурациями сборки CMake (RelWithDebugInfo и Debug) - PullRequest
0 голосов
/ 20 марта 2019

В моем проекте я использую protobuf 3.5. Мне нужны как минимум конфигурации отладки и RelWithDebugInfo. Чтобы иметь возможность собрать проект с отладочными библиотеками protobuf, возникли некоторые проблемы:

Мне нужно было собрать библиотеки protobuf из исходного кода, используя как релиз, так и цель отладки, поскольку _ITERATOR_DEBUG_LEVEL моих библиотек (= 2) не соответствовали уровню библиотек protobuf (= 0). После сборки библиотек отладки, а также библиотек релизов, возможна компиляция в конфигурации отладки.

Теперь, после возврата на RelWithDebugInfo я снова получаю ту же ошибку, но теперь как раз наоборот: _ITERATOR_DEBUG_LEVEL моих библиотек - 0, а уровень используемых библиотек protobuf - 2.

При проверке конфигурации компоновщика я вижу, что мои библиотеки связаны с libprotobuf d .lib. Это имеет смысл, поскольку я где-то читал, что все, что является , а не Release, будет использовать библиотеки отладки, если они доступны. И это приводит к моей проблеме:

Я не буду строить свои библиотеки в Release во время разработки. Большую часть времени RelWithDebugInfo. Но _ITERATOR_DEBUG_LEVEL для этой конфигурации, очевидно, установлено на 0 (поскольку является конфигурацией выпуска с дополнительной информацией). Но затем CMake связывается с библиотеками отладки protobuf, которые не совместимы с остальными.

Сейчас я ищу возможность сказать CMake не использовать отладочную версию библиотек, а версию выпуска вместо без изменения сценариев CMake самого protobuf .

Обычно мой путь - связывать различные библиотеки в зависимости от фактической конфигурации сборки. Но, к сожалению, конфигурация protobuf CMake пытается справиться с этим сама.

# Load information for each installed configuration.
get_filename_component(_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
file(GLOB CONFIG_FILES "${_DIR}/protobuf-targets-*.cmake")
foreach(f ${CONFIG_FILES})
  include(${f})
endforeach()

, в то время как импортируемая цель перезаписывается выбирается в зависимости от фактической конфигурации:

Protobuf-мишени-release.cmake:

# Import target "protobuf::libprotobuf-lite" for configuration "Release"
set_property(TARGET protobuf::libprotobuf-lite APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE)
set_target_properties(protobuf::libprotobuf-lite PROPERTIES
  IMPORTED_LINK_INTERFACE_LANGUAGES_RELEASE "CXX"
  IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/lib/libprotobuf-lite.lib"
  )

Protobuf-мишени-debug.cmake:

# Import target "protobuf::libprotobuf-lite" for configuration "Debug"
set_property(TARGET protobuf::libprotobuf-lite APPEND PROPERTY IMPORTED_CONFIGURATIONS DEBUG)
set_target_properties(protobuf::libprotobuf-lite PROPERTIES
  IMPORTED_LINK_INTERFACE_LANGUAGES_DEBUG "CXX"
  IMPORTED_LOCATION_DEBUG "${_IMPORT_PREFIX}/lib/libprotobuf-lited.lib"
  )

тогда как ссылки в моем CMakeLists.txt выглядят так:

target_link_libraries(${PROJECT_NAME} PRIVATE
    protobuf::libprotobuf
    protobuf::libprotoc
)

Я не вижу здесь никакой возможности указать нужную библиотеку. Обычно я бы сказал, что укажу это так:

target_link_libraries(MyEXE
    debug protobuf::libprotobufd optimized protobuf::libprotobuf
    debug protobuf::libprotocd optimized protobuf::libprotoc)

или оберните вокруг него какое-нибудь причудливое условие if для различных конфигураций сборки. Но из-за того, что protobuf эффективно перезаписывает цель, я не знаю, как извлечь правильную библиотеку для каждой сборки.

Есть идеи?

1 Ответ

1 голос
/ 20 марта 2019

Сейчас я ищу возможность сказать CMake не использовать отладочную версию библиотек, но вместо этого используется версия выпуска

Переменные CMAKE_MAP_IMPORTED_CONFIG_ предназначеныДля решения именно этой проблемы:

# When build your project in RelWithDebugInfo configuration,
# try to use Release configuration of the *IMPORTED* libraries.
# If some IMPORTED library has no Release configuration, fallback to Debug one.
set(CMAKE_MAP_IMPORTED_CONFIG_RELWITHDEBUGINFO Release Debug)

# Imported targets set with given call will be aware of the variable's set above
find_package(Protobuf REQUIRED)

# Simply link with an IMPORTED library. 
target_link_libraries(MyExe protobuf::libprotobuf)

Если вы хотите использовать конфигурацию выпуска только из определенных ИМПОРТИРОВАННЫХ библиотек, но не все, вы можете установить соответствующие свойства для этих конкретных библиотек:

# Firstly, create needed IMPORTED target.
find_package(Protobuf REQUIRED)

# Then adjust its properties.
# While the target is created by others, given property is specifically
# designed to be set in *your project*.
set_property(TARGET protobuf::libprotobuf PROPERTY MAP_IMPORTED_CONFIG_RELWITHDEBUGINFO Release Debug)

# Simply link with an IMPORTED library. 
target_link_libraries(MyExe protobuf::libprotobuf)
...