Начало

This commit is contained in:
Andrei Astafev 2019-02-12 19:31:17 +03:00
commit 6e5e08aac0
26 changed files with 802 additions and 0 deletions

49
CMLibBuildTypes.cmake Normal file
View File

@ -0,0 +1,49 @@
cmake_policy(SET CMP0057 NEW)
# Добавление конфигурации для профилирования
if(CMAKE_CONFIGURATION_TYPES)
if(NOT "Profile" IN_LIST CMAKE_CONFIGURATION_TYPES)
list(APPEND CMAKE_CONFIGURATION_TYPES Profile)
endif()
else()
set(_allowed_build_types None Debug Release Profile)
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS ${_allowed_build_types})
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Debug CACHE STRING "" FORCE)
elseif(NOT "${CMAKE_BUILD_TYPE}" IN_LIST _allowed_build_types)
message(FATAL_ERROR "Invalid build type: ${CMAKE_BUILD_TYPE}")
endif()
endif()
if(CMAKE_BUILD_TYPE STREQUAL Profile)
# Ключи компиляции для режима профилирования в зависимости от типа компилятора
if (CMAKE_CXX_COMPILER_IS_Clang OR CMAKE_CXX_COMPILER_IS_GCC)
set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE} -g -p" CACHE STRING "")
set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE} -g -p" CACHE STRING "")
set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} -g -p" CACHE STRING "")
set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}" CACHE STRING "")
set(CMAKE_STATIC_LINKER_FLAGS_PROFILE "${CMAKE_STATIC_LINKER_FLAGS_RELEASE}" CACHE STRING "")
set(CMAKE_MODULE_LINKER_FLAGS_PROFILE "${CMAKE_MODULE_LINKER_FLAGS_RELEASE} -g -p" CACHE STRING "")
elseif (CMAKE_CXX_COMPILER_IS_Intel)
message("Set options for profiling with Intel C++")
elseif (CMAKE_CXX_COMPILER_IS_MSVC)
message("Set options for profiling with Visual Studio C++")
endif()
set(PROFILE 1)
elseif(CMAKE_BUILD_TYPE STREQUAL Debug)
# В режиме отладки подробный вывод сообщений компилятора
set(CMAKE_VERBOSE_MAKEFILE 1)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(DEBUG 1)
elseif(CMAKE_BUILD_TYPE STREQUAL Release)
set(RELEASE 1)
elseif(CMAKE_BUILD_TYPE STREQUAL None)
# Режим None используется для статического анализа кода
set(ANALYSIS 1)
set(CMAKE_VERBOSE_MAKEFILE 1)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# set(USE_CLANG_TIDY ON CACHE BOOL "Use clang-tidy")
# set(USE_CPPCHECK ON CACHE BOOL "Use cppcheck")
# set(USE_PVS_STUDIO ON CACHE BOOL "Use PVS-Studio")
endif()

9
CMLibCPackSources.cmake Normal file
View File

@ -0,0 +1,9 @@
get_property(CPACK_PACKAGE_VERSION GLOBAL PROPERTY VERSION_STR)
set(CPACK_SOURCE_GENERATOR TXZ)
set(CPACK_SOURCE_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME}-${CPACK_PACKAGE_VERSION}")
set(CPACK_IGNORE_FILE "cmake/etc/cpack_ignore.txt")
file(STRINGS ${CPACK_IGNORE_FILE} CPACK_SOURCE_IGNORE_FILES)
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${CPACK_IGNORE_FILE})
include(CPack)
add_custom_target(dist COMMAND ${CMAKE_MAKE_PROGRAM} package_source)

37
CMLibCommon.cmake Normal file
View File

@ -0,0 +1,37 @@
cmake_minimum_required(VERSION 3.3 FATAL_ERROR)
cmake_policy(VERSION 3.0.2..3.7)
if(CMAKE_INSTALL_PREFIX STREQUAL PROJECT_BINARY_DIR)
message(FATAL_ERROR "Cannot install into build directory")
endif()
include(CMLibDisableInSourceBuild)
include(CMakeParseArguments)
include(GNUInstallDirs)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
include(CMLibProjectVersion)
set_project_version()
include(CMLibOrganizationName)
set_organization_name()
include(CMLibInstallInOpt)
include(CMLibLSBInfo)
include(CMLibCompiler)
include(CMLibCompilerFlags)
include(CMLibCompilerFeaturesHPPGenerate)
include(CMLibCommonTargetProperties)
include(CMLibCommonLibraryTarget)
include(CMLibFlagRemove)
include(CMLibBuildTypes)
include(CMLibQtTranslation)
include(CMLibToday)
include(CMLibConfigHPPGenerate)
include(CMLibCPackSources)
include(CMLibUninstall)

View File

