From 5f47d6fa8e2ef9ee7ac0223bc60c680b141c95a0 Mon Sep 17 00:00:00 2001 From: Andrey Astafyev Date: Fri, 30 Sep 2022 10:23:30 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9D=D0=B0=D1=87=D0=B0=D0=BB=D0=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 254 ++++++++++ CMakeLists.txt | 27 + cmake/myx/MyxCMakeConfig.cmake | 34 ++ cmake/myx/MyxCMakeConfigVersion.cmake | 9 + cmake/myx/backports/FetchContent.cmake | 464 ++++++++++++++++++ .../FetchContent/CMakeLists.cmake.in | 28 ++ cmake/myx/backports/IncludeGuard.cmake | 12 + cmake/myx/backports/TopLevelProject.cmake | 10 + cmake/myx/config/Globals.cmake | 8 + cmake/myx/lib/AddLibrary.cmake | 77 +++ cmake/myx/lib/ColoredMessages.cmake | 43 ++ cmake/myx/lib/DirectoriesGuards.cmake | 50 ++ cmake/myx/lib/InstallLibrary.cmake | 65 +++ cmake/myx/lib/InstallLibraryConfig.cmake.in | 5 + cmake/myx/lib/NinjaGeneratorWarning.cmake | 8 + cmake/myx/lib/NinjaGeneratorWrapper.cmake | 11 + cmake/myx/lib/Qt5TargetSetup.cmake | 42 ++ cmake/myx/lib/SemanticProjectVersion.cmake | 17 + cmake/myx/lib/TargetSetup.cmake | 28 ++ include/pow/pow.hpp | 10 + 20 files changed, 1202 insertions(+) create mode 100644 .gitignore create mode 100644 CMakeLists.txt create mode 100644 cmake/myx/MyxCMakeConfig.cmake create mode 100644 cmake/myx/MyxCMakeConfigVersion.cmake create mode 100644 cmake/myx/backports/FetchContent.cmake create mode 100644 cmake/myx/backports/FetchContent/CMakeLists.cmake.in create mode 100644 cmake/myx/backports/IncludeGuard.cmake create mode 100644 cmake/myx/backports/TopLevelProject.cmake create mode 100644 cmake/myx/config/Globals.cmake create mode 100644 cmake/myx/lib/AddLibrary.cmake create mode 100644 cmake/myx/lib/ColoredMessages.cmake create mode 100644 cmake/myx/lib/DirectoriesGuards.cmake create mode 100644 cmake/myx/lib/InstallLibrary.cmake create mode 100644 cmake/myx/lib/InstallLibraryConfig.cmake.in create mode 100644 cmake/myx/lib/NinjaGeneratorWarning.cmake create mode 100644 cmake/myx/lib/NinjaGeneratorWrapper.cmake create mode 100644 cmake/myx/lib/Qt5TargetSetup.cmake create mode 100644 cmake/myx/lib/SemanticProjectVersion.cmake create mode 100644 cmake/myx/lib/TargetSetup.cmake create mode 100644 include/pow/pow.hpp diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1e50ba1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,254 @@ +# Каталог для результатов сборки проекта +_build +build + +# Каталог для тестирования установки +_output + +# Файлы настроек, редактируемые во время отладки, +# за исключением шаблонных файлов +files/etc/*.conf +!files/etc/*.example.conf +files/etc/*.ini +!files/etc/*.example.ini +files/etc/*.yml +!files/etc/*.example.yml + +# Каталоги, в которые разрешена запись данных во время работы программы +files/var/* +files/lib/* +files/log/* + +!.gitkeep +!.gitignore + +### +### Общие настройки для C, C++, Fortran, Qt, CMake, Ninja, LaTeX и редакторов +### + +### +### Временные файлы текстовых редакторов +### +*.bak +*.gho +*.tmp +*.dotdropbak + +### +### LyX +### +*.lyx~ +*.lyx# + +### +### Vim +### +# Swap +[._]*.s[a-v][a-z] +!*.svg # comment out if you don't need vector files +[._]*.sw[a-p] +[._]s[a-rt-v][a-z] +[._]ss[a-gi-z] +[._]sw[a-p] + +# Project +.vimprj +# Temporary +.netrwhist +*~ +# Auto-generated tag files +tags +# Persistent undo +[._]*.un~ + + +### +### C++ +### + +# +export_autogen.hpp + +# Prerequisites +*.d + +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries +*.so +*.so.* +*.dylib +*.dll + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app + + +### +### CMake +### +CMakeLists.txt.user* +CMakeCache.txt +CMakeFiles +CMakeScripts +Testing +Makefile +cmake_install.cmake +install_manifest.txt +compile_commands.json +CTestTestfile.cmake +_deps +.cmake + +### CMake Patch ### +# External projects +*-prefix/ + + +### +### Ninja +### +.ninja_deps +.ninja_log + + +### +### GCC coverage testing tool files +### +*.gcno +*.gcda +*.gcov + + +### +### Qt +### +object_script.*.Release +object_script.*.Debug +*_plugin_import.cpp +/.qmake.cache +/.qmake.stash +*.pro.user +*.pro.user.* +*.qbs.user +*.qbs.user.* +*.moc +moc_*.cpp +moc_*.h +qrc_*.cpp +ui_*.h +*.qmlc +*.jsc +Makefile* +*build-* +*.qm +*.prl + +# Qt unit tests +target_wrapper.* + +# QtCreator +*.autosave + +# QtCreator Qml +*.qmlproject.user +*.qmlproject.user.* + +# QtCreator local machine specific files for imported projects +*creator.user* + +*_qmlcache.qrc + + +### KDevelop4 ### +*.kdev4 +.kdev4/ + + +### vscode ### +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +*.code-workspace + +### IDEA ### +.idea + +### Eclipse ### +.metadata +.settings/ +.recommenders/ + +# TeXlipse +.texlipse + +# PyDev specific (Python IDE for Eclipse) +*.pydevproject + +# CDT-specific (C/C++ Development Tooling) +.cproject + +# CDT- autotools +.autotools + + +### +### Latex +### +*.acn +*.acr +*.alg +*.aux +*.bbl +*.blg +*.dvi +*.fdb_latexmk +*.fls +*.glg +*.glo +*.gls +*.idx +*.ilg +*.ind +*.ist +*.lof +*.log +*.lot +*.maf +*.mtc +*.mtc0 +*.nav +*.nlo +*.out +*.pdfsync +*.ps +*.snm +*.synctex.gz +*.toc +*.vrb +*.xdv +*.xdy +*.tdo + diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..2885576 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,27 @@ +# Минимальная версия CMake, требуемая для сборки проекта +cmake_minimum_required(VERSION 3.6 FATAL_ERROR) + +# Предпочтительно следовать стандартам принятым в указанном диапазоне версий +cmake_policy(VERSION 3.6..3.7) + +# Название и версия проекта и используемые языки программирования +project(pow VERSION 1.1.1 LANGUAGES CXX) + +### +# Подключение дополнительных функций для CMake +### +find_package(MyxCMake 1.99.9 PATHS ${PROJECT_SOURCE_DIR}/cmake/myx NO_DEFAULT_PATH QUIET REQUIRED) + +# Цель для создания библиотеки, состоящей из заголовочных файлов +myx_pow_library(${PROJECT_NAME} + TYPE INTERFACE +) + +myx_target_setup(${PROJECT_NAME} + SOURCES + ${PROJECT_SOURCE_DIR}/include/pow/pow.hpp +) + +if(PROJECT_IS_TOP_LEVEL) + myx_install_library(${PROJECT_NAME}) +endif() diff --git a/cmake/myx/MyxCMakeConfig.cmake b/cmake/myx/MyxCMakeConfig.cmake new file mode 100644 index 0000000..5bb204f --- /dev/null +++ b/cmake/myx/MyxCMakeConfig.cmake @@ -0,0 +1,34 @@ +cmake_policy(PUSH) +cmake_policy(SET CMP0057 NEW) # IN_LIST operator + +get_filename_component(MYX_CMAKE_SOURCE_DIR "${CMAKE_CURRENT_LIST_FILE}" DIRECTORY) + +set(MYX_CMAKE_CONFIG_DIR "${MYX_CMAKE_SOURCE_DIR}/config") +set(MYX_CMAKE_BACKPORTS_DIR "${MYX_CMAKE_SOURCE_DIR}/backports") +set(MYX_CMAKE_LIB_DIR "${MYX_CMAKE_SOURCE_DIR}/lib") + +include(${MYX_CMAKE_CONFIG_DIR}/Globals.cmake) + +include(${MYX_CMAKE_BACKPORTS_DIR}/IncludeGuard.cmake) +include(${MYX_CMAKE_BACKPORTS_DIR}/TopLevelProject.cmake) +if(${CMAKE_VERSION} VERSION_LESS "3.11.0") + include(${MYX_CMAKE_BACKPORTS_DIR}/FetchContent.cmake) +endif() + +include(${MYX_CMAKE_LIB_DIR}/ColoredMessages.cmake) +include(${MYX_CMAKE_LIB_DIR}/NinjaGeneratorWarning.cmake) +include(${MYX_CMAKE_LIB_DIR}/DirectoriesGuards.cmake) +include(${MYX_CMAKE_LIB_DIR}/SemanticProjectVersion.cmake) +include(${MYX_CMAKE_LIB_DIR}/NinjaGeneratorWrapper.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) + +unset(MYX_CMAKE_SOURCE_DIR) +unset(MYX_CMAKE_BACKPORTS_DIR) +unset(MYX_CMAKE_CONFIG_DIR) +unset(MYX_CMAKE_LIB_DIR) + +cmake_policy(POP) diff --git a/cmake/myx/MyxCMakeConfigVersion.cmake b/cmake/myx/MyxCMakeConfigVersion.cmake new file mode 100644 index 0000000..c3b26c6 --- /dev/null +++ b/cmake/myx/MyxCMakeConfigVersion.cmake @@ -0,0 +1,9 @@ +set(MYX_CMAKE_PACKAGE_VERSION "1.99.9") +if(MYX_CMAKE_PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION) + set(PACKAGE_VERSION_COMPATIBLE FALSE) +else() + set(PACKAGE_VERSION_COMPATIBLE TRUE) + if(PACKAGE_FIND_VERSION STREQUAL PACKAGE_VERSION) + set(PACKAGE_VERSION_EXACT TRUE) + endif() +endif() diff --git a/cmake/myx/backports/FetchContent.cmake b/cmake/myx/backports/FetchContent.cmake new file mode 100644 index 0000000..a8a2c2e --- /dev/null +++ b/cmake/myx/backports/FetchContent.cmake @@ -0,0 +1,464 @@ +include_guard(GLOBAL) + +set(__FetchContent_privateDir "${CMAKE_CURRENT_LIST_DIR}/FetchContent") + +#======================================================================= +# Recording and retrieving content details for later population +#======================================================================= + +# Internal use, projects must not call this directly. It is +# intended for use by FetchContent_Declare() only. +# +# Sets a content-specific global property (not meant for use +# outside of functions defined here in this file) which can later +# be retrieved using __FetchContent_getSavedDetails() with just the +# same content name. If there is already a value stored in the +# property, it is left unchanged and this call has no effect. +# This allows parent projects to define the content details, +# overriding anything a child project may try to set (properties +# are not cached between runs, so the first thing to set it in a +# build will be in control). +function(__FetchContent_declareDetails contentName) + + string(TOLOWER ${contentName} contentNameLower) + set(propertyName "_FetchContent_${contentNameLower}_savedDetails") + get_property(alreadyDefined GLOBAL PROPERTY ${propertyName} DEFINED) + if(NOT alreadyDefined) + define_property(GLOBAL PROPERTY ${propertyName} + BRIEF_DOCS "Internal implementation detail of FetchContent_Populate()" + FULL_DOCS "Details used by FetchContent_Populate() for ${contentName}" + ) + set_property(GLOBAL PROPERTY ${propertyName} ${ARGN}) + endif() + +endfunction() + + +# Internal use, projects must not call this directly. It is +# intended for use by the FetchContent_Declare() function. +# +# Retrieves details saved for the specified content in an +# earlier call to __FetchContent_declareDetails(). +function(__FetchContent_getSavedDetails contentName outVar) + + string(TOLOWER ${contentName} contentNameLower) + set(propertyName "_FetchContent_${contentNameLower}_savedDetails") + get_property(alreadyDefined GLOBAL PROPERTY ${propertyName} DEFINED) + if(NOT alreadyDefined) + message(FATAL_ERROR "No content details recorded for ${contentName}") + endif() + get_property(propertyValue GLOBAL PROPERTY ${propertyName}) + set(${outVar} "${propertyValue}" PARENT_SCOPE) + +endfunction() + + +# Saves population details of the content, sets defaults for the +# SOURCE_DIR and BUILD_DIR. +function(FetchContent_Declare contentName) + + set(options "") + set(oneValueArgs SVN_REPOSITORY) + set(multiValueArgs "") + + cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + unset(srcDirSuffix) + unset(svnRepoArgs) + if(ARG_SVN_REPOSITORY) + # Add a hash of the svn repository URL to the source dir. This works + # around the problem where if the URL changes, the download would + # fail because it tries to checkout/update rather than switch the + # old URL to the new one. We limit the hash to the first 7 characters + # so that the source path doesn't get overly long (which can be a + # problem on windows due to path length limits). + string(SHA1 urlSHA ${ARG_SVN_REPOSITORY}) + string(SUBSTRING ${urlSHA} 0 7 urlSHA) + set(srcDirSuffix "-${urlSHA}") + set(svnRepoArgs SVN_REPOSITORY ${ARG_SVN_REPOSITORY}) + endif() + + string(TOLOWER ${contentName} contentNameLower) + __FetchContent_declareDetails( + ${contentNameLower} + SOURCE_DIR "${FETCHCONTENT_BASE_DIR}/${contentNameLower}-src${srcDirSuffix}" + BINARY_DIR "${FETCHCONTENT_BASE_DIR}/${contentNameLower}-build" + ${svnRepoArgs} + # List these last so they can override things we set above + ${ARG_UNPARSED_ARGUMENTS} + ) + +endfunction() + + +#======================================================================= +# Set/get whether the specified content has been populated yet. +# The setter also records the source and binary dirs used. +#======================================================================= + +# Internal use, projects must not call this directly. It is +# intended for use by the FetchContent_Populate() function to +# record when FetchContent_Populate() is called for a particular +# content name. +function(__FetchContent_setPopulated contentName sourceDir binaryDir) + + string(TOLOWER ${contentName} contentNameLower) + set(prefix "_FetchContent_${contentNameLower}") + + set(propertyName "${prefix}_sourceDir") + define_property(GLOBAL PROPERTY ${propertyName} + BRIEF_DOCS "Internal implementation detail of FetchContent_Populate()" + FULL_DOCS "Details used by FetchContent_Populate() for ${contentName}" + ) + set_property(GLOBAL PROPERTY ${propertyName} ${sourceDir}) + + set(propertyName "${prefix}_binaryDir") + define_property(GLOBAL PROPERTY ${propertyName} + BRIEF_DOCS "Internal implementation detail of FetchContent_Populate()" + FULL_DOCS "Details used by FetchContent_Populate() for ${contentName}" + ) + set_property(GLOBAL PROPERTY ${propertyName} ${binaryDir}) + + set(propertyName "${prefix}_populated") + define_property(GLOBAL PROPERTY ${propertyName} + BRIEF_DOCS "Internal implementation detail of FetchContent_Populate()" + FULL_DOCS "Details used by FetchContent_Populate() for ${contentName}" + ) + set_property(GLOBAL PROPERTY ${propertyName} True) + +endfunction() + + +# Set variables in the calling scope for any of the retrievable +# properties. If no specific properties are requested, variables +# will be set for all retrievable properties. +# +# This function is intended to also be used by projects as the canonical +# way to detect whether they should call FetchContent_Populate() +# and pull the populated source into the build with add_subdirectory(), +# if they are using the populated content in that way. +function(FetchContent_GetProperties contentName) + + string(TOLOWER ${contentName} contentNameLower) + + set(options "") + set(oneValueArgs SOURCE_DIR BINARY_DIR POPULATED) + set(multiValueArgs "") + + cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + if(NOT ARG_SOURCE_DIR AND + NOT ARG_BINARY_DIR AND + NOT ARG_POPULATED) + # No specific properties requested, provide them all + set(ARG_SOURCE_DIR ${contentNameLower}_SOURCE_DIR) + set(ARG_BINARY_DIR ${contentNameLower}_BINARY_DIR) + set(ARG_POPULATED ${contentNameLower}_POPULATED) + endif() + + set(prefix "_FetchContent_${contentNameLower}") + + if(ARG_SOURCE_DIR) + set(propertyName "${prefix}_sourceDir") + get_property(value GLOBAL PROPERTY ${propertyName}) + if(value) + set(${ARG_SOURCE_DIR} ${value} PARENT_SCOPE) + endif() + endif() + + if(ARG_BINARY_DIR) + set(propertyName "${prefix}_binaryDir") + get_property(value GLOBAL PROPERTY ${propertyName}) + if(value) + set(${ARG_BINARY_DIR} ${value} PARENT_SCOPE) + endif() + endif() + + if(ARG_POPULATED) + set(propertyName "${prefix}_populated") + get_property(value GLOBAL PROPERTY ${propertyName} DEFINED) + set(${ARG_POPULATED} ${value} PARENT_SCOPE) + endif() + +endfunction() + + +#======================================================================= +# Performing the population +#======================================================================= + +# The value of contentName will always have been lowercased by the caller. +# All other arguments are assumed to be options that are understood by +# ExternalProject_Add(), except for QUIET and SUBBUILD_DIR. +function(__FetchContent_directPopulate contentName) + + set(options + QUIET + ) + set(oneValueArgs + SUBBUILD_DIR + SOURCE_DIR + BINARY_DIR + # Prevent the following from being passed through + CONFIGURE_COMMAND + BUILD_COMMAND + INSTALL_COMMAND + TEST_COMMAND + # We force both of these to be ON since we are always executing serially + # and we want all steps to have access to the terminal in case they + # need input from the command line (e.g. ask for a private key password) + # or they want to provide timely progress. We silently absorb and + # discard these if they are set by the caller. + USES_TERMINAL_DOWNLOAD + USES_TERMINAL_UPDATE + ) + set(multiValueArgs "") + + cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + if(NOT ARG_SUBBUILD_DIR) + message(FATAL_ERROR "Internal error: SUBBUILD_DIR not set") + elseif(NOT IS_ABSOLUTE "${ARG_SUBBUILD_DIR}") + set(ARG_SUBBUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}/${ARG_SUBBUILD_DIR}") + endif() + + if(NOT ARG_SOURCE_DIR) + message(FATAL_ERROR "Internal error: SOURCE_DIR not set") + elseif(NOT IS_ABSOLUTE "${ARG_SOURCE_DIR}") + set(ARG_SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/${ARG_SOURCE_DIR}") + endif() + + if(NOT ARG_BINARY_DIR) + message(FATAL_ERROR "Internal error: BINARY_DIR not set") + elseif(NOT IS_ABSOLUTE "${ARG_BINARY_DIR}") + set(ARG_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/${ARG_BINARY_DIR}") + endif() + + # Ensure the caller can know where to find the source and build directories + # with some convenient variables. Doing this here ensures the caller sees + # the correct result in the case where the default values are overridden by + # the content details set by the project. + set(${contentName}_SOURCE_DIR "${ARG_SOURCE_DIR}" PARENT_SCOPE) + set(${contentName}_BINARY_DIR "${ARG_BINARY_DIR}" PARENT_SCOPE) + + # The unparsed arguments may contain spaces, so build up ARG_EXTRA + # in such a way that it correctly substitutes into the generated + # CMakeLists.txt file with each argument quoted. + unset(ARG_EXTRA) + foreach(arg IN LISTS ARG_UNPARSED_ARGUMENTS) + set(ARG_EXTRA "${ARG_EXTRA} \"${arg}\"") + endforeach() + + # Hide output if requested, but save it to a variable in case there's an + # error so we can show the output upon failure. When not quiet, don't + # capture the output to a variable because the user may want to see the + # output as it happens (e.g. progress during long downloads). Combine both + # stdout and stderr in the one capture variable so the output stays in order. + if (ARG_QUIET) + set(outputOptions + OUTPUT_VARIABLE capturedOutput + ERROR_VARIABLE capturedOutput + ) + else() + set(capturedOutput) + set(outputOptions) + message(STATUS "Populating ${contentName}") + endif() + + if(CMAKE_GENERATOR) + set(generatorOpts "-G${CMAKE_GENERATOR}") + if(CMAKE_GENERATOR_PLATFORM) + list(APPEND generatorOpts "-A${CMAKE_GENERATOR_PLATFORM}") + endif() + if(CMAKE_GENERATOR_TOOLSET) + list(APPEND generatorOpts "-T${CMAKE_GENERATOR_TOOLSET}") + endif() + + if(CMAKE_MAKE_PROGRAM) + list(APPEND generatorOpts "-DCMAKE_MAKE_PROGRAM:FILEPATH=${CMAKE_MAKE_PROGRAM}") + endif() + + else() + # Likely we've been invoked via CMake's script mode where no + # generator is set (and hence CMAKE_MAKE_PROGRAM could not be + # trusted even if provided). We will have to rely on being + # able to find the default generator and build tool. + unset(generatorOpts) + endif() + + # Create and build a separate CMake project to carry out the population. + # If we've already previously done these steps, they will not cause + # anything to be updated, so extra rebuilds of the project won't occur. + # Make sure to pass through CMAKE_MAKE_PROGRAM in case the main project + # has this set to something not findable on the PATH. + configure_file("${__FetchContent_privateDir}/CMakeLists.cmake.in" + "${ARG_SUBBUILD_DIR}/CMakeLists.txt") + execute_process( + COMMAND ${CMAKE_COMMAND} ${generatorOpts} . + RESULT_VARIABLE result + ${outputOptions} + WORKING_DIRECTORY "${ARG_SUBBUILD_DIR}" + ) + if(result) + if(capturedOutput) + message("${capturedOutput}") + endif() + message(FATAL_ERROR "CMake step for ${contentName} failed: ${result}") + endif() + execute_process( + COMMAND ${CMAKE_COMMAND} --build . + RESULT_VARIABLE result + ${outputOptions} + WORKING_DIRECTORY "${ARG_SUBBUILD_DIR}" + ) + if(result) + if(capturedOutput) + message("${capturedOutput}") + endif() + message(FATAL_ERROR "Build step for ${contentName} failed: ${result}") + endif() + +endfunction() + + +option(FETCHCONTENT_FULLY_DISCONNECTED "Disables all attempts to download or update content and assumes source dirs already exist") +option(FETCHCONTENT_UPDATES_DISCONNECTED "Enables UPDATE_DISCONNECTED behavior for all content population") +option(FETCHCONTENT_QUIET "Enables QUIET option for all content population" ON) +set(FETCHCONTENT_BASE_DIR "${CMAKE_BINARY_DIR}/_deps" CACHE PATH "Directory under which to collect all populated content") + +# Populate the specified content using details stored from +# an earlier call to FetchContent_Declare(). +function(FetchContent_Populate contentName) + + if(NOT contentName) + message(FATAL_ERROR "Empty contentName not allowed for FetchContent_Populate()") + endif() + + string(TOLOWER ${contentName} contentNameLower) + + if(ARGN) + # This is the direct population form with details fully specified + # as part of the call, so we already have everything we need + __FetchContent_directPopulate( + ${contentNameLower} + SUBBUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}/${contentNameLower}-subbuild" + SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/${contentNameLower}-src" + BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/${contentNameLower}-build" + ${ARGN} # Could override any of the above ..._DIR variables + ) + + # Pass source and binary dir variables back to the caller + set(${contentNameLower}_SOURCE_DIR "${${contentNameLower}_SOURCE_DIR}" PARENT_SCOPE) + set(${contentNameLower}_BINARY_DIR "${${contentNameLower}_BINARY_DIR}" PARENT_SCOPE) + + # Don't set global properties, or record that we did this population, since + # this was a direct call outside of the normal declared details form. + # We only want to save values in the global properties for content that + # honours the hierarchical details mechanism so that projects are not + # robbed of the ability to override details set in nested projects. + return() + endif() + + # No details provided, so assume they were saved from an earlier call + # to FetchContent_Declare(). Do a check that we haven't already + # populated this content before in case the caller forgot to check. + FetchContent_GetProperties(${contentName}) + if(${contentNameLower}_POPULATED) + message(FATAL_ERROR "Content ${contentName} already populated in ${${contentNameLower}_SOURCE_DIR}") + endif() + + string(TOUPPER ${contentName} contentNameUpper) + set(FETCHCONTENT_SOURCE_DIR_${contentNameUpper} + "${FETCHCONTENT_SOURCE_DIR_${contentNameUpper}}" + CACHE PATH "When not empty, overrides where to find pre-populated content for ${contentName}") + + if(FETCHCONTENT_SOURCE_DIR_${contentNameUpper}) + # The source directory has been explicitly provided in the cache, + # so no population is required + set(${contentNameLower}_SOURCE_DIR "${FETCHCONTENT_SOURCE_DIR_${contentNameUpper}}") + set(${contentNameLower}_BINARY_DIR "${FETCHCONTENT_BASE_DIR}/${contentNameLower}-build") + + elseif(FETCHCONTENT_FULLY_DISCONNECTED) + # Bypass population and assume source is already there from a previous run + set(${contentNameLower}_SOURCE_DIR "${FETCHCONTENT_BASE_DIR}/${contentNameLower}-src") + set(${contentNameLower}_BINARY_DIR "${FETCHCONTENT_BASE_DIR}/${contentNameLower}-build") + + else() + # Support both a global "disconnect all updates" and a per-content + # update test (either one being set disables updates for this content). + option(FETCHCONTENT_UPDATES_DISCONNECTED_${contentNameUpper} + "Enables UPDATE_DISCONNECTED behavior just for population of ${contentName}") + if(FETCHCONTENT_UPDATES_DISCONNECTED OR + FETCHCONTENT_UPDATES_DISCONNECTED_${contentNameUpper}) + set(disconnectUpdates True) + else() + set(disconnectUpdates False) + endif() + + if(FETCHCONTENT_QUIET) + set(quietFlag QUIET) + else() + unset(quietFlag) + endif() + + __FetchContent_getSavedDetails(${contentName} contentDetails) + if("${contentDetails}" STREQUAL "") + message(FATAL_ERROR "No details have been set for content: ${contentName}") + endif() + + __FetchContent_directPopulate( + ${contentNameLower} + ${quietFlag} + UPDATE_DISCONNECTED ${disconnectUpdates} + SUBBUILD_DIR "${FETCHCONTENT_BASE_DIR}/${contentNameLower}-subbuild" + SOURCE_DIR "${FETCHCONTENT_BASE_DIR}/${contentNameLower}-src" + BINARY_DIR "${FETCHCONTENT_BASE_DIR}/${contentNameLower}-build" + # Put the saved details last so they can override any of the + # the options we set above (this can include SOURCE_DIR or + # BUILD_DIR) + ${contentDetails} + ) + endif() + + __FetchContent_setPopulated( + ${contentName} + ${${contentNameLower}_SOURCE_DIR} + ${${contentNameLower}_BINARY_DIR} + ) + + # Pass variables back to the caller. The variables passed back here + # must match what FetchContent_GetProperties() sets when it is called + # with just the content name. + set(${contentNameLower}_SOURCE_DIR "${${contentNameLower}_SOURCE_DIR}" PARENT_SCOPE) + set(${contentNameLower}_BINARY_DIR "${${contentNameLower}_BINARY_DIR}" PARENT_SCOPE) + set(${contentNameLower}_POPULATED True PARENT_SCOPE) + +endfunction() + +# Arguments are assumed to be the names of dependencies that have been +# declared previously and should be populated. It is not an error if +# any of them have already been populated (they will just be skipped in +# that case). The command is implemented as a macro so that the variables +# defined by the FetchContent_GetProperties() and FetchContent_Populate() +# calls will be available to the caller. +macro(FetchContent_MakeAvailable) + + foreach(contentName IN ITEMS ${ARGV}) + string(TOLOWER ${contentName} contentNameLower) + FetchContent_GetProperties(${contentName}) + if(NOT ${contentNameLower}_POPULATED) + FetchContent_Populate(${contentName}) + + # Only try to call add_subdirectory() if the populated content + # can be treated that way. Protecting the call with the check + # allows this function to be used for projects that just want + # to ensure the content exists, such as to provide content at + # a known location. + if(EXISTS ${${contentNameLower}_SOURCE_DIR}/CMakeLists.txt) + add_subdirectory(${${contentNameLower}_SOURCE_DIR} + ${${contentNameLower}_BINARY_DIR}) + endif() + endif() + endforeach() + +endmacro() diff --git a/cmake/myx/backports/FetchContent/CMakeLists.cmake.in b/cmake/myx/backports/FetchContent/CMakeLists.cmake.in new file mode 100644 index 0000000..d94b0f4 --- /dev/null +++ b/cmake/myx/backports/FetchContent/CMakeLists.cmake.in @@ -0,0 +1,28 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +cmake_minimum_required(VERSION ${CMAKE_VERSION}) + +# We name the project and the target for the ExternalProject_Add() call +# to something that will highlight to the user what we are working on if +# something goes wrong and an error message is produced. + +project(${contentName}-populate NONE) + +@__FETCHCONTENT_CACHED_INFO@ + +include(ExternalProject) +ExternalProject_Add(${contentName}-populate + ${ARG_EXTRA} + SOURCE_DIR "${ARG_SOURCE_DIR}" + BINARY_DIR "${ARG_BINARY_DIR}" + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + TEST_COMMAND "" + USES_TERMINAL_DOWNLOAD YES + USES_TERMINAL_UPDATE YES + USES_TERMINAL_PATCH YES +) + +@__FETCHCONTENT_COPY_FILE@ diff --git a/cmake/myx/backports/IncludeGuard.cmake b/cmake/myx/backports/IncludeGuard.cmake new file mode 100644 index 0000000..1e577c3 --- /dev/null +++ b/cmake/myx/backports/IncludeGuard.cmake @@ -0,0 +1,12 @@ +# Защита для однократного включения файла *.cmake +# Функция include_guard() реализована в версии 3.10 +# Макрос реализован для обратной совместимости +if(${CMAKE_VERSION} VERSION_LESS "3.10.0") + macro(include_guard) + if (CMAKE_FILE_${CMAKE_CURRENT_LIST_FILE}_ALREADY_INCLUDED) + return() + endif() + set(CMAKE_FILE_${CMAKE_CURRENT_LIST_FILE}_ALREADY_INCLUDED TRUE) + endmacro() +endif() + diff --git a/cmake/myx/backports/TopLevelProject.cmake b/cmake/myx/backports/TopLevelProject.cmake new file mode 100644 index 0000000..b1b89ee --- /dev/null +++ b/cmake/myx/backports/TopLevelProject.cmake @@ -0,0 +1,10 @@ +include_guard(GLOBAL) + +if(CMAKE_VERSION VERSION_LESS 3.21) + get_property(nt DIRECTORY PROPERTY PARENT_DIRECTORY) + if(NOT nt) + set(PROJECT_IS_TOP_LEVEL true) + endif() + unset(nt) +endif() + diff --git a/cmake/myx/config/Globals.cmake b/cmake/myx/config/Globals.cmake new file mode 100644 index 0000000..239ce77 --- /dev/null +++ b/cmake/myx/config/Globals.cmake @@ -0,0 +1,8 @@ +include(GNUInstallDirs) + +#set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR} PARENT_SCOPE) +#set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR} PARENT_SCOPE) +#set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_BINDIR} PARENT_SCOPE) + +#set(MYX_CMAKE_SCRIPTS_PREFIX ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME} PARENT_SCOPE) + diff --git a/cmake/myx/lib/AddLibrary.cmake b/cmake/myx/lib/AddLibrary.cmake new file mode 100644 index 0000000..74b1769 --- /dev/null +++ b/cmake/myx/lib/AddLibrary.cmake @@ -0,0 +1,77 @@ +include_guard(GLOBAL) + +include(GenerateExportHeader) + +function(myx_add_library NAME) + set(options) + set(oneValueArgs TYPE) + set(multiValueArgs SOURCES) + cmake_parse_arguments(arg "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + if(NOT arg_TYPE) + set(arg_TYPE "OBJECT") + endif() + + add_library(${NAME} ${arg_TYPE}) + + if(arg_TYPE STREQUAL INTERFACE) + target_include_directories(${NAME} + INTERFACE + $ + $ + ) + else() + string(TOUPPER ${NAME} PROJECT_NAME_UPPER) + # Опция для разрешения сборки разделяемой библиотеки + option(${PROJECT_NAME_UPPER}_BUILD_SHARED "Build shared library" ON) + # Опция для разрешения сборки статической библиотеки + option(${PROJECT_NAME_UPPER}_BUILD_STATIC "Build static library" ON) + + target_include_directories(${NAME} + PUBLIC + $ + PRIVATE + $ + ) + + set_target_properties(${NAME} PROPERTIES POSITION_INDEPENDENT_CODE ON) + + string(TOUPPER ${NAME} suffix) + generate_export_header(${NAME} + BASE_NAME "${suffix}" + EXPORT_MACRO_NAME "EXPORT_${suffix}" + DEPRECATED_MACRO_NAME "DEPRECATED_${suffix}" + NO_DEPRECATED_MACRO_NAME "NO_DEPRECATED_${suffix}" + NO_EXPORT_MACRO_NAME "NO_EXPORT_${suffix}" + STATIC_DEFINE "STATIC_DEFINE_${suffix}" + EXPORT_FILE_NAME "${PROJECT_SOURCE_DIR}/include/${NAME}/export_autogen.hpp" + DEFINE_NO_DEPRECATED + ) + + # Цель для создания разделяемой библиотеки из объектных файлов + if(${PROJECT_NAME_UPPER}_BUILD_SHARED) + # Для создания разделяемой библиотеки используются объектные файлы цели ${NAME} + add_library(${NAME}_shared SHARED $) + # Установка дополнительных свойств для цели ${NAME}_shared + # OUTPUT_NAME: базовое имя выходного файла (без учёта расширения) + # VERSION: версия библиотеки + # SOVERSION: мажорная версия библиотеки + set_target_properties(${NAME}_shared + PROPERTIES + VERSION ${PROJECT_VERSION} + SOVERSION ${PROJECT_VERSION_MAJOR} + OUTPUT_NAME ${NAME}) + endif() + + # Цель для создания статической библиотеки из объектных файлов + if(${PROJECT_NAME_UPPER}_BUILD_STATIC) + # Для создания статической библиотеки используются объектные файлы цели ${NAME} + add_library(${NAME}_static STATIC $) + # Установка дополнительных свойств для цели ${NAME}_static + # OUTPUT_NAME: базовое имя выходного файла (без учёта расширения) + set_target_properties(${NAME}_static + PROPERTIES + OUTPUT_NAME ${NAME}) + endif() + endif() +endfunction() diff --git a/cmake/myx/lib/ColoredMessages.cmake b/cmake/myx/lib/ColoredMessages.cmake new file mode 100644 index 0000000..5ae5f3d --- /dev/null +++ b/cmake/myx/lib/ColoredMessages.cmake @@ -0,0 +1,43 @@ +# Обёртки для функций вывода сообщений + +include_guard(GLOBAL) + +if(DEFINED ENV{TERM} AND UNIX) + string(ASCII 27 Esc) + set(MyxColorReset "${Esc}[m") + set(MyxColorBold "${Esc}[1m") + set(MyxColorRed "${Esc}[31m") + set(MyxColorGreen "${Esc}[32m") + set(MyxColorYellow "${Esc}[33m") + set(MyxColorBlue "${Esc}[34m") + set(MyxColorMagenta "${Esc}[35m") + set(MyxColorCyan "${Esc}[36m") + set(MyxColorWhite "${Esc}[37m") + set(MyxColorBoldRed "${Esc}[1;31m") + set(MyxColorBoldGreen "${Esc}[1;32m") + set(MyxColorBoldYellow "${Esc}[1;33m") + set(MyxColorBoldBlue "${Esc}[1;34m") + set(MyxColorBoldMagenta "${Esc}[1;35m") + set(MyxColorBoldCyan "${Esc}[1;36m") + set(MyxColorBoldWhite "${Esc}[1;37m") +endif() + +function(myx_message_error) + message(FATAL_ERROR ${MyxColorBoldRed}${ARGV}${MyxColorReset}) +endfunction() + +function(myx_message_warning) + message(WARNING ${MyxColorRed}${ARGV}${MyxColorReset}) +endfunction() + +function(myx_message_status) + message(STATUS ${MyxColorMagenta}${ARGV}${MyxColorReset}) +endfunction() + +function(myx_message_notice) + message(${MyxColorBold}${ARGV}${MyxColorReset}) +endfunction() + +function(myx_message) + message(${MyxColorReset}${ARGV}${MyxColorReset}) +endfunction() diff --git a/cmake/myx/lib/DirectoriesGuards.cmake b/cmake/myx/lib/DirectoriesGuards.cmake new file mode 100644 index 0000000..addab82 --- /dev/null +++ b/cmake/myx/lib/DirectoriesGuards.cmake @@ -0,0 +1,50 @@ +# Запись результатов сборки проекта внутрь иерархии каталогов с исходными текстами +# приводит к засорению файлами формируемыми на этапе сборки, которые затрудняют +# разработку, поиск в оригинальных файлах и мешают ориентироваться в проекте. +# При работе с несколькими типами сборки, например, отладка и выпуск, появляется +# необходимость корректного полного удаления результатов предыдущего варианта. + +include_guard(GLOBAL) + +get_filename_component(cmake_source_dir "${CMAKE_SOURCE_DIR}" REALPATH) +get_filename_component(cmake_binary_dir "${CMAKE_BINARY_DIR}" REALPATH) +get_filename_component(project_source_dir "${PROJECT_SOURCE_DIR}" REALPATH) +get_filename_component(project_binary_dir "${PROJECT_BINARY_DIR}" REALPATH) +get_filename_component(cmake_install_prefix "${CMAKE_INSTALL_PREFIX}" REALPATH) + +if(cmake_install_prefix STREQUAL cmake_binary_dir) + myx_message_error( + "Myx: Cannot install into build directory ${CMAKE_INSTALL_PREFIX}.") +endif() + +if(cmake_install_prefix STREQUAL cmake_source_dir) + myx_message_error( + "Myx: Cannot install into source directory ${CMAKE_INSTALL_PREFIX}.") +endif() + +if(cmake_install_prefix STREQUAL project_binary_dir) + myx_message_error( + "Myx: Cannot install into build directory ${CMAKE_INSTALL_PREFIX}.") +endif() + +if(cmake_install_prefix STREQUAL project_source_dir) + myx_message_error( + "Myx: Cannot install into source directory ${CMAKE_INSTALL_PREFIX}.") +endif() + +if(cmake_binary_dir STREQUAL cmake_source_dir) + myx_message_error( + "Myx: Cannot build in source directory ${CMAKE_SOURCE_DIR}") +endif() + +if(project_binary_dir STREQUAL project_source_dir) + myx_message_error( + "Myx: Cannot build in source directory ${CMAKE_SOURCE_DIR}") +endif() + +unset(cmake_source_dir) +unset(cmake_binary_dir) +unset(project_source_dir) +unset(project_binary_dir) +unset(cmake_install_prefix) + diff --git a/cmake/myx/lib/InstallLibrary.cmake b/cmake/myx/lib/InstallLibrary.cmake new file mode 100644 index 0000000..f2a18d4 --- /dev/null +++ b/cmake/myx/lib/InstallLibrary.cmake @@ -0,0 +1,65 @@ +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() + + 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(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() +endfunction() diff --git a/cmake/myx/lib/InstallLibraryConfig.cmake.in b/cmake/myx/lib/InstallLibraryConfig.cmake.in new file mode 100644 index 0000000..5e1d770 --- /dev/null +++ b/cmake/myx/lib/InstallLibraryConfig.cmake.in @@ -0,0 +1,5 @@ +@PACKAGE_INIT@ + +include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake") + +check_required_components("@PROJECT_NAME@") diff --git a/cmake/myx/lib/NinjaGeneratorWarning.cmake b/cmake/myx/lib/NinjaGeneratorWarning.cmake new file mode 100644 index 0000000..b9118d7 --- /dev/null +++ b/cmake/myx/lib/NinjaGeneratorWarning.cmake @@ -0,0 +1,8 @@ +# Версии CMake, как минимум до 3.8.0, генерируют некорректные +# правила для ninja. + +include_guard(GLOBAL) + +if(${CMAKE_VERSION} VERSION_LESS "3.8.0" AND CMAKE_GENERATOR MATCHES Ninja) + myx_message_error("Myx: Old CMake versions should use Makefile generator") +endif() diff --git a/cmake/myx/lib/NinjaGeneratorWrapper.cmake b/cmake/myx/lib/NinjaGeneratorWrapper.cmake new file mode 100644 index 0000000..be97d52 --- /dev/null +++ b/cmake/myx/lib/NinjaGeneratorWrapper.cmake @@ -0,0 +1,11 @@ +# Если выбран генератор Ninja, то в основном сборочном каталоге создаётся +# файл Makefile, который обрабатывается командой make и передаёт исполнение +# системе сборки ninja. Таким образом можно выполнять команду make, +# даже если правила сборки проекта сгенерированы для ninja. + +include_guard(GLOBAL) + +if(CMAKE_GENERATOR MATCHES Ninja AND PROJECT_IS_TOP_LEVEL) + file(WRITE ${CMAKE_BINARY_DIR}/Makefile + ".PHONY: build\n" "%:\n" "\t@ninja \$@\n" "build:\n" "\t@ninja\n") +endif() diff --git a/cmake/myx/lib/Qt5TargetSetup.cmake b/cmake/myx/lib/Qt5TargetSetup.cmake new file mode 100644 index 0000000..f225130 --- /dev/null +++ b/cmake/myx/lib/Qt5TargetSetup.cmake @@ -0,0 +1,42 @@ +include_guard(GLOBAL) + +function(myx_qt5_target_setup NAME) + set(options) + set(oneValueArgs) + set(multiValueArgs COMPONENTS PRIVATE SOURCES MOC UI QRC LANGS) + cmake_parse_arguments(arg "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + if(arg_COMPONENTS) + find_package(Qt5 COMPONENTS ${arg_COMPONENTS} REQUIRED) + foreach(iter ${arg_COMPONENTS}) + target_include_directories(${NAME} PRIVATE ${Qt5${iter}_INCLUDE_DIRS}) + endforeach() + endif() + + if(arg_PRIVATE) + foreach(iter ${arg_PRIVATE}) + find_package(Qt5${iter} COMPONENTS Private REQUIRED) + endforeach() + endif() + + qt5_wrap_cpp(moc_cpp ${arg_MOC}) + qt5_wrap_ui(ui_h ${arg_UI}) + qt5_add_resources(qrc_cpp ${arg_QRC}) + + if("LinguistTools" IN_LIST arg_COMPONENTS) + set(ts) + foreach(iter ${arg_LANGS}) + list(APPEND ts ${PROJECT_SOURCE_DIR}/l10n/${NAME}_${iter}.ts) + endforeach() + + qt5_create_translation(qm + ${PROJECT_SOURCE_DIR}/include + ${PROJECT_SOURCE_DIR}/src + ${ts} + ) + endif() + + target_sources(${NAME} + PRIVATE + ${arg_SOURCES} ${moc_cpp} ${ui_h} ${qrc_cpp} ${qm}) +endfunction() diff --git a/cmake/myx/lib/SemanticProjectVersion.cmake b/cmake/myx/lib/SemanticProjectVersion.cmake new file mode 100644 index 0000000..4d410e6 --- /dev/null +++ b/cmake/myx/lib/SemanticProjectVersion.cmake @@ -0,0 +1,17 @@ +include_guard(GLOBAL) + +function(myx_is_semantic_project_version) + if(NOT ${PROJECT_VERSION_PATCH} MATCHES "([0-9]+)") + myx_message_error("Myx: Please set project version in X.Y.Z format") + endif() +endfunction() + +function(myx_project_version_int) + # cmake-format: off + myx_is_semantic_project_version() + math(EXPR v "(${PROJECT_VERSION_MAJOR} << 32) + (${PROJECT_VERSION_MINOR} << 16) + ${PROJECT_VERSION_PATCH}") + set_property(GLOBAL PROPERTY PROJECT_VERSION_INT ${v}) + # cmake-format: on +endfunction() + +myx_is_semantic_project_version() diff --git a/cmake/myx/lib/TargetSetup.cmake b/cmake/myx/lib/TargetSetup.cmake new file mode 100644 index 0000000..9501472 --- /dev/null +++ b/cmake/myx/lib/TargetSetup.cmake @@ -0,0 +1,28 @@ +include_guard(GLOBAL) + +function(myx_target_setup NAME) + set(options) + set(oneValueArgs PCH) + set(multiValueArgs COMPILE_DEFINITIONS FIND_PACKAGES LINK_LIBRARIES SOURCES) + cmake_parse_arguments(arg "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + foreach(iter ${arg_FIND_PACKAGES}) + find_package(${iter} CONFIG REQUIRED) + target_include_directories(${NAME} PRIVATE ${${iter}_INCLUDE_DIRS}) + target_compile_definitions(${NAME} PRIVATE ${${iter}_COMPILE_DEFINITIONS}) + endforeach() + target_compile_definitions(${NAME} PRIVATE ${arg_COMPILE_DEFINITIONS}) + + if(arg_PCH) + if(${CMAKE_VERSION} VERSION_GREATER_EQUAL 3.16) + target_precompile_headers(${NAME} PRIVATE ${PROJECT_SOURCE_DIR}/${arg_PCH}) + else() + target_compile_options(${NAME} PRIVATE -include ${PROJECT_SOURCE_DIR}/${arg_PCH}) + endif() + target_sources(${NAME} PRIVATE ${PROJECT_SOURCE_DIR}/${arg_PCH}) + endif() + + target_sources(${NAME} PRIVATE ${arg_SOURCES}) + target_link_libraries(${NAME} PRIVATE ${arg_LINK_LIBRARIES}) + target_compile_definitions(${NAME} PRIVATE ${arg_COMPILE_DEFINITIONS}) +endfunction() diff --git a/include/pow/pow.hpp b/include/pow/pow.hpp new file mode 100644 index 0000000..fca9c5e --- /dev/null +++ b/include/pow/pow.hpp @@ -0,0 +1,10 @@ +#pragma once + +#include +#include + +template < typename T > +T pow(T v1, T v2) { + static_assert( std::is_arithmetic< T >::value, "Arithmetic type is required." ); + return (pow(v1, v2)); +}