summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJordan Justen <jordan.l.justen@intel.com>2021-04-14 01:15:10 -0700
committerJordan Justen <jordan.l.justen@intel.com>2021-04-14 12:08:15 -0700
commit8d4649353b43aab92e70b48a30a38318a68edc2e (patch)
tree62d14dc6f2c129f7887323dcc1df5ef458c249ff
parent5fa0e32874e67afd4a84f0c9546c1827db4e0f4d (diff)
piglit: statically link to MSVC runtimes
Signed-off-by: Jordan Justen <jordan.l.justen@intel.com>
-rw-r--r--CMakeLists.txt3
-rw-r--r--ucm.cmake663
2 files changed, 666 insertions, 0 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 01cdf2ebb..d615abe5f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -496,6 +496,9 @@ configure_file(
"${piglit_BINARY_DIR}/tests/util/config.h"
)
+include(ucm.cmake)
+ucm_set_runtime(STATIC)
+
include(cmake/piglit_util.cmake)
include(cmake/piglit_dispatch.cmake)
diff --git a/ucm.cmake b/ucm.cmake
new file mode 100644
index 000000000..1c28218a0
--- /dev/null
+++ b/ucm.cmake
@@ -0,0 +1,663 @@
+#
+# ucm.cmake - useful cmake macros
+#
+# Copyright (c) 2016 Viktor Kirilov
+#
+# Distributed under the MIT Software License
+# See accompanying file LICENSE.txt or copy at
+# https://opensource.org/licenses/MIT
+#
+# The documentation can be found at the library's page:
+# https://github.com/onqtam/ucm
+
+cmake_minimum_required(VERSION 2.8.12)
+
+include(CMakeParseArguments)
+
+# optionally include cotire - the git submodule might not be inited (or the user might have already included it)
+if(NOT COMMAND cotire)
+ include(${CMAKE_CURRENT_LIST_DIR}/../cotire/CMake/cotire.cmake OPTIONAL)
+endif()
+
+if(COMMAND cotire AND "1.7.9" VERSION_LESS "${COTIRE_CMAKE_MODULE_VERSION}")
+ set(ucm_with_cotire 1)
+else()
+ set(ucm_with_cotire 0)
+endif()
+
+option(UCM_UNITY_BUILD "Enable unity build for targets registered with the ucm_add_target() macro" OFF)
+option(UCM_NO_COTIRE_FOLDER "Do not use a cotire folder in the solution explorer for all unity and cotire related targets" ON)
+
+# ucm_add_flags
+# Adds compiler flags to CMAKE_<LANG>_FLAGS or to a specific config
+macro(ucm_add_flags)
+ cmake_parse_arguments(ARG "C;CXX;CLEAR_OLD" "" "CONFIG" ${ARGN})
+
+ if(NOT ARG_CONFIG)
+ set(ARG_CONFIG " ")
+ endif()
+
+ foreach(CONFIG ${ARG_CONFIG})
+ # determine to which flags to add
+ if(NOT ${CONFIG} STREQUAL " ")
+ string(TOUPPER ${CONFIG} CONFIG)
+ set(CXX_FLAGS CMAKE_CXX_FLAGS_${CONFIG})
+ set(C_FLAGS CMAKE_C_FLAGS_${CONFIG})
+ else()
+ set(CXX_FLAGS CMAKE_CXX_FLAGS)
+ set(C_FLAGS CMAKE_C_FLAGS)
+ endif()
+
+ # clear the old flags
+ if(${ARG_CLEAR_OLD})
+ if("${ARG_CXX}" OR NOT "${ARG_C}")
+ set(${CXX_FLAGS} "")
+ endif()
+ if("${ARG_C}" OR NOT "${ARG_CXX}")
+ set(${C_FLAGS} "")
+ endif()
+ endif()
+
+ # add all the passed flags
+ foreach(flag ${ARG_UNPARSED_ARGUMENTS})
+ if("${ARG_CXX}" OR NOT "${ARG_C}")
+ set(${CXX_FLAGS} "${${CXX_FLAGS}} ${flag}")
+ endif()
+ if("${ARG_C}" OR NOT "${ARG_CXX}")
+ set(${C_FLAGS} "${${C_FLAGS}} ${flag}")
+ endif()
+ endforeach()
+ endforeach()
+
+endmacro()
+
+# ucm_set_flags
+# Sets the CMAKE_<LANG>_FLAGS compiler flags or for a specific config
+macro(ucm_set_flags)
+ ucm_add_flags(CLEAR_OLD ${ARGN})
+endmacro()
+
+# ucm_add_linker_flags
+# Adds linker flags to CMAKE_<TYPE>_LINKER_FLAGS or to a specific config
+macro(ucm_add_linker_flags)
+ cmake_parse_arguments(ARG "CLEAR_OLD;EXE;MODULE;SHARED;STATIC" "" "CONFIG" ${ARGN})
+
+ if(NOT ARG_CONFIG)
+ set(ARG_CONFIG " ")
+ endif()
+
+ foreach(CONFIG ${ARG_CONFIG})
+ string(TOUPPER "${CONFIG}" CONFIG)
+
+ if(NOT ${ARG_EXE} AND NOT ${ARG_MODULE} AND NOT ${ARG_SHARED} AND NOT ${ARG_STATIC})
+ set(ARG_EXE 1)
+ set(ARG_MODULE 1)
+ set(ARG_SHARED 1)
+ set(ARG_STATIC 1)
+ endif()
+
+ set(flags_configs "")
+ if(${ARG_EXE})
+ if(NOT "${CONFIG}" STREQUAL " ")
+ list(APPEND flags_configs CMAKE_EXE_LINKER_FLAGS_${CONFIG})
+ else()
+ list(APPEND flags_configs CMAKE_EXE_LINKER_FLAGS)
+ endif()
+ endif()
+ if(${ARG_MODULE})
+ if(NOT "${CONFIG}" STREQUAL " ")
+ list(APPEND flags_configs CMAKE_MODULE_LINKER_FLAGS_${CONFIG})
+ else()
+ list(APPEND flags_configs CMAKE_MODULE_LINKER_FLAGS)
+ endif()
+ endif()
+ if(${ARG_SHARED})
+ if(NOT "${CONFIG}" STREQUAL " ")
+ list(APPEND flags_configs CMAKE_SHARED_LINKER_FLAGS_${CONFIG})
+ else()
+ list(APPEND flags_configs CMAKE_SHARED_LINKER_FLAGS)
+ endif()
+ endif()
+ if(${ARG_STATIC})
+ if(NOT "${CONFIG}" STREQUAL " ")
+ list(APPEND flags_configs CMAKE_STATIC_LINKER_FLAGS_${CONFIG})
+ else()
+ list(APPEND flags_configs CMAKE_STATIC_LINKER_FLAGS)
+ endif()
+ endif()
+
+ # clear the old flags
+ if(${ARG_CLEAR_OLD})
+ foreach(flags ${flags_configs})
+ set(${flags} "")
+ endforeach()
+ endif()
+
+ # add all the passed flags
+ foreach(flag ${ARG_UNPARSED_ARGUMENTS})
+ foreach(flags ${flags_configs})
+ set(${flags} "${${flags}} ${flag}")
+ endforeach()
+ endforeach()
+ endforeach()
+endmacro()
+
+# ucm_set_linker_flags
+# Sets the CMAKE_<TYPE>_LINKER_FLAGS linker flags or for a specific config
+macro(ucm_set_linker_flags)
+ ucm_add_linker_flags(CLEAR_OLD ${ARGN})
+endmacro()
+
+# ucm_gather_flags
+# Gathers all lists of flags for printing or manipulation
+macro(ucm_gather_flags with_linker result)
+ set(${result} "")
+ # add the main flags without a config
+ list(APPEND ${result} CMAKE_C_FLAGS)
+ list(APPEND ${result} CMAKE_CXX_FLAGS)
+ if(${with_linker})
+ list(APPEND ${result} CMAKE_EXE_LINKER_FLAGS)
+ list(APPEND ${result} CMAKE_MODULE_LINKER_FLAGS)
+ list(APPEND ${result} CMAKE_SHARED_LINKER_FLAGS)
+ list(APPEND ${result} CMAKE_STATIC_LINKER_FLAGS)
+ endif()
+
+ if("${CMAKE_CONFIGURATION_TYPES}" STREQUAL "" AND NOT "${CMAKE_BUILD_TYPE}" STREQUAL "")
+ # handle single config generators - like makefiles/ninja - when CMAKE_BUILD_TYPE is set
+ string(TOUPPER ${CMAKE_BUILD_TYPE} config)
+ list(APPEND ${result} CMAKE_C_FLAGS_${config})
+ list(APPEND ${result} CMAKE_CXX_FLAGS_${config})
+ if(${with_linker})
+ list(APPEND ${result} CMAKE_EXE_LINKER_FLAGS_${config})
+ list(APPEND ${result} CMAKE_MODULE_LINKER_FLAGS_${config})
+ list(APPEND ${result} CMAKE_SHARED_LINKER_FLAGS_${config})
+ list(APPEND ${result} CMAKE_STATIC_LINKER_FLAGS_${config})
+ endif()
+ else()
+ # handle multi config generators (like msvc, xcode)
+ foreach(config ${CMAKE_CONFIGURATION_TYPES})
+ string(TOUPPER ${config} config)
+ list(APPEND ${result} CMAKE_C_FLAGS_${config})
+ list(APPEND ${result} CMAKE_CXX_FLAGS_${config})
+ if(${with_linker})
+ list(APPEND ${result} CMAKE_EXE_LINKER_FLAGS_${config})
+ list(APPEND ${result} CMAKE_MODULE_LINKER_FLAGS_${config})
+ list(APPEND ${result} CMAKE_SHARED_LINKER_FLAGS_${config})
+ list(APPEND ${result} CMAKE_STATIC_LINKER_FLAGS_${config})
+ endif()
+ endforeach()
+ endif()
+endmacro()
+
+# ucm_set_runtime
+# Sets the runtime (static/dynamic) for msvc/gcc
+macro(ucm_set_runtime)
+ cmake_parse_arguments(ARG "STATIC;DYNAMIC" "" "" ${ARGN})
+
+ if(ARG_UNPARSED_ARGUMENTS)
+ message(FATAL_ERROR "unrecognized arguments: ${ARG_UNPARSED_ARGUMENTS}")
+ endif()
+
+ if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" STREQUAL "")
+ message(AUTHOR_WARNING "ucm_set_runtime() does not support clang yet!")
+ endif()
+
+ ucm_gather_flags(0 flags_configs)
+
+ # add/replace the flags
+ # note that if the user has messed with the flags directly this function might fail
+ # - for example if with MSVC and the user has removed the flags - here we just switch/replace them
+ if("${ARG_STATIC}")
+ foreach(flags ${flags_configs})
+ if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
+ if(NOT ${flags} MATCHES "-static-libstdc\\+\\+")
+ set(${flags} "${${flags}} -static-libstdc++")
+ endif()
+ if(NOT ${flags} MATCHES "-static-libgcc")
+ set(${flags} "${${flags}} -static-libgcc")
+ endif()
+ elseif(MSVC)
+ if(${flags} MATCHES "/MD")
+ string(REGEX REPLACE "/MD" "/MT" ${flags} "${${flags}}")
+ endif()
+ endif()
+ endforeach()
+ elseif("${ARG_DYNAMIC}")
+ foreach(flags ${flags_configs})
+ if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
+ if(${flags} MATCHES "-static-libstdc\\+\\+")
+ string(REGEX REPLACE "-static-libstdc\\+\\+" "" ${flags} "${${flags}}")
+ endif()
+ if(${flags} MATCHES "-static-libgcc")
+ string(REGEX REPLACE "-static-libgcc" "" ${flags} "${${flags}}")
+ endif()
+ elseif(MSVC)
+ if(${flags} MATCHES "/MT")
+ string(REGEX REPLACE "/MT" "/MD" ${flags} "${${flags}}")
+ endif()
+ endif()
+ endforeach()
+ endif()
+endmacro()
+
+# ucm_print_flags
+# Prints all compiler flags for all configurations
+macro(ucm_print_flags)
+ ucm_gather_flags(1 flags_configs)
+ message(STATUS "")
+ foreach(flags ${flags_configs})
+ message(STATUS "${flags}: ${${flags}}")
+ endforeach()
+ message(STATUS "")
+endmacro()
+
+# ucm_set_xcode_attrib
+# Set xcode attributes - name value CONFIG config1 conifg2..
+macro(ucm_set_xcode_attrib)
+ cmake_parse_arguments(ARG "" "CLEAR" "CONFIG" ${ARGN})
+
+ if(NOT ARG_CONFIG)
+ set(ARG_CONFIG " ")
+ endif()
+
+ foreach(CONFIG ${ARG_CONFIG})
+ # determine to which attributes to add
+ if(${CONFIG} STREQUAL " ")
+ if(${ARG_CLEAR})
+ # clear the old flags
+ unset(CMAKE_XCODE_ATTRIBUTE_${ARGV0})
+ else()
+ set(CMAKE_XCODE_ATTRIBUTE_${ARGV0} ${ARGV1})
+ endif()
+ else()
+ if(${ARG_CLEAR})
+ # clear the old flags
+ unset(CMAKE_XCODE_ATTRIBUTE_${ARGV0}[variant=${CONFIG}])
+ else()
+ set(CMAKE_XCODE_ATTRIBUTE_${ARGV0}[variant=${CONFIG}] ${ARGV1})
+ endif()
+ endif()
+ endforeach()
+endmacro()
+
+# ucm_count_sources
+# Counts the number of source files
+macro(ucm_count_sources)
+ cmake_parse_arguments(ARG "" "RESULT" "" ${ARGN})
+ if(${ARG_RESULT} STREQUAL "")
+ message(FATAL_ERROR "Need to pass RESULT and a variable name to ucm_count_sources()")
+ endif()
+
+ set(result 0)
+ foreach(SOURCE_FILE ${ARG_UNPARSED_ARGUMENTS})
+ if("${SOURCE_FILE}" MATCHES \\.\(c|C|cc|cp|cpp|CPP|c\\+\\+|cxx|i|ii\)$)
+ math(EXPR result "${result} + 1")
+ endif()
+ endforeach()
+ set(${ARG_RESULT} ${result})
+endmacro()
+
+# ucm_include_file_in_sources
+# Includes the file to the source with compiler flags
+macro(ucm_include_file_in_sources)
+ cmake_parse_arguments(ARG "" "HEADER" "" ${ARGN})
+ if(${ARG_HEADER} STREQUAL "")
+ message(FATAL_ERROR "Need to pass HEADER and a header file to ucm_include_file_in_sources()")
+ endif()
+
+ foreach(src ${ARG_UNPARSED_ARGUMENTS})
+ if(${src} MATCHES \\.\(c|C|cc|cp|cpp|CPP|c\\+\\+|cxx\)$)
+ # get old flags
+ get_source_file_property(old_compile_flags ${src} COMPILE_FLAGS)
+ if(old_compile_flags STREQUAL "NOTFOUND")
+ set(old_compile_flags "")
+ endif()
+
+ # update flags
+ if(MSVC)
+ set_source_files_properties(${src} PROPERTIES COMPILE_FLAGS
+ "${old_compile_flags} /FI\"${CMAKE_CURRENT_SOURCE_DIR}/${ARG_HEADER}\"")
+ else()
+ set_source_files_properties(${src} PROPERTIES COMPILE_FLAGS
+ "${old_compile_flags} -include \"${CMAKE_CURRENT_SOURCE_DIR}/${ARG_HEADER}\"")
+ endif()
+ endif()
+ endforeach()
+endmacro()
+
+# ucm_dir_list
+# Returns a list of subdirectories for a given directory
+macro(ucm_dir_list thedir result)
+ file(GLOB sub-dir "${thedir}/*")
+ set(list_of_dirs "")
+ foreach(dir ${sub-dir})
+ if(IS_DIRECTORY ${dir})
+ get_filename_component(DIRNAME ${dir} NAME)
+ LIST(APPEND list_of_dirs ${DIRNAME})
+ endif()
+ endforeach()
+ set(${result} ${list_of_dirs})
+endmacro()
+
+# ucm_trim_front_words
+# Trims X times the front word from a string separated with "/" and removes
+# the front "/" characters after that (used for filters for visual studio)
+macro(ucm_trim_front_words source out num_filter_trims)
+ set(result "${source}")
+ set(counter 0)
+ while(${counter} LESS ${num_filter_trims})
+ MATH(EXPR counter "${counter} + 1")
+ # removes everything at the front up to a "/" character
+ string(REGEX REPLACE "^([^/]+)" "" result "${result}")
+ # removes all consecutive "/" characters from the front
+ string(REGEX REPLACE "^(/+)" "" result "${result}")
+ endwhile()
+ set(${out} ${result})
+endmacro()
+
+# ucm_remove_files
+# Removes source files from a list of sources (path is the relative path for it to be found)
+macro(ucm_remove_files)
+ cmake_parse_arguments(ARG "" "FROM" "" ${ARGN})
+
+ if("${ARG_UNPARSED_ARGUMENTS}" STREQUAL "")
+ message(FATAL_ERROR "Need to pass some relative files to ucm_remove_files()")
+ endif()
+ if(${ARG_FROM} STREQUAL "")
+ message(FATAL_ERROR "Need to pass FROM and a variable name to ucm_remove_files()")
+ endif()
+
+ foreach(cur_file ${ARG_UNPARSED_ARGUMENTS})
+ list(REMOVE_ITEM ${ARG_FROM} ${cur_file})
+ endforeach()
+endmacro()
+
+# ucm_remove_directories
+# Removes all source files from the given directories from the sources list
+macro(ucm_remove_directories)
+ cmake_parse_arguments(ARG "" "FROM" "MATCHES" ${ARGN})
+
+ if("${ARG_UNPARSED_ARGUMENTS}" STREQUAL "")
+ message(FATAL_ERROR "Need to pass some relative directories to ucm_remove_directories()")
+ endif()
+ if(${ARG_FROM} STREQUAL "")
+ message(FATAL_ERROR "Need to pass FROM and a variable name to ucm_remove_directories()")
+ endif()
+
+ foreach(cur_dir ${ARG_UNPARSED_ARGUMENTS})
+ foreach(cur_file ${${ARG_FROM}})
+ string(REGEX MATCH ${cur_dir} res ${cur_file})
+ if(NOT "${res}" STREQUAL "")
+ if("${ARG_MATCHES}" STREQUAL "")
+ list(REMOVE_ITEM ${ARG_FROM} ${cur_file})
+ else()
+ foreach(curr_ptrn ${ARG_MATCHES})
+ string(REGEX MATCH ${curr_ptrn} res ${cur_file})
+ if(NOT "${res}" STREQUAL "")
+ list(REMOVE_ITEM ${ARG_FROM} ${cur_file})
+ break()
+ endif()
+ endforeach()
+ endif()
+ endif()
+ endforeach()
+ endforeach()
+endmacro()
+
+# ucm_add_files_impl
+macro(ucm_add_files_impl result trim files)
+ foreach(cur_file ${files})
+ SET(${result} ${${result}} ${cur_file})
+ get_filename_component(FILEPATH ${cur_file} PATH)
+ ucm_trim_front_words("${FILEPATH}" FILEPATH "${trim}")
+ # replacing forward slashes with back slashes so filters can be generated (back slash used in parsing...)
+ STRING(REPLACE "/" "\\" FILTERS "${FILEPATH}")
+ SOURCE_GROUP("${FILTERS}" FILES ${cur_file})
+ endforeach()
+endmacro()
+
+# ucm_add_files
+# Adds files to a list of sources
+macro(ucm_add_files)
+ cmake_parse_arguments(ARG "" "TO;FILTER_POP" "" ${ARGN})
+
+ if("${ARG_UNPARSED_ARGUMENTS}" STREQUAL "")
+ message(FATAL_ERROR "Need to pass some relative files to ucm_add_files()")
+ endif()
+ if(${ARG_TO} STREQUAL "")
+ message(FATAL_ERROR "Need to pass TO and a variable name to ucm_add_files()")
+ endif()
+
+ if("${ARG_FILTER_POP}" STREQUAL "")
+ set(ARG_FILTER_POP 0)
+ endif()
+
+ ucm_add_files_impl(${ARG_TO} ${ARG_FILTER_POP} "${ARG_UNPARSED_ARGUMENTS}")
+endmacro()
+
+# ucm_add_dir_impl
+macro(ucm_add_dir_impl result rec trim dirs_in additional_ext)
+ set(dirs "${dirs_in}")
+
+ # handle the "" and "." cases
+ if("${dirs}" STREQUAL "" OR "${dirs}" STREQUAL ".")
+ set(dirs "./")
+ endif()
+
+ foreach(cur_dir ${dirs})
+ # to circumvent some linux/cmake/path issues - barely made it work...
+ if(cur_dir STREQUAL "./")
+ set(cur_dir "")
+ else()
+ set(cur_dir "${cur_dir}/")
+ endif()
+
+ # since unix is case sensitive - add these valid extensions too
+ # we don't use "UNIX" but instead "CMAKE_HOST_UNIX" because we might be cross
+ # compiling (for example emscripten) under windows and UNIX may be set to 1
+ # Also OSX is case insensitive like windows...
+ set(additional_file_extensions "")
+ if(CMAKE_HOST_UNIX AND NOT APPLE)
+ set(additional_file_extensions
+ "${cur_dir}*.CPP"
+ "${cur_dir}*.C"
+ "${cur_dir}*.H"
+ "${cur_dir}*.HPP"
+ )
+ endif()
+
+ foreach(ext ${additional_ext})
+ list(APPEND additional_file_extensions "${cur_dir}*.${ext}")
+ endforeach()
+
+ # find all sources and set them as result
+ FILE(GLOB found_sources RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}"
+ # https://gcc.gnu.org/onlinedocs/gcc-4.4.1/gcc/Overall-Options.html#index-file-name-suffix-71
+ # sources
+ "${cur_dir}*.cpp"
+ "${cur_dir}*.cxx"
+ "${cur_dir}*.c++"
+ "${cur_dir}*.cc"
+ "${cur_dir}*.cp"
+ "${cur_dir}*.c"
+ "${cur_dir}*.i"
+ "${cur_dir}*.ii"
+ # headers
+ "${cur_dir}*.h"
+ "${cur_dir}*.h++"
+ "${cur_dir}*.hpp"
+ "${cur_dir}*.hxx"
+ "${cur_dir}*.hh"
+ "${cur_dir}*.inl"
+ "${cur_dir}*.inc"
+ "${cur_dir}*.ipp"
+ "${cur_dir}*.ixx"
+ "${cur_dir}*.txx"
+ "${cur_dir}*.tpp"
+ "${cur_dir}*.tcc"
+ "${cur_dir}*.tpl"
+ ${additional_file_extensions})
+ SET(${result} ${${result}} ${found_sources})
+
+ # set the proper filters
+ ucm_trim_front_words("${cur_dir}" cur_dir "${trim}")
+ # replacing forward slashes with back slashes so filters can be generated (back slash used in parsing...)
+ STRING(REPLACE "/" "\\" FILTERS "${cur_dir}")
+ SOURCE_GROUP("${FILTERS}" FILES ${found_sources})
+ endforeach()
+
+ if(${rec})
+ foreach(cur_dir ${dirs})
+ ucm_dir_list("${cur_dir}" subdirs)
+ foreach(subdir ${subdirs})
+ ucm_add_dir_impl(${result} ${rec} ${trim} "${cur_dir}/${subdir}" "${additional_ext}")
+ endforeach()
+ endforeach()
+ endif()
+endmacro()
+
+# ucm_add_dirs
+# Adds all files from directories traversing them recursively to a list of sources
+# and generates filters according to their location (accepts relative paths only).
+# Also this macro trims X times the front word from the filter string for visual studio filters.
+macro(ucm_add_dirs)
+ cmake_parse_arguments(ARG "RECURSIVE" "TO;FILTER_POP" "ADDITIONAL_EXT" ${ARGN})
+
+ if(${ARG_TO} STREQUAL "")
+ message(FATAL_ERROR "Need to pass TO and a variable name to ucm_add_dirs()")
+ endif()
+
+ if("${ARG_FILTER_POP}" STREQUAL "")
+ set(ARG_FILTER_POP 0)
+ endif()
+
+ ucm_add_dir_impl(${ARG_TO} ${ARG_RECURSIVE} ${ARG_FILTER_POP} "${ARG_UNPARSED_ARGUMENTS}" "${ARG_ADDITIONAL_EXT}")
+endmacro()
+
+# ucm_add_target
+# Adds a target eligible for cotiring - unity build and/or precompiled header
+macro(ucm_add_target)
+ cmake_parse_arguments(ARG "UNITY" "NAME;TYPE;PCH_FILE;CPP_PER_UNITY" "UNITY_EXCLUDED;SOURCES" ${ARGN})
+
+ if(NOT "${ARG_UNPARSED_ARGUMENTS}" STREQUAL "")
+ message(FATAL_ERROR "Unrecognized options passed to ucm_add_target()")
+ endif()
+ if("${ARG_NAME}" STREQUAL "")
+ message(FATAL_ERROR "Need to pass NAME and a name for the target to ucm_add_target()")
+ endif()
+ set(valid_types EXECUTABLE STATIC SHARED MODULE)
+ list(FIND valid_types "${ARG_TYPE}" is_type_valid)
+ if(${is_type_valid} STREQUAL "-1")
+ message(FATAL_ERROR "Need to pass TYPE and the type for the target [EXECUTABLE/STATIC/SHARED/MODULE] to ucm_add_target()")
+ endif()
+ if("${ARG_SOURCES}" STREQUAL "")
+ message(FATAL_ERROR "Need to pass SOURCES and a list of source files to ucm_add_target()")
+ endif()
+
+ # init with the global unity flag
+ set(do_unity ${UCM_UNITY_BUILD})
+
+ # check the UNITY argument
+ if(NOT ARG_UNITY)
+ set(do_unity FALSE)
+ endif()
+
+ # if target is excluded through the exclusion list
+ list(FIND UCM_UNITY_BUILD_EXCLUDE_TARGETS ${ARG_NAME} is_target_excluded)
+ if(NOT ${is_target_excluded} STREQUAL "-1")
+ set(do_unity FALSE)
+ endif()
+
+ # unity build only for targets with > 1 source file (otherwise there will be an additional unnecessary target)
+ if(do_unity) # optimization
+ ucm_count_sources(${ARG_SOURCES} RESULT num_sources)
+ if(${num_sources} LESS 2)
+ set(do_unity FALSE)
+ endif()
+ endif()
+
+ set(wanted_cotire ${do_unity})
+
+ # if cotire cannot be used
+ if(do_unity AND NOT ucm_with_cotire)
+ set(do_unity FALSE)
+ endif()
+
+ # inform the developer that the current target might benefit from a unity build
+ if(NOT ARG_UNITY AND ${UCM_UNITY_BUILD})
+ ucm_count_sources(${ARG_SOURCES} RESULT num_sources)
+ if(${num_sources} GREATER 1)
+ message(AUTHOR_WARNING "Target '${ARG_NAME}' may benefit from a unity build.\nIt has ${num_sources} sources - enable with UNITY flag")
+ endif()
+ endif()
+
+ # prepare for the unity build
+ set(orig_target ${ARG_NAME})
+ if(do_unity)
+ # the original target will be added with a different name than the requested
+ set(orig_target ${ARG_NAME}_ORIGINAL)
+
+ # exclude requested files from unity build of the current target
+ foreach(excluded_file "${ARG_UNITY_EXCLUDED}")
+ set_source_files_properties(${excluded_file} PROPERTIES COTIRE_EXCLUDED TRUE)
+ endforeach()
+ endif()
+
+ # add the original target
+ if(${ARG_TYPE} STREQUAL "EXECUTABLE")
+ add_executable(${orig_target} ${ARG_SOURCES})
+ else()
+ add_library(${orig_target} ${ARG_TYPE} ${ARG_SOURCES})
+ endif()
+
+ if(do_unity)
+ # set the number of unity cpp files to be used for the unity target
+ if(NOT "${ARG_CPP_PER_UNITY}" STREQUAL "")
+ set_property(TARGET ${orig_target} PROPERTY COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES "${ARG_CPP_PER_UNITY}")
+ else()
+ set_property(TARGET ${orig_target} PROPERTY COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES "100")
+ endif()
+
+ if(NOT "${ARG_PCH_FILE}" STREQUAL "")
+ set_target_properties(${orig_target} PROPERTIES COTIRE_CXX_PREFIX_HEADER_INIT "${ARG_PCH_FILE}")
+ else()
+ set_target_properties(${orig_target} PROPERTIES COTIRE_ENABLE_PRECOMPILED_HEADER FALSE)
+ endif()
+ # add a unity target for the original one with the name intended for the original
+ set_target_properties(${orig_target} PROPERTIES COTIRE_UNITY_TARGET_NAME ${ARG_NAME})
+
+ # this is the library call that does the magic
+ cotire(${orig_target})
+ set_target_properties(clean_cotire PROPERTIES FOLDER "CMakePredefinedTargets")
+
+ # disable the original target and enable the unity one
+ get_target_property(unity_target_name ${orig_target} COTIRE_UNITY_TARGET_NAME)
+ set_target_properties(${orig_target} PROPERTIES EXCLUDE_FROM_ALL 1 EXCLUDE_FROM_DEFAULT_BUILD 1)
+ set_target_properties(${unity_target_name} PROPERTIES EXCLUDE_FROM_ALL 0 EXCLUDE_FROM_DEFAULT_BUILD 0)
+
+ # also set the name of the target output as the original one
+ set_target_properties(${unity_target_name} PROPERTIES OUTPUT_NAME ${ARG_NAME})
+ if(UCM_NO_COTIRE_FOLDER)
+ # reset the folder property so all unity targets dont end up in a single folder in the solution explorer of VS
+ set_target_properties(${unity_target_name} PROPERTIES FOLDER "")
+ endif()
+ set_target_properties(all_unity PROPERTIES FOLDER "CMakePredefinedTargets")
+ elseif(NOT "${ARG_PCH_FILE}" STREQUAL "")
+ set(wanted_cotire TRUE)
+ if(ucm_with_cotire)
+ set_target_properties(${orig_target} PROPERTIES COTIRE_ADD_UNITY_BUILD FALSE)
+ set_target_properties(${orig_target} PROPERTIES COTIRE_CXX_PREFIX_HEADER_INIT "${ARG_PCH_FILE}")
+ cotire(${orig_target})
+ set_target_properties(clean_cotire PROPERTIES FOLDER "CMakePredefinedTargets")
+ endif()
+ endif()
+
+ # print a message if the target was requested to be cotired but it couldn't
+ if(wanted_cotire AND NOT ucm_with_cotire)
+ if(NOT COMMAND cotire)
+ message(AUTHOR_WARNING "Target \"${ARG_NAME}\" not cotired because cotire isn't loaded")
+ else()
+ message(AUTHOR_WARNING "Target \"${ARG_NAME}\" not cotired because cotire is older than the required version")
+ endif()
+ endif()
+endmacro()