@ -0,0 +1,27 @@
# Create a shared and static library
function(add_common_library LIBNAME SOURCES)
add_library(${LIBNAME} OBJECT ${SOURCES})
target_include_directories(${LIBNAME} PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
$<BUILD_INTERFACE:${CMAKE_BINARY_DIR}/include>
$<INSTALL_INTERFACE:include/${LIBNAME}>)
get_property(VER GLOBAL PROPERTY VERSION_STR)
get_property(SOVER GLOBAL PROPERTY VERSION_MAJOR)
set_property(TARGET ${LIBNAME} PROPERTY VERSION "${VER}")
set_property(TARGET ${LIBNAME} PROPERTY SOVERSION "${SOVER}")
set_property(TARGET ${LIBNAME} PROPERTY POSITION_INDEPENDENT_CODE ON)
add_library(${LIBNAME}_shared SHARED $<TARGET_OBJECTS:${LIBNAME}>)
set_target_properties(${LIBNAME}_shared PROPERTIES OUTPUT_NAME ${LIBNAME})
add_library(${LIBNAME}_static STATIC $<TARGET_OBJECTS:${LIBNAME}>)
set_target_properties(${LIBNAME}_static PROPERTIES OUTPUT_NAME ${LIBNAME})
set(_libdir "${CMAKE_BINARY_DIR}/lib")
if(DEFINED ENV{DEB_HOST_MULTIARCH})
string(APPEND _libdir "/$ENV{DEB_HOST_MULTIARCH}")
endif()
set_target_properties(${LIBNAME}_shared PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${_libdir})
set_target_properties(${LIBNAME}_static PROPERTIES ARCHIVE_OUTPUT_DIRECTORY ${_libdir})
endfunction()

View File

@ -0,0 +1,39 @@
include(CMLibLargeFiles)
set(COMMON_CXX_FEATURES
cxx_alias_templates cxx_nullptr cxx_override)
function(common_target_properties Name)
get_target_property(__type ${Name} TYPE)
set(__visibility PUBLIC)
if(__type STREQUAL INTERFACE_LIBRARY)
set(__interface 1)
set(__visibility INTERFACE)
endif()
set(_FILE_OFFSET_BITS ON)
set(_LARGEFILE_SOURCE ON)
set(_LARGEFILE64_SOURCE ON)
use_large_files(${Name} ON)
target_compile_features(${Name} ${__visibility} ${COMMON_CXX_FEATURES})
target_include_directories(${current_target} PUBLIC
$<INSTALL_INTERFACE:include>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
$<BUILD_INTERFACE:${CMAKE_BINARY_DIR}/include>)
if(APPLE)
target_compile_definitions(${Name} ${__visibility} Darwin)
endif()
if(NOT __interface)
if(TARGET Qt5::Core)
target_compile_options(${Name} PUBLIC "${Qt5Core_EXECUTABLE_COMPILE_FLAGS}")
set_target_properties(${Name} PROPERTIES AUTOMOC TRUE AUTORCC TRUE)
endif()
if(TARGET Qt5::Widgets)
set_target_properties(${Name} PROPERTIES AUTOUIC TRUE)
endif()
if(CMAKE_CXX_COMPILER_IS_GCC AND NOT APPLE)
set_target_properties(${Name} PROPERTIES LINK_FLAGS "-Wl,--no-as-needed")
endif()
endif()
endfunction()

24
CMLibCompiler.cmake Normal file
View File

@ -0,0 +1,24 @@
# C compiler name
if(CMAKE_C_COMPILER_ID STREQUAL "Intel")
set(CMAKE_C_COMPILER_IS_INTEL ON)
elseif(CMAKE_C_COMPILER_ID STREQUAL "Clang" OR
CMAKE_C_COMPILER_ID STREQUAL "AppleClang")
set(CMAKE_C_COMPILER_IS_CLANG ON)
elseif(CMAKE_C_COMPILER_ID STREQUAL "GNU")
set(CMAKE_C_COMPILER_IS_GCC ON)
elseif(CMAKE_C_COMPILER_ID STREQUAL "MSVC")
set(CMAKE_C_COMPILER_IS_MSVC ON)
endif()
# C++ compiler name
if(CMAKE_CXX_COMPILER_ID STREQUAL "Intel")
set(CMAKE_CXX_COMPILER_IS_INTEL ON)
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR
CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
set(CMAKE_CXX_COMPILER_IS_CLANG ON)
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
set(CMAKE_CXX_COMPILER_IS_GCC ON)
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
set(CMAKE_CXX_COMPILER_IS_MSVC ON)
endif()

View File

@ -0,0 +1,31 @@
include(WriteCompilerDetectionHeader)
string(TOUPPER ${PROJECT_NAME} _project_name_uppercase)
write_compiler_detection_header(
FILE compiler_features.hpp
PREFIX ${_project_name_uppercase}
COMPILERS GNU Clang MSVC Intel
FEATURES
cxx_nullptr
cxx_override
)
# cxx_std_11
# cxx_alignas
# cxx_alignof
# cxx_attributes
# cxx_auto_type
# cxx_constexpr
# cxx_digit_separators
# cxx_range_for
# ALLOW_UNKNOWN_COMPILERS
# ALLOW_UNKNOWN_COMPILER_VERSIONS
#install(FILES
# compiler_features.hpp
# DESTINATION include
# )
#install(FILES
# ${support_files}
# DESTINATION include/compilers
# )

115
CMLibCompilerFlags.cmake Normal file
View File

