diff --git a/MyxCMakeConfig.cmake b/MyxCMakeConfig.cmake index 8cfb635..ca3eaca 100644 --- a/MyxCMakeConfig.cmake +++ b/MyxCMakeConfig.cmake @@ -23,7 +23,6 @@ include(${MYX_CMAKE_LIB_DIR}/NinjaGeneratorWrapper.cmake) include(${MYX_CMAKE_LIB_DIR}/FetchContentAdd.cmake) include(${MYX_CMAKE_LIB_DIR}/AddLibrary.cmake) -include(${MYX_CMAKE_LIB_DIR}/InstallLibrary.cmake) include(${MYX_CMAKE_LIB_DIR}/TargetSetup.cmake) include(${MYX_CMAKE_LIB_DIR}/Qt5TargetSetup.cmake) diff --git a/MyxCMakeConfigVersion.cmake b/MyxCMakeConfigVersion.cmake index 3715903..0f92cff 100644 --- a/MyxCMakeConfigVersion.cmake +++ b/MyxCMakeConfigVersion.cmake @@ -1,4 +1,4 @@ -set(MYX_CMAKE_PACKAGE_VERSION "1.99.12") +set(MYX_CMAKE_PACKAGE_VERSION "1.99.20") if(MYX_CMAKE_PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION) set(PACKAGE_VERSION_COMPATIBLE FALSE) else() diff --git a/README.md b/README.md index c94c818..7bb413a 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ ```cmake if(MYX_CMAKE_USE_SYSTEM) - find_package(MyxCMake 1.99.12 REQUIRED) + find_package(MyxCMake 1.99.20 REQUIRED) else() include(${PROJECT_SOURCE_DIR}/cmake/myx/MyxCMakeConfig.cmake) endif() diff --git a/lib/AddLibrary.cmake b/lib/AddLibrary.cmake index 75b5ea8..4156041 100644 --- a/lib/AddLibrary.cmake +++ b/lib/AddLibrary.cmake @@ -13,6 +13,11 @@ myx_add_library include_guard(GLOBAL) +if(${CMAKE_VERSION} VERSION_LESS "3.17.0") + set(CMAKE_CURRENT_FUNCTION_LIST_DIR ${CMAKE_CURRENT_LIST_DIR}) +endif() + +include(CMakePackageConfigHelpers) include(GenerateExportHeader) function(myx_add_library NAME TYPE) @@ -25,17 +30,8 @@ function(myx_add_library NAME TYPE) # Вызов стандартной функции `add_library()` add_library(${NAME} ${TYPE} ${ARG_UNPARSED_ARGUMENTS}) - # Если вызов был выполнен не из проекта верхнего уровня, - # то созданная цель исключается из цели `all`. - # При этом сама цель `${NAME}` может участвовать в сборке, - # если окажется в перечне зависимостей. - if(NOT PROJECT_IS_TOP_LEVEL) - set_target_properties(${NAME} PROPERTIES - EXCLUDE_FROM_ALL True - ) - endif() - - if(TYPE STREQUAL INTERFACE) + if(TYPE STREQUAL "INTERFACE") + # Библиотека, состоящая только из заголовочных файлов не требует сборки. # Стандартные пути к заголовочным файлам target_include_directories(${NAME} INTERFACE @@ -44,10 +40,12 @@ function(myx_add_library NAME TYPE) ) else() string(TOUPPER ${NAME} PROJECT_NAME_UPPER) - # Опция для разрешения сборки разделяемой библиотеки - option(${PROJECT_NAME_UPPER}_BUILD_SHARED "Build shared library" ON) + # Опция для разрешения сборки динамической библиотеки + cmake_dependent_option(${PROJECT_NAME_UPPER}_BUILD_SHARED + "Build shared library for ${NAME}" ON "BUILD_SHARED_LIBS" OFF) # Опция для разрешения сборки статической библиотеки - option(${PROJECT_NAME_UPPER}_BUILD_STATIC "Build static library" ON) + cmake_dependent_option(${PROJECT_NAME_UPPER}_BUILD_STATIC + "Build static library for ${NAME}" ON "NOT BUILD_SHARED_LIBS" OFF) # Стандартные пути к заголовочным файлам target_include_directories(${NAME} @@ -58,6 +56,8 @@ function(myx_add_library NAME TYPE) $ ) + # Сборка позиционно-независимых объектных файлов нужна + # для создания динамической библиотеки set_target_properties(${NAME} PROPERTIES POSITION_INDEPENDENT_CODE ON) string(TOUPPER ${NAME} suffix) @@ -72,18 +72,20 @@ function(myx_add_library NAME TYPE) DEFINE_NO_DEPRECATED ) - # Цель для создания разделяемой библиотеки из объектных файлов + # Цель для создания динамической библиотеки из объектных файлов if(${PROJECT_NAME_UPPER}_BUILD_SHARED) - # Для создания разделяемой библиотеки используются объектные файлы цели ${NAME} + # Для создания динамической библиотеки используются объектные файлы цели ${NAME} add_library(${NAME}_shared SHARED $) # Установка дополнительных свойств для цели ${NAME}_shared - # OUTPUT_NAME: базовое имя выходного файла (без учёта расширения) # 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 ${NAME}) endif() @@ -92,10 +94,117 @@ function(myx_add_library NAME TYPE) # Для создания статической библиотеки используются объектные файлы цели ${NAME} add_library(${NAME}_static STATIC $) # Установка дополнительных свойств для цели ${NAME}_static + # ARCHIVE_OUTPUT_DIRECTORY: каталог для записи результатов сборки # OUTPUT_NAME: базовое имя выходного файла (без учёта расширения) set_target_properties(${NAME}_static PROPERTIES + ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR} OUTPUT_NAME ${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(DIRECTORY ${PROJECT_SOURCE_DIR}/include/ + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + COMPONENT dev + ) + + 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 "${CMAKE_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 "${CMAKE_BINARY_DIR}/${NAME}.pc" + "libdir=${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}\n") + endif() + + file(APPEND "${CMAKE_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 "${CMAKE_BINARY_DIR}/${NAME}.pc" + "Libs: -L${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR} -l${NAME}\n") + endif() + + install( + FILES "${CMAKE_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() diff --git a/lib/Includes.cmake b/lib/Includes.cmake index 8b54c46..788516e 100644 --- a/lib/Includes.cmake +++ b/lib/Includes.cmake @@ -2,3 +2,4 @@ include_guard(GLOBAL) include(FetchContent) include(GNUInstallDirs) +include(CMakeDependentOption) diff --git a/lib/InstallLibrary.cmake b/lib/InstallLibrary.cmake deleted file mode 100644 index 21296ed..0000000 --- a/lib/InstallLibrary.cmake +++ /dev/null @@ -1,75 +0,0 @@ -include_guard(GLOBAL) - -if(${CMAKE_VERSION} VERSION_LESS "3.17.0") - set(CMAKE_CURRENT_FUNCTION_LIST_DIR ${CMAKE_CURRENT_LIST_DIR}) -endif() - -include(CMakePackageConfigHelpers) - -function(myx_install_library NAME) - if(NOT PROJECT_IS_TOP_LEVEL) - return() - endif() - - get_target_property(type ${NAME} TYPE) - - 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}/InstallLibraryConfig.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(DIRECTORY ${PROJECT_SOURCE_DIR}/include/ - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} - COMPONENT dev - ) - - 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 - ) - - if(${type} STREQUAL "OBJECT_LIBRARY") - 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 lib - ) - endif() - endif() - - if(${type} STREQUAL "INTERFACE_LIBRARY") - install( - TARGETS ${NAME} - EXPORT ${NAME}Targets - COMPONENT lib - ) - endif() -endfunction() diff --git a/lib/Qt5TargetSetup.cmake b/lib/Qt5TargetSetup.cmake index 9cc53b6..6bfa4a2 100644 --- a/lib/Qt5TargetSetup.cmake +++ b/lib/Qt5TargetSetup.cmake @@ -5,7 +5,7 @@ function(myx_qt5_target_setup NAME) set(oneValueArgs) set(multiValueArgs COMPONENTS PRIVATE SOURCES MOC UI QRC LANGS) - cmake_parse_arguments(arg "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) get_target_property(type ${NAME} TYPE) @@ -13,7 +13,7 @@ function(myx_qt5_target_setup NAME) find_package(Qt5 COMPONENTS ${ARG_COMPONENTS} REQUIRED) foreach(iter ${ARG_COMPONENTS}) target_include_directories(${NAME} PRIVATE ${Qt5${iter}_INCLUDE_DIRS}) - if(type STREQUAL "EXECUTABLE") + if(type STREQUAL "EXECUTABLE" AND NOT iter STREQUAL "LinguistTools") target_link_libraries(${NAME} PRIVATE "Qt5::${iter}") endif() endforeach() @@ -36,18 +36,16 @@ function(myx_qt5_target_setup NAME) endif() if("LinguistTools" IN_LIST ARG_COMPONENTS) - set(ts) foreach(iter ${ARG_LANGS}) - list(APPEND ts ${PROJECT_SOURCE_DIR}/l10n/${NAME}_${iter}.ts) + qt5_create_translation(qm + "${PROJECT_SOURCE_DIR}/include" + "${PROJECT_SOURCE_DIR}/src" + "${PROJECT_SOURCE_DIR}/l10n/${NAME}_${iter}.ts") + target_sources(${NAME} PRIVATE ${qm}) endforeach() - - qt5_create_translation(qm - ${PROJECT_SOURCE_DIR}/include - ${PROJECT_SOURCE_DIR}/src - ${ts} - ) + unset(qm) endif() - target_sources(${NAME} PRIVATE ${ARG_SOURCES} ${ARG_MOC} ${moc_cpp} ${ui_h} ${qrc_cpp} ${qm}) + target_sources(${NAME} PRIVATE ${ARG_SOURCES} ${ARG_MOC} ${moc_cpp} ${ui_h} ${qrc_cpp}) endfunction() diff --git a/lib/InstallLibraryConfig.cmake.in b/lib/library-config.cmake.in similarity index 100% rename from lib/InstallLibraryConfig.cmake.in rename to lib/library-config.cmake.in