Files
TinyORM/cmake/CommonModules/TinyCommon.cmake
silverqx d5d9bcdbe2 cmake added/revisited all Synopsis
Function descriptions for functions which call cmake_parse_arguments().
2024-12-09 13:38:38 +01:00

329 lines
14 KiB
CMake

include_guard(GLOBAL)
include(CheckCXXCompilerFlag)
# Common interface library used by all TinyORM targets
#
# Set common variables and create interface-only library target so all other targets
# will be able to link to, either directly or transitively, to consume common compile
# options/definitions.
#
# Synopsis:
# tiny_common(<target>
# NAMESPACE <namespace>
# [EXPORT] NAME <name>
# )
#
# <target> name to operate on.
# NAMESPACE name used for an Alias Target.
# EXPORT set the EXPORT_NAME target property to <name>.
# NAME used for an Alias Target name and EXPORT_NAME target property.
function(tiny_common target)
# Arguments
set(options EXPORT)
set(oneValueArgs NAMESPACE NAME)
cmake_parse_arguments(PARSE_ARGV 1 TINY "${options}" "${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_NAMESPACE}" STREQUAL "" OR "${TINY_NAME}" STREQUAL "")
message(FATAL_ERROR "The ${CMAKE_CURRENT_FUNCTION}() is missing single-valued \
keyword or its value is empty: NAME, NAMESPACE")
endif()
# Body
add_library(${target} INTERFACE)
add_library(${TINY_NAMESPACE}::${TINY_NAME} ALIAS ${target})
if(TINY_EXPORT)
set_target_properties(${target} PROPERTIES EXPORT_NAME ${TINY_NAME})
endif()
# Full C++ 20 support is required
target_compile_features(${target} INTERFACE cxx_std_20)
# Qt defines
# ---
# Disable deprecated APIs up to the given Qt version
# Disable all the APIs deprecated up to Qt v6.9.0 (including)
# Must be disabled with vcpkg because the qtbase port doesn't define it and it causes
# incompatible API, eg. QByteArray::isNull() or QString::toLongLong() is defined
# inline through this QT_CORE_INLINE_SINCE() deprecated macros and we end up
# with multiple defined symbols, which means QtCore is compiled with old API without
# inline because it doesn't define this QT_DISABLE_DEPRECATED_UP_TO and TinyORM has
# inlined symbols. It of course works with shared DLL builds but fails with static/-md
# triplets (builds). It's a good idea to use the same setting for this like qtbase
# has anyway.
# See https://bugreports.qt.io/browse/QTBUG-127070
if(NOT TINY_VCPKG)
target_compile_definitions(${target} INTERFACE
QT_DISABLE_DEPRECATED_UP_TO=0x060900
)
endif()
target_compile_definitions(${target}
INTERFACE
#QT_NO_DEPRECATED_WARNINGS
#QT_WARN_DEPRECATED_UP_TO=0x060900
#QT_ASCII_CAST_WARNINGS
#QT_NO_CAST_FROM_ASCII
#QT_RESTRICTED_CAST_FROM_ASCII
QT_NO_CAST_TO_ASCII
QT_NO_CAST_FROM_BYTEARRAY
# Don't define globally, it's better for compatibility, instead use % when needed
#QT_USE_QSTRINGBUILDER
QT_STRICT_ITERATORS
QT_NO_KEYWORDS
# Disable debug output in Release mode
$<$<NOT:$<CONFIG:Debug>>:QT_NO_DEBUG_OUTPUT>
)
# Platform specific configurations
# ---
# WinApi
# For orientation in these versions, see:
# https://developer.microsoft.com/en-us/windows/downloads/sdk-archive/
# https://microsoft.fandom.com/wiki/List_of_Windows_codenames
# https://en.wikipedia.org/wiki/Windows_11_version_history
# https://en.wikipedia.org/wiki/Microsoft_Windows_SDK
# The ideal case would be not to define these and rely on what is defined
# in <qt_/windows.h> but Qt uses too old values for these, eg. MSYS2 patches these and
# uses the latest versions, so we have to define these manually because the original
# Qt code doesn't maintain these correctly.
# All have to be defined because of checks at the beginning of <qt_windows.h> (fixed)
# WINVER, _WIN32_WINNT, NTDDI_VERSION
if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
# MSYS2 Qt 6 already defines these macros in the Qt6Targets.cmake Qt6::Platform
# which is included in Package Config file. These C macros comes
# from the QtBaseConfigureTests.cmake#qt_internal_ensure_latest_win_nt_api(),
# this functions is doing compile test using the check_cxx_source_compiles(),
# it includes the <windows.h> and checks whether these C macros are defined and
# if they are not then it appends them to the QT_PLATFORM_DEFINITIONS, then
# the QT_PLATFORM_DEFINITIONS is set for the Qt6::Platform interface library.
# So these C macros are set on MSVC (in <sdkddkver.h> is advanced guess logic)
# and are not set on mingw-w64/MSYS2 in the <windows.h> file.
# What means we can't set them on MSYS2 because it throws [-Wmacro-redefined].
# Also, don't use the names like _WIN32_WINNT_WIN10 because eg. fileapi.h
# #include-ed inside the windows.h - winbase.h fails to compile and I don't know
# why, I think it doesn't have access to these macro names and it doesn't know
# the actual value, even if the sdkddkver.h is included before!
# The previous Windows SDK 22621 worked with these names, so maybe there is a bug
# in Windows SDK 26100.
# Flipped expression of : if(MINGW AND QT_VERSION_MAJOR GREATER_EQUAL 6)
if(NOT MINGW OR NOT QT_VERSION_MAJOR GREATER_EQUAL 6)
target_compile_definitions(${target} INTERFACE
# Windows 11 "24H2" - 0x0A000010 - Germanium
WINVER=0x0A00 # _WIN32_WINNT_WIN10
_WIN32_WINNT=0x0A00 # _WIN32_WINNT_WIN10
)
endif()
target_compile_definitions(${target} INTERFACE
# Windows 11 "24H2" - 0x0A000010 - Germanium
NTDDI_VERSION=0x0A000010 # NTDDI_WIN10_GE
# Internet Explorer 11
_WIN32_IE=0x0A00 # _WIN32_IE_IE110
# Exclude unneeded header files
WIN32_LEAN_AND_MEAN
NOMINMAX
# Others
UNICODE _UNICODE
)
endif()
# Compiler and Linker options
# ---
# clang-cl.exe notes:
# /RTC - https://lists.llvm.org/pipermail/cfe-commits/Week-of-Mon-20130902/088105.html
# /bigobj - Clang-cl uses it by default - https://reviews.llvm.org/D12981
if(MSVC)
# Common for MSVC and Clang-cl
target_compile_options(${target} INTERFACE
# Suppress banner and info messages
/nologo
# Is safer to provide this explicitly, qmake do it for MSVC too
/EHsc
/utf-8
# Has to be enabled explicitly
# https://devblogs.microsoft.com/cppblog/msvc-now-correctly-reports-__cplusplus/
/Zc:__cplusplus
# Standards-conforming behavior
/Zc:strictStrings
)
# Increase warning level and Enable Additional Security Checks (Debug builds only)
# Do not change the vcpkg build system (keep its default settings)
if(NOT TINY_VCPKG)
target_compile_options(${target} INTERFACE /W4 $<$<CONFIG:Debug>:/sdl>)
endif()
# Abort compiling on warnings for Debug builds only (excluding vcpkg),
# Release and vcpkg builds must go on as far as possible
if(TinyCompileWarningAsError)
target_compile_options(${target} INTERFACE $<$<CONFIG:Debug>:/WX>)
endif()
if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
target_compile_options(${target} INTERFACE
# Set by default by c++20 but from VS 16.11, can be removed when
# minMsvcReqVersion will be >= 16.11
/permissive-
# Clang-cl 16 throws -Wunused-command-line-argument, so provide it
# only for the MSVC
/guard:cf
/bigobj
# Standards-conforming behavior
/Zc:wchar_t,rvalueCast,inline
/Zc:throwingNew,referenceBinding,ternary
# C/C++ conformant preprocessor
/Zc:preprocessor
/external:anglebrackets /external:W0
# Enable and check it from time to time
# /external:templates-
/wd4702
# Enable only when needed to invoke the MSVC Analyzer
# Also, add external libraries on the CAExcludePath environment variables as
# the /analyze:external- doesn't work in all cases (for me)
# /analyze
# /analyze:external-
)
# TODO cmake this will not work with clang-cl problem is that CMAKE_CXX_SIMULATE_VERSION reports only short version like 19.40, so I can't fix it easily silverqx
# Needed to suppress this because lot of new warnings on latest MSVC, also doesn't
# matter too much because TinyORM compiles even without it with Qt v6, warnings were
# only on Qt v5
if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "19.38.32914.95")
target_compile_definitions(${target} INTERFACE
_SILENCE_STDEXT_ARR_ITERS_DEPRECATION_WARNING
)
endif()
endif()
target_link_options(${target} INTERFACE
/guard:cf
$<$<NOT:$<CONFIG:Debug>>:/OPT:REF,ICF=5>
# /OPT:REF,ICF does not support incremental linking
$<$<CONFIG:RelWithDebInfo>:/INCREMENTAL:NO>
)
# Abort linking on warnings for Debug builds only (excluding vcpkg),
# Release and vcpkg builds must go on as far as possible
if(TinyCompileWarningAsError)
target_link_options(${target} INTERFACE $<$<CONFIG:Debug>:/WX>)
endif()
endif()
if(MINGW)
target_compile_options(${target} INTERFACE
$<$<CXX_COMPILER_ID:Clang,AppleClang>:-Wno-ignored-attributes>
)
# All security flags below are enabled by default on MSYS2 and MinGW-w64
# Legend:
# - ASLR - Address space layout randomization
# - same as PIC on Linux (position-independent code)
# - DEP - Windows Data Execution Prevention feature
# ---
# Linker options (supported by both bfd and LLD):
# --dynamicbase - Randomly rebase at load time by using the ASLR
# --high-entropy-va - ASLR can use the entire 64-bit address space
# --nxcompat - Executable is DEP compatible
# --default-image-base-high - Default image bases over 4GB (ASLR)
# ---
# Can be checked by:
# - Exe64bitDetector.exe -f .\TinyOrm0.dll
# - dumpbin.exe /HEADERS .\TinyOrm0.dll
# TODO cmake MSYS2 track /GUARD:CF progress and enable it when will work everywhere; see: https://gist.github.com/alvinhochun/a65e4177e2b34d551d7ecb02b55a4b0a silverqx
# target_link_options(${target} INTERFACE
# $<$<CONFIG:Debug,RelWithDebInfo>:
# LINKER:--dynamicbase,--high-entropy-va,--nxcompat
# LINKER:--default-image-base-high>
# )
endif()
if(NOT MSVC AND
(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR
CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR
CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
)
# Abort compiling on warnings for Debug builds only (excluding vcpkg),
# Release and vcpkg builds must go on as far as possible
if(TinyCompileWarningAsError)
target_compile_options(${target} INTERFACE
$<$<CONFIG:Debug>:-Werror -Wfatal-errors -pedantic-errors>
)
endif()
target_compile_options(${target} INTERFACE
# -fexceptions for Linux is not needed, it is on by default
-Wall
-Wextra
# Weffc++ is outdated, it warnings about bullshits 🤬, even word about this
# in docs: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110186
# -Weffc++
# CMake already defines it
# -Winvalid-pch
-pedantic
-Wcast-qual
-Wcast-align
-Woverloaded-virtual
-Wold-style-cast
-Wshadow
-Wundef
-Wfloat-equal
-Wformat-security
-Wdouble-promotion
-Wconversion
-Wzero-as-null-pointer-constant
-Wuninitialized
-Wdeprecated-copy-dtor
# Reduce I/O operations (use pipes between commands when possible)
-pipe
)
# Clang 12 still doesn't support -Wstrict-null-sentinel
check_cxx_compiler_flag(-Wstrict-null-sentinel SNS_SUPPORT)
if(SNS_SUPPORT)
target_compile_options(${target} INTERFACE -Wstrict-null-sentinel)
endif()
# Has the potential to catch weird code
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
target_compile_options(${target} INTERFACE -Wdeprecated)
endif()
endif()
# Use faster lld linker on Clang (target the Clang except Clang-cl with MSVC)
# TODO use LINKER_TYPE target property when min. version will be CMake v3.29 silverqx
if(NOT MSVC AND CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND
(CMAKE_VERSION VERSION_LESS "3.29" OR
(CMAKE_VERSION VERSION_GREATER_EQUAL "3.29" AND
NOT DEFINED CMAKE_LINKER_TYPE))
)
find_program(tiny_lld lld)
if(tiny_lld)
target_link_options(${target} INTERFACE -fuse-ld=lld)
endif()
endif()
# Use 64-bit off_t on 32-bit Linux, ensure 64bit offsets are used for filesystem
# accesses for 32bit compilation
if(CMAKE_SYSTEM_NAME STREQUAL "Linux" AND CMAKE_SIZEOF_VOID_P EQUAL 4)
target_compile_definitions(${target} INTERFACE -D_FILE_OFFSET_BITS=64)
endif()
endfunction()