@ -0,0 +1,115 @@
# based on https://github.com/bluescarni/yacma
include(CheckCXXCompilerFlag)
macro(CHECK_ENABLE_CXX_FLAG flag)
set(CMAKE_REQUIRED_QUIET TRUE)
check_cxx_compiler_flag("${flag}" CHECK_CXX_FLAG)
unset(CMAKE_REQUIRED_QUIET)
if(CHECK_CXX_FLAG)
message(STATUS "'${flag}': flag is enabled.")
add_compile_options("${flag}")
else()
message(STATUS "'${flag}': flag is NOT supported.")
endif()
# NOTE: check_cxx_compiler stores variables in the cache.
unset(CHECK_CXX_FLAG CACHE)
endmacro()
# Common configuration for GCC, clang and Intel.
if(CMAKE_CXX_COMPILER_IS_CLANG OR CMAKE_CXX_COMPILER_IS_INTEL OR CMAKE_CXX_COMPILER_IS_GCC)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED YES)
set(CMAKE_CXX_EXTENSIONS YES)
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
CHECK_ENABLE_CXX_FLAG(-Wall)
CHECK_ENABLE_CXX_FLAG(-Wextra)
CHECK_ENABLE_CXX_FLAG(-Wnon-virtual-dtor)
CHECK_ENABLE_CXX_FLAG(-Wnoexcept)
CHECK_ENABLE_CXX_FLAG(-Wlogical-op)
CHECK_ENABLE_CXX_FLAG(-Wconversion)
CHECK_ENABLE_CXX_FLAG(-Wdeprecated)
# This limit is supposed to be at least 1024 in C++11, but for some reason
# clang sets this to 256, and gcc to 900.
CHECK_ENABLE_CXX_FLAG(-ftemplate-depth=1024)
CHECK_ENABLE_CXX_FLAG(-Wold-style-cast)
CHECK_ENABLE_CXX_FLAG(-Wdisabled-optimization)
# This is useful when the compiler decides the template backtrace is too verbose.
CHECK_ENABLE_CXX_FLAG(-ftemplate-backtrace-limit=0)
CHECK_ENABLE_CXX_FLAG(-fstack-protector-all)
# A few suggestion flags.
CHECK_ENABLE_CXX_FLAG(-Wsuggest-attribute=pure)
CHECK_ENABLE_CXX_FLAG(-Wsuggest-attribute=const)
CHECK_ENABLE_CXX_FLAG(-Wsuggest-attribute=noreturn)
CHECK_ENABLE_CXX_FLAG(-Wsuggest-attribute=format)
# From GCC 5.
CHECK_ENABLE_CXX_FLAG(-Wodr)
CHECK_ENABLE_CXX_FLAG(-Wsuggest-final-types)
CHECK_ENABLE_CXX_FLAG(-Wsuggest-final-methods)
CHECK_ENABLE_CXX_FLAG(-Wsuggest-override)
# From GCC 6.
CHECK_ENABLE_CXX_FLAG(-Wshift-negative-value)
CHECK_ENABLE_CXX_FLAG(-Wshift-overflow=2)
CHECK_ENABLE_CXX_FLAG(-Wduplicated-cond)
CHECK_ENABLE_CXX_FLAG(-Wnull-dereference)
# From GCC 7.
CHECK_ENABLE_CXX_FLAG(-Wrestrict)
CHECK_ENABLE_CXX_FLAG(-Waligned-new)
# From GCC 8.
CHECK_ENABLE_CXX_FLAG(-Wcast-align=strict)
# This is supposed to produce a nice graphical visualization
# of mismatching template errors.
CHECK_ENABLE_CXX_FLAG(-fdiagnostics-show-template-tree)
CHECK_ENABLE_CXX_FLAG(-fdiagnostics-show-option)
CHECK_ENABLE_CXX_FLAG(-pedantic)
CHECK_ENABLE_CXX_FLAG(-Wcast-align)
CHECK_ENABLE_CXX_FLAG(-Wcast-qual)
CHECK_ENABLE_CXX_FLAG(-Wctor-dtor-privacy)
CHECK_ENABLE_CXX_FLAG(-Wdisabled-optimization)
CHECK_ENABLE_CXX_FLAG(-Wformat=2)
CHECK_ENABLE_CXX_FLAG(-Winit-self)
CHECK_ENABLE_CXX_FLAG(-Wmissing-include-dirs)
CHECK_ENABLE_CXX_FLAG(-Woverloaded-virtual)
CHECK_ENABLE_CXX_FLAG(-Wredundant-decls)
CHECK_ENABLE_CXX_FLAG(-Wsign-promo)
CHECK_ENABLE_CXX_FLAG(-Wstrict-overflow=5)
CHECK_ENABLE_CXX_FLAG(-Wundef)
CHECK_ENABLE_CXX_FLAG(-Wno-unused)
CHECK_ENABLE_CXX_FLAG(-Wno-variadic-macros)
CHECK_ENABLE_CXX_FLAG(-Wno-parentheses)
CHECK_ENABLE_CXX_FLAG(-Wstrict-null-sentinel)
CHECK_ENABLE_CXX_FLAG(-Wshadow)
CHECK_ENABLE_CXX_FLAG(-Wshadow-all)
endif()
if(CMAKE_BUILD_TYPE STREQUAL "Release")
CHECK_ENABLE_CXX_FLAG(-flto)
if(CMAKE_CXX_COMPILER_IS_GCC AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER "4.8")
# Doesn't work with GCC 4.7.2 in Astra Linux 1.5
CHECK_ENABLE_CXX_FLAG(-fno-fat-lto-objects)
endif()
endif()
endif()
if (CMAKE_CXX_COMPILER_IS_GCC)
CHECK_ENABLE_CXX_FLAG(-fdiagnostics-color=auto)
# The -Wmaybe-uninitialized flag is enabled by -Wall, but it is known
# to emit a lot of possibly spurious warnings. Let's just disable it.
CHECK_ENABLE_CXX_FLAG(-Wno-maybe-uninitialized)
if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER "5.999")
# NOTE: GCC >= 6 seems to be wrongly warning about visibility attributes
# in some situations:
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80947
# Let's just disable the warning for now.
CHECK_ENABLE_CXX_FLAG(-Wno-attributes)
endif()
endif()
if(CMAKE_SYSTEM_PROCESSOR STREQUAL "e2k")
add_definitions(-DQT_NO_VERSION_TAGGING)
list(APPEND CMAKE_LIBRARY_PATH "/usr/lib/e2k-linux-gnu")
endif()

