#[=======================================================================[.rst: myx_add_interface_library ------------------------- Вспомогательная функция для создания интерфейсной библиотеки:: myx_add_interface_library(TARGET_NAME [ PACKAGES packages ] | [ LINK_LIBRARIES link_libraries ] | [ OUTPUT_NAME output_name ] | [ HEADERS headers ]) Обязательные параметры: `TARGET_NAME` - имя библиотеки. Параметр `OUTPUT_NAME` определяет базовое имя выходных файлов. Все остальные параметры передаются в стандартную функцию `add_library()` #]=======================================================================] include_guard(GLOBAL) include(CMakePackageConfigHelpers) if(${CMAKE_VERSION} VERSION_LESS 3.17) set(MYX_CMAKE_LIB_DIR_BACKPORT "${CMAKE_CURRENT_LIST_DIR}") endif() function(myx_add_interface_library TARGET_NAME) if(${CMAKE_VERSION} VERSION_LESS 3.17) set(CMAKE_CURRENT_FUNCTION_LIST_DIR ${MYX_CMAKE_LIB_DIR_BACKPORT}) endif() if(TARGET ${TARGET_NAME}) myx_message_fatal_error("Target ${TARGET_NAME} already exists") endif() set(options) set(oneValueArgs OUTPUT_NAME) set(multiValueArgs HEADERS LINK_LIBRARIES PACKAGES) cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) if(NOT ARG_OUTPUT_NAME) set(ARG_OUTPUT_NAME ${TARGET_NAME}) endif() # Вызов стандартной функции `add_library()` if(${CMAKE_VERSION} VERSION_LESS 3.19) add_library(${TARGET_NAME} INTERFACE) target_sources(${TARGET_NAME} INTERFACE $) else() add_library(${TARGET_NAME} INTERFACE ${ARG_HEADERS}) endif() foreach(iter ${ARG_PACKAGES}) target_include_directories(${TARGET_NAME} INTERFACE ${${iter}_INCLUDE_DIRS}) target_compile_definitions(${TARGET_NAME} INTERFACE ${${iter}_COMPILE_DEFINITIONS}) endforeach() if(ARG_LINK_LIBRARIES) foreach(lib ${ARG_LINK_LIBRARIES}) if(TARGET ${lib}) set(exlib ${lib}) get_target_property(type ${lib} TYPE) if(type) get_target_property(include_dirs ${lib} INTERFACE_INCLUDE_DIRECTORIES) if(include_dirs) target_include_directories(${TARGET_NAME} INTERFACE ${include_dirs}) endif() endif() if(${CMAKE_VERSION} VERSION_GREATER 3.13) install(TARGETS ${lib} EXPORT ${TARGET_NAME}Targets COMPONENT DEV) else() get_target_property(target_type ${lib} TYPE) if(target_type STREQUAL "OBJECT_LIBRARY") if(TARGET "${lib}_static") set(exlib "${lib}_static") elseif(TARGET "${lib}_shared") set(exlib "${lib}_shared") endif() endif() endif() target_link_libraries(${TARGET_NAME} INTERFACE ${exlib}) endif() endforeach() endif() # Библиотека, состоящая только из заголовочных файлов не требует сборки. # Стандартные пути к заголовочным файлам target_include_directories(${TARGET_NAME} INTERFACE $ $ ) # Если вызов был выполнен не из проекта верхнего уровня, # то созданная цель исключается из цели `all`. # При этом сама цель `${TARGET_NAME}` может участвовать в сборке, # если окажется в перечне зависимостей. if(NOT PROJECT_IS_TOP_LEVEL) if(${CMAKE_VERSION} VERSION_GREATER 3.17) set_target_properties(${TARGET_NAME} PROPERTIES EXCLUDE_FROM_ALL True) else() set_target_properties(${TARGET_NAME} PROPERTIES INTERFACE_EXCLUDE_FROM_ALL True) endif() return() endif() # Правила для установки библиотек и относящихся к ним файлов. # Если вызов был выполнен не из проекта верхнего уровня, # то эти правила не обрабатываются. write_basic_package_version_file( ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME}ConfigVersion.cmake VERSION ${PROJECT_VERSION} COMPATIBILITY AnyNewerVersion ) configure_package_config_file( ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/library-config.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME}Config.cmake INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${TARGET_NAME} NO_SET_AND_CHECK_MACRO NO_CHECK_REQUIRED_COMPONENTS_MACRO ) if(${CMAKE_VERSION} VERSION_GREATER 3.13) install( EXPORT ${TARGET_NAME}Targets DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${TARGET_NAME} COMPONENT DEV) endif() install( FILES ${PROJECT_BINARY_DIR}/${TARGET_NAME}ConfigVersion.cmake ${PROJECT_BINARY_DIR}/${TARGET_NAME}Config.cmake DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${TARGET_NAME} COMPONENT DEV) # Формирование файла для pkg-config file(WRITE "${PROJECT_BINARY_DIR}/${TARGET_NAME}.pc" "prefix=${CMAKE_INSTALL_PREFIX}\n" "exec_prefix=${CMAKE_INSTALL_PREFIX}\n" "includedir=${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}\n" "\n" "Name: ${TARGET_NAME}\n" "Description: ${TARGET_NAME} library\n" "Version: ${PROJECT_VERSION}\n" "\n" "Requires:\n" "Cflags: -I${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}\n") # Установка файла для pkg-config install( FILES "${PROJECT_BINARY_DIR}/${TARGET_NAME}.pc" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig" COMPONENT DEV) # Установка библиотеки из заголовочных файлов target_include_directories(${TARGET_NAME} SYSTEM INTERFACE $) if(${CMAKE_VERSION} VERSION_GREATER 3.13) install( TARGETS ${TARGET_NAME} EXPORT ${TARGET_NAME}Targets COMPONENT DEV) endif() # Установка публичных заголовочных файлов if(PROJECT_IS_TOP_LEVEL AND ARG_HEADERS) myx_install_relative(${PROJECT_SOURCE_DIR} FILES ${ARG_HEADERS} DESTINATION ${CMAKE_INSTALL_PREFIX} COMPONENT DEV) endif() endfunction()