myx/MyxCMake/lib/AddLibrary.cmake
2022-10-06 11:10:43 +03:00

228 lines
9.3 KiB
CMake
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#[=======================================================================[.rst:
myx_add_library
---------------
Вспомогательная функция для создания библиотеки::
myx_add_library(NAME TYPE
[ OUTPUT_NAME output_name ] |
[ EXPORT_FILE_NAME file_name ] |
[ EXPORT_BASE_NAME base_name ])
Обязательные параметры: `NAME` - имя библиотеки и `TYPE` - тип цели.
Параметр `OUTPUT_NAME` определяет базовое имя выходных файлов.
Параметр `EXPORT_FILE_NAME` задаёт имя заголовочного файла экспортируемых
переменных, а `EXPORT_BASE_NAME` - базовый суффикс для формирования имён переменных.
Все остальные параметры передаются в стандартную функцию `add_library()`
#]=======================================================================]
include_guard(GLOBAL)
include(CMakePackageConfigHelpers)
include(GenerateExportHeader)
if(${CMAKE_VERSION} VERSION_LESS "3.17.0")
set(MYX_CMAKE_LIB_DIR_BACKPORT "${CMAKE_CURRENT_LIST_DIR}")
endif()
function(myx_add_library NAME TYPE)
if(${CMAKE_VERSION} VERSION_LESS "3.17.0")
set(CMAKE_CURRENT_FUNCTION_LIST_DIR ${MYX_CMAKE_LIB_DIR_BACKPORT})
endif()
set(options)
set(oneValueArgs OUTPUT_NAME EXPORT_FILE_NAME EXPORT_BASE_NAME)
set(multiValueArgs)
cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
if(NOT ARG_OUTPUT_NAME)
set(ARG_OUTPUT_NAME ${NAME})
endif()
# Вызов стандартной функции `add_library()`
add_library(${NAME} ${TYPE} ${ARG_UNPARSED_ARGUMENTS})
if(TYPE STREQUAL "INTERFACE")
# Библиотека, состоящая только из заголовочных файлов не требует сборки.
# Стандартные пути к заголовочным файлам
target_include_directories(${NAME}
INTERFACE
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)
else()
string(TOUPPER ${NAME} PROJECT_NAME_UPPER)
# Опция для разрешения сборки динамической библиотеки
cmake_dependent_option(${PROJECT_NAME_UPPER}_BUILD_SHARED
"Build shared library for ${NAME}" ON "BUILD_SHARED_LIBS" OFF)
# Опция для разрешения сборки статической библиотеки
cmake_dependent_option(${PROJECT_NAME_UPPER}_BUILD_STATIC
"Build static library for ${NAME}" ON "NOT BUILD_SHARED_LIBS" OFF)
# Стандартные пути к заголовочным файлам
target_include_directories(${NAME}
PUBLIC
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
PRIVATE
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/src>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)
# Сборка позиционно-независимых объектных файлов нужна
# для создания динамической библиотеки
set_target_properties(${NAME} PROPERTIES POSITION_INDEPENDENT_CODE ON)
if(NOT EXPORT_BASE_NAME)
string(TOUPPER ${NAME} ARG_EXPORT_BASE_NAME)
endif()
if(NOT ARG_EXPORT_FILE_NAME)
set(ARG_EXPORT_FILE_NAME "${PROJECT_SOURCE_DIR}/include/${NAME}/${NAME}_export.hpp")
endif()
generate_export_header(${NAME}
BASE_NAME ${ARG_EXPORT_BASE_NAME}
EXPORT_MACRO_NAME "EXPORT_${ARG_EXPORT_BASE_NAME}"
DEPRECATED_MACRO_NAME "DEPRECATED_${ARG_EXPORT_BASE_NAME}"
NO_DEPRECATED_MACRO_NAME "NO_DEPRECATED_${ARG_EXPORT_BASE_NAME}"
NO_EXPORT_MACRO_NAME "NO_EXPORT_${ARG_EXPORT_BASE_NAME}"
STATIC_DEFINE "STATIC_DEFINE_${ARG_EXPORT_BASE_NAME}"
EXPORT_FILE_NAME ${ARG_EXPORT_FILE_NAME}
DEFINE_NO_DEPRECATED
)
set_property(TARGET ${NAME} APPEND PROPERTY INTERFACE_HEADER_FILES "${ARG_EXPORT_FILE_NAME}")
# Цель для создания динамической библиотеки из объектных файлов
if(${PROJECT_NAME_UPPER}_BUILD_SHARED)
# Для создания динамической библиотеки используются объектные файлы цели ${NAME}
add_library(${NAME}_shared SHARED $<TARGET_OBJECTS:${NAME}>)
# Установка дополнительных свойств для цели ${NAME}_shared
# VERSION: версия библиотеки
# SOVERSION: мажорная версия библиотеки
# LIBRARY_OUTPUT_DIRECTORY: каталог для записи результатов сборки
# OUTPUT_NAME: базовое имя выходного файла (без учёта расширения)
set_target_properties(${NAME}_shared
PROPERTIES
VERSION ${PROJECT_VERSION}
SOVERSION ${PROJECT_VERSION_MAJOR}
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}
OUTPUT_NAME ${ARG_OUTPUT_NAME})
endif()
# Цель для создания статической библиотеки из объектных файлов
if(${PROJECT_NAME_UPPER}_BUILD_STATIC)
# Для создания статической библиотеки используются объектные файлы цели ${NAME}
add_library(${NAME}_static STATIC $<TARGET_OBJECTS:${NAME}>)
# Установка дополнительных свойств для цели ${NAME}_static
# ARCHIVE_OUTPUT_DIRECTORY: каталог для записи результатов сборки
# OUTPUT_NAME: базовое имя выходного файла (без учёта расширения)
set_target_properties(${NAME}_static
PROPERTIES
ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}
OUTPUT_NAME ${ARG_OUTPUT_NAME})
endif()
endif()
# Если вызов был выполнен не из проекта верхнего уровня,
# то созданная цель исключается из цели `all`.
# При этом сама цель `${NAME}` может участвовать в сборке,
# если окажется в перечне зависимостей.
if(NOT PROJECT_IS_TOP_LEVEL)
set_target_properties(${NAME} PROPERTIES EXCLUDE_FROM_ALL True)
return()
endif()
# Правила для установки библиотек и относящихся к ним файлов.
# Если вызов был выполнен не из проекта верхнего уровня,
# то эти правила не обрабатываются.
write_basic_package_version_file(
${CMAKE_CURRENT_BINARY_DIR}/${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}/${NAME}Config.cmake
INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${NAME}
NO_SET_AND_CHECK_MACRO
NO_CHECK_REQUIRED_COMPONENTS_MACRO
)
install(EXPORT ${NAME}Targets
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${NAME}
COMPONENT dev
)
install(
FILES
${PROJECT_BINARY_DIR}/${NAME}ConfigVersion.cmake
${PROJECT_BINARY_DIR}/${NAME}Config.cmake
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${NAME}
COMPONENT dev
)
# Формирование файла для pkg-config
file(WRITE "${PROJECT_BINARY_DIR}/${NAME}.pc"
"prefix=${CMAKE_INSTALL_PREFIX}\n"
"exec_prefix=${CMAKE_INSTALL_PREFIX}\n"
"includedir=${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}\n")
if(NOT TYPE STREQUAL "INTERFACE")
file(APPEND "${PROJECT_BINARY_DIR}/${NAME}.pc"
"libdir=${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}\n")
endif()
file(APPEND "${PROJECT_BINARY_DIR}/${NAME}.pc"
"\n"
"Name: ${NAME}\n"
"Description: ${NAME} library\n"
"Version: ${PROJECT_VERSION}\n"
"\n"
"Requires:\n"
"Cflags: -I${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}\n")
if(NOT TYPE STREQUAL "INTERFACE")
file(APPEND "${PROJECT_BINARY_DIR}/${NAME}.pc"
"Libs: -L${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR} -l${NAME}\n")
endif()
# Установка файла для pkg-config
install(
FILES "${PROJECT_BINARY_DIR}/${NAME}.pc"
COMPONENT dev
DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
if(TYPE STREQUAL "OBJECT")
# Установка динамической библиотеки
if(TARGET ${NAME}_shared)
install(
TARGETS ${NAME}_shared
EXPORT ${NAME}Targets
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
COMPONENT lib
)
endif()
if(TARGET ${NAME}_static)
# Установка статической библиотеки
install(
TARGETS ${NAME}_static
EXPORT ${NAME}Targets
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
COMPONENT static
)
endif()
endif()
if(TYPE STREQUAL "INTERFACE")
# Установка библиотеки из заголовочных файлов
install(
TARGETS ${NAME}
EXPORT ${NAME}Targets
COMPONENT lib
)
endif()
endfunction()