View File

@ -0,0 +1,7 @@
function(cmlib_config_hpp_generate)
get_property(VERSION_INT GLOBAL PROPERTY VERSION_INT)
get_property(VERSION_STR GLOBAL PROPERTY VERSION_STR)
get_property(ORGANIZATION_NAME GLOBAL PROPERTY ORGANIZATION_NAME)
string(TOUPPER ${PROJECT_NAME} PROJECT_NAME_UPPERCASE)
configure_file(${CMAKE_SOURCE_DIR}/cmake/cmlib/hpp/config.hpp.in ${CMAKE_BINARY_DIR}/include/config.hpp)
endfunction()

View File

@ -0,0 +1,14 @@
# Запись результатов сборки проекта внутрь иерархии каталогов
# с исходными текстами приводит к засорению файлами формируемыми
# на этапе сборки, которые затрудняют разработку, поиск в оригинальных
# файлах и мешают ориентироваться в проекте. При работе с несколькими
# типами сборки, например, отладка и выпуск, появляется необходимость
# корректного полного удаления результатов предыдущего варианта.
get_filename_component(_source_realpath "${CMAKE_SOURCE_DIR}" REALPATH)
get_filename_component(_binary_realpath "${CMAKE_BINARY_DIR}" REALPATH)
if(${_source_realpath} STREQUAL ${_binary_realpath})
message(FATAL_ERROR "In-source builds are not allowed.")
endif()

71
CMLibFlagRemove.cmake Normal file
View File

@ -0,0 +1,71 @@
# https://stackoverflow.com/a/49216539
#
# Removes the specified compile flag from the specified target.
# _target - The target to remove the compile flag from
# _flag - The compile flag to remove
#
# Pre: apply_global_cxx_flags_to_all_targets() must be invoked.
#
macro(remove_flag_from_target _target _flag)
get_target_property(_target_cxx_flags ${_target} COMPILE_OPTIONS)
if(_target_cxx_flags)
list(REMOVE_ITEM _target_cxx_flags ${_flag})
set_target_properties(${_target} PROPERTIES COMPILE_OPTIONS "${_target_cxx_flags}")
endif()
endmacro()
#
# Removes the specified compiler flag from the specified file.
# _target - The target that _file belongs to
# _file - The file to remove the compiler flag from
# _flag - The compiler flag to remove.
#
# Pre: apply_global_cxx_flags_to_all_targets() must be invoked.
#
macro(remove_flag_from_file _target _file _flag)
get_target_property(_target_sources ${_target} SOURCES)
# Check if a sync is required, in which case we'll force a rewrite of the cache variables.
if(_flag_sync_required)
unset(_cached_${_target}_cxx_flags CACHE)
unset(_cached_${_target}_${_file}_cxx_flags CACHE)
endif()
get_target_property(_${_target}_cxx_flags ${_target} COMPILE_OPTIONS)
# On first entry, cache the target compile flags and apply them to each source file
# in the target.
if(NOT _cached_${_target}_cxx_flags)
# Obtain and cache the target compiler options, then clear them.
get_target_property(_target_cxx_flags ${_target} COMPILE_OPTIONS)
set(_cached_${_target}_cxx_flags "${_target_cxx_flags}" CACHE INTERNAL "")
set_target_properties(${_target} PROPERTIES COMPILE_OPTIONS "")
# Apply the target compile flags to each source file.
foreach(_source_file ${_target_sources})
# Check for pre-existing flags set by set_source_files_properties().
get_source_file_property(_source_file_cxx_flags ${_source_file} COMPILE_FLAGS)
if(_source_file_cxx_flags)
separate_arguments(_source_file_cxx_flags UNIX_COMMAND ${_source_file_cxx_flags})
list(APPEND _source_file_cxx_flags "${_target_cxx_flags}")
else()
set(_source_file_cxx_flags "${_target_cxx_flags}")
endif()
# Apply the compile flags to the current source file.
string(REPLACE ";" " " _source_file_cxx_flags_string "${_source_file_cxx_flags}")
set_source_files_properties(${_source_file} PROPERTIES COMPILE_FLAGS "${_source_file_cxx_flags_string}")
endforeach()
endif()
list(FIND _target_sources ${_file} _file_found_at)
if(_file_found_at GREATER -1)
if(NOT _cached_${_target}_${_file}_cxx_flags)
# Cache the compile flags for the specified file.
# This is the list that we'll be removing flags from.
get_source_file_property(_source_file_cxx_flags ${_file} COMPILE_FLAGS)
separate_arguments(_source_file_cxx_flags UNIX_COMMAND ${_source_file_cxx_flags})
set(_cached_${_target}_${_file}_cxx_flags ${_source_file_cxx_flags} CACHE INTERNAL "")
endif()
# Remove the specified flag, then re-apply the rest.
list(REMOVE_ITEM _cached_${_target}_${_file}_cxx_flags ${_flag})
string(REPLACE ";" " " _cached_${_target}_${_file}_cxx_flags_string "${_cached_${_target}_${_file}_cxx_flags}")
set_source_files_properties(${_file} PROPERTIES COMPILE_FLAGS "${_cached_${_target}_${_file}_cxx_flags_string}")
endif()
endmacro()

