|
|
@@ -211,18 +211,39 @@ endfunction()
|
|
|
#[[
|
|
|
Find Qt libraries. Don't wrap it in any functions.
|
|
|
|
|
|
- qm_find_qt(<modules...>)
|
|
|
+ qm_find_qt(<modules...> [QUIET | REQUIRED | EXACT])
|
|
|
#]]
|
|
|
macro(qm_find_qt)
|
|
|
- foreach(_module ${ARGN})
|
|
|
+ set(options QUIET REQUIRED EXACT)
|
|
|
+ set(oneValueArgs)
|
|
|
+ set(multiValueArgs)
|
|
|
+ cmake_parse_arguments(FUNC "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
|
|
+
|
|
|
+ set(_qm_find_qt_options)
|
|
|
+
|
|
|
+ if(FUNC_QUIET)
|
|
|
+ list(APPEND _qm_find_qt_options QUIET)
|
|
|
+ elseif(FUNC_REQUIRED)
|
|
|
+ list(APPEND _qm_find_qt_options REQUIRED)
|
|
|
+ elseif(FUNC_EXACT)
|
|
|
+ list(APPEND _qm_find_qt_options EXACT)
|
|
|
+ endif()
|
|
|
+
|
|
|
+ if(NOT _qm_find_qt_options)
|
|
|
+ set(_qm_find_qt_options REQUIRED)
|
|
|
+ endif()
|
|
|
+
|
|
|
+ foreach(_module ${FUNC_UNPARSED_ARGUMENTS})
|
|
|
if(NOT QT_VERSION_MAJOR)
|
|
|
- find_package(QT NAMES ${QMSETUP_FIND_QT_ORDER} COMPONENTS ${_module} REQUIRED)
|
|
|
+ find_package(QT NAMES ${QMSETUP_FIND_QT_ORDER} COMPONENTS ${_module} ${_qm_find_qt_options})
|
|
|
endif()
|
|
|
|
|
|
if(NOT TARGET Qt${QT_VERSION_MAJOR}::${_module})
|
|
|
- find_package(Qt${QT_VERSION_MAJOR} COMPONENTS ${_module} REQUIRED)
|
|
|
+ find_package(Qt${QT_VERSION_MAJOR} COMPONENTS ${_module} ${_qm_find_qt_options})
|
|
|
endif()
|
|
|
endforeach()
|
|
|
+
|
|
|
+ unset(_qm_find_qt_options)
|
|
|
endmacro()
|
|
|
|
|
|
#[[
|
|
|
@@ -244,8 +265,13 @@ endmacro()
|
|
|
#]]
|
|
|
macro(qm_include_qt_private _target _scope)
|
|
|
foreach(_module ${ARGN})
|
|
|
- qm_find_qt(${_module})
|
|
|
- target_include_directories(${_target} ${_scope} ${Qt${QT_VERSION_MAJOR}${_module}_PRIVATE_INCLUDE_DIRS})
|
|
|
+ qm_find_qt(${_module}Private QUIET)
|
|
|
+ if (TARGET Qt${QT_VERSION_MAJOR}::${_module}Private)
|
|
|
+ target_link_libraries(${_target} ${_scope} Qt${QT_VERSION_MAJOR}::${_module}Private)
|
|
|
+ else()
|
|
|
+ qm_find_qt(${_module})
|
|
|
+ target_include_directories(${_target} ${_scope} ${Qt${QT_VERSION_MAJOR}${_module}_PRIVATE_INCLUDE_DIRS})
|
|
|
+ endif()
|
|
|
endforeach()
|
|
|
endmacro()
|
|
|
|
|
|
@@ -253,31 +279,40 @@ endmacro()
|
|
|
Helper to set or append all kinds of attributes to a target. Don't wrap it in any functions.
|
|
|
|
|
|
qm_configure_target(<target>
|
|
|
- [SOURCES <files>]
|
|
|
+ [SOURCES <files>]
|
|
|
|
|
|
- [LINKS <libs>]
|
|
|
- [LINKS_PRIVATE <libs>]
|
|
|
+ [LINKS <libs>]
|
|
|
+ [LINKS_INTERFACE <libs>]
|
|
|
+ [LINKS_PRIVATE <libs>]
|
|
|
|
|
|
- [INCLUDE <dirs>]
|
|
|
- [INCLUDE_PRIVATE <dirs>]
|
|
|
+ [INCLUDE <dirs>]
|
|
|
+ [INCLUDE_INTERFACE <dirs>]
|
|
|
+ [INCLUDE_PRIVATE <dirs>]
|
|
|
|
|
|
- [LINKDIR <dirs>]
|
|
|
- [LINKDIR_PRIVATE <dirs>]
|
|
|
+ [LINKDIR <dirs>]
|
|
|
+ [LINKDIR_INTERFACE <dirs>]
|
|
|
+ [LINKDIR_PRIVATE <dirs>]
|
|
|
|
|
|
- [DEFINES <defs>]
|
|
|
- [DEFINES_PRIVATE <defs>]
|
|
|
+ [DEFINES <defs>]
|
|
|
+ [DEFINES_INTERFACE <defs>]
|
|
|
+ [DEFINES_PRIVATE <defs>]
|
|
|
|
|
|
- [FEATURES <features>]
|
|
|
- [FEATURES_PRIVATE <features>]
|
|
|
+ [FEATURES <features>]
|
|
|
+ [FEATURES_INTERFACE <features>]
|
|
|
+ [FEATURES_PRIVATE <features>]
|
|
|
|
|
|
- [CCFLAGS <flags>]
|
|
|
- [CCFLAGS_PUBLIC <flags>]
|
|
|
+ [CCFLAGS <flags>]
|
|
|
+ [CCFLAGS_INTERFACE <flags>]
|
|
|
+ [CCFLAGS_PUBLIC <flags>]
|
|
|
|
|
|
- [LDFLAGS <flags>]
|
|
|
- [LDFLAGS_PUBLIC <flags>]
|
|
|
+ [LDFLAGS <flags>]
|
|
|
+ [LDFLAGS_INTERFACE <flags>]
|
|
|
+ [LDFLAGS_PUBLIC <flags>]
|
|
|
|
|
|
[QT_LINKS <modules>]
|
|
|
+ [QT_LINKS_INTERFACE <modules>]
|
|
|
[QT_LINKS_PRIVATE <modules>]
|
|
|
+
|
|
|
[QT_INCLUDE_PRIVATE <modules>]
|
|
|
|
|
|
[SKIP_AUTOMOC <dir/file...>]
|
|
|
@@ -291,98 +326,96 @@ macro(qm_configure_target _target)
|
|
|
set(oneValueArgs)
|
|
|
set(multiValueArgs
|
|
|
SOURCES
|
|
|
- LINKS LINKS_PRIVATE
|
|
|
- INCLUDE INCLUDE_PRIVATE
|
|
|
- LINKDIR LINKDIR_PRIVATE
|
|
|
- DEFINES DEFINES_PRIVATE
|
|
|
- FEATURES FEATURES_PRIVATE
|
|
|
- CCFLAGS CCFLAGS_PUBLIC
|
|
|
- LDFLAGS LDFLAGS_PUBLIC
|
|
|
- QT_LINKS QT_LINKS_PRIVATE QT_INCLUDE_PRIVATE
|
|
|
+ LINKS LINKS_INTERFACE LINKS_PRIVATE
|
|
|
+ INCLUDE INCLUDE_INTERFACE INCLUDE_PRIVATE
|
|
|
+ LINKDIR LINKDIR_INTERFACE LINKDIR_PRIVATE
|
|
|
+ DEFINES DEFINES_INTERFACE DEFINES_PRIVATE
|
|
|
+ FEATURES FEATURES_INTERFACE FEATURES_PRIVATE
|
|
|
+ CCFLAGS CCFLAGS_INTERFACE CCFLAGS_PUBLIC
|
|
|
+ LDFLAGS LDFLAGS_INTERFACE LDFLAGS_PUBLIC
|
|
|
+ QT_LINKS QT_LINKS_PRIVATE QT_LINKS_INTERFACE
|
|
|
+ QT_INCLUDE_PRIVATE
|
|
|
SKIP_AUTOMOC
|
|
|
)
|
|
|
cmake_parse_arguments(FUNC "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
|
|
|
|
|
- macro(_resolve_dir_helper _dirs _out)
|
|
|
- set(${_out})
|
|
|
-
|
|
|
- foreach(_item IN LISTS ${_dirs})
|
|
|
- if(_item STREQUAL "*")
|
|
|
- set(_cur_dir ".")
|
|
|
- file(GLOB _subdirs LIST_DIRECTORIES true "*")
|
|
|
- elseif(_item STREQUAL "**")
|
|
|
- set(_cur_dir ".")
|
|
|
- file(GLOB_RECURSE _subdirs LIST_DIRECTORIES true "*")
|
|
|
- elseif(_item MATCHES "(.+)/\\*$")
|
|
|
- set(_cur_dir ${CMAKE_MATCH_1})
|
|
|
- file(GLOB _subdirs LIST_DIRECTORIES true "${_cur_dir}/*")
|
|
|
- elseif(_item MATCHES "(.+)/\\*\\*$")
|
|
|
- set(_cur_dir ${CMAKE_MATCH_1})
|
|
|
- file(GLOB_RECURSE _subdirs LIST_DIRECTORIES true "${_cur_dir}/*")
|
|
|
- else()
|
|
|
- list(APPEND ${_out} ${_item})
|
|
|
- continue()
|
|
|
- endif()
|
|
|
-
|
|
|
- list(APPEND ${_out} ${_cur_dir})
|
|
|
-
|
|
|
- foreach(_subdir IN LISTS _subdirs)
|
|
|
- if(IS_DIRECTORY ${_subdir})
|
|
|
- get_filename_component(_subdir ${_subdir} ABSOLUTE)
|
|
|
- list(APPEND ${_out} ${_subdir})
|
|
|
- endif()
|
|
|
- endforeach()
|
|
|
- endforeach()
|
|
|
- endmacro()
|
|
|
-
|
|
|
target_sources(${_target} PRIVATE ${FUNC_SOURCES})
|
|
|
|
|
|
target_link_libraries(${_target} PUBLIC ${FUNC_LINKS})
|
|
|
target_link_libraries(${_target} PRIVATE ${FUNC_LINKS_PRIVATE})
|
|
|
|
|
|
if(FUNC_INCLUDE)
|
|
|
- _resolve_dir_helper(FUNC_INCLUDE _temp_dirs)
|
|
|
+ _qm_resolve_dir_helper("${FUNC_INCLUDE}" _temp_dirs)
|
|
|
target_include_directories(${_target} PUBLIC ${_temp_dirs})
|
|
|
unset(_temp_dirs)
|
|
|
endif()
|
|
|
|
|
|
+ if(FUNC_INCLUDE_INTERFACE)
|
|
|
+ _qm_resolve_dir_helper("${FUNC_INCLUDE_INTERFACE}" _temp_dirs)
|
|
|
+ target_include_directories(${_target} INTERFACE ${_temp_dirs})
|
|
|
+ unset(_temp_dirs)
|
|
|
+ endif()
|
|
|
+
|
|
|
if(FUNC_INCLUDE_PRIVATE)
|
|
|
- _resolve_dir_helper(FUNC_INCLUDE_PRIVATE _temp_dirs)
|
|
|
+ _qm_resolve_dir_helper("${FUNC_INCLUDE_PRIVATE}" _temp_dirs)
|
|
|
target_include_directories(${_target} PRIVATE ${_temp_dirs})
|
|
|
unset(_temp_dirs)
|
|
|
endif()
|
|
|
|
|
|
if(FUNC_LINKDIR)
|
|
|
- _resolve_dir_helper(FUNC_LINKDIR _temp_dirs)
|
|
|
+ _qm_resolve_dir_helper("${FUNC_LINKDIR}" _temp_dirs)
|
|
|
target_link_directories(${_target} PUBLIC ${_temp_dirs})
|
|
|
unset(_temp_dirs)
|
|
|
endif()
|
|
|
|
|
|
+ if(FUNC_LINKDIR_INTERFACE)
|
|
|
+ _qm_resolve_dir_helper("${FUNC_LINKDIR}" _temp_dirs)
|
|
|
+ target_link_directories(${_target} INTERFACE ${_temp_dirs})
|
|
|
+ unset(_temp_dirs)
|
|
|
+ endif()
|
|
|
+
|
|
|
if(FUNC_LINKDIR_PRIVATE)
|
|
|
- _resolve_dir_helper(FUNC_LINKDIR_PRIVATE _temp_dirs)
|
|
|
+ _qm_resolve_dir_helper("${FUNC_LINKDIR_PRIVATE}" _temp_dirs)
|
|
|
target_link_directories(${_target} PRIVATE ${_temp_dirs})
|
|
|
unset(_temp_dirs)
|
|
|
endif()
|
|
|
|
|
|
target_compile_definitions(${_target} PUBLIC ${FUNC_DEFINES})
|
|
|
+ target_compile_definitions(${_target} INTERFACE ${FUNC_DEFINES_INTERFACE})
|
|
|
target_compile_definitions(${_target} PRIVATE ${FUNC_DEFINES_PRIVATE})
|
|
|
|
|
|
target_compile_features(${_target} PUBLIC ${FUNC_FEATURES})
|
|
|
+ target_compile_features(${_target} INTERFACE ${FUNC_FEATURES_INTERFACE})
|
|
|
target_compile_features(${_target} PRIVATE ${FUNC_FEATURES_PRIVATE})
|
|
|
|
|
|
+ # CMake won't add language standard flag if the compiler default mode supports the standard,
|
|
|
+ # however, if the -std argument is not explicitly specified, the clang language server will
|
|
|
+ # not work properly.
|
|
|
+ # https://discourse.cmake.org/t/cmake-does-not-set-the-compiler-option-std-to-gnu17-or-c-17-although-i-set-the-target-compile-features-to-cxx-std-17/3299/8
|
|
|
+ foreach(_item IN LISTS FUNC_FEATURES FUNC_FEATURES_PRIVATE)
|
|
|
+ if(_item MATCHES "cxx_std_(.+)")
|
|
|
+ set_property(TARGET APPEND PROPERTY CXX_STANDARD ${CMAKE_MATCH_1})
|
|
|
+ elseif(_item MATCHES "c_std_(.+)")
|
|
|
+ set_property(TARGET APPEND PROPERTY C_STANDARD ${CMAKE_MATCH_1})
|
|
|
+ endif()
|
|
|
+ endforeach()
|
|
|
+
|
|
|
target_compile_options(${_target} PUBLIC ${FUNC_CCFLAGS_PUBLIC})
|
|
|
+ target_compile_options(${_target} INTERFACE ${FUNC_CCFLAGS_INTERFACE})
|
|
|
target_compile_options(${_target} PRIVATE ${FUNC_CCFLAGS})
|
|
|
|
|
|
target_link_options(${_target} PUBLIC ${FUNC_LDFLAGS_PUBLIC})
|
|
|
+ target_link_options(${_target} INTERFACE ${FUNC_LDFLAGS_INTERFACE})
|
|
|
target_link_options(${_target} PRIVATE ${FUNC_LDFLAGS})
|
|
|
|
|
|
qm_link_qt(${_target} PUBLIC ${FUNC_QT_LINKS})
|
|
|
+ qm_link_qt(${_target} INTERFACE ${FUNC_QT_LINKS_INTERFACE})
|
|
|
qm_link_qt(${_target} PRIVATE ${FUNC_QT_LINKS_PRIVATE})
|
|
|
|
|
|
qm_include_qt_private(${_target} PRIVATE ${FUNC_QT_INCLUDE_PRIVATE})
|
|
|
|
|
|
if(FUNC_SKIP_AUTOMOC)
|
|
|
- _resolve_dir_helper(FUNC_SKIP_AUTOMOC _temp_files)
|
|
|
+ _qm_resolve_file_helper("${FUNC_SKIP_AUTOMOC}" _temp_files)
|
|
|
qm_skip_automoc(${_temp_files})
|
|
|
unset(_temp_files)
|
|
|
endif()
|
|
|
@@ -623,20 +656,27 @@ function(qm_add_win_manifest _target)
|
|
|
set(_out_path "${_out_dir}/${_target}_manifest.exe.manifest")
|
|
|
configure_file("${QMSETUP_MODULES_DIR}/windows/WinManifest.manifest.in" ${_out_path} @ONLY)
|
|
|
|
|
|
- # https://cmake.org/cmake/help/latest/release/3.4.html#other
|
|
|
- # CMake learned to honor *.manifest source files with MSVC tools. Manifest files named as sources
|
|
|
- # of .exe and .dll targets will be merged with linker-generated manifests and embedded in the binary.
|
|
|
- # NOTE: CMake will automatically generate a default manifest file and embed it into the binary file
|
|
|
- # when we are using MSVC toolchain, so it will conflict with the one we embed in the RC file. So in
|
|
|
- # this case, we just follow the CMake documentation, add the manifest file into the sources and let
|
|
|
- # CMake handle it. What's more, CMake can automatically merge all manifest files so we can actually
|
|
|
- # add multiple manifest files, eg. each manifest file contains a separate section.
|
|
|
if(MSVC)
|
|
|
- target_sources(${_target} PRIVATE ${_out_path})
|
|
|
-
|
|
|
- # The manifest file contains a UAC field, we should prevent MSVC from embedding the
|
|
|
- # automatically generated UAC field
|
|
|
- target_link_options(${_target} PRIVATE "/manifestuac:no")
|
|
|
+ if(CMAKE_GENERATOR MATCHES "Visual Studio")
|
|
|
+ # Visual Studio
|
|
|
+ target_link_options(${_target} PRIVATE "/manifest" "/manifestinput:${_out_path}")
|
|
|
+
|
|
|
+ # The manifest file contains a UAC field, we should prevent Ninja from embedding the
|
|
|
+ # automatically generated UAC field
|
|
|
+ target_link_options(${_target} PRIVATE "/manifest" "/manifestuac:no")
|
|
|
+ else() # Ninja
|
|
|
+ # https://cmake.org/cmake/help/latest/release/3.4.html#other
|
|
|
+ # CMake learned to honor *.manifest source files with MSVC tools. Manifest files named as sources
|
|
|
+ # of .exe and .dll targets will be merged with linker-generated manifests and embedded in the binary.
|
|
|
+
|
|
|
+ # NOTE: CMake will automatically generate a default manifest file and embed it into the binary file
|
|
|
+ # when we are using MSVC toolchain, so it will conflict with the one we embed in the RC file. So in
|
|
|
+ # this case, we just follow the CMake documentation, add the manifest file into the sources and let
|
|
|
+ # CMake handle it. What's more, CMake can automatically merge all manifest files so we can actually
|
|
|
+ # add multiple manifest files, eg. each manifest file contains a separate section.
|
|
|
+ target_sources(${_target} PRIVATE ${_out_path})
|
|
|
+ target_link_options(${_target} PRIVATE "/manifestuac:no")
|
|
|
+ endif()
|
|
|
else()
|
|
|
# For non-MSVC toolchains we can only embed the manifest file into the RC file, sadly we have
|
|
|
# to merge all manifest files into one by ourself if we have multiple of them, but luckily
|
|
|
@@ -856,23 +896,23 @@ function(qm_get_subdirs _var)
|
|
|
set(_dir ${CMAKE_CURRENT_SOURCE_DIR})
|
|
|
endif()
|
|
|
|
|
|
- file(GLOB _subdirs LIST_DIRECTORIES true RELATIVE ${_dir} "${_dir}/*")
|
|
|
+ file(GLOB _entries LIST_DIRECTORIES true RELATIVE ${_dir} "${_dir}/*")
|
|
|
|
|
|
if(FUNC_EXCLUDE)
|
|
|
foreach(_exclude_dir IN LISTS FUNC_EXCLUDE)
|
|
|
- list(REMOVE_ITEM _subdirs ${_exclude_dir})
|
|
|
+ list(REMOVE_ITEM _entries ${_exclude_dir})
|
|
|
endforeach()
|
|
|
endif()
|
|
|
|
|
|
if(FUNC_REGEX_INCLUDE)
|
|
|
foreach(_exp IN LISTS FUNC_REGEX_INCLUDE)
|
|
|
- list(FILTER _subdirs INCLUDE REGEX ${_exp})
|
|
|
+ list(FILTER _entries INCLUDE REGEX ${_exp})
|
|
|
endforeach()
|
|
|
endif()
|
|
|
|
|
|
if(FUNC_REGEX_EXCLUDE)
|
|
|
foreach(_exp IN LISTS FUNC_REGEX_EXCLUDE)
|
|
|
- list(FILTER _subdirs EXCLUDE REGEX ${_exp})
|
|
|
+ list(FILTER _entries EXCLUDE REGEX ${_exp})
|
|
|
endforeach()
|
|
|
endif()
|
|
|
|
|
|
@@ -884,7 +924,7 @@ function(qm_get_subdirs _var)
|
|
|
set(_relative)
|
|
|
endif()
|
|
|
|
|
|
- foreach(_sub IN LISTS _subdirs)
|
|
|
+ foreach(_sub IN LISTS _entries)
|
|
|
if(IS_DIRECTORY ${_dir}/${_sub})
|
|
|
if(FUNC_ABSOLUTE)
|
|
|
list(APPEND _res ${_dir}/${_sub})
|
|
|
@@ -1003,3 +1043,50 @@ macro(_qm_check_target_type_helper _target _type)
|
|
|
unset(_tmp_target_type)
|
|
|
unset(_tmp_target_type_list)
|
|
|
endmacro()
|
|
|
+
|
|
|
+function(_qm_resolve_file_helper _dirs _out)
|
|
|
+ set(_res)
|
|
|
+
|
|
|
+ foreach(_item ${_dirs})
|
|
|
+ if(_item STREQUAL "*")
|
|
|
+ set(_cur_dir ".")
|
|
|
+ file(GLOB _files LIST_DIRECTORIES true "*")
|
|
|
+ elseif(_item STREQUAL "**")
|
|
|
+ set(_cur_dir ".")
|
|
|
+ file(GLOB_RECURSE _files LIST_DIRECTORIES true "*")
|
|
|
+ elseif(_item MATCHES "(.+)[/\\]\\*$")
|
|
|
+ set(_cur_dir ${CMAKE_MATCH_1})
|
|
|
+ file(GLOB _files LIST_DIRECTORIES true "${_cur_dir}/*")
|
|
|
+ elseif(_item MATCHES "(.+)[/\\]\\*\\*$")
|
|
|
+ set(_cur_dir ${CMAKE_MATCH_1})
|
|
|
+ file(GLOB_RECURSE _files LIST_DIRECTORIES true "${_cur_dir}/*")
|
|
|
+ else()
|
|
|
+ get_filename_component(_item ${_item} ABSOLUTE)
|
|
|
+ list(APPEND _res ${_item})
|
|
|
+ continue()
|
|
|
+ endif()
|
|
|
+
|
|
|
+ get_filename_component(_cur_dir ${_cur_dir} ABSOLUTE)
|
|
|
+ list(APPEND _res ${_cur_dir})
|
|
|
+
|
|
|
+ foreach(_item IN LISTS _files)
|
|
|
+ get_filename_component(_item ${_item} ABSOLUTE)
|
|
|
+ list(APPEND _res ${_item})
|
|
|
+ endforeach()
|
|
|
+ endforeach()
|
|
|
+
|
|
|
+ set(${_out} ${_res} PARENT_SCOPE)
|
|
|
+endfunction()
|
|
|
+
|
|
|
+function(_qm_resolve_dir_helper _dirs _out)
|
|
|
+ set(_files)
|
|
|
+ _qm_resolve_file_helper("${_dirs}" _files)
|
|
|
+
|
|
|
+ foreach(_item IN LISTS _files)
|
|
|
+ if(IS_DIRECTORY ${_item})
|
|
|
+ list(APPEND _res ${_item})
|
|
|
+ endif()
|
|
|
+ endforeach()
|
|
|
+
|
|
|
+ set(${_out} ${_res} PARENT_SCOPE)
|
|
|
+endfunction()
|