mirror of
https://github.com/silverqx/TinyORM.git
synced 2025-12-21 10:29:36 -06:00
881 lines
32 KiB
CMake
881 lines
32 KiB
CMake
include_guard(GLOBAL)
|
|
|
|
# Convert to the boolean value
|
|
function(tiny_to_bool out_variable value)
|
|
|
|
# This function may look useless, but I'm using it because I want to have unified
|
|
# boolean values, so it's TRUE or FALSE and not ON/OFF, ...
|
|
|
|
# Don't use the Variable Reference here ${value}, an undefined value can be
|
|
# controlled while passing the value to this function using an unquoted
|
|
# Variable Reference like:
|
|
# tiny_to_bool(xyz ${some_bool})
|
|
# This means if the value is undefined (empty) and will be unquoted, then it fails;
|
|
# if it is undefined and quoted, it returns FALSE
|
|
if(value)
|
|
set(${out_variable} TRUE PARENT_SCOPE)
|
|
else()
|
|
set(${out_variable} FALSE PARENT_SCOPE)
|
|
endif()
|
|
|
|
endfunction()
|
|
|
|
# Convert to the boolean value and invert this boolean value (currently unused)
|
|
function(tiny_invert_bool out_variable value)
|
|
|
|
# This function may look useless, but I'm using it because I want to have unified
|
|
# boolean values, so it's TRUE or FALSE and not ON/OFF, ...
|
|
|
|
# Don't use the Variable Reference here ${value}, an undefined value can be
|
|
# controlled while passing the value to this function using an unquoted
|
|
# Variable Reference like:
|
|
# tiny_invert_bool(xyz ${some_bool})
|
|
# This means if the value is undefined (empty) and will be unquoted, then it fails;
|
|
# if it is undefined and quoted, it returns TRUE (as it's inverted)
|
|
if(value)
|
|
set(${out_variable} FALSE PARENT_SCOPE)
|
|
else()
|
|
set(${out_variable} TRUE PARENT_SCOPE)
|
|
endif()
|
|
|
|
endfunction()
|
|
|
|
# Get a default value from the given environment variable and set the cache variable
|
|
# Do nothing if the given CMake variable is already defined or the environment variable
|
|
# is not defined. It's intended for CMake cache boolean variables.
|
|
function(tiny_set_cache_bool_from_environment name description environment_variable_name)
|
|
|
|
# Nothing to do, CMake variable is already defined or env. variable is not defined
|
|
if(DEFINED ${name} OR NOT DEFINED ENV{${environment_variable_name}})
|
|
return()
|
|
endif()
|
|
|
|
# Normalize the default value to ON/OFF values only
|
|
if("$ENV{${environment_variable_name}}")
|
|
set(defaultValue ON)
|
|
else()
|
|
set(defaultValue OFF)
|
|
endif()
|
|
|
|
set(${name} ${defaultValue} CACHE BOOL "${description}")
|
|
|
|
endfunction()
|
|
|
|
# A helper macro that calls find_package() and appends the package (if found) to the
|
|
# TINY_PACKAGE_DEPENDENCIES list that will be used later to generate find_dependency()
|
|
# calls for the TinyORM package configuration file
|
|
macro(tiny_find_package package_name)
|
|
|
|
find_package(${package_name} ${ARGN})
|
|
|
|
if(${package_name}_FOUND) # Quotes not needed, will be _FOUND at least, so FALSE on empty/undefined ${package_name}
|
|
set(args "${package_name}")
|
|
# These arguments will be forwarded to the find_package() by find_dependency()
|
|
list(APPEND args "${ARGN}")
|
|
# REQUIRED and QUIETLY arguments are handled by find_dependency() macro
|
|
# find_dependency() forwards the correct parameters for QUIET and REQUIRED which
|
|
# were passed to the original find_package() call
|
|
list(REMOVE_ITEM args "REQUIRED" "QUIET")
|
|
# Remove all empty items
|
|
list(REMOVE_ITEM args "")
|
|
# Convert to the string
|
|
string(REPLACE ";" " " args "${args}")
|
|
|
|
# Check if the given args are in the TINY_PACKAGE_DEPENDENCIES list
|
|
get_property(packageDependencies GLOBAL PROPERTY TINY_PACKAGE_DEPENDENCIES)
|
|
|
|
if(NOT args IN_LIST packageDependencies) # Automatic Variable Expansion applies
|
|
set_property(GLOBAL APPEND PROPERTY TINY_PACKAGE_DEPENDENCIES "${args}")
|
|
endif()
|
|
endif()
|
|
|
|
unset(args)
|
|
|
|
endmacro()
|
|
|
|
# Generate find_dependency() calls for the TinyORM package config file
|
|
function(tiny_generate_find_dependency_calls out_dependency_calls)
|
|
|
|
set(findDependencyCalls "")
|
|
|
|
get_property(packageDependencies GLOBAL PROPERTY TINY_PACKAGE_DEPENDENCIES)
|
|
|
|
# The ([^;]+) regex matches every list item excluding the ; character 😮
|
|
string(REGEX REPLACE "([^;]+)" "find_dependency(\\1)" findDependencyCalls
|
|
"${packageDependencies}")
|
|
|
|
string(REPLACE ";" "\n" findDependencyCalls "${findDependencyCalls}")
|
|
|
|
set(${out_dependency_calls} ${findDependencyCalls} PARENT_SCOPE)
|
|
|
|
endfunction()
|
|
|
|
# Find package and call target_link_libraries() for MySQL client library
|
|
# By default it uses FindMySQL.cmake module and in vcpkg it uses unofficial-libmysql
|
|
# package config file
|
|
macro(tiny_find_and_link_mysql target)
|
|
|
|
# Currently, I don't need to control the PRIVATE (it's PRIVATE in all cases)
|
|
if(NOT TINY_VCPKG)
|
|
tiny_find_package(MySQL REQUIRED)
|
|
target_link_libraries(${target} PRIVATE MySQL::MySQL)
|
|
else()
|
|
tiny_find_package(unofficial-libmysql REQUIRED)
|
|
target_link_libraries(${target} PRIVATE unofficial::libmysql::libmysql)
|
|
endif()
|
|
|
|
endmacro()
|
|
|
|
# Set TINYORM_LTO macro based on the INTERPROCEDURAL_OPTIMIZATION target property
|
|
# Used by the tom about command to show if the LTO is enabled
|
|
function(tiny_set_lto_compile_definition target)
|
|
|
|
get_target_property(tinyHasLTO ${target} INTERPROCEDURAL_OPTIMIZATION)
|
|
|
|
target_compile_definitions(${target} PRIVATE -DTINYORM_LTO=${tinyHasLTO})
|
|
|
|
endfunction()
|
|
|
|
# Create an empty SQLite database file if it does not exist
|
|
function(tiny_create_sqlite_db db_filepath)
|
|
|
|
if(EXISTS ${db_filepath}) # Quotes not needed, the target cannot be a list (it fails on the list which is good, it quotes it doesn't fail with the list) and spaces are handled correctly without quotes
|
|
return()
|
|
endif()
|
|
|
|
message(STATUS "Creating SQLite database at '${db_filepath}'")
|
|
|
|
file(TOUCH "${db_filepath}")
|
|
|
|
endfunction()
|
|
|
|
# Create an empty .build_tree file in the folder where the TinyDrivers shared library is
|
|
# located (inside the build tree)
|
|
function(tiny_create_buildtree_tagfiles filepaths)
|
|
|
|
foreach(filepath ${filepaths})
|
|
# Nothing to do, .build_tree tag already exists
|
|
if(EXISTS ${filepath}) # Quotes not needed, the target cannot be a list (it fails on the list which is good, it quotes it doesn't fail with the list) and spaces are handled correctly without quotes
|
|
continue()
|
|
endif()
|
|
|
|
message(VERBOSE "Creating .build_tree tag file at '${filepath}'")
|
|
|
|
file(TOUCH "${filepath}")
|
|
endforeach()
|
|
|
|
endfunction()
|
|
|
|
# Find version numbers in the version header file using the given <prefix>
|
|
#
|
|
# Synopsis:
|
|
# tiny_read_version(out_version out_major out_minor out_patch out_tweak
|
|
# VERSION_HEADER <filepath>
|
|
# PREFIX <prefix>
|
|
# HEADER_FOR <target>
|
|
# )
|
|
#
|
|
# <out_version> output variable for the whole version number.
|
|
# <out_major|minor|patch|tweak> output variables for individual version numbers.
|
|
# VERSION_HEADER relative or absolute filepath is directly passed to the file(STRINGS).
|
|
# It's relative to the CMAKE_CURRENT_SOURCE_DIR.
|
|
# PREFIX for the file(STRINGS REGEX) to find #define <prefix>_VERSION_<MAJOR|...> lines.
|
|
# HEADER_FOR <target> name for the message(DEBUG) (use TinyXyz_target variables for this).
|
|
#
|
|
# Search following tokens <prefix>_VERSION_<MAJOR|MINOR|BUGFIX|BUILD> and return obtained
|
|
# values using the <out_xyz> variables.
|
|
function(tiny_read_version out_version out_major out_minor out_patch out_tweak)
|
|
|
|
# Arguments
|
|
set(oneValueArgs VERSION_HEADER PREFIX HEADER_FOR)
|
|
cmake_parse_arguments(PARSE_ARGV 5 TINY "" "${oneValueArgs}" "")
|
|
|
|
# Arguments checks
|
|
if(DEFINED TINY_UNPARSED_ARGUMENTS)
|
|
message(FATAL_ERROR "The ${CMAKE_CURRENT_FUNCTION}() was passed extra arguments: \
|
|
${TINY_UNPARSED_ARGUMENTS}")
|
|
endif()
|
|
|
|
if("${TINY_VERSION_HEADER}" STREQUAL "" OR "${TINY_PREFIX}" STREQUAL "" OR
|
|
"${TINY_HEADER_FOR}" STREQUAL ""
|
|
)
|
|
message(FATAL_ERROR "The ${CMAKE_CURRENT_FUNCTION}() is missing single-valued \
|
|
keyword or its value is empty: HEADER_FOR, PREFIX, VERSION_HEADER")
|
|
endif()
|
|
|
|
# Body
|
|
# Debug setup
|
|
list(APPEND CMAKE_MESSAGE_CONTEXT VersionHeader)
|
|
set(mainMessage "Reading Version Header for ${TINY_HEADER_FOR}")
|
|
message(DEBUG ${mainMessage})
|
|
list(APPEND CMAKE_MESSAGE_INDENT " ")
|
|
|
|
# ---
|
|
|
|
message(DEBUG "Version header filepath - ${TINY_VERSION_HEADER}")
|
|
|
|
file(STRINGS ${TINY_VERSION_HEADER} versionFileContent
|
|
REGEX "^#define ${TINY_PREFIX}.*_VERSION_[A-Z]+ +[0-9]+"
|
|
ENCODING UTF-8
|
|
)
|
|
|
|
message(DEBUG "Version file content - ${versionFileContent}")
|
|
|
|
set(regex ".+_MAJOR +([0-9]+);.+_MINOR +([0-9]+);.+_BUGFIX +([0-9]+);\
|
|
.+_BUILD +([0-9]+)")
|
|
string(REGEX MATCHALL "${regex}" match "${versionFileContent}")
|
|
|
|
if(NOT match)
|
|
message(FATAL_ERROR "Could not detect project version number \
|
|
from ${versionHeader} in ${CMAKE_CURRENT_FUNCTION}().")
|
|
endif()
|
|
|
|
message(DEBUG "Matched version string - ${match}")
|
|
|
|
set(version "${CMAKE_MATCH_1}.${CMAKE_MATCH_2}.${CMAKE_MATCH_3}.${CMAKE_MATCH_4}")
|
|
|
|
# ---
|
|
|
|
message(DEBUG "${out_version} - ${version}")
|
|
message(DEBUG "${out_major} - ${CMAKE_MATCH_1}")
|
|
message(DEBUG "${out_minor} - ${CMAKE_MATCH_2}")
|
|
message(DEBUG "${out_patch} - ${CMAKE_MATCH_3}")
|
|
message(DEBUG "${out_tweak} - ${CMAKE_MATCH_4}")
|
|
|
|
# Debug finish
|
|
list(POP_BACK CMAKE_MESSAGE_INDENT)
|
|
message(DEBUG "${mainMessage} - done")
|
|
list(POP_BACK CMAKE_MESSAGE_CONTEXT)
|
|
|
|
# Return values
|
|
set(${out_version} ${version} PARENT_SCOPE)
|
|
set(${out_major} ${CMAKE_MATCH_1} PARENT_SCOPE)
|
|
set(${out_minor} ${CMAKE_MATCH_2} PARENT_SCOPE)
|
|
set(${out_patch} ${CMAKE_MATCH_3} PARENT_SCOPE)
|
|
set(${out_tweak} ${CMAKE_MATCH_4} PARENT_SCOPE)
|
|
|
|
endfunction()
|
|
|
|
# Command for manipulating CMAKE_RC_FLAGS, supports APPEND and RESTORE operations
|
|
#
|
|
# Synopsis:
|
|
# tiny_rc_flags(APPEND [<flags>...])
|
|
#
|
|
# APPEND the given flags, it only restores the original CMAKE_RC_FLAGS value and
|
|
# appends nothing if the <flags> value is empty.
|
|
#
|
|
# Append flags to the CMAKE_RC_FLAGS. It will also save and restore the original content
|
|
# of the CMAKE_RC_FLAGS variable, so that rc/windres compilation commands are not
|
|
# polluted with include paths from previous tiny_rc_flags(APPEND) function calls.
|
|
#
|
|
# Synopsis:
|
|
# tiny_rc_flags(RESTORE)
|
|
#
|
|
# RESTORE the original CMAKE_RC_FLAGS value.
|
|
#
|
|
# Restore the original value of CMAKE_RC_FLAGS.
|
|
function(tiny_rc_flags)
|
|
|
|
# Arguments
|
|
set(options RESTORE)
|
|
set(multiValueArgs APPEND)
|
|
cmake_parse_arguments(PARSE_ARGV 0 TINY "${options}" "" "${multiValueArgs}")
|
|
|
|
# Arguments checks
|
|
if(DEFINED TINY_UNPARSED_ARGUMENTS)
|
|
message(FATAL_ERROR "The ${CMAKE_CURRENT_FUNCTION}() was passed extra arguments: \
|
|
${TINY_UNPARSED_ARGUMENTS}")
|
|
endif()
|
|
|
|
# To evaluate only once
|
|
if(DEFINED TINY_APPEND OR "APPEND" IN_LIST TINY_KEYWORDS_MISSING_VALUES)
|
|
set(isAppendSet TRUE)
|
|
else()
|
|
set(isAppendSet FALSE)
|
|
endif()
|
|
|
|
if(TINY_RESTORE AND isAppendSet)
|
|
message(FATAL_ERROR "The RESTORE and APPEND arguments cannot be defined \
|
|
at the same time in ${CMAKE_CURRENT_FUNCTION}().")
|
|
endif()
|
|
|
|
# Body
|
|
# Invoke the correct implementation
|
|
# APPEND
|
|
if(isAppendSet)
|
|
_tiny_rc_flags_append(${TINY_APPEND}) # Don't quote here
|
|
|
|
# RESTORE
|
|
elseif(TINY_RESTORE)
|
|
_tiny_rc_flags_restore()
|
|
|
|
else()
|
|
message(FATAL_ERROR "${CMAKE_CURRENT_FUNCTION}() must be called with at least \
|
|
one argument.")
|
|
endif()
|
|
|
|
set(CMAKE_RC_FLAGS "${CMAKE_RC_FLAGS}" PARENT_SCOPE)
|
|
set(TinyRcFlagsToRemove "${TinyRcFlagsToRemove}" PARENT_SCOPE)
|
|
|
|
endfunction()
|
|
|
|
# Append flags to the CMAKE_RC_FLAGS
|
|
# It will also save and restore original content of the CMAKE_RC_FLAGS variable, so that
|
|
# rc/windres compilation commands are not polluted with include paths from previous calls.
|
|
function(_tiny_rc_flags_append)
|
|
|
|
# Restore the original value of CMAKE_RC_FLAGS (even if ARGC == 0)
|
|
_tiny_rc_flags_restore()
|
|
|
|
# Copy as we need to modify it
|
|
# It doesn't matter we are using the ARGN as it would need much more effort
|
|
# to implement it correctly, like adding another cmake_parse_arguments() and escaping
|
|
# \; once more like \\; before list() operations. I'm not gonna do this as I don't
|
|
# need it, it can be overcome by replacing the ; with eg. | as it's not an allowed
|
|
# character in paths and filenames.
|
|
set(rcFlags "${ARGN}")
|
|
|
|
# Strip and remove all empty values
|
|
list(TRANSFORM rcFlags STRIP OUTPUT_VARIABLE rcFlags)
|
|
list(REMOVE_ITEM rcFlags "")
|
|
|
|
# Nothing to do
|
|
list(LENGTH rcFlags rcFlagsCount)
|
|
if(rcFlagsCount EQUAL 0)
|
|
return()
|
|
endif()
|
|
|
|
# Prepend it this way so the space at beginning is also saved in TinyRcFlagsToRemove
|
|
# to correctly remove this space in the _tiny_rc_flags_restore().
|
|
if(NOT "${CMAKE_RC_FLAGS}" STREQUAL "")
|
|
string(PREPEND rcFlags " ")
|
|
endif()
|
|
|
|
# CMAKE_RC_FLAGS is command-line string fragment (must be separated by spaces)
|
|
list(JOIN rcFlags " " rcFlags)
|
|
string(APPEND CMAKE_RC_FLAGS "${rcFlags}")
|
|
|
|
set(CMAKE_RC_FLAGS "${CMAKE_RC_FLAGS}" PARENT_SCOPE)
|
|
# Will be removed from the CMAKE_RC_FLAGS during the next invocation
|
|
set(TinyRcFlagsToRemove "${rcFlags}" PARENT_SCOPE)
|
|
|
|
endfunction()
|
|
|
|
# Restore the original value of CMAKE_RC_FLAGS
|
|
# In our code for all targets it will always remove -I PROJECT_SOURCE_DIR/resources as
|
|
# all add_subdirectory() calls make copy of a scope from the TinyOrm target.
|
|
function(_tiny_rc_flags_restore)
|
|
|
|
# Nothing to do
|
|
list(LENGTH TinyRcFlagsToRemove rcFlagsToRemoveCount)
|
|
if(rcFlagsToRemoveCount EQUAL 0)
|
|
return()
|
|
endif()
|
|
|
|
# Remove RC flags from the previous call
|
|
foreach(toRemove ${TinyRcFlagsToRemove})
|
|
string(REPLACE "${toRemove}" "" CMAKE_RC_FLAGS "${CMAKE_RC_FLAGS}")
|
|
endforeach()
|
|
|
|
string(STRIP "${CMAKE_RC_FLAGS}" CMAKE_RC_FLAGS)
|
|
|
|
set(CMAKE_RC_FLAGS "${CMAKE_RC_FLAGS}" PARENT_SCOPE)
|
|
set(TinyRcFlagsToRemove "" PARENT_SCOPE)
|
|
|
|
endfunction()
|
|
|
|
# Print a VERBOSE message against which library is project linking
|
|
function(tiny_print_linking_against target)
|
|
|
|
# TINY_BUILD_TYPE_UPPER STREQUAL "" means that the CMAKE_BUILD_TYPE was not defined or is empty
|
|
if(TINY_IS_MULTI_CONFIG OR TINY_BUILD_TYPE_UPPER STREQUAL "")
|
|
return()
|
|
endif()
|
|
|
|
if(WIN32 AND BUILD_SHARED_LIBS)
|
|
get_target_property(libraryFilepath ${target}
|
|
IMPORTED_IMPLIB_${TINY_BUILD_TYPE_UPPER}
|
|
)
|
|
else()
|
|
get_target_property(libraryFilepath ${target}
|
|
IMPORTED_LOCATION_${TINY_BUILD_TYPE_UPPER}
|
|
)
|
|
endif()
|
|
|
|
message(VERBOSE "Linking against ${target} at ${libraryFilepath}")
|
|
|
|
endfunction()
|
|
|
|
# Determine whether the CMAKE_CXX_COMPILER_LAUNCHER contains ccache/sccache
|
|
function(tiny_is_ccache_compiler_launcher out_variable)
|
|
|
|
if(NOT DEFINED CMAKE_CXX_COMPILER_LAUNCHER)
|
|
set(${out_variable} FALSE PARENT_SCOPE)
|
|
return()
|
|
endif()
|
|
|
|
# Support the ccache and also sccache (I have tried and sccache doesn't work)
|
|
cmake_path(GET CMAKE_CXX_COMPILER_LAUNCHER STEM ccacheStem)
|
|
if(NOT ccacheStem STREQUAL "ccache" AND NOT ccacheStem STREQUAL "sccache")
|
|
set(${out_variable} FALSE PARENT_SCOPE)
|
|
return()
|
|
endif()
|
|
|
|
set(${out_variable} TRUE PARENT_SCOPE)
|
|
|
|
endfunction()
|
|
|
|
# Determine if the current platform needs fixes and the CMAKE_CXX_COMPILER_LAUNCHER
|
|
# contains ccache/sccache (fixes for MSVC compilers)
|
|
function(tiny_should_fix_ccache_msvc out_variable)
|
|
|
|
# Target the MSVC and Clang-cl with MSVC compilers on Windows
|
|
if(NOT WIN32 OR NOT MSVC OR MINGW OR NOT DEFINED CMAKE_CXX_COMPILER_LAUNCHER)
|
|
set(${out_variable} FALSE PARENT_SCOPE)
|
|
return()
|
|
endif()
|
|
|
|
# Support the ccache and also sccache (I have tried and sccache doesn't work)
|
|
set(isCcacheCompilerLauncher FALSE)
|
|
tiny_is_ccache_compiler_launcher(isCcacheCompilerLauncher)
|
|
|
|
set(${out_variable} ${isCcacheCompilerLauncher} PARENT_SCOPE)
|
|
|
|
endfunction()
|
|
|
|
# Determine whether to disable PCH based on the ccache --print-version and set
|
|
# the internal cache variable TINY_CCACHE_VERSION (MSVC only)
|
|
# Precompiled headers are fully supported on MSVC for ccache >=4.10, so
|
|
# disable PCH for ccache <4.10 only.
|
|
# The git-ref is a special value, it means that the ccache was built manually from eg.
|
|
# master branch, in this case suppose the version is always >=4.10.
|
|
# If the ccache isn't on the system path or parsing the version failed set to 0.
|
|
function(tiny_should_disable_precompile_headers out_variable)
|
|
|
|
# Nothing to do, ccache version was already populated (cache hit)
|
|
if(DEFINED TINY_CCACHE_VERSION AND NOT TINY_CCACHE_VERSION STREQUAL "")
|
|
if(TINY_CCACHE_VERSION VERSION_GREATER_EQUAL "4.10" OR
|
|
TINY_CCACHE_VERSION STREQUAL "git-ref"
|
|
)
|
|
set(${out_variable} FALSE PARENT_SCOPE)
|
|
else()
|
|
set(${out_variable} TRUE PARENT_SCOPE)
|
|
endif()
|
|
|
|
return()
|
|
endif()
|
|
|
|
set(helpString "Ccache version used to determine whether to disable PCH (MSVC only).")
|
|
|
|
execute_process(
|
|
COMMAND "${CMAKE_CXX_COMPILER_LAUNCHER}" --print-version
|
|
RESULT_VARIABLE exitCode
|
|
OUTPUT_VARIABLE ccacheVersionRaw
|
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
|
ERROR_QUIET
|
|
)
|
|
|
|
# ccache can't be executed, don't disable PCH in this case and even don't cache
|
|
# the TINY_CCACHE_VERSION because the build is gonna to fail and we don't want to
|
|
# cache the wrong value
|
|
if(exitCode STREQUAL "no such file or directory")
|
|
set(${out_variable} FALSE PARENT_SCOPE)
|
|
return()
|
|
endif()
|
|
|
|
# ccache <4.10 doesn't have the --print-version parameter, we can be pretty sure that
|
|
# the version is <4.10 because we know the ccache is on the system path
|
|
if(NOT exitCode EQUAL 0)
|
|
set(TINY_CCACHE_VERSION "0" CACHE INTERNAL "${helpString}")
|
|
set(${out_variable} TRUE PARENT_SCOPE)
|
|
return()
|
|
endif()
|
|
|
|
# Detect a manual build version (git reference).
|
|
# The git-ref is a special value, it means that the ccache was built manually from eg.
|
|
# master branch, in this case set ccache version as the git-ref string. This version
|
|
# will be supposed as the latest version and will be assumed it supports PCH.
|
|
# CMake doesn't support {x,y}. 😮
|
|
set(regexpGitRef
|
|
"^.*\.[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]*$")
|
|
|
|
if(ccacheVersionRaw MATCHES "${regexpGitRef}")
|
|
set(TINY_CCACHE_VERSION "git-ref" CACHE INTERNAL "${helpString}")
|
|
set(${out_variable} FALSE PARENT_SCOPE)
|
|
return()
|
|
endif()
|
|
|
|
# Detect a normal tag version like eg. 4.10
|
|
set(regexpVersion "^[0-9]+\.[0-9]+(\.[0-9]+)?(\.[0-9]+)?$")
|
|
|
|
# This should never happen :/
|
|
if(NOT ccacheVersionRaw MATCHES "${regexpVersion}")
|
|
message(FATAL_ERROR "Parsing of the 'ccache --print-version' failed \
|
|
in ${CMAKE_CURRENT_FUNCTION}().")
|
|
endif()
|
|
|
|
set(TINY_CCACHE_VERSION "${CMAKE_MATCH_0}" CACHE INTERNAL "${helpString}")
|
|
|
|
if(TINY_CCACHE_VERSION VERSION_GREATER_EQUAL "4.10")
|
|
set(${out_variable} FALSE PARENT_SCOPE)
|
|
else()
|
|
set(${out_variable} TRUE PARENT_SCOPE)
|
|
endif()
|
|
|
|
endfunction()
|
|
|
|
# Disable the precompilation of header files
|
|
function(tiny_disable_precompile_headers)
|
|
|
|
# Determine whether to disable PCH based on the ccache --print-version
|
|
set(shouldDisablePCH FALSE)
|
|
tiny_should_disable_precompile_headers(shouldDisablePCH)
|
|
|
|
if(NOT shouldDisablePCH)
|
|
return()
|
|
endif()
|
|
|
|
message(VERBOSE "Disabled PCH because ccache or sccache is used as compiler \
|
|
launcher for MSVC")
|
|
|
|
get_property(help_string CACHE CMAKE_DISABLE_PRECOMPILE_HEADERS
|
|
PROPERTY HELPSTRING
|
|
)
|
|
if(NOT help_string)
|
|
set(help_string "Default value for DISABLE_PRECOMPILE_HEADERS of targets.")
|
|
endif()
|
|
|
|
set(CMAKE_DISABLE_PRECOMPILE_HEADERS ON CACHE BOOL ${help_string} FORCE)
|
|
|
|
endfunction()
|
|
|
|
# Determine whether the CMAKE_MSVC_DEBUG_INFORMATION_FORMAT, a new MSVC debug information
|
|
# format is in effect
|
|
function(tiny_is_new_msvc_debug_information_format_325 out_variable)
|
|
|
|
if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.25")
|
|
|
|
cmake_policy(GET CMP0141 policy_cmp0141)
|
|
if(policy_cmp0141 STREQUAL "NEW")
|
|
set(${out_variable} TRUE PARENT_SCOPE)
|
|
return()
|
|
endif()
|
|
|
|
endif()
|
|
|
|
set(${out_variable} FALSE PARENT_SCOPE)
|
|
|
|
endfunction()
|
|
|
|
# Support the MSVC debug information format flags selected by an abstraction added
|
|
# in the CMake 3.25
|
|
function(tiny_fix_ccache_msvc_325)
|
|
|
|
get_property(help_string CACHE CMAKE_MSVC_DEBUG_INFORMATION_FORMAT
|
|
PROPERTY HELPSTRING
|
|
)
|
|
if(NOT help_string)
|
|
set(help_string "Default value for MSVC_DEBUG_INFORMATION_FORMAT of targets.")
|
|
endif()
|
|
|
|
set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT
|
|
"$<$<CONFIG:Debug,RelWithDebInfo>:Embedded>"
|
|
CACHE BOOL ${help_string} FORCE
|
|
)
|
|
|
|
mark_as_advanced(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT)
|
|
|
|
endfunction()
|
|
|
|
# Helper function to replace /Zi and /ZI by /Z7 in the CMAKE_<C|CXX>_FLAGS_<CONFIG> option
|
|
function(tiny_replace_Zi_by_Z7_for option help_string)
|
|
|
|
# Don't quote: ${option} MATCHES; it would change the meaning and stop working;
|
|
# CMake first do the Variable Expansion and then the Automatic Variable Evaluation
|
|
# on this replaced/expanded value (eg. CMAKE_CXX_FLAGS_DEBUG)
|
|
if(DEFINED ${option} AND ${option} MATCHES "(/|-)(Zi|ZI)")
|
|
string(REGEX REPLACE "(/|-)(Zi|ZI)" "/Z7" ${option} "${${option}}")
|
|
|
|
get_property(help_string_property CACHE ${option} PROPERTY HELPSTRING)
|
|
if(NOT help_string_property)
|
|
set(help_string_property ${help_string})
|
|
endif()
|
|
|
|
set(${option} ${${option}} CACHE STRING ${help_string_property} FORCE)
|
|
endif()
|
|
|
|
endfunction()
|
|
|
|
# Replace /Zi or /ZI by /Z7 in the CMAKE_<C|CXX>_FLAGS_<CONFIG> option for the CMake <3.25
|
|
function(tiny_fix_ccache_msvc_324)
|
|
|
|
# Nothing to do, multi-configuration generators are not supported
|
|
if(TINY_IS_MULTI_CONFIG OR TINY_BUILD_TYPE_LOWER STREQUAL "")
|
|
message(STATUS "The ccache compiler launcher is not supported for multi-configuration \
|
|
generators or with undefined CMAKE_BUILD_TYPE on CMake <3.25")
|
|
return()
|
|
endif()
|
|
|
|
# Replace /Zi and /ZI by /Z7 by the build config type, for the CMake <=3.24
|
|
if(TINY_BUILD_TYPE_LOWER STREQUAL "debug")
|
|
tiny_replace_Zi_by_Z7_for(CMAKE_CXX_FLAGS_DEBUG
|
|
"Flags used by the CXX compiler during DEBUG builds.")
|
|
tiny_replace_Zi_by_Z7_for(CMAKE_C_FLAGS_DEBUG
|
|
"Flags used by the C compiler during DEBUG builds.")
|
|
|
|
# This should never happen, but I leave it here because it won't hurt anything
|
|
elseif(TINY_BUILD_TYPE_LOWER STREQUAL "release")
|
|
tiny_replace_Zi_by_Z7_for(CMAKE_CXX_FLAGS_RELEASE
|
|
"Flags used by the CXX compiler during RELEASE builds.")
|
|
tiny_replace_Zi_by_Z7_for(CMAKE_C_FLAGS_RELEASE
|
|
"Flags used by the C compiler during RELEASE builds.")
|
|
|
|
elseif(TINY_BUILD_TYPE_LOWER STREQUAL "relwithdebinfo")
|
|
tiny_replace_Zi_by_Z7_for(CMAKE_CXX_FLAGS_RELWITHDEBINFO
|
|
"Flags used by the CXX compiler during RELWITHDEBINFO builds.")
|
|
tiny_replace_Zi_by_Z7_for(CMAKE_C_FLAGS_RELWITHDEBINFO
|
|
"Flags used by the C compiler during RELWITHDEBINFO builds.")
|
|
endif()
|
|
|
|
endfunction()
|
|
|
|
# Fix CMake variables if CMAKE_CXX_COMPILER_LAUNCHER is ccache or sccache
|
|
# It applies fixes for MSVC compiler. It disables precompiled headers as they are not
|
|
# supported on Windows with ccache and changes the -Zi and -ZI compiler options to the -Z7
|
|
# for debug builds for CMake <3.25 as the -Zi and -ZI compiler options is not supported or
|
|
# set up the CMAKE_MSVC_DEBUG_INFORMATION_FORMAT for CMake >=3.25
|
|
# (https://github.com/ccache/ccache/issues/1040)
|
|
function(tiny_fix_ccache_msvc)
|
|
|
|
# I will check only the CMAKE_CXX_COMPILER_LAUNCHER and not also the
|
|
# CMAKE_C_COMPILER_LAUNCHER as this is a pure c++ project and c compiler is not used
|
|
# anyway but I will replace the Zi to Z7 compiler options in both
|
|
# CMAKE_<C|CXX>_FLAGS_<CONFIG> to be consistent 🤔
|
|
|
|
# Fix the MSVC debug information format by the CMake version
|
|
set(isNewMsvcDebugInformationFormat FALSE)
|
|
tiny_is_new_msvc_debug_information_format_325(isNewMsvcDebugInformationFormat)
|
|
|
|
if(isNewMsvcDebugInformationFormat)
|
|
# Support the MSVC debug information format flags added in the CMake 3.25
|
|
tiny_fix_ccache_msvc_325()
|
|
else()
|
|
# Replace /Zi and /ZI by /Z7 in the CMAKE_<C|CXX>_FLAGS_<CONFIG>
|
|
# for the CMake <3.25
|
|
tiny_fix_ccache_msvc_324()
|
|
endif()
|
|
|
|
# Don't disable PCH if no fixes were applied
|
|
# The new MSVC debug information format flags method also supports multi-config generators
|
|
# The old replace (/Zi|/ZI) by /Z7 method doesn't support multi-config generators
|
|
# Don't remove this isNewMsvcDebugInformationFormat check, is correct!
|
|
if(isNewMsvcDebugInformationFormat OR NOT TINY_IS_MULTI_CONFIG)
|
|
tiny_disable_precompile_headers()
|
|
endif()
|
|
|
|
endfunction()
|
|
|
|
# Determine if the current platform needs fixes and the CMAKE_CXX_COMPILER_LAUNCHER
|
|
# contains ccache/sccache (fixes for Clang compilers)
|
|
function(tiny_should_fix_ccache_clang out_variable)
|
|
|
|
# Target the Clang on Linux, MSYS2, and also Clang-cl with MSVC
|
|
if(NOT CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
|
set(${out_variable} FALSE PARENT_SCOPE)
|
|
return()
|
|
endif()
|
|
|
|
# Support the ccache and also sccache (I have tried and sccache doesn't work)
|
|
set(isCcacheCompilerLauncher FALSE)
|
|
tiny_is_ccache_compiler_launcher(isCcacheCompilerLauncher)
|
|
|
|
set(${out_variable} ${isCcacheCompilerLauncher} PARENT_SCOPE)
|
|
|
|
endfunction()
|
|
|
|
# Fix CMake variables if CMAKE_CXX_COMPILER_LAUNCHER is ccache or sccache
|
|
# This is a general function that applies fixes for MSVC and Clang compilers, it checks
|
|
# the current platform and based on it applies correct fixes
|
|
function(tiny_fix_ccache)
|
|
|
|
# MSYS2 g++ or clang++ work well with the precompiled headers but the msvc doesn't
|
|
|
|
# Fixes for the MSVC compiler (including the Clang-cl with MSVC)
|
|
set(shouldFixCcacheMsvc FALSE)
|
|
tiny_should_fix_ccache_msvc(shouldFixCcacheMsvc)
|
|
|
|
if(shouldFixCcacheMsvc)
|
|
tiny_fix_ccache_msvc()
|
|
endif()
|
|
|
|
# Fixes for the Clang compiler on Linux, MSYS2, and also Clang-cl with MSVC
|
|
# Ignore PCH timestamps if the ccache is used (recommended in ccache docs)
|
|
set(shouldFixCcacheClang FALSE)
|
|
tiny_should_fix_ccache_clang(shouldFixCcacheClang)
|
|
|
|
if(shouldFixCcacheClang)
|
|
list(APPEND CMAKE_CXX_COMPILE_OPTIONS_CREATE_PCH -Xclang -fno-pch-timestamp)
|
|
|
|
set(CMAKE_CXX_COMPILE_OPTIONS_CREATE_PCH
|
|
"${CMAKE_CXX_COMPILE_OPTIONS_CREATE_PCH}" PARENT_SCOPE
|
|
)
|
|
endif()
|
|
|
|
endfunction()
|
|
|
|
# Set the Compatible Interface Requirement for the given property names
|
|
#
|
|
# Every TinyORM library sets the Compatible Interface Requirement for the VERSION_MAJOR
|
|
# and SOVERSION target properties.
|
|
#
|
|
# Synopsis:
|
|
# tiny_set_compatible_interface_string(<target>
|
|
# PROPERTIES <name>...
|
|
# )
|
|
#
|
|
# <target> name to operate on.
|
|
# PROPERTIES names list for which to add the Compatible Interface Requirements.
|
|
#
|
|
# PROPERTIES list is passed to the foreach() loop, then set the INTERFACE_<name> <target>
|
|
# property value that is obtained from the <target>'s property <name>, and then the <name>
|
|
# is appended to the COMPATIBLE_INTERFACE_STRING <target> property.
|
|
function(tiny_set_compatible_interface_string target)
|
|
|
|
# Arguments
|
|
set(multiValueArgs PROPERTIES)
|
|
cmake_parse_arguments(PARSE_ARGV 1 TINY "" "" "${multiValueArgs}")
|
|
|
|
# Arguments checks
|
|
if(DEFINED TINY_UNPARSED_ARGUMENTS)
|
|
message(FATAL_ERROR "The ${CMAKE_CURRENT_FUNCTION}() was passed extra arguments: \
|
|
${TINY_UNPARSED_ARGUMENTS}")
|
|
endif()
|
|
|
|
# Body
|
|
foreach(property ${TINY_PROPERTIES})
|
|
# TinyXyz_VERSION_MAJOR or TinyXyz_SOVERSION
|
|
# Don't remove the TinyXyz_ or replace it with eg. TINY_ because these names
|
|
# are exposed to COMPATIBLE_INTERFACE_STRING so it's clearly visible for which
|
|
# targets these names are (although it's strange that a property for the target
|
|
# contains the target name itself).
|
|
set(targetProperty ${target}_${property})
|
|
|
|
# Skip the TinyOrm_VERSION_MAJOR as it's already defined in the main/parent
|
|
# CMakeLists.txt file
|
|
if(NOT (target STREQUAL TinyOrm_target AND property STREQUAL "VERSION_MAJOR"))
|
|
get_target_property(${targetProperty} ${target} ${property})
|
|
endif()
|
|
|
|
set_property(
|
|
TARGET ${target}
|
|
PROPERTY INTERFACE_${targetProperty} ${${targetProperty}}
|
|
)
|
|
|
|
set_property(
|
|
TARGET ${target}
|
|
APPEND PROPERTY COMPATIBLE_INTERFACE_STRING ${targetProperty}
|
|
)
|
|
endforeach()
|
|
|
|
endfunction()
|
|
|
|
# Get target includes that contain IMPORTED targets for the TinyORM package config file
|
|
function(tiny_generate_target_includes out_variable)
|
|
|
|
set(includeTmpl "include(\"\${CMAKE_CURRENT_LIST_DIR}/@target@.cmake\")")
|
|
set(includeReplaced "")
|
|
set(result "")
|
|
|
|
# The order is important here, the TinyDriversTargets must be included before
|
|
# the TinyOrmTargets because of the checks whether the exported targets exist
|
|
# at the end of the TinyOrmTargets.cmake file
|
|
|
|
# TinyDriversTargets
|
|
if(BUILD_DRIVERS)
|
|
string(REPLACE "@target@" "TinyDriversTargets" includeReplaced "${includeTmpl}")
|
|
list(APPEND result ${includeReplaced})
|
|
endif()
|
|
|
|
# TinyOrmTargets
|
|
string(REPLACE "@target@" "TinyOrmTargets" includeReplaced "${includeTmpl}")
|
|
list(APPEND result ${includeReplaced})
|
|
|
|
# No need to escape the ; character as include() statement can't contain it
|
|
list(JOIN result "\n" result)
|
|
|
|
set(${out_variable} ${result} PARENT_SCOPE)
|
|
|
|
endfunction()
|
|
|
|
# Set up package properties using the set_package_properties()
|
|
macro(set_packages_properties) # Exception no tiny_ prefix, that's OK
|
|
|
|
set_package_properties(QT
|
|
PROPERTIES
|
|
URL "https://doc.qt.io/qt-${QT_VERSION_MAJOR}/"
|
|
DESCRIPTION "Qt is a full development framework"
|
|
TYPE REQUIRED
|
|
PURPOSE "Provides SQL database layer by the QtSql module, QVariant, and QString"
|
|
)
|
|
set_package_properties(Qt${QT_VERSION_MAJOR}
|
|
PROPERTIES
|
|
URL "https://doc.qt.io/qt-${QT_VERSION_MAJOR}/"
|
|
DESCRIPTION "Qt is a full development framework"
|
|
TYPE REQUIRED
|
|
PURPOSE "Provides SQL database layer by the QtSql module, QVariant, and QString"
|
|
)
|
|
set_package_properties(Qt${QT_VERSION_MAJOR}Core
|
|
PROPERTIES
|
|
URL "https://doc.qt.io/qt-${QT_VERSION_MAJOR}/qtcore-index.html"
|
|
DESCRIPTION "Core non-graphical classes used by other modules"
|
|
TYPE REQUIRED
|
|
PURPOSE "Provides QVariant, QString, and Qt containers"
|
|
)
|
|
if(NOT BUILD_DRIVERS)
|
|
set_package_properties(Qt${QT_VERSION_MAJOR}Sql
|
|
PROPERTIES
|
|
URL "https://doc.qt.io/qt-${QT_VERSION_MAJOR}/qtsql-index.html"
|
|
DESCRIPTION "Classes for database integration using SQL"
|
|
TYPE REQUIRED
|
|
PURPOSE "Provides SQL database layer"
|
|
)
|
|
endif()
|
|
set_package_properties(range-v3
|
|
PROPERTIES
|
|
URL "https://ericniebler.github.io/range-v3/"
|
|
DESCRIPTION "Range algorithms, views, and actions for STL"
|
|
TYPE REQUIRED
|
|
PURPOSE "Used to have a nice and clear code"
|
|
)
|
|
if(MYSQL_PING OR BUILD_MYSQL_DRIVER)
|
|
if(TINY_VCPKG)
|
|
set_package_properties(unofficial-libmysql
|
|
PROPERTIES
|
|
URL "https://www.mysql.com"
|
|
DESCRIPTION "MySQL client library (vcpkg unofficial)"
|
|
TYPE REQUIRED
|
|
PURPOSE "Provides low-level access to the MySQL client/server \
|
|
protocol (used by mysql-ping or build-mysql-driver vcpkg features)"
|
|
)
|
|
else()
|
|
set_package_properties(MySQL
|
|
PROPERTIES
|
|
# URL and DESCRIPTION are already set by Find-module Package (FindMySQL.cmake)
|
|
TYPE REQUIRED
|
|
PURPOSE "Provides low-level access to the MySQL client/server \
|
|
protocol (used by MySqlConnection::pingDatabase() or if BUILD_MYSQL_DRIVER is enabled)"
|
|
)
|
|
endif()
|
|
endif()
|
|
if(TOM)
|
|
set_package_properties(tabulate
|
|
PROPERTIES
|
|
URL "https://github.com/p-ranav/tabulate"
|
|
DESCRIPTION "Table Maker for Modern C++"
|
|
TYPE REQUIRED
|
|
PURPOSE "Used by the Tom in the migrate:status command"
|
|
)
|
|
endif()
|
|
|
|
endmacro()
|