6
CMLibInstallInOpt.cmake Normal file
View File

@ -0,0 +1,6 @@
option(INSTALL_TO_OPT "Install to proprietary /opt hierarchy" FALSE)
if(INSTALL_TO_OPT)
string(TOLOWER "/opt/${ORGANIZATION_NAME}/${PROJECT_NAME}" CMAKE_INSTALL_PREFIX)
endif()

21
CMLibLSBInfo.cmake Normal file
View File

@ -0,0 +1,21 @@
if(LSB_RELEASE)
return()
endif()
find_program(_lsb_release_executable lsb_release)
if(_lsb_release_executable)
execute_process(COMMAND ${_lsb_release_executable} -sc
OUTPUT_VARIABLE LSB_CODENAME OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process(COMMAND ${_lsb_release_executable} -sr
OUTPUT_VARIABLE LSB_RELEASE OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process(COMMAND ${_lsb_release_executable} -si
OUTPUT_VARIABLE LSB_DISTRIBUTOR_ID OUTPUT_STRIP_TRAILING_WHITESPACE)
else()
set(LSB_DISTRIBUTOR_ID "unknown")
set(LSB_RELEASE "unknown")
set(LSB_CODENAME "unknown")
endif()

107
CMLibLargeFiles.cmake Normal file
View File

@ -0,0 +1,107 @@
macro(test_large_files VARIABLE USE_64_SUFFIX)
if(NOT DEFINED ${VARIABLE})
message(STATUS "Checking if large (64-bit) file support is available...")
if(USE_64_SUFFIX)
set(SUFFIX_64 "64")
else(USE_64_SUFFIX)
set(SUFFIX_64 "")
endif(USE_64_SUFFIX)
# First try without any macros defined
try_compile(LARGE_FILES_SUPPORTED "${CMAKE_BINARY_DIR}"
"${CMAKE_MODULE_PATH}/tests/LargeFiles${SUFFIX_64}.c"
OUTPUT_VARIABLE TRY_LARGE_FILES_OUTPUT)
if(VERBOSE_LARGE_FILES)
message(STATUS "Large file output (no special flags):\n${TRY_LARGE_FILES_OUTPUT}")
endif(VERBOSE_LARGE_FILES)
if(NOT LARGE_FILES_SUPPORTED)
# Try with C macro _FILE_OFFSET_BITS=64
try_compile(LARGE_FILES_SUPPORTED "${CMAKE_BINARY_DIR}"
"${CMAKE_MODULE_PATH}/tests/LargeFiles${SUFFIX_64}.c"
COMPILE_DEFINITIONS "-D_FILE_OFFSET_BITS=64"
OUTPUT_VARIABLE TRY_LARGE_FILES_OUTPUT)
if(VERBOSE_LARGE_FILES)
message(STATUS "Large file output (_FILE_OFFSET_BITS=64):\n${TRY_LARGE_FILES_OUTPUT}")
endif(VERBOSE_LARGE_FILES)
if(LARGE_FILES_SUPPORTED)
set(_FILE_OFFSET_BITS=64 CACHE INTERNAL "C macro _FILE_OFFSET_BITS=64 is required for 64-bit file support")
endif(LARGE_FILES_SUPPORTED)
endif(NOT LARGE_FILES_SUPPORTED)
if(NOT LARGE_FILES_SUPPORTED)
# Try with C macro _LARGEFILE_SOURCE
try_compile(LARGE_FILES_SUPPORTED "${CMAKE_BINARY_DIR}"
"${CMAKE_MODULE_PATH}/tests/LargeFiles${SUFFIX_64}.c"
COMPILE_DEFINITIONS "-D_LARGEFILE${SUFFIX_64}_SOURCE"
OUTPUT_VARIABLE TRY_LARGE_FILES_OUTPUT)
if(VERBOSE_LARGE_FILES)
message(STATUS "Large file output (_LARGEFILE${SUFFIX_64}_SOURCE):\n${TRY_LARGE_FILES_OUTPUT}")
endif(VERBOSE_LARGE_FILES)
if(LARGE_FILES_SUPPORTED)
set(_LARGEFILE${SUFFIX_64}_SOURCE=1 CACHE INTERNAL "C macro _LARGEFILE${SUFFIX_64}_SOURCE is required for 64-bit file support")
endif(LARGE_FILES_SUPPORTED)
endif(NOT LARGE_FILES_SUPPORTED)
if(NOT LARGE_FILES_SUPPORTED)
# Try with both C macro _FILE_OFFSET_BITS=64 and _LARGEFILE_SOURCE
try_compile(LARGE_FILES_SUPPORTED "${CMAKE_BINARY_DIR}"
"${CMAKE_MODULE_PATH}/tests/LargeFiles${SUFFIX_64}.c"
COMPILE_DEFINITIONS "-D_FILE_OFFSET_BITS=64" "-D_LARGEFILE${SUFFIX_64}_SOURCE"
OUTPUT_VARIABLE TRY_LARGE_FILES_OUTPUT)
if(VERBOSE_LARGE_FILES)
message(STATUS "Large file output (_FILE_OFFSET_BITS=64 and _LARGEFILE${SUFFIX_64}_SOURCE):\n${TRY_LARGE_FILES_OUTPUT}")
endif(VERBOSE_LARGE_FILES)
if(LARGE_FILES_SUPPORTED)
set(_FILE_OFFSET_BITS=64 CACHE INTERNAL "C macro _FILE_OFFSET_BITS=64 is required for 64-bit file support")
set(_LARGEFILE${SUFFIX_64}_SOURCE=1 CACHE INTERNAL "C macro _LARGEFILE${SUFFIX_64}_SOURCE is required for 64-bit file support")
endif(LARGE_FILES_SUPPORTED)
endif(NOT LARGE_FILES_SUPPORTED)
if(NOT LARGE_FILES_SUPPORTED)
# Maybe we are using the Windows C standard library
try_compile(LARGE_FILES_SUPPORTED "${CMAKE_BINARY_DIR}"
"${CMAKE_MODULE_PATH}/tests/LargeFilesWindows.c")
endif(NOT LARGE_FILES_SUPPORTED)
if(LARGE_FILES_SUPPORTED)
message(STATUS "Checking if large (64-bit) file support is available - yes")
set(${VARIABLE} 1 CACHE INTERNAL "Is large file support available?")
else(LARGE_FILES_SUPPORTED)
message(STATUS "Checking if large (64-bit) file support is available - no")
set(${VARIABLE} 0 CACHE INTERNAL "Is large file support available?")
endif(LARGE_FILES_SUPPORTED)
endif(NOT DEFINED ${VARIABLE})
endmacro(test_large_files VARIABLE USE_64_SUFFIX)
macro(use_large_files TARGET USE_64_SUFFIX)
test_large_files(USING_LARGE_FILES ${USE_64_SUFFIX})
if(USING_LARGE_FILES)
if(DEFINED _FILE_OFFSET_BITS)
set_property(TARGET ${TARGET}
APPEND PROPERTY COMPILE_DEFINITIONS "_FILE_OFFSET_BITS=${_FILE_OFFSET_BITS}")
endif(DEFINED _FILE_OFFSET_BITS)
if(DEFINED _LARGEFILE_SOURCE)
set_property(TARGET ${TARGET}
APPEND PROPERTY COMPILE_DEFINITIONS "_LARGEFILE_SOURCE")
endif(DEFINED _LARGEFILE_SOURCE)
if(DEFINED _LARGEFILE64_SOURCE)
set_property(TARGET ${TARGET}
APPEND PROPERTY COMPILE_DEFINITIONS "_LARGEFILE64_SOURCE")
endif(DEFINED _LARGEFILE64_SOURCE)
else(USING_LARGE_FILES)
message(FATAL_ERROR "Large file support not available")
endif(USING_LARGE_FILES)
endmacro(use_large_files TARGET USE_64_SUFFIX)

View File

@ -0,0 +1,19 @@
# read file cmake/etc/organization.txt and set global property ORGANIZATION_NAME
function(set_organization_name)
set(_organization_file "${CMAKE_SOURCE_DIR}/cmake/etc/organization.txt")
if(NOT EXISTS "${_organization_file}")
message(FATAL_ERROR "File ${ORGANIZATION_FILE} doesn't exist")
endif()
file(READ "${_organization_file}" _org)
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${_organization_file})
if(NOT "${_org}" MATCHES "^([0-9A-Za-z ,.]+)\n")
message(FATAL_ERROR "File ${_organization_file} has wrong format")
endif()
string(REGEX MATCH "^([0-9A-Za-z ,.]+)\n" _ ${_org})
set_property(GLOBAL PROPERTY ORGANIZATION_NAME ${CMAKE_MATCH_1})
endfunction()

25
CMLibProjectVersion.cmake Normal file
View File

@ -0,0 +1,25 @@
# read file cmake/etc/version.txt and set global properties
# VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH, VERSION_INT and VERSION_STR
function(set_project_version)
set(_version_file "${CMAKE_SOURCE_DIR}/cmake/etc/version.txt")
if(NOT EXISTS "${_version_file}")
message(FATAL_ERROR "File ${_version_file} doesn't exists")
endif()
file(READ "${_version_file}" _version)
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${_version_file})
if(NOT "${_version}" MATCHES "^([0-9]+)\\.([0-9]+)\\.([0-9]+)\n")
message(FATAL_ERROR "${_version_file} has wrong format")
endif()
string(REGEX MATCH "^([0-9]+)\\.([0-9]+)\\.([0-9]+)\n" _ ${_version})
set_property(GLOBAL PROPERTY VERSION_MAJOR ${CMAKE_MATCH_1})
set_property(GLOBAL PROPERTY VERSION_MINOR ${CMAKE_MATCH_2})
set_property(GLOBAL PROPERTY VERSION_PATCH ${CMAKE_MATCH_3})
math(EXPR _version_int "(${CMAKE_MATCH_1} << 16) + (${CMAKE_MATCH_2} << 8) + ${CMAKE_MATCH_3}")
set_property(GLOBAL PROPERTY VERSION_INT ${_version_int})
set_property(GLOBAL PROPERTY VERSION_STR "${CMAKE_MATCH_1}.${CMAKE_MATCH_2}.${CMAKE_MATCH_3}")
endfunction()

54
CMLibQtTranslation.cmake Normal file
View File

@ -0,0 +1,54 @@
function(qt_translation)
find_package(Qt5 COMPONENTS LinguistTools REQUIRED)
set(options)
set(oneValueArgs TARGET TS_DIR)
set(multiValueArgs LANGUAGES)
cmake_parse_arguments(_QTTR "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
set(_target ${_QTTR_TARGET})
set(_ts_dir ${_QTTR_TS_DIR})
set(_languages ${_QTTR_LANGUAGES})
get_target_property(_sources ${_target} SOURCES)
get_target_property(_source_dir ${_target} SOURCE_DIR)
set(L10N_QRC_BODY "")
make_directory(${_ts_dir})
set(_sources_list "")
foreach(_s ${_sources})
list(APPEND _sources_list ${_source_dir}/${_s})
endforeach()
foreach(_lang ${_languages})
set(_ts "${_target}_${_lang}.ts")
set(_qm "${_target}_${_lang}.qm")
list(APPEND _ts_list ${_ts_dir}/${_ts})
if(NOT EXISTS ${_ts_dir}/${_ts})
file(WRITE ${_ts_dir}/${_ts} "<?xml version=\"1.0\" encoding=\"utf-8\"?>
<!DOCTYPE TS>
<TS version=\"2.1\" language=\"${_lang}\"></TS>")
endif()
string(APPEND L10N_QRC_BODY "<file alias=\"${_qm}\">${CMAKE_BINARY_DIR}/${_qm}</file>\n")
add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/${_qm}
COMMAND ${Qt5_LRELEASE_EXECUTABLE} ARGS ${_ts_dir}/${_ts} -qm ${CMAKE_BINARY_DIR}/${_qm}
DEPENDS ${_ts_dir}/${_ts})
endforeach()
add_custom_command(OUTPUT ${_ts_list}
COMMAND ${Qt5_LUPDATE_EXECUTABLE} ARGS ${_sources_list} -ts ${_ts_list})
configure_file(${CMAKE_SOURCE_DIR}/cmake/cmlib/qrc/l10n.qrc.in ${CMAKE_BINARY_DIR}/${_target}_l10n.qrc)
qt5_add_resources(_qrc ${CMAKE_BINARY_DIR}/${_target}_l10n.qrc)
add_custom_target(_qrc_target DEPENDS ${_qrc})
foreach(_lang ${_languages})
set(_ts "${_target}_${_lang}.ts")
set(_qm "${_target}_${_lang}.qm")
endforeach()
add_dependencies(${_target} _qrc_target)
target_sources(${_target} PUBLIC ${_qrc})
endfunction()

8
CMLibToday.cmake Normal file
View File

@ -0,0 +1,8 @@
if(NOT TODAY)
if(WIN32)
execute_process(COMMAND "cmd" " /C date /T" OUTPUT_VARIABLE TODAY)
else()
execute_process(COMMAND "date" "+%d/%m/%Y" OUTPUT_VARIABLE TODAY)
endif()
string(REGEX REPLACE "(..)/(..)/(....).*" "\\3-\\2-\\1" TODAY ${TODAY})
endif()

9
CMLibUninstall.cmake Normal file
View File

@ -0,0 +1,9 @@
if(NOT TARGET uninstall)
configure_file(
"${CMAKE_SOURCE_DIR}/cmake/cmlib/CMLibUninstall.cmake.in"
"${CMAKE_BINARY_DIR}/cmake_uninstall.cmake"
IMMEDIATE @ONLY)
add_custom_target(uninstall
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_BINARY_DIR}/cmake_uninstall.cmake)
endif()

22
CMLibUninstall.cmake.in Normal file
View File

@ -0,0 +1,22 @@
if(NOT EXISTS "@CMAKE_BINARY_DIR@/install_manifest.txt")
message(FATAL_ERROR "Cannot find install manifest: @CMAKE_BINARY_DIR@/install_manifest.txt")
endif(NOT EXISTS "@CMAKE_BINARY_DIR@/install_manifest.txt")
file(READ "@CMAKE_BINARY_DIR@/install_manifest.txt" files)
string(REGEX REPLACE "\n" ";" files "${files}")
foreach(file ${files})
message(STATUS "Uninstalling $ENV{DESTDIR}${file}")
if(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
exec_program(
"@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\""
OUTPUT_VARIABLE rm_out
RETURN_VALUE rm_retval
)
if(NOT "${rm_retval}" STREQUAL 0)
message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}")
endif(NOT "${rm_retval}" STREQUAL 0)
else(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
message(STATUS "File $ENV{DESTDIR}${file} does not exist.")
endif(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
endforeach(file)

49
README.md Normal file
View File

@ -0,0 +1,49 @@
# CMake Modules
Репозиторий модулей для CMake.
## Установка
В каталоге проекта выполнить команду
```sh
git submodule add ssh://git@host/user/cmlib cmake/cmlib
```
заменив `host` и `user` на нужные значения.
## Использование
В основном для проекта файле `CMakeLists.txt` добавить:
```cmake
if(IS_DIRECTORY ${CMAKE_SOURCE_DIR}/cmake/cmlib)
list(INSERT CMAKE_MODULE_PATH 0 ${CMAKE_SOURCE_DIR}/cmake/cmlib)
else()
message(FATAL_ERROR "CMake library directory not exists")
endif()
include(CMLibCommon)
```
Создать файл `cmake/etc/version.txt`, в который нужно
записать номер версии проекта, отвечающий стандарту
[семантического версионирования](https://semver.org/lang/ru/).
В файле `cmake/etc/organization.txt` записать название
организации, которой принадлежит проект.
В файле `cmake/etc/cpack_ignore.txt` перечислить шаблоны
для исключения из создаваемого целью `dist` архива. Например,
```
cmake/lib/.git$
.git$
files/var
CMakeLists.txt.user
~$
\\\\..*\\\\.bak$
\\\\..*\\\\.tmp$
\\\\..*\\\\.swp$
```

15
hpp/config.hpp.in Normal file
View File

@ -0,0 +1,15 @@
#ifndef @PROJECT_NAME_UPPERCASE@_CONFIG_HPP_
#define @PROJECT_NAME_UPPERCASE@_CONFIG_HPP_
#define @PROJECT_NAME_UPPERCASE@_VERSION_STR "@VERSION_STR@"
#define @PROJECT_NAME_UPPERCASE@_VERSION_INT @VERSION_INT@
#define ORGANIZATION_NAME "@ORGANIZATION_NAME@"
#define PROJECT_NAME "@CMAKE_PROJECT_NAME@"
#define BUILD_TYPE "@CMAKE_BUILD_TYPE@"
#define BUILD_DATE "@TODAY@"
#cmakedefine PROFILE @PROFILE@
#cmakedefine DEBUG @DEBUG@
#cmakedefine RELEASE @RELEASE@
#cmakedefine ANALYSIS @ANALYSIS@
#endif // @PROJECT_NAME_UPPERCASE@_CONFIG_HPP_

5
qrc/l10n.qrc.in Normal file
View File

@ -0,0 +1,5 @@
<RCC>
<qresource prefix="/qm">
@L10N_QRC_BODY@
</qresource>
</RCC>

15
tests/LargeFiles.c Normal file
View File

@ -0,0 +1,15 @@
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
#define VALID_ARRAY_LENGTH 1
#define INVALID_ARRAY_LENGTH -1
int main(int argc, const char **argv)
{
int a[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? VALID_ARRAY_LENGTH : INVALID_ARRAY_LENGTH];
off_t offset = ftello(NULL);
fseeko(NULL, offset, SEEK_SET);
return 0;
}

16
tests/LargeFiles64.c Normal file
View File

@ -0,0 +1,16 @@
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
#define VALID_ARRAY_LENGTH 1
#define INVALID_ARRAY_LENGTH -1
int main(int argc, const char **argv)
{
int a[(LARGE_OFF_T % 2147483629 == 721 && LARGE_OFF_T % 2147483647 == 1) ? VALID_ARRAY_LENGTH : INVALID_ARRAY_LENGTH];
off64_t offset = ftello64(NULL);
fseeko64(NULL, offset, SEEK_SET);
return 0;
}

View File

@ -0,0 +1,8 @@
#include <stdio.h>
int main()
{
__int64 off = 0;
_fseeki64(NULL, off, SEEK_SET);
return 0;
}