1# - cotire (compile time reducer)
2#
3# See the cotire manual for usage hints.
4#
5#=============================================================================
6# Copyright 2012-2016 Sascha Kratky
7#
8# Permission is hereby granted, free of charge, to any person
9# obtaining a copy of this software and associated documentation
10# files (the "Software"), to deal in the Software without
11# restriction, including without limitation the rights to use,
12# copy, modify, merge, publish, distribute, sublicense, and/or sell
13# copies of the Software, and to permit persons to whom the
14# Software is furnished to do so, subject to the following
15# conditions:
16#
17# The above copyright notice and this permission notice shall be
18# included in all copies or substantial portions of the Software.
19#
20# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
22# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
24# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
25# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27# OTHER DEALINGS IN THE SOFTWARE.
28#=============================================================================
29
30if(__COTIRE_INCLUDED)
31	return()
32endif()
33set(__COTIRE_INCLUDED TRUE)
34
35# call cmake_minimum_required, but prevent modification of the CMake policy stack in include mode
36# cmake_minimum_required also sets the policy version as a side effect, which we have to avoid
37if (NOT CMAKE_SCRIPT_MODE_FILE)
38	cmake_policy(PUSH)
39endif()
40cmake_minimum_required(VERSION 2.8.12)
41if (NOT CMAKE_SCRIPT_MODE_FILE)
42	cmake_policy(POP)
43endif()
44
45set (COTIRE_CMAKE_MODULE_FILE "${CMAKE_CURRENT_LIST_FILE}")
46set (COTIRE_CMAKE_MODULE_VERSION "1.7.8")
47
48# activate select policies
49if (POLICY CMP0025)
50	# Compiler id for Apple Clang is now AppleClang
51	cmake_policy(SET CMP0025 NEW)
52endif()
53
54if (POLICY CMP0026)
55	# disallow use of the LOCATION target property
56	cmake_policy(SET CMP0026 NEW)
57endif()
58
59if (POLICY CMP0038)
60	# targets may not link directly to themselves
61	cmake_policy(SET CMP0038 NEW)
62endif()
63
64if (POLICY CMP0039)
65	# utility targets may not have link dependencies
66	cmake_policy(SET CMP0039 NEW)
67endif()
68
69if (POLICY CMP0040)
70	# target in the TARGET signature of add_custom_command() must exist
71	cmake_policy(SET CMP0040 NEW)
72endif()
73
74if (POLICY CMP0045)
75	# error on non-existent target in get_target_property
76	cmake_policy(SET CMP0045 NEW)
77endif()
78
79if (POLICY CMP0046)
80	# error on non-existent dependency in add_dependencies
81	cmake_policy(SET CMP0046 NEW)
82endif()
83
84if (POLICY CMP0049)
85	# do not expand variables in target source entries
86	cmake_policy(SET CMP0049 NEW)
87endif()
88
89if (POLICY CMP0050)
90	# disallow add_custom_command SOURCE signatures
91	cmake_policy(SET CMP0050 NEW)
92endif()
93
94if (POLICY CMP0051)
95	# include TARGET_OBJECTS expressions in a target's SOURCES property
96	cmake_policy(SET CMP0051 NEW)
97endif()
98
99if (POLICY CMP0053)
100	# simplify variable reference and escape sequence evaluation
101	cmake_policy(SET CMP0053 NEW)
102endif()
103
104if (POLICY CMP0054)
105	# only interpret if() arguments as variables or keywords when unquoted
106	cmake_policy(SET CMP0054 NEW)
107endif()
108
109include(CMakeParseArguments)
110include(ProcessorCount)
111
112function (cotire_get_configuration_types _configsVar)
113	set (_configs "")
114	if (CMAKE_CONFIGURATION_TYPES)
115		list (APPEND _configs ${CMAKE_CONFIGURATION_TYPES})
116	endif()
117	if (CMAKE_BUILD_TYPE)
118		list (APPEND _configs "${CMAKE_BUILD_TYPE}")
119	endif()
120	if (_configs)
121		list (REMOVE_DUPLICATES _configs)
122		set (${_configsVar} ${_configs} PARENT_SCOPE)
123	else()
124		set (${_configsVar} "None" PARENT_SCOPE)
125	endif()
126endfunction()
127
128function (cotire_get_source_file_extension _sourceFile _extVar)
129	# get_filename_component returns extension from first occurrence of . in file name
130	# this function computes the extension from last occurrence of . in file name
131	string (FIND "${_sourceFile}" "." _index REVERSE)
132	if (_index GREATER -1)
133		math (EXPR _index "${_index} + 1")
134		string (SUBSTRING "${_sourceFile}" ${_index} -1 _sourceExt)
135	else()
136		set (_sourceExt "")
137	endif()
138	set (${_extVar} "${_sourceExt}" PARENT_SCOPE)
139endfunction()
140
141macro (cotire_check_is_path_relative_to _path _isRelativeVar)
142	set (${_isRelativeVar} FALSE)
143	if (IS_ABSOLUTE "${_path}")
144		foreach (_dir ${ARGN})
145			file (RELATIVE_PATH _relPath "${_dir}" "${_path}")
146			if (NOT _relPath OR (NOT IS_ABSOLUTE "${_relPath}" AND NOT "${_relPath}" MATCHES "^\\.\\."))
147				set (${_isRelativeVar} TRUE)
148				break()
149			endif()
150		endforeach()
151	endif()
152endmacro()
153
154function (cotire_filter_language_source_files _language _target _sourceFilesVar _excludedSourceFilesVar _cotiredSourceFilesVar)
155	if (CMAKE_${_language}_SOURCE_FILE_EXTENSIONS)
156		set (_languageExtensions "${CMAKE_${_language}_SOURCE_FILE_EXTENSIONS}")
157	else()
158		set (_languageExtensions "")
159	endif()
160	if (CMAKE_${_language}_IGNORE_EXTENSIONS)
161		set (_ignoreExtensions "${CMAKE_${_language}_IGNORE_EXTENSIONS}")
162	else()
163		set (_ignoreExtensions "")
164	endif()
165	if (COTIRE_UNITY_SOURCE_EXCLUDE_EXTENSIONS)
166		set (_excludeExtensions "${COTIRE_UNITY_SOURCE_EXCLUDE_EXTENSIONS}")
167	else()
168		set (_excludeExtensions "")
169	endif()
170	if (COTIRE_DEBUG AND _languageExtensions)
171		message (STATUS "${_language} source file extensions: ${_languageExtensions}")
172	endif()
173	if (COTIRE_DEBUG AND _ignoreExtensions)
174		message (STATUS "${_language} ignore extensions: ${_ignoreExtensions}")
175	endif()
176	if (COTIRE_DEBUG AND _excludeExtensions)
177		message (STATUS "${_language} exclude extensions: ${_excludeExtensions}")
178	endif()
179	if (CMAKE_VERSION VERSION_LESS "3.1.0")
180		set (_allSourceFiles ${ARGN})
181	else()
182		# as of CMake 3.1 target sources may contain generator expressions
183		# since we cannot obtain required property information about source files added
184		# through generator expressions at configure time, we filter them out
185		string (GENEX_STRIP "${ARGN}" _allSourceFiles)
186	endif()
187	set (_filteredSourceFiles "")
188	set (_excludedSourceFiles "")
189	foreach (_sourceFile ${_allSourceFiles})
190		get_source_file_property(_sourceIsHeaderOnly "${_sourceFile}" HEADER_FILE_ONLY)
191		get_source_file_property(_sourceIsExternal "${_sourceFile}" EXTERNAL_OBJECT)
192		get_source_file_property(_sourceIsSymbolic "${_sourceFile}" SYMBOLIC)
193		if (NOT _sourceIsHeaderOnly AND NOT _sourceIsExternal AND NOT _sourceIsSymbolic)
194			cotire_get_source_file_extension("${_sourceFile}" _sourceExt)
195			if (_sourceExt)
196				list (FIND _ignoreExtensions "${_sourceExt}" _ignoreIndex)
197				if (_ignoreIndex LESS 0)
198					list (FIND _excludeExtensions "${_sourceExt}" _excludeIndex)
199					if (_excludeIndex GREATER -1)
200						list (APPEND _excludedSourceFiles "${_sourceFile}")
201					else()
202						list (FIND _languageExtensions "${_sourceExt}" _sourceIndex)
203						if (_sourceIndex GREATER -1)
204							# consider source file unless it is excluded explicitly
205							get_source_file_property(_sourceIsExcluded "${_sourceFile}" COTIRE_EXCLUDED)
206							if (_sourceIsExcluded)
207								list (APPEND _excludedSourceFiles "${_sourceFile}")
208							else()
209								list (APPEND _filteredSourceFiles "${_sourceFile}")
210							endif()
211						else()
212							get_source_file_property(_sourceLanguage "${_sourceFile}" LANGUAGE)
213							if ("${_sourceLanguage}" STREQUAL "${_language}")
214								# add to excluded sources, if file is not ignored and has correct language without having the correct extension
215								list (APPEND _excludedSourceFiles "${_sourceFile}")
216							endif()
217						endif()
218					endif()
219				endif()
220			endif()
221		endif()
222	endforeach()
223	# separate filtered source files from already cotired ones
224	# the COTIRE_TARGET property of a source file may be set while a target is being processed by cotire
225	set (_sourceFiles "")
226	set (_cotiredSourceFiles "")
227	foreach (_sourceFile ${_filteredSourceFiles})
228		get_source_file_property(_sourceIsCotired "${_sourceFile}" COTIRE_TARGET)
229		if (_sourceIsCotired)
230			list (APPEND _cotiredSourceFiles "${_sourceFile}")
231		else()
232			get_source_file_property(_sourceCompileFlags "${_sourceFile}" COMPILE_FLAGS)
233			if (_sourceCompileFlags)
234				# add to excluded sources, if file has custom compile flags
235				list (APPEND _excludedSourceFiles "${_sourceFile}")
236			else()
237				list (APPEND _sourceFiles "${_sourceFile}")
238			endif()
239		endif()
240	endforeach()
241	if (COTIRE_DEBUG)
242		if (_sourceFiles)
243			message (STATUS "Filtered ${_target} ${_language} sources: ${_sourceFiles}")
244		endif()
245		if (_excludedSourceFiles)
246			message (STATUS "Excluded ${_target} ${_language} sources: ${_excludedSourceFiles}")
247		endif()
248		if (_cotiredSourceFiles)
249			message (STATUS "Cotired ${_target} ${_language} sources: ${_cotiredSourceFiles}")
250		endif()
251	endif()
252	set (${_sourceFilesVar} ${_sourceFiles} PARENT_SCOPE)
253	set (${_excludedSourceFilesVar} ${_excludedSourceFiles} PARENT_SCOPE)
254	set (${_cotiredSourceFilesVar} ${_cotiredSourceFiles} PARENT_SCOPE)
255endfunction()
256
257function (cotire_get_objects_with_property_on _filteredObjectsVar _property _type)
258	set (_filteredObjects "")
259	foreach (_object ${ARGN})
260		get_property(_isSet ${_type} "${_object}" PROPERTY ${_property} SET)
261		if (_isSet)
262			get_property(_propertyValue ${_type} "${_object}" PROPERTY ${_property})
263			if (_propertyValue)
264				list (APPEND _filteredObjects "${_object}")
265			endif()
266		endif()
267	endforeach()
268	set (${_filteredObjectsVar} ${_filteredObjects} PARENT_SCOPE)
269endfunction()
270
271function (cotire_get_objects_with_property_off _filteredObjectsVar _property _type)
272	set (_filteredObjects "")
273	foreach (_object ${ARGN})
274		get_property(_isSet ${_type} "${_object}" PROPERTY ${_property} SET)
275		if (_isSet)
276			get_property(_propertyValue ${_type} "${_object}" PROPERTY ${_property})
277			if (NOT _propertyValue)
278				list (APPEND _filteredObjects "${_object}")
279			endif()
280		endif()
281	endforeach()
282	set (${_filteredObjectsVar} ${_filteredObjects} PARENT_SCOPE)
283endfunction()
284
285function (cotire_get_source_file_property_values _valuesVar _property)
286	set (_values "")
287	foreach (_sourceFile ${ARGN})
288		get_source_file_property(_propertyValue "${_sourceFile}" ${_property})
289		if (_propertyValue)
290			list (APPEND _values "${_propertyValue}")
291		endif()
292	endforeach()
293	set (${_valuesVar} ${_values} PARENT_SCOPE)
294endfunction()
295
296function (cotire_resolve_config_properites _configurations _propertiesVar)
297	set (_properties "")
298	foreach (_property ${ARGN})
299		if ("${_property}" MATCHES "<CONFIG>")
300			foreach (_config ${_configurations})
301				string (TOUPPER "${_config}" _upperConfig)
302				string (REPLACE "<CONFIG>" "${_upperConfig}" _configProperty "${_property}")
303				list (APPEND _properties ${_configProperty})
304			endforeach()
305		else()
306			list (APPEND _properties ${_property})
307		endif()
308	endforeach()
309	set (${_propertiesVar} ${_properties} PARENT_SCOPE)
310endfunction()
311
312function (cotire_copy_set_properites _configurations _type _source _target)
313	cotire_resolve_config_properites("${_configurations}" _properties ${ARGN})
314	foreach (_property ${_properties})
315		get_property(_isSet ${_type} ${_source} PROPERTY ${_property} SET)
316		if (_isSet)
317			get_property(_propertyValue ${_type} ${_source} PROPERTY ${_property})
318			set_property(${_type} ${_target} PROPERTY ${_property} "${_propertyValue}")
319		endif()
320	endforeach()
321endfunction()
322
323function (cotire_get_target_usage_requirements _target _targetRequirementsVar)
324	set (_targetRequirements "")
325	get_target_property(_librariesToProcess ${_target} LINK_LIBRARIES)
326	while (_librariesToProcess)
327		# remove from head
328		list (GET _librariesToProcess 0 _library)
329		list (REMOVE_AT _librariesToProcess 0)
330		if (TARGET ${_library})
331			list (FIND _targetRequirements ${_library} _index)
332			if (_index LESS 0)
333				list (APPEND _targetRequirements ${_library})
334				# BFS traversal of transitive libraries
335				get_target_property(_libraries ${_library} INTERFACE_LINK_LIBRARIES)
336				if (_libraries)
337					list (APPEND _librariesToProcess ${_libraries})
338					list (REMOVE_DUPLICATES _librariesToProcess)
339				endif()
340			endif()
341		endif()
342	endwhile()
343	set (${_targetRequirementsVar} ${_targetRequirements} PARENT_SCOPE)
344endfunction()
345
346function (cotire_filter_compile_flags _language _flagFilter _matchedOptionsVar _unmatchedOptionsVar)
347	if (WIN32 AND CMAKE_${_language}_COMPILER_ID MATCHES "MSVC|Intel")
348		set (_flagPrefix "[/-]")
349	else()
350		set (_flagPrefix "--?")
351	endif()
352	set (_optionFlag "")
353	set (_matchedOptions "")
354	set (_unmatchedOptions "")
355	foreach (_compileFlag ${ARGN})
356		if (_compileFlag)
357			if (_optionFlag AND NOT "${_compileFlag}" MATCHES "^${_flagPrefix}")
358				# option with separate argument
359				list (APPEND _matchedOptions "${_compileFlag}")
360				set (_optionFlag "")
361			elseif ("${_compileFlag}" MATCHES "^(${_flagPrefix})(${_flagFilter})$")
362				# remember option
363				set (_optionFlag "${CMAKE_MATCH_2}")
364			elseif ("${_compileFlag}" MATCHES "^(${_flagPrefix})(${_flagFilter})(.+)$")
365				# option with joined argument
366				list (APPEND _matchedOptions "${CMAKE_MATCH_3}")
367				set (_optionFlag "")
368			else()
369				# flush remembered option
370				if (_optionFlag)
371					list (APPEND _matchedOptions "${_optionFlag}")
372					set (_optionFlag "")
373				endif()
374				# add to unfiltered options
375				list (APPEND _unmatchedOptions "${_compileFlag}")
376			endif()
377		endif()
378	endforeach()
379	if (_optionFlag)
380		list (APPEND _matchedOptions "${_optionFlag}")
381	endif()
382	if (COTIRE_DEBUG AND _matchedOptions)
383		message (STATUS "Filter ${_flagFilter} matched: ${_matchedOptions}")
384	endif()
385	if (COTIRE_DEBUG AND _unmatchedOptions)
386		message (STATUS "Filter ${_flagFilter} unmatched: ${_unmatchedOptions}")
387	endif()
388	set (${_matchedOptionsVar} ${_matchedOptions} PARENT_SCOPE)
389	set (${_unmatchedOptionsVar} ${_unmatchedOptions} PARENT_SCOPE)
390endfunction()
391
392function (cotire_is_target_supported _target _isSupportedVar)
393	if (NOT TARGET "${_target}")
394		set (${_isSupportedVar} FALSE PARENT_SCOPE)
395		return()
396	endif()
397	get_target_property(_imported ${_target} IMPORTED)
398	if (_imported)
399		set (${_isSupportedVar} FALSE PARENT_SCOPE)
400		return()
401	endif()
402	get_target_property(_targetType ${_target} TYPE)
403	if (NOT _targetType MATCHES "EXECUTABLE|(STATIC|SHARED|MODULE|OBJECT)_LIBRARY")
404		set (${_isSupportedVar} FALSE PARENT_SCOPE)
405		return()
406	endif()
407	set (${_isSupportedVar} TRUE PARENT_SCOPE)
408endfunction()
409
410function (cotire_get_target_compile_flags _config _language _target _flagsVar)
411	string (TOUPPER "${_config}" _upperConfig)
412	# collect options from CMake language variables
413	set (_compileFlags "")
414	if (CMAKE_${_language}_FLAGS)
415		set (_compileFlags "${_compileFlags} ${CMAKE_${_language}_FLAGS}")
416	endif()
417	if (CMAKE_${_language}_FLAGS_${_upperConfig})
418		set (_compileFlags "${_compileFlags} ${CMAKE_${_language}_FLAGS_${_upperConfig}}")
419	endif()
420	if (_target)
421		# add target compile flags
422		get_target_property(_targetflags ${_target} COMPILE_FLAGS)
423		if (_targetflags)
424			set (_compileFlags "${_compileFlags} ${_targetflags}")
425		endif()
426	endif()
427	if (UNIX)
428		separate_arguments(_compileFlags UNIX_COMMAND "${_compileFlags}")
429	elseif(WIN32)
430		separate_arguments(_compileFlags WINDOWS_COMMAND "${_compileFlags}")
431	else()
432		separate_arguments(_compileFlags)
433	endif()
434	# target compile options
435	if (_target)
436		get_target_property(_targetOptions ${_target} COMPILE_OPTIONS)
437		if (_targetOptions)
438			list (APPEND _compileFlags ${_targetOptions})
439		endif()
440	endif()
441	# interface compile options from linked library targets
442	if (_target)
443		set (_linkedTargets "")
444		cotire_get_target_usage_requirements(${_target} _linkedTargets)
445		foreach (_linkedTarget ${_linkedTargets})
446			get_target_property(_targetOptions ${_linkedTarget} INTERFACE_COMPILE_OPTIONS)
447			if (_targetOptions)
448				list (APPEND _compileFlags ${_targetOptions})
449			endif()
450		endforeach()
451	endif()
452	# handle language standard properties
453	if (_target)
454		get_target_property(_targetLanguageStandard ${_target} ${_language}_STANDARD)
455		get_target_property(_targetLanguageExtensions ${_target} ${_language}_EXTENSIONS)
456		get_target_property(_targetLanguageStandardRequired ${_target} ${_language}_STANDARD_REQUIRED)
457		if (_targetLanguageExtensions)
458			if (CMAKE_${_language}${_targetLanguageExtensions}_EXTENSION_COMPILE_OPTION)
459				list (APPEND _compileFlags "${CMAKE_${_language}${_targetLanguageExtensions}_EXTENSION_COMPILE_OPTION}")
460			endif()
461		elseif (_targetLanguageStandard)
462			if (_targetLanguageStandardRequired)
463				if (CMAKE_${_language}${_targetLanguageStandard}_STANDARD_COMPILE_OPTION)
464					list (APPEND _compileFlags "${CMAKE_${_language}${_targetLanguageStandard}_STANDARD_COMPILE_OPTION}")
465				endif()
466			else()
467				if (CMAKE_${_language}${_targetLanguageStandard}_EXTENSION_COMPILE_OPTION)
468					list (APPEND _compileFlags "${CMAKE_${_language}${_targetLanguageStandard}_EXTENSION_COMPILE_OPTION}")
469				endif()
470			endif()
471		endif()
472	endif()
473	# handle the POSITION_INDEPENDENT_CODE target property
474	if (_target)
475		get_target_property(_targetPIC ${_target} POSITION_INDEPENDENT_CODE)
476		if (_targetPIC)
477			get_target_property(_targetType ${_target} TYPE)
478			if (_targetType STREQUAL "EXECUTABLE" AND CMAKE_${_language}_COMPILE_OPTIONS_PIE)
479				list (APPEND _compileFlags "${CMAKE_${_language}_COMPILE_OPTIONS_PIE}")
480			elseif (CMAKE_${_language}_COMPILE_OPTIONS_PIC)
481				list (APPEND _compileFlags "${CMAKE_${_language}_COMPILE_OPTIONS_PIC}")
482			endif()
483		endif()
484	endif()
485	# handle visibility target properties
486	if (_target)
487		get_target_property(_targetVisibility ${_target} ${_language}_VISIBILITY_PRESET)
488		if (_targetVisibility AND CMAKE_${_language}_COMPILE_OPTIONS_VISIBILITY)
489			list (APPEND _compileFlags "${CMAKE_${_language}_COMPILE_OPTIONS_VISIBILITY}${_targetVisibility}")
490		endif()
491		get_target_property(_targetVisibilityInlines ${_target} VISIBILITY_INLINES_HIDDEN)
492		if (_targetVisibilityInlines AND CMAKE_${_language}_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN)
493			list (APPEND _compileFlags "${CMAKE_${_language}_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN}")
494		endif()
495	endif()
496	# platform specific flags
497	if (APPLE)
498		get_target_property(_architectures ${_target} OSX_ARCHITECTURES_${_upperConfig})
499		if (NOT _architectures)
500			get_target_property(_architectures ${_target} OSX_ARCHITECTURES)
501		endif()
502		if (_architectures)
503			foreach (_arch ${_architectures})
504				list (APPEND _compileFlags "-arch" "${_arch}")
505			endforeach()
506		endif()
507		if (CMAKE_OSX_SYSROOT)
508			if (CMAKE_${_language}_SYSROOT_FLAG)
509				list (APPEND _compileFlags "${CMAKE_${_language}_SYSROOT_FLAG}" "${CMAKE_OSX_SYSROOT}")
510			else()
511				list (APPEND _compileFlags "-isysroot" "${CMAKE_OSX_SYSROOT}")
512			endif()
513		endif()
514		if (CMAKE_OSX_DEPLOYMENT_TARGET)
515			if (CMAKE_${_language}_OSX_DEPLOYMENT_TARGET_FLAG)
516				list (APPEND _compileFlags "${CMAKE_${_language}_OSX_DEPLOYMENT_TARGET_FLAG}${CMAKE_OSX_DEPLOYMENT_TARGET}")
517			else()
518				list (APPEND _compileFlags "-mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}")
519			endif()
520		endif()
521	endif()
522	if (COTIRE_DEBUG AND _compileFlags)
523		message (STATUS "Target ${_target} compile flags: ${_compileFlags}")
524	endif()
525	set (${_flagsVar} ${_compileFlags} PARENT_SCOPE)
526endfunction()
527
528function (cotire_get_target_include_directories _config _language _target _includeDirsVar _systemIncludeDirsVar)
529	set (_includeDirs "")
530	set (_systemIncludeDirs "")
531	# default include dirs
532	if (CMAKE_INCLUDE_CURRENT_DIR)
533		list (APPEND _includeDirs "${CMAKE_CURRENT_BINARY_DIR}")
534		list (APPEND _includeDirs "${CMAKE_CURRENT_SOURCE_DIR}")
535	endif()
536	set (_targetFlags "")
537	cotire_get_target_compile_flags("${_config}" "${_language}" "${_target}" _targetFlags)
538	# parse additional include directories from target compile flags
539	if (CMAKE_INCLUDE_FLAG_${_language})
540		string (STRIP "${CMAKE_INCLUDE_FLAG_${_language}}" _includeFlag)
541		string (REGEX REPLACE "^[-/]+" "" _includeFlag "${_includeFlag}")
542		if (_includeFlag)
543			set (_dirs "")
544			cotire_filter_compile_flags("${_language}" "${_includeFlag}" _dirs _ignore ${_targetFlags})
545			if (_dirs)
546				list (APPEND _includeDirs ${_dirs})
547			endif()
548		endif()
549	endif()
550	# parse additional system include directories from target compile flags
551	if (CMAKE_INCLUDE_SYSTEM_FLAG_${_language})
552		string (STRIP "${CMAKE_INCLUDE_SYSTEM_FLAG_${_language}}" _includeFlag)
553		string (REGEX REPLACE "^[-/]+" "" _includeFlag "${_includeFlag}")
554		if (_includeFlag)
555			set (_dirs "")
556			cotire_filter_compile_flags("${_language}" "${_includeFlag}" _dirs _ignore ${_targetFlags})
557			if (_dirs)
558				list (APPEND _systemIncludeDirs ${_dirs})
559			endif()
560		endif()
561	endif()
562	# target include directories
563	get_directory_property(_dirs DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" INCLUDE_DIRECTORIES)
564	if (_target)
565		get_target_property(_targetDirs ${_target} INCLUDE_DIRECTORIES)
566		if (_targetDirs)
567			list (APPEND _dirs ${_targetDirs})
568		endif()
569		get_target_property(_targetDirs ${_target} INTERFACE_SYSTEM_INCLUDE_DIRECTORIES)
570		if (_targetDirs)
571			list (APPEND _systemIncludeDirs ${_targetDirs})
572		endif()
573	endif()
574	# interface include directories from linked library targets
575	if (_target)
576		set (_linkedTargets "")
577		cotire_get_target_usage_requirements(${_target} _linkedTargets)
578		foreach (_linkedTarget ${_linkedTargets})
579			get_target_property(_linkedTargetType ${_linkedTarget} TYPE)
580			if (CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE AND NOT CMAKE_VERSION VERSION_LESS "3.4.0" AND
581				_linkedTargetType MATCHES "(STATIC|SHARED|MODULE|OBJECT)_LIBRARY")
582				# CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE refers to CMAKE_CURRENT_BINARY_DIR and CMAKE_CURRENT_SOURCE_DIR
583				# at the time, when the target was created. These correspond to the target properties BINARY_DIR and SOURCE_DIR
584				# which are only available with CMake 3.4 or later.
585				get_target_property(_targetDirs ${_linkedTarget} BINARY_DIR)
586				if (_targetDirs)
587					list (APPEND _dirs ${_targetDirs})
588				endif()
589				get_target_property(_targetDirs ${_linkedTarget} SOURCE_DIR)
590				if (_targetDirs)
591					list (APPEND _dirs ${_targetDirs})
592				endif()
593			endif()
594			get_target_property(_targetDirs ${_linkedTarget} INTERFACE_INCLUDE_DIRECTORIES)
595			if (_targetDirs)
596				list (APPEND _dirs ${_targetDirs})
597			endif()
598			get_target_property(_targetDirs ${_linkedTarget} INTERFACE_SYSTEM_INCLUDE_DIRECTORIES)
599			if (_targetDirs)
600				list (APPEND _systemIncludeDirs ${_targetDirs})
601			endif()
602		endforeach()
603	endif()
604	if (dirs)
605		list (REMOVE_DUPLICATES _dirs)
606	endif()
607	list (LENGTH _includeDirs _projectInsertIndex)
608	foreach (_dir ${_dirs})
609		if (CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE)
610			cotire_check_is_path_relative_to("${_dir}" _isRelative "${CMAKE_SOURCE_DIR}" "${CMAKE_BINARY_DIR}")
611			if (_isRelative)
612				list (LENGTH _includeDirs _len)
613				if (_len EQUAL _projectInsertIndex)
614					list (APPEND _includeDirs "${_dir}")
615				else()
616					list (INSERT _includeDirs _projectInsertIndex "${_dir}")
617				endif()
618				math (EXPR _projectInsertIndex "${_projectInsertIndex} + 1")
619			else()
620				list (APPEND _includeDirs "${_dir}")
621			endif()
622		else()
623			list (APPEND _includeDirs "${_dir}")
624		endif()
625	endforeach()
626	list (REMOVE_DUPLICATES _includeDirs)
627	list (REMOVE_DUPLICATES _systemIncludeDirs)
628	if (CMAKE_${_language}_IMPLICIT_INCLUDE_DIRECTORIES)
629		list (REMOVE_ITEM _includeDirs ${CMAKE_${_language}_IMPLICIT_INCLUDE_DIRECTORIES})
630	endif()
631	if (COTIRE_DEBUG AND _includeDirs)
632		message (STATUS "Target ${_target} include dirs: ${_includeDirs}")
633	endif()
634	set (${_includeDirsVar} ${_includeDirs} PARENT_SCOPE)
635	if (COTIRE_DEBUG AND _systemIncludeDirs)
636		message (STATUS "Target ${_target} system include dirs: ${_systemIncludeDirs}")
637	endif()
638	set (${_systemIncludeDirsVar} ${_systemIncludeDirs} PARENT_SCOPE)
639endfunction()
640
641function (cotire_get_target_export_symbol _target _exportSymbolVar)
642	set (_exportSymbol "")
643	get_target_property(_targetType ${_target} TYPE)
644	get_target_property(_enableExports ${_target} ENABLE_EXPORTS)
645	if (_targetType MATCHES "(SHARED|MODULE)_LIBRARY" OR
646		(_targetType STREQUAL "EXECUTABLE" AND _enableExports))
647		get_target_property(_exportSymbol ${_target} DEFINE_SYMBOL)
648		if (NOT _exportSymbol)
649			set (_exportSymbol "${_target}_EXPORTS")
650		endif()
651		string (MAKE_C_IDENTIFIER "${_exportSymbol}" _exportSymbol)
652	endif()
653	set (${_exportSymbolVar} ${_exportSymbol} PARENT_SCOPE)
654endfunction()
655
656function (cotire_get_target_compile_definitions _config _language _target _definitionsVar)
657	string (TOUPPER "${_config}" _upperConfig)
658	set (_configDefinitions "")
659	# CMAKE_INTDIR for multi-configuration build systems
660	if (NOT "${CMAKE_CFG_INTDIR}" STREQUAL ".")
661		list (APPEND _configDefinitions "CMAKE_INTDIR=\"${_config}\"")
662	endif()
663	# target export define symbol
664	cotire_get_target_export_symbol("${_target}" _defineSymbol)
665	if (_defineSymbol)
666		list (APPEND _configDefinitions "${_defineSymbol}")
667	endif()
668	# directory compile definitions
669	get_directory_property(_definitions DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" COMPILE_DEFINITIONS)
670	if (_definitions)
671		list (APPEND _configDefinitions ${_definitions})
672	endif()
673	get_directory_property(_definitions DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" COMPILE_DEFINITIONS_${_upperConfig})
674	if (_definitions)
675		list (APPEND _configDefinitions ${_definitions})
676	endif()
677	# target compile definitions
678	get_target_property(_definitions ${_target} COMPILE_DEFINITIONS)
679	if (_definitions)
680		list (APPEND _configDefinitions ${_definitions})
681	endif()
682	get_target_property(_definitions ${_target} COMPILE_DEFINITIONS_${_upperConfig})
683	if (_definitions)
684		list (APPEND _configDefinitions ${_definitions})
685	endif()
686	# interface compile definitions from linked library targets
687	set (_linkedTargets "")
688	cotire_get_target_usage_requirements(${_target} _linkedTargets)
689	foreach (_linkedTarget ${_linkedTargets})
690		get_target_property(_definitions ${_linkedTarget} INTERFACE_COMPILE_DEFINITIONS)
691		if (_definitions)
692			list (APPEND _configDefinitions ${_definitions})
693		endif()
694	endforeach()
695	# parse additional compile definitions from target compile flags
696	# and don't look at directory compile definitions, which we already handled
697	set (_targetFlags "")
698	cotire_get_target_compile_flags("${_config}" "${_language}" "${_target}" _targetFlags)
699	cotire_filter_compile_flags("${_language}" "D" _definitions _ignore ${_targetFlags})
700	if (_definitions)
701		list (APPEND _configDefinitions ${_definitions})
702	endif()
703	list (REMOVE_DUPLICATES _configDefinitions)
704	if (COTIRE_DEBUG AND _configDefinitions)
705		message (STATUS "Target ${_target} compile definitions: ${_configDefinitions}")
706	endif()
707	set (${_definitionsVar} ${_configDefinitions} PARENT_SCOPE)
708endfunction()
709
710function (cotire_get_target_compiler_flags _config _language _target _compilerFlagsVar)
711	# parse target compile flags omitting compile definitions and include directives
712	set (_targetFlags "")
713	cotire_get_target_compile_flags("${_config}" "${_language}" "${_target}" _targetFlags)
714	set (_flagFilter "D")
715	if (CMAKE_INCLUDE_FLAG_${_language})
716		string (STRIP "${CMAKE_INCLUDE_FLAG_${_language}}" _includeFlag)
717		string (REGEX REPLACE "^[-/]+" "" _includeFlag "${_includeFlag}")
718		if (_includeFlag)
719			set (_flagFilter "${_flagFilter}|${_includeFlag}")
720		endif()
721	endif()
722	if (CMAKE_INCLUDE_SYSTEM_FLAG_${_language})
723		string (STRIP "${CMAKE_INCLUDE_SYSTEM_FLAG_${_language}}" _includeFlag)
724		string (REGEX REPLACE "^[-/]+" "" _includeFlag "${_includeFlag}")
725		if (_includeFlag)
726			set (_flagFilter "${_flagFilter}|${_includeFlag}")
727		endif()
728	endif()
729	set (_compilerFlags "")
730	cotire_filter_compile_flags("${_language}" "${_flagFilter}" _ignore _compilerFlags ${_targetFlags})
731	if (COTIRE_DEBUG AND _compilerFlags)
732		message (STATUS "Target ${_target} compiler flags: ${_compilerFlags}")
733	endif()
734	set (${_compilerFlagsVar} ${_compilerFlags} PARENT_SCOPE)
735endfunction()
736
737function (cotire_add_sys_root_paths _pathsVar)
738	if (APPLE)
739		if (CMAKE_OSX_SYSROOT AND CMAKE_${_language}_HAS_ISYSROOT)
740			foreach (_path IN LISTS ${_pathsVar})
741				if (IS_ABSOLUTE "${_path}")
742					get_filename_component(_path "${CMAKE_OSX_SYSROOT}/${_path}" ABSOLUTE)
743					if (EXISTS "${_path}")
744						list (APPEND ${_pathsVar} "${_path}")
745					endif()
746				endif()
747			endforeach()
748		endif()
749	endif()
750	set (${_pathsVar} ${${_pathsVar}} PARENT_SCOPE)
751endfunction()
752
753function (cotire_get_source_extra_properties _sourceFile _pattern _resultVar)
754	set (_extraProperties ${ARGN})
755	set (_result "")
756	if (_extraProperties)
757		list (FIND _extraProperties "${_sourceFile}" _index)
758		if (_index GREATER -1)
759			math (EXPR _index "${_index} + 1")
760			list (LENGTH _extraProperties _len)
761			math (EXPR _len "${_len} - 1")
762			foreach (_index RANGE ${_index} ${_len})
763				list (GET _extraProperties ${_index} _value)
764				if (_value MATCHES "${_pattern}")
765					list (APPEND _result "${_value}")
766				else()
767					break()
768				endif()
769			endforeach()
770		endif()
771	endif()
772	set (${_resultVar} ${_result} PARENT_SCOPE)
773endfunction()
774
775function (cotire_get_source_compile_definitions _config _language _sourceFile _definitionsVar)
776	set (_compileDefinitions "")
777	if (NOT CMAKE_SCRIPT_MODE_FILE)
778		string (TOUPPER "${_config}" _upperConfig)
779		get_source_file_property(_definitions "${_sourceFile}" COMPILE_DEFINITIONS)
780		if (_definitions)
781			list (APPEND _compileDefinitions ${_definitions})
782		endif()
783		get_source_file_property(_definitions "${_sourceFile}" COMPILE_DEFINITIONS_${_upperConfig})
784		if (_definitions)
785			list (APPEND _compileDefinitions ${_definitions})
786		endif()
787	endif()
788	cotire_get_source_extra_properties("${_sourceFile}" "^[a-zA-Z0-9_]+(=.*)?$" _definitions ${ARGN})
789	if (_definitions)
790		list (APPEND _compileDefinitions ${_definitions})
791	endif()
792	if (COTIRE_DEBUG AND _compileDefinitions)
793		message (STATUS "Source ${_sourceFile} compile definitions: ${_compileDefinitions}")
794	endif()
795	set (${_definitionsVar} ${_compileDefinitions} PARENT_SCOPE)
796endfunction()
797
798function (cotire_get_source_files_compile_definitions _config _language _definitionsVar)
799	set (_configDefinitions "")
800	foreach (_sourceFile ${ARGN})
801		cotire_get_source_compile_definitions("${_config}" "${_language}" "${_sourceFile}" _sourceDefinitions)
802		if (_sourceDefinitions)
803			list (APPEND _configDefinitions "${_sourceFile}" ${_sourceDefinitions} "-")
804		endif()
805	endforeach()
806	set (${_definitionsVar} ${_configDefinitions} PARENT_SCOPE)
807endfunction()
808
809function (cotire_get_source_undefs _sourceFile _property _sourceUndefsVar)
810	set (_sourceUndefs "")
811	if (NOT CMAKE_SCRIPT_MODE_FILE)
812		get_source_file_property(_undefs "${_sourceFile}" ${_property})
813		if (_undefs)
814			list (APPEND _sourceUndefs ${_undefs})
815		endif()
816	endif()
817	cotire_get_source_extra_properties("${_sourceFile}" "^[a-zA-Z0-9_]+$" _undefs ${ARGN})
818	if (_undefs)
819		list (APPEND _sourceUndefs ${_undefs})
820	endif()
821	if (COTIRE_DEBUG AND _sourceUndefs)
822		message (STATUS "Source ${_sourceFile} ${_property} undefs: ${_sourceUndefs}")
823	endif()
824	set (${_sourceUndefsVar} ${_sourceUndefs} PARENT_SCOPE)
825endfunction()
826
827function (cotire_get_source_files_undefs _property _sourceUndefsVar)
828	set (_sourceUndefs "")
829	foreach (_sourceFile ${ARGN})
830		cotire_get_source_undefs("${_sourceFile}" ${_property} _undefs)
831		if (_undefs)
832			list (APPEND _sourceUndefs "${_sourceFile}" ${_undefs} "-")
833		endif()
834	endforeach()
835	set (${_sourceUndefsVar} ${_sourceUndefs} PARENT_SCOPE)
836endfunction()
837
838macro (cotire_set_cmd_to_prologue _cmdVar)
839	set (${_cmdVar} "${CMAKE_COMMAND}")
840	if (COTIRE_DEBUG)
841		list (APPEND ${_cmdVar} "--warn-uninitialized")
842	endif()
843	list (APPEND ${_cmdVar} "-DCOTIRE_BUILD_TYPE:STRING=$<CONFIGURATION>")
844	if (COTIRE_VERBOSE)
845		list (APPEND ${_cmdVar} "-DCOTIRE_VERBOSE:BOOL=ON")
846	elseif("${CMAKE_GENERATOR}" MATCHES "Makefiles")
847		list (APPEND ${_cmdVar} "-DCOTIRE_VERBOSE:BOOL=$(VERBOSE)")
848	endif()
849endmacro()
850
851function (cotire_init_compile_cmd _cmdVar _language _compilerLauncher _compilerExe _compilerArg1)
852	if (NOT _compilerLauncher)
853		set (_compilerLauncher ${CMAKE_${_language}_COMPILER_LAUNCHER})
854	endif()
855	if (NOT _compilerExe)
856		set (_compilerExe "${CMAKE_${_language}_COMPILER}")
857	endif()
858	if (NOT _compilerArg1)
859		set (_compilerArg1 ${CMAKE_${_language}_COMPILER_ARG1})
860	endif()
861	string (STRIP "${_compilerArg1}" _compilerArg1)
862	if ("${CMAKE_GENERATOR}" MATCHES "Make|Ninja")
863		# compiler launcher is only supported for Makefile and Ninja
864		set (${_cmdVar} ${_compilerLauncher} "${_compilerExe}" ${_compilerArg1} PARENT_SCOPE)
865	else()
866		set (${_cmdVar} "${_compilerExe}" ${_compilerArg1} PARENT_SCOPE)
867	endif()
868endfunction()
869
870macro (cotire_add_definitions_to_cmd _cmdVar _language)
871	foreach (_definition ${ARGN})
872		if (WIN32 AND CMAKE_${_language}_COMPILER_ID MATCHES "MSVC|Intel")
873			list (APPEND ${_cmdVar} "/D${_definition}")
874		else()
875			list (APPEND ${_cmdVar} "-D${_definition}")
876		endif()
877	endforeach()
878endmacro()
879
880function (cotire_add_includes_to_cmd _cmdVar _language _includesVar _systemIncludesVar)
881	set (_includeDirs ${${_includesVar}} ${${_systemIncludesVar}})
882	if (_includeDirs)
883		list (REMOVE_DUPLICATES _includeDirs)
884		foreach (_include ${_includeDirs})
885			if (WIN32 AND CMAKE_${_language}_COMPILER_ID MATCHES "MSVC|Intel")
886				file (TO_NATIVE_PATH "${_include}" _include)
887				list (APPEND ${_cmdVar} "${CMAKE_INCLUDE_FLAG_${_language}}${CMAKE_INCLUDE_FLAG_${_language}_SEP}${_include}")
888			else()
889				set (_index -1)
890				if ("${CMAKE_INCLUDE_SYSTEM_FLAG_${_language}}" MATCHES ".+")
891					list (FIND ${_systemIncludesVar} "${_include}" _index)
892				endif()
893				if (_index GREATER -1)
894					list (APPEND ${_cmdVar} "${CMAKE_INCLUDE_SYSTEM_FLAG_${_language}}${_include}")
895				else()
896					list (APPEND ${_cmdVar} "${CMAKE_INCLUDE_FLAG_${_language}}${CMAKE_INCLUDE_FLAG_${_language}_SEP}${_include}")
897				endif()
898			endif()
899		endforeach()
900	endif()
901	set (${_cmdVar} ${${_cmdVar}} PARENT_SCOPE)
902endfunction()
903
904function (cotire_add_frameworks_to_cmd _cmdVar _language _includesVar _systemIncludesVar)
905	if (APPLE)
906		set (_frameworkDirs "")
907		foreach (_include ${${_includesVar}})
908			if (IS_ABSOLUTE "${_include}" AND _include MATCHES "\\.framework$")
909				get_filename_component(_frameworkDir "${_include}" DIRECTORY)
910				list (APPEND _frameworkDirs "${_frameworkDir}")
911			endif()
912		endforeach()
913		set (_systemFrameworkDirs "")
914		foreach (_include ${${_systemIncludesVar}})
915			if (IS_ABSOLUTE "${_include}" AND _include MATCHES "\\.framework$")
916				get_filename_component(_frameworkDir "${_include}" DIRECTORY)
917				list (APPEND _systemFrameworkDirs "${_frameworkDir}")
918			endif()
919		endforeach()
920		if (_systemFrameworkDirs)
921			list (APPEND _frameworkDirs ${_systemFrameworkDirs})
922		endif()
923		if (_frameworkDirs)
924			list (REMOVE_DUPLICATES _frameworkDirs)
925			foreach (_frameworkDir ${_frameworkDirs})
926				set (_index -1)
927				if ("${CMAKE_${_language}_SYSTEM_FRAMEWORK_SEARCH_FLAG}" MATCHES ".+")
928					list (FIND _systemFrameworkDirs "${_frameworkDir}" _index)
929				endif()
930				if (_index GREATER -1)
931					list (APPEND ${_cmdVar} "${CMAKE_${_language}_SYSTEM_FRAMEWORK_SEARCH_FLAG}${_frameworkDir}")
932				else()
933					list (APPEND ${_cmdVar} "${CMAKE_${_language}_FRAMEWORK_SEARCH_FLAG}${_frameworkDir}")
934				endif()
935			endforeach()
936		endif()
937	endif()
938	set (${_cmdVar} ${${_cmdVar}} PARENT_SCOPE)
939endfunction()
940
941macro (cotire_add_compile_flags_to_cmd _cmdVar)
942	foreach (_flag ${ARGN})
943		list (APPEND ${_cmdVar} "${_flag}")
944	endforeach()
945endmacro()
946
947function (cotire_check_file_up_to_date _fileIsUpToDateVar _file)
948	if (EXISTS "${_file}")
949		set (_triggerFile "")
950		foreach (_dependencyFile ${ARGN})
951			if (EXISTS "${_dependencyFile}")
952				# IS_NEWER_THAN returns TRUE if both files have the same timestamp
953				# thus we do the comparison in both directions to exclude ties
954				if ("${_dependencyFile}" IS_NEWER_THAN "${_file}" AND
955					NOT "${_file}" IS_NEWER_THAN "${_dependencyFile}")
956					set (_triggerFile "${_dependencyFile}")
957					break()
958				endif()
959			endif()
960		endforeach()
961		if (_triggerFile)
962			if (COTIRE_VERBOSE)
963				get_filename_component(_fileName "${_file}" NAME)
964				message (STATUS "${_fileName} update triggered by ${_triggerFile} change.")
965			endif()
966			set (${_fileIsUpToDateVar} FALSE PARENT_SCOPE)
967		else()
968			if (COTIRE_VERBOSE)
969				get_filename_component(_fileName "${_file}" NAME)
970				message (STATUS "${_fileName} is up-to-date.")
971			endif()
972			set (${_fileIsUpToDateVar} TRUE PARENT_SCOPE)
973		endif()
974	else()
975		if (COTIRE_VERBOSE)
976			get_filename_component(_fileName "${_file}" NAME)
977			message (STATUS "${_fileName} does not exist yet.")
978		endif()
979		set (${_fileIsUpToDateVar} FALSE PARENT_SCOPE)
980	endif()
981endfunction()
982
983macro (cotire_find_closest_relative_path _headerFile _includeDirs _relPathVar)
984	set (${_relPathVar} "")
985	foreach (_includeDir ${_includeDirs})
986		if (IS_DIRECTORY "${_includeDir}")
987			file (RELATIVE_PATH _relPath "${_includeDir}" "${_headerFile}")
988			if (NOT IS_ABSOLUTE "${_relPath}" AND NOT "${_relPath}" MATCHES "^\\.\\.")
989				string (LENGTH "${${_relPathVar}}" _closestLen)
990				string (LENGTH "${_relPath}" _relLen)
991				if (_closestLen EQUAL 0 OR _relLen LESS _closestLen)
992					set (${_relPathVar} "${_relPath}")
993				endif()
994			endif()
995		elseif ("${_includeDir}" STREQUAL "${_headerFile}")
996			# if path matches exactly, return short non-empty string
997			set (${_relPathVar} "1")
998			break()
999		endif()
1000	endforeach()
1001endmacro()
1002
1003macro (cotire_check_header_file_location _headerFile _insideIncludeDirs _outsideIncludeDirs _headerIsInside)
1004	# check header path against ignored and honored include directories
1005	cotire_find_closest_relative_path("${_headerFile}" "${_insideIncludeDirs}" _insideRelPath)
1006	if (_insideRelPath)
1007		# header is inside, but could be become outside if there is a shorter outside match
1008		cotire_find_closest_relative_path("${_headerFile}" "${_outsideIncludeDirs}" _outsideRelPath)
1009		if (_outsideRelPath)
1010			string (LENGTH "${_insideRelPath}" _insideRelPathLen)
1011			string (LENGTH "${_outsideRelPath}" _outsideRelPathLen)
1012			if (_outsideRelPathLen LESS _insideRelPathLen)
1013				set (${_headerIsInside} FALSE)
1014			else()
1015				set (${_headerIsInside} TRUE)
1016			endif()
1017		else()
1018			set (${_headerIsInside} TRUE)
1019		endif()
1020	else()
1021		# header is outside
1022		set (${_headerIsInside} FALSE)
1023	endif()
1024endmacro()
1025
1026macro (cotire_check_ignore_header_file_path _headerFile _headerIsIgnoredVar)
1027	if (NOT EXISTS "${_headerFile}")
1028		set (${_headerIsIgnoredVar} TRUE)
1029	elseif (IS_DIRECTORY "${_headerFile}")
1030		set (${_headerIsIgnoredVar} TRUE)
1031	elseif ("${_headerFile}" MATCHES "\\.\\.|[_-]fixed" AND "${_headerFile}" MATCHES "\\.h$")
1032		# heuristic: ignore C headers with embedded parent directory references or "-fixed" or "_fixed" in path
1033		# these often stem from using GCC #include_next tricks, which may break the precompiled header compilation
1034		# with the error message "error: no include path in which to search for header.h"
1035		set (${_headerIsIgnoredVar} TRUE)
1036	else()
1037		set (${_headerIsIgnoredVar} FALSE)
1038	endif()
1039endmacro()
1040
1041macro (cotire_check_ignore_header_file_ext _headerFile _ignoreExtensionsVar _headerIsIgnoredVar)
1042	# check header file extension
1043	cotire_get_source_file_extension("${_headerFile}" _headerFileExt)
1044	set (${_headerIsIgnoredVar} FALSE)
1045	if (_headerFileExt)
1046		list (FIND ${_ignoreExtensionsVar} "${_headerFileExt}" _index)
1047		if (_index GREATER -1)
1048			set (${_headerIsIgnoredVar} TRUE)
1049		endif()
1050	endif()
1051endmacro()
1052
1053macro (cotire_parse_line _line _headerFileVar _headerDepthVar)
1054	if (MSVC)
1055		# cl.exe /showIncludes output looks different depending on the language pack used, e.g.:
1056		# English: "Note: including file:   C:\directory\file"
1057		# German: "Hinweis: Einlesen der Datei:   C:\directory\file"
1058		# We use a very general regular expression, relying on the presence of the : characters
1059		if (_line MATCHES "( +)([a-zA-Z]:[^:]+)$")
1060			# Visual Studio compiler output
1061			string (LENGTH "${CMAKE_MATCH_1}" ${_headerDepthVar})
1062			get_filename_component(${_headerFileVar} "${CMAKE_MATCH_2}" ABSOLUTE)
1063		else()
1064			set (${_headerFileVar} "")
1065			set (${_headerDepthVar} 0)
1066		endif()
1067	else()
1068		if (_line MATCHES "^(\\.+) (.*)$")
1069			# GCC like output
1070			string (LENGTH "${CMAKE_MATCH_1}" ${_headerDepthVar})
1071			if (IS_ABSOLUTE "${CMAKE_MATCH_2}")
1072				set (${_headerFileVar} "${CMAKE_MATCH_2}")
1073			else()
1074				get_filename_component(${_headerFileVar} "${CMAKE_MATCH_2}" REALPATH)
1075			endif()
1076		else()
1077			set (${_headerFileVar} "")
1078			set (${_headerDepthVar} 0)
1079		endif()
1080	endif()
1081endmacro()
1082
1083function (cotire_parse_includes _language _scanOutput _ignoredIncludeDirs _honoredIncludeDirs _ignoredExtensions _selectedIncludesVar _unparsedLinesVar)
1084	if (WIN32)
1085		# prevent CMake macro invocation errors due to backslash characters in Windows paths
1086		string (REPLACE "\\" "/" _scanOutput "${_scanOutput}")
1087	endif()
1088	# canonize slashes
1089	string (REPLACE "//" "/" _scanOutput "${_scanOutput}")
1090	# prevent semicolon from being interpreted as a line separator
1091	string (REPLACE ";" "\\;" _scanOutput "${_scanOutput}")
1092	# then separate lines
1093	string (REGEX REPLACE "\n" ";" _scanOutput "${_scanOutput}")
1094	list (LENGTH _scanOutput _len)
1095	# remove duplicate lines to speed up parsing
1096	list (REMOVE_DUPLICATES _scanOutput)
1097	list (LENGTH _scanOutput _uniqueLen)
1098	if (COTIRE_VERBOSE OR COTIRE_DEBUG)
1099		message (STATUS "Scanning ${_uniqueLen} unique lines of ${_len} for includes")
1100		if (_ignoredExtensions)
1101			message (STATUS "Ignored extensions: ${_ignoredExtensions}")
1102		endif()
1103		if (_ignoredIncludeDirs)
1104			message (STATUS "Ignored paths: ${_ignoredIncludeDirs}")
1105		endif()
1106		if (_honoredIncludeDirs)
1107			message (STATUS "Included paths: ${_honoredIncludeDirs}")
1108		endif()
1109	endif()
1110	set (_sourceFiles ${ARGN})
1111	set (_selectedIncludes "")
1112	set (_unparsedLines "")
1113	# stack keeps track of inside/outside project status of processed header files
1114	set (_headerIsInsideStack "")
1115	foreach (_line IN LISTS _scanOutput)
1116		if (_line)
1117			cotire_parse_line("${_line}" _headerFile _headerDepth)
1118			if (_headerFile)
1119				cotire_check_header_file_location("${_headerFile}" "${_ignoredIncludeDirs}" "${_honoredIncludeDirs}" _headerIsInside)
1120				if (COTIRE_DEBUG)
1121					message (STATUS "${_headerDepth}: ${_headerFile} ${_headerIsInside}")
1122				endif()
1123				# update stack
1124				list (LENGTH _headerIsInsideStack _stackLen)
1125				if (_headerDepth GREATER _stackLen)
1126					math (EXPR _stackLen "${_stackLen} + 1")
1127					foreach (_index RANGE ${_stackLen} ${_headerDepth})
1128						list (APPEND _headerIsInsideStack ${_headerIsInside})
1129					endforeach()
1130				else()
1131					foreach (_index RANGE ${_headerDepth} ${_stackLen})
1132						list (REMOVE_AT _headerIsInsideStack -1)
1133					endforeach()
1134					list (APPEND _headerIsInsideStack ${_headerIsInside})
1135				endif()
1136				if (COTIRE_DEBUG)
1137					message (STATUS "${_headerIsInsideStack}")
1138				endif()
1139				# header is a candidate if it is outside project
1140				if (NOT _headerIsInside)
1141					# get parent header file's inside/outside status
1142					if (_headerDepth GREATER 1)
1143						math (EXPR _index "${_headerDepth} - 2")
1144						list (GET _headerIsInsideStack ${_index} _parentHeaderIsInside)
1145					else()
1146						set (_parentHeaderIsInside TRUE)
1147					endif()
1148					# select header file if parent header file is inside project
1149					# (e.g., a project header file that includes a standard header file)
1150					if (_parentHeaderIsInside)
1151						cotire_check_ignore_header_file_path("${_headerFile}" _headerIsIgnored)
1152						if (NOT _headerIsIgnored)
1153							cotire_check_ignore_header_file_ext("${_headerFile}" _ignoredExtensions _headerIsIgnored)
1154							if (NOT _headerIsIgnored)
1155								list (APPEND _selectedIncludes "${_headerFile}")
1156							else()
1157								# fix header's inside status on stack, it is ignored by extension now
1158								list (REMOVE_AT _headerIsInsideStack -1)
1159								list (APPEND _headerIsInsideStack TRUE)
1160							endif()
1161						endif()
1162						if (COTIRE_DEBUG)
1163							message (STATUS "${_headerFile} ${_ignoredExtensions} ${_headerIsIgnored}")
1164						endif()
1165					endif()
1166				endif()
1167			else()
1168				if (MSVC)
1169					# for cl.exe do not keep unparsed lines which solely consist of a source file name
1170					string (FIND "${_sourceFiles}" "${_line}" _index)
1171					if (_index LESS 0)
1172						list (APPEND _unparsedLines "${_line}")
1173					endif()
1174				else()
1175					list (APPEND _unparsedLines "${_line}")
1176				endif()
1177			endif()
1178		endif()
1179	endforeach()
1180	list (REMOVE_DUPLICATES _selectedIncludes)
1181	set (${_selectedIncludesVar} ${_selectedIncludes} PARENT_SCOPE)
1182	set (${_unparsedLinesVar} ${_unparsedLines} PARENT_SCOPE)
1183endfunction()
1184
1185function (cotire_scan_includes _includesVar)
1186	set(_options "")
1187	set(_oneValueArgs COMPILER_ID COMPILER_EXECUTABLE COMPILER_ARG1 COMPILER_VERSION LANGUAGE UNPARSED_LINES)
1188	set(_multiValueArgs COMPILE_DEFINITIONS COMPILE_FLAGS INCLUDE_DIRECTORIES SYSTEM_INCLUDE_DIRECTORIES
1189		IGNORE_PATH INCLUDE_PATH IGNORE_EXTENSIONS INCLUDE_PRIORITY_PATH COMPILER_LAUNCHER)
1190	cmake_parse_arguments(_option "${_options}" "${_oneValueArgs}" "${_multiValueArgs}" ${ARGN})
1191	set (_sourceFiles ${_option_UNPARSED_ARGUMENTS})
1192	if (NOT _option_LANGUAGE)
1193		set (_option_LANGUAGE "CXX")
1194	endif()
1195	if (NOT _option_COMPILER_ID)
1196		set (_option_COMPILER_ID "${CMAKE_${_option_LANGUAGE}_ID}")
1197	endif()
1198	if (NOT _option_COMPILER_VERSION)
1199		set (_option_COMPILER_VERSION "${CMAKE_${_option_LANGUAGE}_COMPILER_VERSION}")
1200	endif()
1201	cotire_init_compile_cmd(_cmd "${_option_LANGUAGE}" "${_option_COMPILER_LAUNCHER}" "${_option_COMPILER_EXECUTABLE}" "${_option_COMPILER_ARG1}")
1202	cotire_add_definitions_to_cmd(_cmd "${_option_LANGUAGE}" ${_option_COMPILE_DEFINITIONS})
1203	cotire_add_compile_flags_to_cmd(_cmd ${_option_COMPILE_FLAGS})
1204	cotire_add_includes_to_cmd(_cmd "${_option_LANGUAGE}" _option_INCLUDE_DIRECTORIES _option_SYSTEM_INCLUDE_DIRECTORIES)
1205	cotire_add_frameworks_to_cmd(_cmd "${_option_LANGUAGE}" _option_INCLUDE_DIRECTORIES _option_SYSTEM_INCLUDE_DIRECTORIES)
1206	cotire_add_makedep_flags("${_option_LANGUAGE}" "${_option_COMPILER_ID}" "${_option_COMPILER_VERSION}" _cmd)
1207	# only consider existing source files for scanning
1208	set (_existingSourceFiles "")
1209	foreach (_sourceFile ${_sourceFiles})
1210		if (EXISTS "${_sourceFile}")
1211			list (APPEND _existingSourceFiles "${_sourceFile}")
1212		endif()
1213	endforeach()
1214	if (NOT _existingSourceFiles)
1215		set (${_includesVar} "" PARENT_SCOPE)
1216		return()
1217	endif()
1218	list (APPEND _cmd ${_existingSourceFiles})
1219	if (COTIRE_VERBOSE)
1220		message (STATUS "execute_process: ${_cmd}")
1221	endif()
1222	if (_option_COMPILER_ID MATCHES "MSVC")
1223		# cl.exe messes with the output streams unless the environment variable VS_UNICODE_OUTPUT is cleared
1224		unset (ENV{VS_UNICODE_OUTPUT})
1225	endif()
1226	execute_process(
1227		COMMAND ${_cmd}
1228		WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
1229		RESULT_VARIABLE _result
1230		OUTPUT_QUIET
1231		ERROR_VARIABLE _output)
1232	if (_result)
1233		message (STATUS "Result ${_result} scanning includes of ${_existingSourceFiles}.")
1234	endif()
1235	cotire_parse_includes(
1236		"${_option_LANGUAGE}" "${_output}"
1237		"${_option_IGNORE_PATH}" "${_option_INCLUDE_PATH}"
1238		"${_option_IGNORE_EXTENSIONS}"
1239		_includes _unparsedLines
1240		${_sourceFiles})
1241	if (_option_INCLUDE_PRIORITY_PATH)
1242		set (_sortedIncludes "")
1243		foreach (_priorityPath ${_option_INCLUDE_PRIORITY_PATH})
1244			foreach (_include ${_includes})
1245				string (FIND ${_include} ${_priorityPath} _position)
1246				if (_position GREATER -1)
1247					list (APPEND _sortedIncludes ${_include})
1248				endif()
1249			endforeach()
1250		endforeach()
1251		if (_sortedIncludes)
1252			list (INSERT _includes 0 ${_sortedIncludes})
1253			list (REMOVE_DUPLICATES _includes)
1254		endif()
1255	endif()
1256	set (${_includesVar} ${_includes} PARENT_SCOPE)
1257	if (_option_UNPARSED_LINES)
1258		set (${_option_UNPARSED_LINES} ${_unparsedLines} PARENT_SCOPE)
1259	endif()
1260endfunction()
1261
1262macro (cotire_append_undefs _contentsVar)
1263	set (_undefs ${ARGN})
1264	if (_undefs)
1265		list (REMOVE_DUPLICATES _undefs)
1266		foreach (_definition ${_undefs})
1267			list (APPEND ${_contentsVar} "#undef ${_definition}")
1268		endforeach()
1269	endif()
1270endmacro()
1271
1272macro (cotire_comment_str _language _commentText _commentVar)
1273	if ("${_language}" STREQUAL "CMAKE")
1274		set (${_commentVar} "# ${_commentText}")
1275	else()
1276		set (${_commentVar} "/* ${_commentText} */")
1277	endif()
1278endmacro()
1279
1280function (cotire_write_file _language _file _contents _force)
1281	get_filename_component(_moduleName "${COTIRE_CMAKE_MODULE_FILE}" NAME)
1282	cotire_comment_str("${_language}" "${_moduleName} ${COTIRE_CMAKE_MODULE_VERSION} generated file" _header1)
1283	cotire_comment_str("${_language}" "${_file}" _header2)
1284	set (_contents "${_header1}\n${_header2}\n${_contents}")
1285	if (COTIRE_DEBUG)
1286		message (STATUS "${_contents}")
1287	endif()
1288	if (_force OR NOT EXISTS "${_file}")
1289		file (WRITE "${_file}" "${_contents}")
1290	else()
1291		file (READ "${_file}" _oldContents)
1292		if (NOT "${_oldContents}" STREQUAL "${_contents}")
1293			file (WRITE "${_file}" "${_contents}")
1294		else()
1295			if (COTIRE_DEBUG)
1296				message (STATUS "${_file} unchanged")
1297			endif()
1298		endif()
1299	endif()
1300endfunction()
1301
1302function (cotire_generate_unity_source _unityFile)
1303	set(_options "")
1304	set(_oneValueArgs LANGUAGE)
1305	set(_multiValueArgs
1306		DEPENDS SOURCES_COMPILE_DEFINITIONS
1307		PRE_UNDEFS SOURCES_PRE_UNDEFS POST_UNDEFS SOURCES_POST_UNDEFS PROLOGUE EPILOGUE)
1308	cmake_parse_arguments(_option "${_options}" "${_oneValueArgs}" "${_multiValueArgs}" ${ARGN})
1309	if (_option_DEPENDS)
1310		cotire_check_file_up_to_date(_unityFileIsUpToDate "${_unityFile}" ${_option_DEPENDS})
1311		if (_unityFileIsUpToDate)
1312			return()
1313		endif()
1314	endif()
1315	set (_sourceFiles ${_option_UNPARSED_ARGUMENTS})
1316	if (NOT _option_PRE_UNDEFS)
1317		set (_option_PRE_UNDEFS "")
1318	endif()
1319	if (NOT _option_SOURCES_PRE_UNDEFS)
1320		set (_option_SOURCES_PRE_UNDEFS "")
1321	endif()
1322	if (NOT _option_POST_UNDEFS)
1323		set (_option_POST_UNDEFS "")
1324	endif()
1325	if (NOT _option_SOURCES_POST_UNDEFS)
1326		set (_option_SOURCES_POST_UNDEFS "")
1327	endif()
1328	set (_contents "")
1329	if (_option_PROLOGUE)
1330		list (APPEND _contents ${_option_PROLOGUE})
1331	endif()
1332	if (_option_LANGUAGE AND _sourceFiles)
1333		if ("${_option_LANGUAGE}" STREQUAL "CXX")
1334			list (APPEND _contents "#ifdef __cplusplus")
1335		elseif ("${_option_LANGUAGE}" STREQUAL "C")
1336			list (APPEND _contents "#ifndef __cplusplus")
1337		endif()
1338	endif()
1339	set (_compileUndefinitions "")
1340	foreach (_sourceFile ${_sourceFiles})
1341		cotire_get_source_compile_definitions(
1342			"${_option_CONFIGURATION}" "${_option_LANGUAGE}" "${_sourceFile}" _compileDefinitions
1343			${_option_SOURCES_COMPILE_DEFINITIONS})
1344		cotire_get_source_undefs("${_sourceFile}" COTIRE_UNITY_SOURCE_PRE_UNDEFS _sourcePreUndefs ${_option_SOURCES_PRE_UNDEFS})
1345		cotire_get_source_undefs("${_sourceFile}" COTIRE_UNITY_SOURCE_POST_UNDEFS _sourcePostUndefs ${_option_SOURCES_POST_UNDEFS})
1346		if (_option_PRE_UNDEFS)
1347			list (APPEND _compileUndefinitions ${_option_PRE_UNDEFS})
1348		endif()
1349		if (_sourcePreUndefs)
1350			list (APPEND _compileUndefinitions ${_sourcePreUndefs})
1351		endif()
1352		if (_compileUndefinitions)
1353			cotire_append_undefs(_contents ${_compileUndefinitions})
1354			set (_compileUndefinitions "")
1355		endif()
1356		if (_sourcePostUndefs)
1357			list (APPEND _compileUndefinitions ${_sourcePostUndefs})
1358		endif()
1359		if (_option_POST_UNDEFS)
1360			list (APPEND _compileUndefinitions ${_option_POST_UNDEFS})
1361		endif()
1362		foreach (_definition ${_compileDefinitions})
1363			if (_definition MATCHES "^([a-zA-Z0-9_]+)=(.+)$")
1364				list (APPEND _contents "#define ${CMAKE_MATCH_1} ${CMAKE_MATCH_2}")
1365				list (INSERT _compileUndefinitions 0 "${CMAKE_MATCH_1}")
1366			else()
1367				list (APPEND _contents "#define ${_definition}")
1368				list (INSERT _compileUndefinitions 0 "${_definition}")
1369			endif()
1370		endforeach()
1371		# use absolute path as source file location
1372		get_filename_component(_sourceFileLocation "${_sourceFile}" ABSOLUTE)
1373		if (WIN32)
1374			file (TO_NATIVE_PATH "${_sourceFileLocation}" _sourceFileLocation)
1375		endif()
1376		list (APPEND _contents "#include \"${_sourceFileLocation}\"")
1377	endforeach()
1378	if (_compileUndefinitions)
1379		cotire_append_undefs(_contents ${_compileUndefinitions})
1380		set (_compileUndefinitions "")
1381	endif()
1382	if (_option_LANGUAGE AND _sourceFiles)
1383		list (APPEND _contents "#endif")
1384	endif()
1385	if (_option_EPILOGUE)
1386		list (APPEND _contents ${_option_EPILOGUE})
1387	endif()
1388	list (APPEND _contents "")
1389	string (REPLACE ";" "\n" _contents "${_contents}")
1390	if (COTIRE_VERBOSE)
1391		message ("${_contents}")
1392	endif()
1393	cotire_write_file("${_option_LANGUAGE}" "${_unityFile}" "${_contents}" TRUE)
1394endfunction()
1395
1396function (cotire_generate_prefix_header _prefixFile)
1397	set(_options "")
1398	set(_oneValueArgs LANGUAGE COMPILER_EXECUTABLE COMPILER_ARG1 COMPILER_ID COMPILER_VERSION)
1399	set(_multiValueArgs DEPENDS COMPILE_DEFINITIONS COMPILE_FLAGS
1400		INCLUDE_DIRECTORIES SYSTEM_INCLUDE_DIRECTORIES IGNORE_PATH INCLUDE_PATH
1401		IGNORE_EXTENSIONS INCLUDE_PRIORITY_PATH COMPILER_LAUNCHER)
1402	cmake_parse_arguments(_option "${_options}" "${_oneValueArgs}" "${_multiValueArgs}" ${ARGN})
1403	if (NOT _option_COMPILER_ID)
1404		set (_option_COMPILER_ID "${CMAKE_${_option_LANGUAGE}_ID}")
1405	endif()
1406	if (NOT _option_COMPILER_VERSION)
1407		set (_option_COMPILER_VERSION "${CMAKE_${_option_LANGUAGE}_COMPILER_VERSION}")
1408	endif()
1409	if (_option_DEPENDS)
1410		cotire_check_file_up_to_date(_prefixFileIsUpToDate "${_prefixFile}" ${_option_DEPENDS})
1411		if (_prefixFileIsUpToDate)
1412			# create empty log file
1413			set (_unparsedLinesFile "${_prefixFile}.log")
1414			file (WRITE "${_unparsedLinesFile}" "")
1415			return()
1416		endif()
1417	endif()
1418	set (_prologue "")
1419	set (_epilogue "")
1420	if (_option_COMPILER_ID MATCHES "Clang")
1421		set (_prologue "#pragma clang system_header")
1422	elseif (_option_COMPILER_ID MATCHES "GNU")
1423		set (_prologue "#pragma GCC system_header")
1424	elseif (_option_COMPILER_ID MATCHES "MSVC")
1425		set (_prologue "#pragma warning(push, 0)")
1426		set (_epilogue "#pragma warning(pop)")
1427	elseif (_option_COMPILER_ID MATCHES "Intel")
1428		# Intel compiler requires hdrstop pragma to stop generating PCH file
1429		set (_epilogue "#pragma hdrstop")
1430	endif()
1431	set (_sourceFiles ${_option_UNPARSED_ARGUMENTS})
1432	cotire_scan_includes(_selectedHeaders ${_sourceFiles}
1433		LANGUAGE "${_option_LANGUAGE}"
1434		COMPILER_LAUNCHER "${_option_COMPILER_LAUNCHER}"
1435		COMPILER_EXECUTABLE "${_option_COMPILER_EXECUTABLE}"
1436		COMPILER_ARG1 "${_option_COMPILER_ARG1}"
1437		COMPILER_ID "${_option_COMPILER_ID}"
1438		COMPILER_VERSION "${_option_COMPILER_VERSION}"
1439		COMPILE_DEFINITIONS ${_option_COMPILE_DEFINITIONS}
1440		COMPILE_FLAGS ${_option_COMPILE_FLAGS}
1441		INCLUDE_DIRECTORIES ${_option_INCLUDE_DIRECTORIES}
1442		SYSTEM_INCLUDE_DIRECTORIES ${_option_SYSTEM_INCLUDE_DIRECTORIES}
1443		IGNORE_PATH ${_option_IGNORE_PATH}
1444		INCLUDE_PATH ${_option_INCLUDE_PATH}
1445		IGNORE_EXTENSIONS ${_option_IGNORE_EXTENSIONS}
1446		INCLUDE_PRIORITY_PATH ${_option_INCLUDE_PRIORITY_PATH}
1447		UNPARSED_LINES _unparsedLines)
1448	cotire_generate_unity_source("${_prefixFile}"
1449		PROLOGUE ${_prologue} EPILOGUE ${_epilogue} LANGUAGE "${_option_LANGUAGE}" ${_selectedHeaders})
1450	set (_unparsedLinesFile "${_prefixFile}.log")
1451	if (_unparsedLines)
1452		if (COTIRE_VERBOSE OR NOT _selectedHeaders)
1453			list (LENGTH _unparsedLines _skippedLineCount)
1454			message (STATUS "${_skippedLineCount} line(s) skipped, see ${_unparsedLinesFile}")
1455		endif()
1456		string (REPLACE ";" "\n" _unparsedLines "${_unparsedLines}")
1457	endif()
1458	file (WRITE "${_unparsedLinesFile}" "${_unparsedLines}")
1459endfunction()
1460
1461function (cotire_add_makedep_flags _language _compilerID _compilerVersion _flagsVar)
1462	set (_flags ${${_flagsVar}})
1463	if (_compilerID MATCHES "MSVC")
1464		# cl.exe options used
1465		# /nologo suppresses display of sign-on banner
1466		# /TC treat all files named on the command line as C source files
1467		# /TP treat all files named on the command line as C++ source files
1468		# /EP preprocess to stdout without #line directives
1469		# /showIncludes list include files
1470		set (_sourceFileTypeC "/TC")
1471		set (_sourceFileTypeCXX "/TP")
1472		if (_flags)
1473			# append to list
1474			list (APPEND _flags /nologo "${_sourceFileType${_language}}" /EP /showIncludes)
1475		else()
1476			# return as a flag string
1477			set (_flags "${_sourceFileType${_language}} /EP /showIncludes")
1478		endif()
1479	elseif (_compilerID MATCHES "GNU")
1480		# GCC options used
1481		# -H print the name of each header file used
1482		# -E invoke preprocessor
1483		# -fdirectives-only do not expand macros, requires GCC >= 4.3
1484		if (_flags)
1485			# append to list
1486			list (APPEND _flags -H -E)
1487			if (NOT "${_compilerVersion}" VERSION_LESS "4.3.0")
1488				list (APPEND _flags "-fdirectives-only")
1489			endif()
1490		else()
1491			# return as a flag string
1492			set (_flags "-H -E")
1493			if (NOT "${_compilerVersion}" VERSION_LESS "4.3.0")
1494				set (_flags "${_flags} -fdirectives-only")
1495			endif()
1496		endif()
1497	elseif (_compilerID MATCHES "Clang")
1498		# Clang options used
1499		# -H print the name of each header file used
1500		# -E invoke preprocessor
1501		# -fno-color-diagnostics don't prints diagnostics in color
1502		if (_flags)
1503			# append to list
1504			list (APPEND _flags -H -E -fno-color-diagnostics)
1505		else()
1506			# return as a flag string
1507			set (_flags "-H -E -fno-color-diagnostics")
1508		endif()
1509	elseif (_compilerID MATCHES "Intel")
1510		if (WIN32)
1511			# Windows Intel options used
1512			# /nologo do not display compiler version information
1513			# /QH display the include file order
1514			# /EP preprocess to stdout, omitting #line directives
1515			# /TC process all source or unrecognized file types as C source files
1516			# /TP process all source or unrecognized file types as C++ source files
1517			set (_sourceFileTypeC "/TC")
1518			set (_sourceFileTypeCXX "/TP")
1519			if (_flags)
1520				# append to list
1521				list (APPEND _flags /nologo "${_sourceFileType${_language}}" /EP /QH)
1522			else()
1523				# return as a flag string
1524				set (_flags "${_sourceFileType${_language}} /EP /QH")
1525			endif()
1526		else()
1527			# Linux / Mac OS X Intel options used
1528			# -H print the name of each header file used
1529			# -EP preprocess to stdout, omitting #line directives
1530			# -Kc++ process all source or unrecognized file types as C++ source files
1531			if (_flags)
1532				# append to list
1533				if ("${_language}" STREQUAL "CXX")
1534					list (APPEND _flags -Kc++)
1535				endif()
1536				list (APPEND _flags -H -EP)
1537			else()
1538				# return as a flag string
1539				if ("${_language}" STREQUAL "CXX")
1540					set (_flags "-Kc++ ")
1541				endif()
1542				set (_flags "${_flags}-H -EP")
1543			endif()
1544		endif()
1545	else()
1546		message (FATAL_ERROR "cotire: unsupported ${_language} compiler ${_compilerID} version ${_compilerVersion}.")
1547	endif()
1548	set (${_flagsVar} ${_flags} PARENT_SCOPE)
1549endfunction()
1550
1551function (cotire_add_pch_compilation_flags _language _compilerID _compilerVersion _prefixFile _pchFile _hostFile _flagsVar)
1552	set (_flags ${${_flagsVar}})
1553	if (_compilerID MATCHES "MSVC")
1554		file (TO_NATIVE_PATH "${_prefixFile}" _prefixFileNative)
1555		file (TO_NATIVE_PATH "${_pchFile}" _pchFileNative)
1556		file (TO_NATIVE_PATH "${_hostFile}" _hostFileNative)
1557		# cl.exe options used
1558		# /Yc creates a precompiled header file
1559		# /Fp specifies precompiled header binary file name
1560		# /FI forces inclusion of file
1561		# /TC treat all files named on the command line as C source files
1562		# /TP treat all files named on the command line as C++ source files
1563		# /Zs syntax check only
1564		# /Zm precompiled header memory allocation scaling factor
1565		set (_sourceFileTypeC "/TC")
1566		set (_sourceFileTypeCXX "/TP")
1567		if (_flags)
1568			# append to list
1569			list (APPEND _flags /nologo "${_sourceFileType${_language}}"
1570				"/Yc${_prefixFileNative}" "/Fp${_pchFileNative}" "/FI${_prefixFileNative}" /Zs "${_hostFileNative}")
1571			if (COTIRE_PCH_MEMORY_SCALING_FACTOR)
1572				list (APPEND _flags "/Zm${COTIRE_PCH_MEMORY_SCALING_FACTOR}")
1573			endif()
1574		else()
1575			# return as a flag string
1576			set (_flags "/Yc\"${_prefixFileNative}\" /Fp\"${_pchFileNative}\" /FI\"${_prefixFileNative}\"")
1577			if (COTIRE_PCH_MEMORY_SCALING_FACTOR)
1578				set (_flags "${_flags} /Zm${COTIRE_PCH_MEMORY_SCALING_FACTOR}")
1579			endif()
1580		endif()
1581	elseif (_compilerID MATCHES "GNU|Clang")
1582		# GCC / Clang options used
1583		# -x specify the source language
1584		# -c compile but do not link
1585		# -o place output in file
1586		# note that we cannot use -w to suppress all warnings upon pre-compiling, because turning off a warning may
1587		# alter compile flags as a side effect (e.g., -Wwrite-string implies -fconst-strings)
1588		set (_xLanguage_C "c-header")
1589		set (_xLanguage_CXX "c++-header")
1590		if (_flags)
1591			# append to list
1592			list (APPEND _flags "-x" "${_xLanguage_${_language}}" "-c" "${_prefixFile}" -o "${_pchFile}")
1593		else()
1594			# return as a flag string
1595			set (_flags "-x ${_xLanguage_${_language}} -c \"${_prefixFile}\" -o \"${_pchFile}\"")
1596		endif()
1597	elseif (_compilerID MATCHES "Intel")
1598		if (WIN32)
1599			file (TO_NATIVE_PATH "${_prefixFile}" _prefixFileNative)
1600			file (TO_NATIVE_PATH "${_pchFile}" _pchFileNative)
1601			file (TO_NATIVE_PATH "${_hostFile}" _hostFileNative)
1602			# Windows Intel options used
1603			# /nologo do not display compiler version information
1604			# /Yc create a precompiled header (PCH) file
1605			# /Fp specify a path or file name for precompiled header files
1606			# /FI tells the preprocessor to include a specified file name as the header file
1607			# /TC process all source or unrecognized file types as C source files
1608			# /TP process all source or unrecognized file types as C++ source files
1609			# /Zs syntax check only
1610			# /Wpch-messages enable diagnostics related to pre-compiled headers (requires Intel XE 2013 Update 2)
1611			set (_sourceFileTypeC "/TC")
1612			set (_sourceFileTypeCXX "/TP")
1613			if (_flags)
1614				# append to list
1615				list (APPEND _flags /nologo "${_sourceFileType${_language}}"
1616					"/Yc" "/Fp${_pchFileNative}" "/FI${_prefixFileNative}" /Zs "${_hostFileNative}")
1617				if (NOT "${_compilerVersion}" VERSION_LESS "13.1.0")
1618					list (APPEND _flags "/Wpch-messages")
1619				endif()
1620			else()
1621				# return as a flag string
1622				set (_flags "/Yc /Fp\"${_pchFileNative}\" /FI\"${_prefixFileNative}\"")
1623				if (NOT "${_compilerVersion}" VERSION_LESS "13.1.0")
1624					set (_flags "${_flags} /Wpch-messages")
1625				endif()
1626			endif()
1627		else()
1628			# Linux / Mac OS X Intel options used
1629			# -pch-dir location for precompiled header files
1630			# -pch-create name of the precompiled header (PCH) to create
1631			# -Kc++ process all source or unrecognized file types as C++ source files
1632			# -fsyntax-only check only for correct syntax
1633			# -Wpch-messages enable diagnostics related to pre-compiled headers (requires Intel XE 2013 Update 2)
1634			get_filename_component(_pchDir "${_pchFile}" DIRECTORY)
1635			get_filename_component(_pchName "${_pchFile}" NAME)
1636			set (_xLanguage_C "c-header")
1637			set (_xLanguage_CXX "c++-header")
1638			if (_flags)
1639				# append to list
1640				if ("${_language}" STREQUAL "CXX")
1641					list (APPEND _flags -Kc++)
1642				endif()
1643				list (APPEND _flags "-include" "${_prefixFile}" "-pch-dir" "${_pchDir}" "-pch-create" "${_pchName}" "-fsyntax-only" "${_hostFile}")
1644				if (NOT "${_compilerVersion}" VERSION_LESS "13.1.0")
1645					list (APPEND _flags "-Wpch-messages")
1646				endif()
1647			else()
1648				# return as a flag string
1649				set (_flags "-include \"${_prefixFile}\" -pch-dir \"${_pchDir}\" -pch-create \"${_pchName}\"")
1650				if (NOT "${_compilerVersion}" VERSION_LESS "13.1.0")
1651					set (_flags "${_flags} -Wpch-messages")
1652				endif()
1653			endif()
1654		endif()
1655	else()
1656		message (FATAL_ERROR "cotire: unsupported ${_language} compiler ${_compilerID} version ${_compilerVersion}.")
1657	endif()
1658	set (${_flagsVar} ${_flags} PARENT_SCOPE)
1659endfunction()
1660
1661function (cotire_add_prefix_pch_inclusion_flags _language _compilerID _compilerVersion _prefixFile _pchFile _flagsVar)
1662	set (_flags ${${_flagsVar}})
1663	if (_compilerID MATCHES "MSVC")
1664		file (TO_NATIVE_PATH "${_prefixFile}" _prefixFileNative)
1665		# cl.exe options used
1666		# /Yu uses a precompiled header file during build
1667		# /Fp specifies precompiled header binary file name
1668		# /FI forces inclusion of file
1669		# /Zm precompiled header memory allocation scaling factor
1670		if (_pchFile)
1671			file (TO_NATIVE_PATH "${_pchFile}" _pchFileNative)
1672			if (_flags)
1673				# append to list
1674				list (APPEND _flags "/Yu${_prefixFileNative}" "/Fp${_pchFileNative}" "/FI${_prefixFileNative}")
1675				if (COTIRE_PCH_MEMORY_SCALING_FACTOR)
1676					list (APPEND _flags "/Zm${COTIRE_PCH_MEMORY_SCALING_FACTOR}")
1677				endif()
1678			else()
1679				# return as a flag string
1680				set (_flags "/Yu\"${_prefixFileNative}\" /Fp\"${_pchFileNative}\" /FI\"${_prefixFileNative}\"")
1681				if (COTIRE_PCH_MEMORY_SCALING_FACTOR)
1682					set (_flags "${_flags} /Zm${COTIRE_PCH_MEMORY_SCALING_FACTOR}")
1683				endif()
1684			endif()
1685		else()
1686			# no precompiled header, force inclusion of prefix header
1687			if (_flags)
1688				# append to list
1689				list (APPEND _flags "/FI${_prefixFileNative}")
1690			else()
1691				# return as a flag string
1692				set (_flags "/FI\"${_prefixFileNative}\"")
1693			endif()
1694		endif()
1695	elseif (_compilerID MATCHES "GNU")
1696		# GCC options used
1697		# -include process include file as the first line of the primary source file
1698		# -Winvalid-pch warns if precompiled header is found but cannot be used
1699		# note: ccache requires the -include flag to be used in order to process precompiled header correctly
1700		if (_flags)
1701			# append to list
1702			list (APPEND _flags "-Winvalid-pch" "-include" "${_prefixFile}")
1703		else()
1704			# return as a flag string
1705			set (_flags "-Winvalid-pch -include \"${_prefixFile}\"")
1706		endif()
1707	elseif (_compilerID MATCHES "Clang")
1708		# Clang options used
1709		# -include process include file as the first line of the primary source file
1710		# -include-pch include precompiled header file
1711		# -Qunused-arguments don't emit warning for unused driver arguments
1712		# note: ccache requires the -include flag to be used in order to process precompiled header correctly
1713		if (_flags)
1714			# append to list
1715			list (APPEND _flags "-Qunused-arguments" "-include" "${_prefixFile}")
1716		else()
1717			# return as a flag string
1718			set (_flags "-Qunused-arguments -include \"${_prefixFile}\"")
1719		endif()
1720	elseif (_compilerID MATCHES "Intel")
1721		if (WIN32)
1722			file (TO_NATIVE_PATH "${_prefixFile}" _prefixFileNative)
1723			# Windows Intel options used
1724			# /Yu use a precompiled header (PCH) file
1725			# /Fp specify a path or file name for precompiled header files
1726			# /FI tells the preprocessor to include a specified file name as the header file
1727			# /Wpch-messages enable diagnostics related to pre-compiled headers (requires Intel XE 2013 Update 2)
1728			if (_pchFile)
1729				file (TO_NATIVE_PATH "${_pchFile}" _pchFileNative)
1730				if (_flags)
1731					# append to list
1732					list (APPEND _flags "/Yu" "/Fp${_pchFileNative}" "/FI${_prefixFileNative}")
1733					if (NOT "${_compilerVersion}" VERSION_LESS "13.1.0")
1734						list (APPEND _flags "/Wpch-messages")
1735					endif()
1736				else()
1737					# return as a flag string
1738					set (_flags "/Yu /Fp\"${_pchFileNative}\" /FI\"${_prefixFileNative}\"")
1739					if (NOT "${_compilerVersion}" VERSION_LESS "13.1.0")
1740						set (_flags "${_flags} /Wpch-messages")
1741					endif()
1742				endif()
1743			else()
1744				# no precompiled header, force inclusion of prefix header
1745				if (_flags)
1746					# append to list
1747					list (APPEND _flags "/FI${_prefixFileNative}")
1748				else()
1749					# return as a flag string
1750					set (_flags "/FI\"${_prefixFileNative}\"")
1751				endif()
1752			endif()
1753		else()
1754			# Linux / Mac OS X Intel options used
1755			# -pch-dir location for precompiled header files
1756			# -pch-use name of the precompiled header (PCH) to use
1757			# -include process include file as the first line of the primary source file
1758			# -Wpch-messages enable diagnostics related to pre-compiled headers (requires Intel XE 2013 Update 2)
1759			if (_pchFile)
1760				get_filename_component(_pchDir "${_pchFile}" DIRECTORY)
1761				get_filename_component(_pchName "${_pchFile}" NAME)
1762				if (_flags)
1763					# append to list
1764					list (APPEND _flags "-include" "${_prefixFile}" "-pch-dir" "${_pchDir}" "-pch-use" "${_pchName}")
1765					if (NOT "${_compilerVersion}" VERSION_LESS "13.1.0")
1766						list (APPEND _flags "-Wpch-messages")
1767					endif()
1768				else()
1769					# return as a flag string
1770					set (_flags "-include \"${_prefixFile}\" -pch-dir \"${_pchDir}\" -pch-use \"${_pchName}\"")
1771					if (NOT "${_compilerVersion}" VERSION_LESS "13.1.0")
1772						set (_flags "${_flags} -Wpch-messages")
1773					endif()
1774				endif()
1775			else()
1776				# no precompiled header, force inclusion of prefix header
1777				if (_flags)
1778					# append to list
1779					list (APPEND _flags "-include" "${_prefixFile}")
1780				else()
1781					# return as a flag string
1782					set (_flags "-include \"${_prefixFile}\"")
1783				endif()
1784			endif()
1785		endif()
1786	else()
1787		message (FATAL_ERROR "cotire: unsupported ${_language} compiler ${_compilerID} version ${_compilerVersion}.")
1788	endif()
1789	set (${_flagsVar} ${_flags} PARENT_SCOPE)
1790endfunction()
1791
1792function (cotire_precompile_prefix_header _prefixFile _pchFile _hostFile)
1793	set(_options "")
1794	set(_oneValueArgs COMPILER_EXECUTABLE COMPILER_ARG1 COMPILER_ID COMPILER_VERSION LANGUAGE)
1795	set(_multiValueArgs COMPILE_DEFINITIONS COMPILE_FLAGS INCLUDE_DIRECTORIES SYSTEM_INCLUDE_DIRECTORIES SYS COMPILER_LAUNCHER)
1796	cmake_parse_arguments(_option "${_options}" "${_oneValueArgs}" "${_multiValueArgs}" ${ARGN})
1797	if (NOT _option_LANGUAGE)
1798		set (_option_LANGUAGE "CXX")
1799	endif()
1800	if (NOT _option_COMPILER_ID)
1801		set (_option_COMPILER_ID "${CMAKE_${_option_LANGUAGE}_ID}")
1802	endif()
1803	if (NOT _option_COMPILER_VERSION)
1804		set (_option_COMPILER_VERSION "${CMAKE_${_option_LANGUAGE}_COMPILER_VERSION}")
1805	endif()
1806	cotire_init_compile_cmd(_cmd "${_option_LANGUAGE}" "${_option_COMPILER_LAUNCHER}" "${_option_COMPILER_EXECUTABLE}" "${_option_COMPILER_ARG1}")
1807	cotire_add_definitions_to_cmd(_cmd "${_option_LANGUAGE}" ${_option_COMPILE_DEFINITIONS})
1808	cotire_add_compile_flags_to_cmd(_cmd ${_option_COMPILE_FLAGS})
1809	cotire_add_includes_to_cmd(_cmd "${_option_LANGUAGE}" _option_INCLUDE_DIRECTORIES _option_SYSTEM_INCLUDE_DIRECTORIES)
1810	cotire_add_frameworks_to_cmd(_cmd "${_option_LANGUAGE}" _option_INCLUDE_DIRECTORIES _option_SYSTEM_INCLUDE_DIRECTORIES)
1811	cotire_add_pch_compilation_flags(
1812		"${_option_LANGUAGE}" "${_option_COMPILER_ID}" "${_option_COMPILER_VERSION}"
1813		"${_prefixFile}" "${_pchFile}" "${_hostFile}" _cmd)
1814	if (COTIRE_VERBOSE)
1815		message (STATUS "execute_process: ${_cmd}")
1816	endif()
1817	if (_option_COMPILER_ID MATCHES "MSVC")
1818		# cl.exe messes with the output streams unless the environment variable VS_UNICODE_OUTPUT is cleared
1819		unset (ENV{VS_UNICODE_OUTPUT})
1820	endif()
1821	execute_process(
1822		COMMAND ${_cmd}
1823		WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
1824		RESULT_VARIABLE _result)
1825	if (_result)
1826		message (FATAL_ERROR "cotire: error ${_result} precompiling ${_prefixFile}.")
1827	endif()
1828endfunction()
1829
1830function (cotire_check_precompiled_header_support _language _target _msgVar)
1831	set (_unsupportedCompiler
1832		"Precompiled headers not supported for ${_language} compiler ${CMAKE_${_language}_COMPILER_ID}")
1833	if (CMAKE_${_language}_COMPILER_ID MATCHES "MSVC")
1834		# supported since Visual Studio C++ 6.0
1835		# and CMake does not support an earlier version
1836		set (${_msgVar} "" PARENT_SCOPE)
1837	elseif (CMAKE_${_language}_COMPILER_ID MATCHES "GNU")
1838		# GCC PCH support requires version >= 3.4
1839		if ("${CMAKE_${_language}_COMPILER_VERSION}" VERSION_LESS "3.4.0")
1840			set (${_msgVar} "${_unsupportedCompiler} version ${CMAKE_${_language}_COMPILER_VERSION}." PARENT_SCOPE)
1841		else()
1842			set (${_msgVar} "" PARENT_SCOPE)
1843		endif()
1844	elseif (CMAKE_${_language}_COMPILER_ID MATCHES "Clang")
1845		# all Clang versions have PCH support
1846		set (${_msgVar} "" PARENT_SCOPE)
1847	elseif (CMAKE_${_language}_COMPILER_ID MATCHES "Intel")
1848		# Intel PCH support requires version >= 8.0.0
1849		if ("${CMAKE_${_language}_COMPILER_VERSION}" VERSION_LESS "8.0.0")
1850			set (${_msgVar} "${_unsupportedCompiler} version ${CMAKE_${_language}_COMPILER_VERSION}." PARENT_SCOPE)
1851		else()
1852			set (${_msgVar} "" PARENT_SCOPE)
1853		endif()
1854	else()
1855		set (${_msgVar} "${_unsupportedCompiler}." PARENT_SCOPE)
1856	endif()
1857	get_target_property(_launcher ${_target} ${_language}_COMPILER_LAUNCHER)
1858	if (CMAKE_${_language}_COMPILER MATCHES "ccache" OR _launcher MATCHES "ccache")
1859		if (NOT "$ENV{CCACHE_SLOPPINESS}" MATCHES "time_macros|pch_defines")
1860			set (${_msgVar}
1861				"ccache requires the environment variable CCACHE_SLOPPINESS to be set to \"pch_defines,time_macros\"."
1862				PARENT_SCOPE)
1863		endif()
1864	endif()
1865	if (APPLE)
1866		# PCH compilation not supported by GCC / Clang for multi-architecture builds (e.g., i386, x86_64)
1867		cotire_get_configuration_types(_configs)
1868		foreach (_config ${_configs})
1869			set (_targetFlags "")
1870			cotire_get_target_compile_flags("${_config}" "${_language}" "${_target}" _targetFlags)
1871			cotire_filter_compile_flags("${_language}" "arch" _architectures _ignore ${_targetFlags})
1872			list (LENGTH _architectures _numberOfArchitectures)
1873			if (_numberOfArchitectures GREATER 1)
1874				string (REPLACE ";" ", " _architectureStr "${_architectures}")
1875				set (${_msgVar}
1876					"Precompiled headers not supported on Darwin for multi-architecture builds (${_architectureStr})."
1877					PARENT_SCOPE)
1878				break()
1879			endif()
1880		endforeach()
1881	endif()
1882endfunction()
1883
1884macro (cotire_get_intermediate_dir _cotireDir)
1885	# ${CMAKE_CFG_INTDIR} may reference a build-time variable when using a generator which supports configuration types
1886	get_filename_component(${_cotireDir} "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${COTIRE_INTDIR}" ABSOLUTE)
1887endmacro()
1888
1889macro (cotire_setup_file_extension_variables)
1890	set (_unityFileExt_C ".c")
1891	set (_unityFileExt_CXX ".cxx")
1892	set (_prefixFileExt_C ".h")
1893	set (_prefixFileExt_CXX ".hxx")
1894	set (_prefixSourceFileExt_C ".c")
1895	set (_prefixSourceFileExt_CXX ".cxx")
1896endmacro()
1897
1898function (cotire_make_single_unity_source_file_path _language _target _unityFileVar)
1899	cotire_setup_file_extension_variables()
1900	if (NOT DEFINED _unityFileExt_${_language})
1901		set (${_unityFileVar} "" PARENT_SCOPE)
1902		return()
1903	endif()
1904	set (_unityFileBaseName "${_target}_${_language}${COTIRE_UNITY_SOURCE_FILENAME_SUFFIX}")
1905	set (_unityFileName "${_unityFileBaseName}${_unityFileExt_${_language}}")
1906	cotire_get_intermediate_dir(_baseDir)
1907	set (_unityFile "${_baseDir}/${_unityFileName}")
1908	set (${_unityFileVar} "${_unityFile}" PARENT_SCOPE)
1909endfunction()
1910
1911function (cotire_make_unity_source_file_paths _language _target _maxIncludes _unityFilesVar)
1912	cotire_setup_file_extension_variables()
1913	if (NOT DEFINED _unityFileExt_${_language})
1914		set (${_unityFileVar} "" PARENT_SCOPE)
1915		return()
1916	endif()
1917	set (_unityFileBaseName "${_target}_${_language}${COTIRE_UNITY_SOURCE_FILENAME_SUFFIX}")
1918	cotire_get_intermediate_dir(_baseDir)
1919	set (_startIndex 0)
1920	set (_index 0)
1921	set (_unityFiles "")
1922	set (_sourceFiles ${ARGN})
1923	foreach (_sourceFile ${_sourceFiles})
1924		get_source_file_property(_startNew "${_sourceFile}" COTIRE_START_NEW_UNITY_SOURCE)
1925		math (EXPR _unityFileCount "${_index} - ${_startIndex}")
1926		if (_startNew OR (_maxIncludes GREATER 0 AND NOT _unityFileCount LESS _maxIncludes))
1927			if (_index GREATER 0)
1928				# start new unity file segment
1929				math (EXPR _endIndex "${_index} - 1")
1930				set (_unityFileName "${_unityFileBaseName}_${_startIndex}_${_endIndex}${_unityFileExt_${_language}}")
1931				list (APPEND _unityFiles "${_baseDir}/${_unityFileName}")
1932			endif()
1933			set (_startIndex ${_index})
1934		endif()
1935		math (EXPR _index "${_index} + 1")
1936	endforeach()
1937	list (LENGTH _sourceFiles _numberOfSources)
1938	if (_startIndex EQUAL 0)
1939		# there is only a single unity file
1940		cotire_make_single_unity_source_file_path(${_language} ${_target} _unityFiles)
1941	elseif (_startIndex LESS _numberOfSources)
1942		# end with final unity file segment
1943		math (EXPR _endIndex "${_index} - 1")
1944		set (_unityFileName "${_unityFileBaseName}_${_startIndex}_${_endIndex}${_unityFileExt_${_language}}")
1945		list (APPEND _unityFiles "${_baseDir}/${_unityFileName}")
1946	endif()
1947	set (${_unityFilesVar} ${_unityFiles} PARENT_SCOPE)
1948	if (COTIRE_DEBUG AND _unityFiles)
1949		message (STATUS "unity files: ${_unityFiles}")
1950	endif()
1951endfunction()
1952
1953function (cotire_unity_to_prefix_file_path _language _target _unityFile _prefixFileVar)
1954	cotire_setup_file_extension_variables()
1955	if (NOT DEFINED _unityFileExt_${_language})
1956		set (${_prefixFileVar} "" PARENT_SCOPE)
1957		return()
1958	endif()
1959	set (_unityFileBaseName "${_target}_${_language}${COTIRE_UNITY_SOURCE_FILENAME_SUFFIX}")
1960	set (_prefixFileBaseName "${_target}_${_language}${COTIRE_PREFIX_HEADER_FILENAME_SUFFIX}")
1961	string (REPLACE "${_unityFileBaseName}" "${_prefixFileBaseName}" _prefixFile "${_unityFile}")
1962	string (REGEX REPLACE "${_unityFileExt_${_language}}$" "${_prefixFileExt_${_language}}" _prefixFile "${_prefixFile}")
1963	set (${_prefixFileVar} "${_prefixFile}" PARENT_SCOPE)
1964endfunction()
1965
1966function (cotire_prefix_header_to_source_file_path _language _prefixHeaderFile _prefixSourceFileVar)
1967	cotire_setup_file_extension_variables()
1968	if (NOT DEFINED _prefixSourceFileExt_${_language})
1969		set (${_prefixSourceFileVar} "" PARENT_SCOPE)
1970		return()
1971	endif()
1972	string (REGEX REPLACE "${_prefixFileExt_${_language}}$" "${_prefixSourceFileExt_${_language}}" _prefixSourceFile "${_prefixHeaderFile}")
1973	set (${_prefixSourceFileVar} "${_prefixSourceFile}" PARENT_SCOPE)
1974endfunction()
1975
1976function (cotire_make_prefix_file_name _language _target _prefixFileBaseNameVar _prefixFileNameVar)
1977	cotire_setup_file_extension_variables()
1978	if (NOT _language)
1979		set (_prefixFileBaseName "${_target}${COTIRE_PREFIX_HEADER_FILENAME_SUFFIX}")
1980		set (_prefixFileName "${_prefixFileBaseName}${_prefixFileExt_C}")
1981	elseif (DEFINED _prefixFileExt_${_language})
1982		set (_prefixFileBaseName "${_target}_${_language}${COTIRE_PREFIX_HEADER_FILENAME_SUFFIX}")
1983		set (_prefixFileName "${_prefixFileBaseName}${_prefixFileExt_${_language}}")
1984	else()
1985		set (_prefixFileBaseName "")
1986		set (_prefixFileName "")
1987	endif()
1988	set (${_prefixFileBaseNameVar} "${_prefixFileBaseName}" PARENT_SCOPE)
1989	set (${_prefixFileNameVar} "${_prefixFileName}" PARENT_SCOPE)
1990endfunction()
1991
1992function (cotire_make_prefix_file_path _language _target _prefixFileVar)
1993	cotire_make_prefix_file_name("${_language}" "${_target}" _prefixFileBaseName _prefixFileName)
1994	set (${_prefixFileVar} "" PARENT_SCOPE)
1995	if (_prefixFileName)
1996		if (NOT _language)
1997			set (_language "C")
1998		endif()
1999		if (CMAKE_${_language}_COMPILER_ID MATCHES "GNU|Clang|Intel|MSVC")
2000			cotire_get_intermediate_dir(_baseDir)
2001			set (${_prefixFileVar} "${_baseDir}/${_prefixFileName}" PARENT_SCOPE)
2002		endif()
2003	endif()
2004endfunction()
2005
2006function (cotire_make_pch_file_path _language _target _pchFileVar)
2007	cotire_make_prefix_file_name("${_language}" "${_target}" _prefixFileBaseName _prefixFileName)
2008	set (${_pchFileVar} "" PARENT_SCOPE)
2009	if (_prefixFileBaseName AND _prefixFileName)
2010		cotire_check_precompiled_header_support("${_language}" "${_target}" _msg)
2011		if (NOT _msg)
2012			if (XCODE)
2013				# For Xcode, we completely hand off the compilation of the prefix header to the IDE
2014				return()
2015			endif()
2016			cotire_get_intermediate_dir(_baseDir)
2017			if (CMAKE_${_language}_COMPILER_ID MATCHES "MSVC")
2018				# MSVC uses the extension .pch added to the prefix header base name
2019				set (${_pchFileVar} "${_baseDir}/${_prefixFileBaseName}.pch" PARENT_SCOPE)
2020			elseif (CMAKE_${_language}_COMPILER_ID MATCHES "Clang")
2021				# Clang looks for a precompiled header corresponding to the prefix header with the extension .pch appended
2022				set (${_pchFileVar} "${_baseDir}/${_prefixFileName}.pch" PARENT_SCOPE)
2023			elseif (CMAKE_${_language}_COMPILER_ID MATCHES "GNU")
2024				# GCC looks for a precompiled header corresponding to the prefix header with the extension .gch appended
2025				set (${_pchFileVar} "${_baseDir}/${_prefixFileName}.gch" PARENT_SCOPE)
2026			elseif (CMAKE_${_language}_COMPILER_ID MATCHES "Intel")
2027				# Intel uses the extension .pchi added to the prefix header base name
2028				set (${_pchFileVar} "${_baseDir}/${_prefixFileBaseName}.pchi" PARENT_SCOPE)
2029			endif()
2030		endif()
2031	endif()
2032endfunction()
2033
2034function (cotire_select_unity_source_files _unityFile _sourcesVar)
2035	set (_sourceFiles ${ARGN})
2036	if (_sourceFiles AND "${_unityFile}" MATCHES "${COTIRE_UNITY_SOURCE_FILENAME_SUFFIX}_([0-9]+)_([0-9]+)")
2037		set (_startIndex ${CMAKE_MATCH_1})
2038		set (_endIndex ${CMAKE_MATCH_2})
2039		list (LENGTH _sourceFiles _numberOfSources)
2040		if (NOT _startIndex LESS _numberOfSources)
2041			math (EXPR _startIndex "${_numberOfSources} - 1")
2042		endif()
2043		if (NOT _endIndex LESS _numberOfSources)
2044			math (EXPR _endIndex "${_numberOfSources} - 1")
2045		endif()
2046		set (_files "")
2047		foreach (_index RANGE ${_startIndex} ${_endIndex})
2048			list (GET _sourceFiles ${_index} _file)
2049			list (APPEND _files "${_file}")
2050		endforeach()
2051	else()
2052		set (_files ${_sourceFiles})
2053	endif()
2054	set (${_sourcesVar} ${_files} PARENT_SCOPE)
2055endfunction()
2056
2057function (cotire_get_unity_source_dependencies _language _target _dependencySourcesVar)
2058	set (_dependencySources "")
2059	# depend on target's generated source files
2060	get_target_property(_targetSourceFiles ${_target} SOURCES)
2061	cotire_get_objects_with_property_on(_generatedSources GENERATED SOURCE ${_targetSourceFiles})
2062	if (_generatedSources)
2063		# but omit all generated source files that have the COTIRE_EXCLUDED property set to true
2064		cotire_get_objects_with_property_on(_excludedGeneratedSources COTIRE_EXCLUDED SOURCE ${_generatedSources})
2065		if (_excludedGeneratedSources)
2066			list (REMOVE_ITEM _generatedSources ${_excludedGeneratedSources})
2067		endif()
2068		# and omit all generated source files that have the COTIRE_DEPENDENCY property set to false explicitly
2069		cotire_get_objects_with_property_off(_excludedNonDependencySources COTIRE_DEPENDENCY SOURCE ${_generatedSources})
2070		if (_excludedNonDependencySources)
2071			list (REMOVE_ITEM _generatedSources ${_excludedNonDependencySources})
2072		endif()
2073		if (_generatedSources)
2074			list (APPEND _dependencySources ${_generatedSources})
2075		endif()
2076	endif()
2077	if (COTIRE_DEBUG AND _dependencySources)
2078		message (STATUS "${_language} ${_target} unity source dependencies: ${_dependencySources}")
2079	endif()
2080	set (${_dependencySourcesVar} ${_dependencySources} PARENT_SCOPE)
2081endfunction()
2082
2083function (cotire_get_prefix_header_dependencies _language _target _dependencySourcesVar)
2084	set (_dependencySources "")
2085	# depend on target source files marked with custom COTIRE_DEPENDENCY property
2086	get_target_property(_targetSourceFiles ${_target} SOURCES)
2087	cotire_get_objects_with_property_on(_dependencySources COTIRE_DEPENDENCY SOURCE ${_targetSourceFiles})
2088	if (COTIRE_DEBUG AND _dependencySources)
2089		message (STATUS "${_language} ${_target} prefix header dependencies: ${_dependencySources}")
2090	endif()
2091	set (${_dependencySourcesVar} ${_dependencySources} PARENT_SCOPE)
2092endfunction()
2093
2094function (cotire_generate_target_script _language _configurations _target _targetScriptVar _targetConfigScriptVar)
2095	set (_targetSources ${ARGN})
2096	cotire_get_prefix_header_dependencies(${_language} ${_target} COTIRE_TARGET_PREFIX_DEPENDS ${_targetSources})
2097	cotire_get_unity_source_dependencies(${_language} ${_target} COTIRE_TARGET_UNITY_DEPENDS ${_targetSources})
2098	# set up variables to be configured
2099	set (COTIRE_TARGET_LANGUAGE "${_language}")
2100	get_target_property(COTIRE_TARGET_IGNORE_PATH ${_target} COTIRE_PREFIX_HEADER_IGNORE_PATH)
2101	cotire_add_sys_root_paths(COTIRE_TARGET_IGNORE_PATH)
2102	get_target_property(COTIRE_TARGET_INCLUDE_PATH ${_target} COTIRE_PREFIX_HEADER_INCLUDE_PATH)
2103	cotire_add_sys_root_paths(COTIRE_TARGET_INCLUDE_PATH)
2104	get_target_property(COTIRE_TARGET_PRE_UNDEFS ${_target} COTIRE_UNITY_SOURCE_PRE_UNDEFS)
2105	get_target_property(COTIRE_TARGET_POST_UNDEFS ${_target} COTIRE_UNITY_SOURCE_POST_UNDEFS)
2106	get_target_property(COTIRE_TARGET_MAXIMUM_NUMBER_OF_INCLUDES ${_target} COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES)
2107	get_target_property(COTIRE_TARGET_INCLUDE_PRIORITY_PATH ${_target} COTIRE_PREFIX_HEADER_INCLUDE_PRIORITY_PATH)
2108	cotire_get_source_files_undefs(COTIRE_UNITY_SOURCE_PRE_UNDEFS COTIRE_TARGET_SOURCES_PRE_UNDEFS ${_targetSources})
2109	cotire_get_source_files_undefs(COTIRE_UNITY_SOURCE_POST_UNDEFS COTIRE_TARGET_SOURCES_POST_UNDEFS ${_targetSources})
2110	set (COTIRE_TARGET_CONFIGURATION_TYPES "${_configurations}")
2111	foreach (_config ${_configurations})
2112		string (TOUPPER "${_config}" _upperConfig)
2113		cotire_get_target_include_directories(
2114			"${_config}" "${_language}" "${_target}" COTIRE_TARGET_INCLUDE_DIRECTORIES_${_upperConfig} COTIRE_TARGET_SYSTEM_INCLUDE_DIRECTORIES_${_upperConfig})
2115		cotire_get_target_compile_definitions(
2116			"${_config}" "${_language}" "${_target}" COTIRE_TARGET_COMPILE_DEFINITIONS_${_upperConfig})
2117		cotire_get_target_compiler_flags(
2118			"${_config}" "${_language}" "${_target}" COTIRE_TARGET_COMPILE_FLAGS_${_upperConfig})
2119		cotire_get_source_files_compile_definitions(
2120			"${_config}" "${_language}" COTIRE_TARGET_SOURCES_COMPILE_DEFINITIONS_${_upperConfig} ${_targetSources})
2121	endforeach()
2122	get_target_property(COTIRE_TARGET_${_language}_COMPILER_LAUNCHER ${_target} ${_language}_COMPILER_LAUNCHER)
2123	# set up COTIRE_TARGET_SOURCES
2124	set (COTIRE_TARGET_SOURCES "")
2125	foreach (_sourceFile ${_targetSources})
2126		get_source_file_property(_generated "${_sourceFile}" GENERATED)
2127		if (_generated)
2128			# use absolute paths for generated files only, retrieving the LOCATION property is an expensive operation
2129			get_source_file_property(_sourceLocation "${_sourceFile}" LOCATION)
2130			list (APPEND COTIRE_TARGET_SOURCES "${_sourceLocation}")
2131		else()
2132			list (APPEND COTIRE_TARGET_SOURCES "${_sourceFile}")
2133		endif()
2134	endforeach()
2135	# copy variable definitions to cotire target script
2136	get_cmake_property(_vars VARIABLES)
2137	string (REGEX MATCHALL "COTIRE_[A-Za-z0-9_]+" _matchVars "${_vars}")
2138	# omit COTIRE_*_INIT variables
2139	string (REGEX MATCHALL "COTIRE_[A-Za-z0-9_]+_INIT" _initVars "${_matchVars}")
2140	if (_initVars)
2141		list (REMOVE_ITEM _matchVars ${_initVars})
2142	endif()
2143	# omit COTIRE_VERBOSE which is passed as a CMake define on command line
2144	list (REMOVE_ITEM _matchVars COTIRE_VERBOSE)
2145	set (_contents "")
2146	set (_contentsHasGeneratorExpressions FALSE)
2147	foreach (_var IN LISTS _matchVars ITEMS
2148		XCODE MSVC CMAKE_GENERATOR CMAKE_BUILD_TYPE CMAKE_CONFIGURATION_TYPES
2149		CMAKE_${_language}_COMPILER_ID CMAKE_${_language}_COMPILER_VERSION
2150		CMAKE_${_language}_COMPILER_LAUNCHER CMAKE_${_language}_COMPILER CMAKE_${_language}_COMPILER_ARG1
2151		CMAKE_INCLUDE_FLAG_${_language} CMAKE_INCLUDE_FLAG_${_language}_SEP
2152		CMAKE_INCLUDE_SYSTEM_FLAG_${_language}
2153		CMAKE_${_language}_FRAMEWORK_SEARCH_FLAG
2154		CMAKE_${_language}_SYSTEM_FRAMEWORK_SEARCH_FLAG
2155		CMAKE_${_language}_SOURCE_FILE_EXTENSIONS)
2156		if (DEFINED ${_var})
2157			string (REPLACE "\"" "\\\"" _value "${${_var}}")
2158			set (_contents "${_contents}set (${_var} \"${_value}\")\n")
2159			if (NOT _contentsHasGeneratorExpressions)
2160				if ("${_value}" MATCHES "\\$<.*>")
2161					set (_contentsHasGeneratorExpressions TRUE)
2162				endif()
2163			endif()
2164		endif()
2165	endforeach()
2166	# generate target script file
2167	get_filename_component(_moduleName "${COTIRE_CMAKE_MODULE_FILE}" NAME)
2168	set (_targetCotireScript "${CMAKE_CURRENT_BINARY_DIR}/${_target}_${_language}_${_moduleName}")
2169	cotire_write_file("CMAKE" "${_targetCotireScript}" "${_contents}" FALSE)
2170	if (_contentsHasGeneratorExpressions)
2171		# use file(GENERATE ...) to expand generator expressions in the target script at CMake generate-time
2172		set (_configNameOrNoneGeneratorExpression "$<$<CONFIG:>:None>$<$<NOT:$<CONFIG:>>:$<CONFIGURATION>>")
2173		set (_targetCotireConfigScript "${CMAKE_CURRENT_BINARY_DIR}/${_target}_${_language}_${_configNameOrNoneGeneratorExpression}_${_moduleName}")
2174		file (GENERATE OUTPUT "${_targetCotireConfigScript}" INPUT "${_targetCotireScript}")
2175	else()
2176		set (_targetCotireConfigScript "${_targetCotireScript}")
2177	endif()
2178	set (${_targetScriptVar} "${_targetCotireScript}" PARENT_SCOPE)
2179	set (${_targetConfigScriptVar} "${_targetCotireConfigScript}" PARENT_SCOPE)
2180endfunction()
2181
2182function (cotire_setup_pch_file_compilation _language _target _targetScript _prefixFile _pchFile _hostFile)
2183	set (_sourceFiles ${ARGN})
2184	if (CMAKE_${_language}_COMPILER_ID MATCHES "MSVC|Intel")
2185		# for Visual Studio and Intel, we attach the precompiled header compilation to the host file
2186		# the remaining files include the precompiled header, see cotire_setup_pch_file_inclusion
2187		if (_sourceFiles)
2188			set (_flags "")
2189			cotire_add_pch_compilation_flags(
2190				"${_language}" "${CMAKE_${_language}_COMPILER_ID}" "${CMAKE_${_language}_COMPILER_VERSION}"
2191				"${_prefixFile}" "${_pchFile}" "${_hostFile}" _flags)
2192			set_property (SOURCE ${_hostFile} APPEND_STRING PROPERTY COMPILE_FLAGS " ${_flags} ")
2193			set_property (SOURCE ${_hostFile} APPEND PROPERTY OBJECT_OUTPUTS "${_pchFile}")
2194			# make object file generated from host file depend on prefix header
2195			set_property (SOURCE ${_hostFile} APPEND PROPERTY OBJECT_DEPENDS "${_prefixFile}")
2196			# mark host file as cotired to prevent it from being used in another cotired target
2197			set_property (SOURCE ${_hostFile} PROPERTY COTIRE_TARGET "${_target}")
2198		endif()
2199	elseif ("${CMAKE_GENERATOR}" MATCHES "Make|Ninja")
2200		# for makefile based generator, we add a custom command to precompile the prefix header
2201		if (_targetScript)
2202			cotire_set_cmd_to_prologue(_cmds)
2203			list (APPEND _cmds -P "${COTIRE_CMAKE_MODULE_FILE}" "precompile" "${_targetScript}" "${_prefixFile}" "${_pchFile}" "${_hostFile}")
2204			if (MSVC_IDE)
2205				file (TO_NATIVE_PATH "${_pchFile}" _pchFileLogPath)
2206			else()
2207				file (RELATIVE_PATH _pchFileLogPath "${CMAKE_BINARY_DIR}" "${_pchFile}")
2208			endif()
2209			if (COTIRE_DEBUG)
2210				message (STATUS "add_custom_command: OUTPUT ${_pchFile} ${_cmds} DEPENDS ${_prefixFile} IMPLICIT_DEPENDS ${_language} ${_prefixFile}")
2211			endif()
2212			set_property (SOURCE "${_pchFile}" PROPERTY GENERATED TRUE)
2213			add_custom_command(
2214				OUTPUT "${_pchFile}"
2215				COMMAND ${_cmds}
2216				DEPENDS "${_prefixFile}"
2217				IMPLICIT_DEPENDS ${_language} "${_prefixFile}"
2218				WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
2219				COMMENT "Building ${_language} precompiled header ${_pchFileLogPath}"
2220				VERBATIM)
2221		endif()
2222	endif()
2223endfunction()
2224
2225function (cotire_setup_pch_file_inclusion _language _target _wholeTarget _prefixFile _pchFile _hostFile)
2226	if (CMAKE_${_language}_COMPILER_ID MATCHES "MSVC|Intel")
2227		# for Visual Studio and Intel, we include the precompiled header in all but the host file
2228		# the host file does the precompiled header compilation, see cotire_setup_pch_file_compilation
2229		set (_sourceFiles ${ARGN})
2230		list (LENGTH _sourceFiles _numberOfSourceFiles)
2231		if (_numberOfSourceFiles GREATER 0)
2232			# mark sources as cotired to prevent them from being used in another cotired target
2233			set_source_files_properties(${_sourceFiles} PROPERTIES COTIRE_TARGET "${_target}")
2234			set (_flags "")
2235			cotire_add_prefix_pch_inclusion_flags(
2236				"${_language}" "${CMAKE_${_language}_COMPILER_ID}" "${CMAKE_${_language}_COMPILER_VERSION}"
2237				"${_prefixFile}" "${_pchFile}" _flags)
2238			set_property (SOURCE ${_sourceFiles} APPEND_STRING PROPERTY COMPILE_FLAGS " ${_flags} ")
2239			# make object files generated from source files depend on precompiled header
2240			set_property (SOURCE ${_sourceFiles} APPEND PROPERTY OBJECT_DEPENDS "${_pchFile}")
2241		endif()
2242	elseif ("${CMAKE_GENERATOR}" MATCHES "Make|Ninja")
2243		set (_sourceFiles ${_hostFile} ${ARGN})
2244		if (NOT _wholeTarget)
2245			# for makefile based generator, we force the inclusion of the prefix header for a subset
2246			# of the source files, if this is a multi-language target or has excluded files
2247			set (_flags "")
2248			cotire_add_prefix_pch_inclusion_flags(
2249				"${_language}" "${CMAKE_${_language}_COMPILER_ID}" "${CMAKE_${_language}_COMPILER_VERSION}"
2250				"${_prefixFile}" "${_pchFile}" _flags)
2251			set_property (SOURCE ${_sourceFiles} APPEND_STRING PROPERTY COMPILE_FLAGS " ${_flags} ")
2252			# mark sources as cotired to prevent them from being used in another cotired target
2253			set_source_files_properties(${_sourceFiles} PROPERTIES COTIRE_TARGET "${_target}")
2254		endif()
2255		# make object files generated from source files depend on precompiled header
2256		set_property (SOURCE ${_sourceFiles} APPEND PROPERTY OBJECT_DEPENDS "${_pchFile}")
2257	endif()
2258endfunction()
2259
2260function (cotire_setup_prefix_file_inclusion _language _target _prefixFile)
2261	set (_sourceFiles ${ARGN})
2262	# force the inclusion of the prefix header for the given source files
2263	set (_flags "")
2264	set (_pchFile "")
2265	cotire_add_prefix_pch_inclusion_flags(
2266		"${_language}" "${CMAKE_${_language}_COMPILER_ID}" "${CMAKE_${_language}_COMPILER_VERSION}"
2267		"${_prefixFile}" "${_pchFile}" _flags)
2268	set_property (SOURCE ${_sourceFiles} APPEND_STRING PROPERTY COMPILE_FLAGS " ${_flags} ")
2269	# mark sources as cotired to prevent them from being used in another cotired target
2270	set_source_files_properties(${_sourceFiles} PROPERTIES COTIRE_TARGET "${_target}")
2271	# make object files generated from source files depend on prefix header
2272	set_property (SOURCE ${_sourceFiles} APPEND PROPERTY OBJECT_DEPENDS "${_prefixFile}")
2273endfunction()
2274
2275function (cotire_get_first_set_property_value _propertyValueVar _type _object)
2276	set (_properties ${ARGN})
2277	foreach (_property ${_properties})
2278		get_property(_propertyValue ${_type} "${_object}" PROPERTY ${_property})
2279		if (_propertyValue)
2280			set (${_propertyValueVar} ${_propertyValue} PARENT_SCOPE)
2281			return()
2282		endif()
2283	endforeach()
2284	set (${_propertyValueVar} "" PARENT_SCOPE)
2285endfunction()
2286
2287function (cotire_setup_combine_command _language _targetScript _joinedFile _cmdsVar)
2288	set (_files ${ARGN})
2289	set (_filesPaths "")
2290	foreach (_file ${_files})
2291		get_filename_component(_filePath "${_file}" ABSOLUTE)
2292		list (APPEND _filesPaths "${_filePath}")
2293	endforeach()
2294	cotire_set_cmd_to_prologue(_prefixCmd)
2295	list (APPEND _prefixCmd -P "${COTIRE_CMAKE_MODULE_FILE}" "combine")
2296	if (_targetScript)
2297		list (APPEND _prefixCmd "${_targetScript}")
2298	endif()
2299	list (APPEND _prefixCmd "${_joinedFile}" ${_filesPaths})
2300	if (COTIRE_DEBUG)
2301		message (STATUS "add_custom_command: OUTPUT ${_joinedFile} COMMAND ${_prefixCmd} DEPENDS ${_files}")
2302	endif()
2303	set_property (SOURCE "${_joinedFile}" PROPERTY GENERATED TRUE)
2304	if (MSVC_IDE)
2305		file (TO_NATIVE_PATH "${_joinedFile}" _joinedFileLogPath)
2306	else()
2307		file (RELATIVE_PATH _joinedFileLogPath "${CMAKE_BINARY_DIR}" "${_joinedFile}")
2308	endif()
2309	get_filename_component(_joinedFileBaseName "${_joinedFile}" NAME_WE)
2310	get_filename_component(_joinedFileExt "${_joinedFile}" EXT)
2311	if (_language AND _joinedFileBaseName MATCHES "${COTIRE_UNITY_SOURCE_FILENAME_SUFFIX}$")
2312		set (_comment "Generating ${_language} unity source ${_joinedFileLogPath}")
2313	elseif (_language AND _joinedFileBaseName MATCHES "${COTIRE_PREFIX_HEADER_FILENAME_SUFFIX}$")
2314		if (_joinedFileExt MATCHES "^\\.c")
2315			set (_comment "Generating ${_language} prefix source ${_joinedFileLogPath}")
2316		else()
2317			set (_comment "Generating ${_language} prefix header ${_joinedFileLogPath}")
2318		endif()
2319	else()
2320		set (_comment "Generating ${_joinedFileLogPath}")
2321	endif()
2322	add_custom_command(
2323		OUTPUT "${_joinedFile}"
2324		COMMAND ${_prefixCmd}
2325		DEPENDS ${_files}
2326		COMMENT "${_comment}"
2327		WORKING_DIRECTORY "${CMAKE_BINARY_DIR}"
2328		VERBATIM)
2329	list (APPEND ${_cmdsVar} COMMAND ${_prefixCmd})
2330	set (${_cmdsVar} ${${_cmdsVar}} PARENT_SCOPE)
2331endfunction()
2332
2333function (cotire_setup_target_pch_usage _languages _target _wholeTarget)
2334	if (XCODE)
2335		# for Xcode, we attach a pre-build action to generate the unity sources and prefix headers
2336		set (_prefixFiles "")
2337		foreach (_language ${_languages})
2338			get_property(_prefixFile TARGET ${_target} PROPERTY COTIRE_${_language}_PREFIX_HEADER)
2339			if (_prefixFile)
2340				list (APPEND _prefixFiles "${_prefixFile}")
2341			endif()
2342		endforeach()
2343		set (_cmds ${ARGN})
2344		list (LENGTH _prefixFiles _numberOfPrefixFiles)
2345		if (_numberOfPrefixFiles GREATER 1)
2346			# we also generate a generic, single prefix header which includes all language specific prefix headers
2347			set (_language "")
2348			set (_targetScript "")
2349			cotire_make_prefix_file_path("${_language}" ${_target} _prefixHeader)
2350			cotire_setup_combine_command("${_language}" "${_targetScript}" "${_prefixHeader}" _cmds ${_prefixFiles})
2351		else()
2352			set (_prefixHeader "${_prefixFiles}")
2353		endif()
2354		if (COTIRE_DEBUG)
2355			message (STATUS "add_custom_command: TARGET ${_target} PRE_BUILD ${_cmds}")
2356		endif()
2357		# because CMake PRE_BUILD command does not support dependencies,
2358		# we check dependencies explicity in cotire script mode when the pre-build action is run
2359		add_custom_command(
2360			TARGET "${_target}"
2361			PRE_BUILD ${_cmds}
2362			WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
2363			COMMENT "Updating target ${_target} prefix headers"
2364			VERBATIM)
2365		# make Xcode precompile the generated prefix header with ProcessPCH and ProcessPCH++
2366		set_target_properties(${_target} PROPERTIES XCODE_ATTRIBUTE_GCC_PRECOMPILE_PREFIX_HEADER "YES")
2367		set_target_properties(${_target} PROPERTIES XCODE_ATTRIBUTE_GCC_PREFIX_HEADER "${_prefixHeader}")
2368	elseif ("${CMAKE_GENERATOR}" MATCHES "Make|Ninja")
2369		# for makefile based generator, we force inclusion of the prefix header for all target source files
2370		# if this is a single-language target without any excluded files
2371		if (_wholeTarget)
2372			set (_language "${_languages}")
2373			# for Visual Studio and Intel, precompiled header inclusion is always done on the source file level
2374			# see cotire_setup_pch_file_inclusion
2375			if (NOT CMAKE_${_language}_COMPILER_ID MATCHES "MSVC|Intel")
2376				get_property(_prefixFile TARGET ${_target} PROPERTY COTIRE_${_language}_PREFIX_HEADER)
2377				if (_prefixFile)
2378					get_property(_pchFile TARGET ${_target} PROPERTY COTIRE_${_language}_PRECOMPILED_HEADER)
2379					set (_options COMPILE_OPTIONS)
2380					cotire_add_prefix_pch_inclusion_flags(
2381						"${_language}" "${CMAKE_${_language}_COMPILER_ID}" "${CMAKE_${_language}_COMPILER_VERSION}"
2382						"${_prefixFile}" "${_pchFile}" _options)
2383					set_property(TARGET ${_target} APPEND PROPERTY ${_options})
2384				endif()
2385			endif()
2386		endif()
2387	endif()
2388endfunction()
2389
2390function (cotire_setup_unity_generation_commands _language _target _targetScript _targetConfigScript _unityFiles _cmdsVar)
2391	set (_dependencySources "")
2392	cotire_get_unity_source_dependencies(${_language} ${_target} _dependencySources ${ARGN})
2393	foreach (_unityFile ${_unityFiles})
2394		set_property (SOURCE "${_unityFile}" PROPERTY GENERATED TRUE)
2395		# set up compiled unity source dependencies via OBJECT_DEPENDS
2396		# this ensures that missing source files are generated before the unity file is compiled
2397		if (COTIRE_DEBUG AND _dependencySources)
2398			message (STATUS "${_unityFile} OBJECT_DEPENDS ${_dependencySources}")
2399		endif()
2400		if (_dependencySources)
2401			# the OBJECT_DEPENDS property requires a list of full paths
2402			set (_objectDependsPaths "")
2403			foreach (_sourceFile ${_dependencySources})
2404				get_source_file_property(_sourceLocation "${_sourceFile}" LOCATION)
2405				list (APPEND _objectDependsPaths "${_sourceLocation}")
2406			endforeach()
2407			set_property (SOURCE "${_unityFile}" PROPERTY OBJECT_DEPENDS ${_objectDependsPaths})
2408		endif()
2409		if (WIN32 AND CMAKE_${_language}_COMPILER_ID MATCHES "MSVC|Intel")
2410			# unity file compilation results in potentially huge object file, thus use /bigobj by default unter MSVC and Windows Intel
2411			set_property (SOURCE "${_unityFile}" APPEND_STRING PROPERTY COMPILE_FLAGS "/bigobj")
2412		endif()
2413		cotire_set_cmd_to_prologue(_unityCmd)
2414		list (APPEND _unityCmd -P "${COTIRE_CMAKE_MODULE_FILE}" "unity" "${_targetConfigScript}" "${_unityFile}")
2415		if (CMAKE_VERSION VERSION_LESS "3.1.0")
2416			set (_unityCmdDepends "${_targetScript}")
2417		else()
2418			# CMake 3.1.0 supports generator expressions in arguments to DEPENDS
2419			set (_unityCmdDepends "${_targetConfigScript}")
2420		endif()
2421		if (MSVC_IDE)
2422			file (TO_NATIVE_PATH "${_unityFile}" _unityFileLogPath)
2423		else()
2424			file (RELATIVE_PATH _unityFileLogPath "${CMAKE_BINARY_DIR}" "${_unityFile}")
2425		endif()
2426		if (COTIRE_DEBUG)
2427			message (STATUS "add_custom_command: OUTPUT ${_unityFile} COMMAND ${_unityCmd} DEPENDS ${_unityCmdDepends}")
2428		endif()
2429		add_custom_command(
2430			OUTPUT "${_unityFile}"
2431			COMMAND ${_unityCmd}
2432			DEPENDS ${_unityCmdDepends}
2433			COMMENT "Generating ${_language} unity source ${_unityFileLogPath}"
2434			WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
2435			VERBATIM)
2436		list (APPEND ${_cmdsVar} COMMAND ${_unityCmd})
2437	endforeach()
2438	set (${_cmdsVar} ${${_cmdsVar}} PARENT_SCOPE)
2439endfunction()
2440
2441function (cotire_setup_prefix_generation_command _language _target _targetScript _prefixFile _unityFiles _cmdsVar)
2442	set (_sourceFiles ${ARGN})
2443	set (_dependencySources "")
2444	cotire_get_prefix_header_dependencies(${_language} ${_target} _dependencySources ${_sourceFiles})
2445	cotire_set_cmd_to_prologue(_prefixCmd)
2446	list (APPEND _prefixCmd -P "${COTIRE_CMAKE_MODULE_FILE}" "prefix" "${_targetScript}" "${_prefixFile}" ${_unityFiles})
2447	set_property (SOURCE "${_prefixFile}" PROPERTY GENERATED TRUE)
2448	if (COTIRE_DEBUG)
2449		message (STATUS "add_custom_command: OUTPUT ${_prefixFile} COMMAND ${_prefixCmd} DEPENDS ${_unityFile} ${_dependencySources}")
2450	endif()
2451	if (MSVC_IDE)
2452		file (TO_NATIVE_PATH "${_prefixFile}" _prefixFileLogPath)
2453	else()
2454		file (RELATIVE_PATH _prefixFileLogPath "${CMAKE_BINARY_DIR}" "${_prefixFile}")
2455	endif()
2456	get_filename_component(_prefixFileExt "${_prefixFile}" EXT)
2457	if (_prefixFileExt MATCHES "^\\.c")
2458		set (_comment "Generating ${_language} prefix source ${_prefixFileLogPath}")
2459	else()
2460		set (_comment "Generating ${_language} prefix header ${_prefixFileLogPath}")
2461	endif()
2462	# prevent pre-processing errors upon generating the prefix header when a target's generated include file does not yet exist
2463	# we do not add a file-level dependency for the target's generated files though, because we only want to depend on their existence
2464	# thus we make the prefix header generation depend on a custom helper target which triggers the generation of the files
2465	set (_preTargetName "${_target}${COTIRE_PCH_TARGET_SUFFIX}_pre")
2466	if (TARGET ${_preTargetName})
2467		# custom helper target has already been generated while processing a different language
2468		list (APPEND _dependencySources ${_preTargetName})
2469	else()
2470		get_target_property(_targetSourceFiles ${_target} SOURCES)
2471		cotire_get_objects_with_property_on(_generatedSources GENERATED SOURCE ${_targetSourceFiles})
2472		if (_generatedSources)
2473			add_custom_target("${_preTargetName}" DEPENDS ${_generatedSources})
2474			cotire_init_target("${_preTargetName}")
2475			list (APPEND _dependencySources ${_preTargetName})
2476		endif()
2477	endif()
2478	add_custom_command(
2479		OUTPUT "${_prefixFile}" "${_prefixFile}.log"
2480		COMMAND ${_prefixCmd}
2481		DEPENDS ${_unityFiles} ${_dependencySources}
2482		COMMENT "${_comment}"
2483		WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
2484		VERBATIM)
2485	list (APPEND ${_cmdsVar} COMMAND ${_prefixCmd})
2486	set (${_cmdsVar} ${${_cmdsVar}} PARENT_SCOPE)
2487endfunction()
2488
2489function (cotire_setup_prefix_generation_from_unity_command _language _target _targetScript _prefixFile _unityFiles _cmdsVar)
2490	set (_sourceFiles ${ARGN})
2491	if (CMAKE_${_language}_COMPILER_ID MATCHES "GNU|Clang")
2492		# GNU and Clang require indirect compilation of the prefix header to make them honor the system_header pragma
2493		cotire_prefix_header_to_source_file_path(${_language} "${_prefixFile}" _prefixSourceFile)
2494	else()
2495		set (_prefixSourceFile "${_prefixFile}")
2496	endif()
2497	cotire_setup_prefix_generation_command(
2498		${_language} ${_target} "${_targetScript}"
2499		"${_prefixSourceFile}" "${_unityFiles}" ${_cmdsVar} ${_sourceFiles})
2500	if (CMAKE_${_language}_COMPILER_ID MATCHES "GNU|Clang")
2501		# set up generation of a prefix source file which includes the prefix header
2502		cotire_setup_combine_command(${_language} "${_targetScript}" "${_prefixFile}" _cmds ${_prefixSourceFile})
2503	endif()
2504	set (${_cmdsVar} ${${_cmdsVar}} PARENT_SCOPE)
2505endfunction()
2506
2507function (cotire_setup_prefix_generation_from_provided_command _language _target _targetScript _prefixFile _cmdsVar)
2508	set (_prefixHeaderFiles ${ARGN})
2509	if (CMAKE_${_language}_COMPILER_ID MATCHES "GNU|Clang")
2510		# GNU and Clang require indirect compilation of the prefix header to make them honor the system_header pragma
2511		cotire_prefix_header_to_source_file_path(${_language} "${_prefixFile}" _prefixSourceFile)
2512	else()
2513		set (_prefixSourceFile "${_prefixFile}")
2514	endif()
2515	cotire_setup_combine_command(${_language} "${_targetScript}" "${_prefixSourceFile}" _cmds ${_prefixHeaderFiles})
2516	if (CMAKE_${_language}_COMPILER_ID MATCHES "GNU|Clang")
2517		# set up generation of a prefix source file which includes the prefix header
2518		cotire_setup_combine_command(${_language} "${_targetScript}" "${_prefixFile}" _cmds ${_prefixSourceFile})
2519	endif()
2520	set (${_cmdsVar} ${${_cmdsVar}} PARENT_SCOPE)
2521endfunction()
2522
2523function (cotire_init_cotire_target_properties _target)
2524	get_property(_isSet TARGET ${_target} PROPERTY COTIRE_ENABLE_PRECOMPILED_HEADER SET)
2525	if (NOT _isSet)
2526		set_property(TARGET ${_target} PROPERTY COTIRE_ENABLE_PRECOMPILED_HEADER TRUE)
2527	endif()
2528	get_property(_isSet TARGET ${_target} PROPERTY COTIRE_ADD_UNITY_BUILD SET)
2529	if (NOT _isSet)
2530		set_property(TARGET ${_target} PROPERTY COTIRE_ADD_UNITY_BUILD TRUE)
2531	endif()
2532	get_property(_isSet TARGET ${_target} PROPERTY COTIRE_ADD_CLEAN SET)
2533	if (NOT _isSet)
2534		set_property(TARGET ${_target} PROPERTY COTIRE_ADD_CLEAN FALSE)
2535	endif()
2536	get_property(_isSet TARGET ${_target} PROPERTY COTIRE_PREFIX_HEADER_IGNORE_PATH SET)
2537	if (NOT _isSet)
2538		set_property(TARGET ${_target} PROPERTY COTIRE_PREFIX_HEADER_IGNORE_PATH "${CMAKE_SOURCE_DIR}")
2539		cotire_check_is_path_relative_to("${CMAKE_BINARY_DIR}" _isRelative "${CMAKE_SOURCE_DIR}")
2540		if (NOT _isRelative)
2541			set_property(TARGET ${_target} APPEND PROPERTY COTIRE_PREFIX_HEADER_IGNORE_PATH "${CMAKE_BINARY_DIR}")
2542		endif()
2543	endif()
2544	get_property(_isSet TARGET ${_target} PROPERTY COTIRE_PREFIX_HEADER_INCLUDE_PATH SET)
2545	if (NOT _isSet)
2546		set_property(TARGET ${_target} PROPERTY COTIRE_PREFIX_HEADER_INCLUDE_PATH "")
2547	endif()
2548	get_property(_isSet TARGET ${_target} PROPERTY COTIRE_PREFIX_HEADER_INCLUDE_PRIORITY_PATH SET)
2549	if (NOT _isSet)
2550		set_property(TARGET ${_target} PROPERTY COTIRE_PREFIX_HEADER_INCLUDE_PRIORITY_PATH "")
2551	endif()
2552	get_property(_isSet TARGET ${_target} PROPERTY COTIRE_UNITY_SOURCE_PRE_UNDEFS SET)
2553	if (NOT _isSet)
2554		set_property(TARGET ${_target} PROPERTY COTIRE_UNITY_SOURCE_PRE_UNDEFS "")
2555	endif()
2556	get_property(_isSet TARGET ${_target} PROPERTY COTIRE_UNITY_SOURCE_POST_UNDEFS SET)
2557	if (NOT _isSet)
2558		set_property(TARGET ${_target} PROPERTY COTIRE_UNITY_SOURCE_POST_UNDEFS "")
2559	endif()
2560	get_property(_isSet TARGET ${_target} PROPERTY COTIRE_UNITY_LINK_LIBRARIES_INIT SET)
2561	if (NOT _isSet)
2562		set_property(TARGET ${_target} PROPERTY COTIRE_UNITY_LINK_LIBRARIES_INIT "COPY_UNITY")
2563	endif()
2564	get_property(_isSet TARGET ${_target} PROPERTY COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES SET)
2565	if (NOT _isSet)
2566		if (COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES)
2567			set_property(TARGET ${_target} PROPERTY COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES "${COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES}")
2568		else()
2569			set_property(TARGET ${_target} PROPERTY COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES "")
2570		endif()
2571	endif()
2572endfunction()
2573
2574function (cotire_make_target_message _target _languages _disableMsg _targetMsgVar)
2575	get_target_property(_targetUsePCH ${_target} COTIRE_ENABLE_PRECOMPILED_HEADER)
2576	get_target_property(_targetAddSCU ${_target} COTIRE_ADD_UNITY_BUILD)
2577	string (REPLACE ";" " " _languagesStr "${_languages}")
2578	math (EXPR _numberOfExcludedFiles "${ARGC} - 4")
2579	if (_numberOfExcludedFiles EQUAL 0)
2580		set (_excludedStr "")
2581	elseif (COTIRE_VERBOSE OR _numberOfExcludedFiles LESS 4)
2582		string (REPLACE ";" ", " _excludedStr "excluding ${ARGN}")
2583	else()
2584		set (_excludedStr "excluding ${_numberOfExcludedFiles} files")
2585	endif()
2586	set (_targetMsg "")
2587	if (NOT _languages)
2588		set (_targetMsg "Target ${_target} cannot be cotired.")
2589		if (_disableMsg)
2590			set (_targetMsg "${_targetMsg} ${_disableMsg}")
2591		endif()
2592	elseif (NOT _targetUsePCH AND NOT _targetAddSCU)
2593		set (_targetMsg "${_languagesStr} target ${_target} cotired without unity build and precompiled header.")
2594		if (_disableMsg)
2595			set (_targetMsg "${_targetMsg} ${_disableMsg}")
2596		endif()
2597	elseif (NOT _targetUsePCH)
2598		if (_excludedStr)
2599			set (_targetMsg "${_languagesStr} target ${_target} cotired without precompiled header ${_excludedStr}.")
2600		else()
2601			set (_targetMsg "${_languagesStr} target ${_target} cotired without precompiled header.")
2602		endif()
2603		if (_disableMsg)
2604			set (_targetMsg "${_targetMsg} ${_disableMsg}")
2605		endif()
2606	elseif (NOT _targetAddSCU)
2607		if (_excludedStr)
2608			set (_targetMsg "${_languagesStr} target ${_target} cotired without unity build ${_excludedStr}.")
2609		else()
2610			set (_targetMsg "${_languagesStr} target ${_target} cotired without unity build.")
2611		endif()
2612	else()
2613		if (_excludedStr)
2614			set (_targetMsg "${_languagesStr} target ${_target} cotired ${_excludedStr}.")
2615		else()
2616			set (_targetMsg "${_languagesStr} target ${_target} cotired.")
2617		endif()
2618	endif()
2619	set (${_targetMsgVar} "${_targetMsg}" PARENT_SCOPE)
2620endfunction()
2621
2622function (cotire_choose_target_languages _target _targetLanguagesVar _wholeTargetVar)
2623	set (_languages ${ARGN})
2624	set (_allSourceFiles "")
2625	set (_allExcludedSourceFiles "")
2626	set (_allCotiredSourceFiles "")
2627	set (_targetLanguages "")
2628	set (_pchEligibleTargetLanguages "")
2629	get_target_property(_targetType ${_target} TYPE)
2630	get_target_property(_targetSourceFiles ${_target} SOURCES)
2631	get_target_property(_targetUsePCH ${_target} COTIRE_ENABLE_PRECOMPILED_HEADER)
2632	get_target_property(_targetAddSCU ${_target} COTIRE_ADD_UNITY_BUILD)
2633	set (_disableMsg "")
2634	foreach (_language ${_languages})
2635		get_target_property(_prefixHeader ${_target} COTIRE_${_language}_PREFIX_HEADER)
2636		get_target_property(_unityBuildFile ${_target} COTIRE_${_language}_UNITY_SOURCE)
2637		if (_prefixHeader OR _unityBuildFile)
2638			message (STATUS "cotire: target ${_target} has already been cotired.")
2639			set (${_targetLanguagesVar} "" PARENT_SCOPE)
2640			return()
2641		endif()
2642		if (_targetUsePCH AND "${_language}" MATCHES "^C|CXX$" AND NOT "${CMAKE_${_language}_COMPILER_ID}" STREQUAL "")
2643			cotire_check_precompiled_header_support("${_language}" "${_target}" _disableMsg)
2644			if (_disableMsg)
2645				set (_targetUsePCH FALSE)
2646			endif()
2647		endif()
2648		set (_sourceFiles "")
2649		set (_excludedSources "")
2650		set (_cotiredSources "")
2651		cotire_filter_language_source_files(${_language} ${_target} _sourceFiles _excludedSources _cotiredSources ${_targetSourceFiles})
2652		if (_sourceFiles OR _excludedSources OR _cotiredSources)
2653			list (APPEND _targetLanguages ${_language})
2654		endif()
2655		if (_sourceFiles)
2656			list (APPEND _allSourceFiles ${_sourceFiles})
2657		endif()
2658		list (LENGTH _sourceFiles _numberOfSources)
2659		if (NOT _numberOfSources LESS ${COTIRE_MINIMUM_NUMBER_OF_TARGET_SOURCES})
2660			list (APPEND _pchEligibleTargetLanguages ${_language})
2661		endif()
2662		if (_excludedSources)
2663			list (APPEND _allExcludedSourceFiles ${_excludedSources})
2664		endif()
2665		if (_cotiredSources)
2666			list (APPEND _allCotiredSourceFiles ${_cotiredSources})
2667		endif()
2668	endforeach()
2669	set (_targetMsgLevel STATUS)
2670	if (NOT _targetLanguages)
2671		string (REPLACE ";" " or " _languagesStr "${_languages}")
2672		set (_disableMsg "No ${_languagesStr} source files.")
2673		set (_targetUsePCH FALSE)
2674		set (_targetAddSCU FALSE)
2675	endif()
2676	if (_targetUsePCH)
2677		if (_allCotiredSourceFiles)
2678			cotire_get_source_file_property_values(_cotireTargets COTIRE_TARGET ${_allCotiredSourceFiles})
2679			list (REMOVE_DUPLICATES _cotireTargets)
2680			string (REPLACE ";" ", " _cotireTargetsStr "${_cotireTargets}")
2681			set (_disableMsg "Target sources already include a precompiled header for target(s) ${_cotireTargets}.")
2682			set (_disableMsg "${_disableMsg} Set target property COTIRE_ENABLE_PRECOMPILED_HEADER to FALSE for targets ${_target},")
2683			set (_disableMsg "${_disableMsg} ${_cotireTargetsStr} to get a workable build system.")
2684			set (_targetMsgLevel SEND_ERROR)
2685			set (_targetUsePCH FALSE)
2686		elseif (NOT _pchEligibleTargetLanguages)
2687			set (_disableMsg "Too few applicable sources.")
2688			set (_targetUsePCH FALSE)
2689		elseif (XCODE AND _allExcludedSourceFiles)
2690			# for Xcode, we cannot apply the precompiled header to individual sources, only to the whole target
2691			set (_disableMsg "Exclusion of source files not supported for generator Xcode.")
2692			set (_targetUsePCH FALSE)
2693		elseif (XCODE AND "${_targetType}" STREQUAL "OBJECT_LIBRARY")
2694			# for Xcode, we cannot apply the required PRE_BUILD action to generate the prefix header to an OBJECT_LIBRARY target
2695			set (_disableMsg "Required PRE_BUILD action not supported for OBJECT_LIBRARY targets for generator Xcode.")
2696			set (_targetUsePCH FALSE)
2697		endif()
2698	endif()
2699	set_property(TARGET ${_target} PROPERTY COTIRE_ENABLE_PRECOMPILED_HEADER ${_targetUsePCH})
2700	set_property(TARGET ${_target} PROPERTY COTIRE_ADD_UNITY_BUILD ${_targetAddSCU})
2701	cotire_make_target_message(${_target} "${_targetLanguages}" "${_disableMsg}" _targetMsg ${_allExcludedSourceFiles})
2702	if (_targetMsg)
2703		if (NOT DEFINED COTIREMSG_${_target})
2704			set (COTIREMSG_${_target} "")
2705		endif()
2706		if (COTIRE_VERBOSE OR NOT "${_targetMsgLevel}" STREQUAL "STATUS" OR
2707			NOT "${COTIREMSG_${_target}}" STREQUAL "${_targetMsg}")
2708			# cache message to avoid redundant messages on re-configure
2709			set (COTIREMSG_${_target} "${_targetMsg}" CACHE INTERNAL "${_target} cotire message.")
2710			message (${_targetMsgLevel} "${_targetMsg}")
2711		endif()
2712	endif()
2713	list (LENGTH _targetLanguages _numberOfLanguages)
2714	if (_numberOfLanguages GREATER 1 OR _allExcludedSourceFiles)
2715		set (${_wholeTargetVar} FALSE PARENT_SCOPE)
2716	else()
2717		set (${_wholeTargetVar} TRUE PARENT_SCOPE)
2718	endif()
2719	set (${_targetLanguagesVar} ${_targetLanguages} PARENT_SCOPE)
2720endfunction()
2721
2722function (cotire_compute_unity_max_number_of_includes _target _maxIncludesVar)
2723	set (_sourceFiles ${ARGN})
2724	get_target_property(_maxIncludes ${_target} COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES)
2725	if (_maxIncludes MATCHES "(-j|--parallel|--jobs) ?([0-9]*)")
2726		set (_numberOfThreads "${CMAKE_MATCH_2}")
2727		if (NOT _numberOfThreads)
2728			# use all available cores
2729			ProcessorCount(_numberOfThreads)
2730		endif()
2731		list (LENGTH _sourceFiles _numberOfSources)
2732		math (EXPR _maxIncludes "(${_numberOfSources} + ${_numberOfThreads} - 1) / ${_numberOfThreads}")
2733	elseif (NOT _maxIncludes MATCHES "[0-9]+")
2734		set (_maxIncludes 0)
2735	endif()
2736	if (COTIRE_DEBUG)
2737		message (STATUS "${_target} unity source max includes: ${_maxIncludes}")
2738	endif()
2739	set (${_maxIncludesVar} ${_maxIncludes} PARENT_SCOPE)
2740endfunction()
2741
2742function (cotire_process_target_language _language _configurations _target _wholeTarget _cmdsVar)
2743	set (${_cmdsVar} "" PARENT_SCOPE)
2744	get_target_property(_targetSourceFiles ${_target} SOURCES)
2745	set (_sourceFiles "")
2746	set (_excludedSources "")
2747	set (_cotiredSources "")
2748	cotire_filter_language_source_files(${_language} ${_target} _sourceFiles _excludedSources _cotiredSources ${_targetSourceFiles})
2749	if (NOT _sourceFiles AND NOT _cotiredSources)
2750		return()
2751	endif()
2752	set (_cmds "")
2753	# check for user provided unity source file list
2754	get_property(_unitySourceFiles TARGET ${_target} PROPERTY COTIRE_${_language}_UNITY_SOURCE_INIT)
2755	if (NOT _unitySourceFiles)
2756		set (_unitySourceFiles ${_sourceFiles} ${_cotiredSources})
2757	endif()
2758	cotire_generate_target_script(
2759		${_language} "${_configurations}" ${_target} _targetScript _targetConfigScript ${_unitySourceFiles})
2760	# set up unity files for parallel compilation
2761	cotire_compute_unity_max_number_of_includes(${_target} _maxIncludes ${_unitySourceFiles})
2762	cotire_make_unity_source_file_paths(${_language} ${_target} ${_maxIncludes} _unityFiles ${_unitySourceFiles})
2763	list (LENGTH _unityFiles _numberOfUnityFiles)
2764	if (_numberOfUnityFiles EQUAL 0)
2765		return()
2766	elseif (_numberOfUnityFiles GREATER 1)
2767		cotire_setup_unity_generation_commands(
2768			${_language} ${_target} "${_targetScript}" "${_targetConfigScript}" "${_unityFiles}" _cmds ${_unitySourceFiles})
2769	endif()
2770	# set up single unity file for prefix header generation
2771	cotire_make_single_unity_source_file_path(${_language} ${_target} _unityFile)
2772	cotire_setup_unity_generation_commands(
2773		${_language} ${_target} "${_targetScript}" "${_targetConfigScript}" "${_unityFile}" _cmds ${_unitySourceFiles})
2774	cotire_make_prefix_file_path(${_language} ${_target} _prefixFile)
2775	# set up prefix header
2776	if (_prefixFile)
2777		# check for user provided prefix header files
2778		get_property(_prefixHeaderFiles TARGET ${_target} PROPERTY COTIRE_${_language}_PREFIX_HEADER_INIT)
2779		if (_prefixHeaderFiles)
2780			cotire_setup_prefix_generation_from_provided_command(
2781				${_language} ${_target} "${_targetConfigScript}" "${_prefixFile}" _cmds ${_prefixHeaderFiles})
2782		else()
2783			cotire_setup_prefix_generation_from_unity_command(
2784				${_language} ${_target} "${_targetConfigScript}" "${_prefixFile}" "${_unityFile}" _cmds ${_unitySourceFiles})
2785		endif()
2786		# check if selected language has enough sources at all
2787		list (LENGTH _sourceFiles _numberOfSources)
2788		if (_numberOfSources LESS ${COTIRE_MINIMUM_NUMBER_OF_TARGET_SOURCES})
2789			set (_targetUsePCH FALSE)
2790		else()
2791			get_target_property(_targetUsePCH ${_target} COTIRE_ENABLE_PRECOMPILED_HEADER)
2792		endif()
2793		if (_targetUsePCH)
2794			cotire_make_pch_file_path(${_language} ${_target} _pchFile)
2795			if (_pchFile)
2796				# first file in _sourceFiles is passed as the host file
2797				cotire_setup_pch_file_compilation(
2798					${_language} ${_target} "${_targetConfigScript}" "${_prefixFile}" "${_pchFile}" ${_sourceFiles})
2799				cotire_setup_pch_file_inclusion(
2800					${_language} ${_target} ${_wholeTarget} "${_prefixFile}" "${_pchFile}" ${_sourceFiles})
2801			endif()
2802		elseif (_prefixHeaderFiles)
2803			# user provided prefix header must be included unconditionally
2804			cotire_setup_prefix_file_inclusion(${_language} ${_target} "${_prefixFile}" ${_sourceFiles})
2805		endif()
2806	endif()
2807	# mark target as cotired for language
2808	set_property(TARGET ${_target} PROPERTY COTIRE_${_language}_UNITY_SOURCE "${_unityFiles}")
2809	if (_prefixFile)
2810		set_property(TARGET ${_target} PROPERTY COTIRE_${_language}_PREFIX_HEADER "${_prefixFile}")
2811		if (_targetUsePCH AND _pchFile)
2812			set_property(TARGET ${_target} PROPERTY COTIRE_${_language}_PRECOMPILED_HEADER "${_pchFile}")
2813		endif()
2814	endif()
2815	set (${_cmdsVar} ${_cmds} PARENT_SCOPE)
2816endfunction()
2817
2818function (cotire_setup_clean_target _target)
2819	set (_cleanTargetName "${_target}${COTIRE_CLEAN_TARGET_SUFFIX}")
2820	if (NOT TARGET "${_cleanTargetName}")
2821		cotire_set_cmd_to_prologue(_cmds)
2822		get_filename_component(_outputDir "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}" ABSOLUTE)
2823		list (APPEND _cmds -P "${COTIRE_CMAKE_MODULE_FILE}" "cleanup" "${_outputDir}" "${COTIRE_INTDIR}" "${_target}")
2824		add_custom_target(${_cleanTargetName}
2825			COMMAND ${_cmds}
2826			WORKING_DIRECTORY "${CMAKE_BINARY_DIR}"
2827			COMMENT "Cleaning up target ${_target} cotire generated files"
2828			VERBATIM)
2829		cotire_init_target("${_cleanTargetName}")
2830	endif()
2831endfunction()
2832
2833function (cotire_setup_pch_target _languages _configurations _target)
2834	if ("${CMAKE_GENERATOR}" MATCHES "Make|Ninja")
2835		# for makefile based generators, we add a custom target to trigger the generation of the cotire related files
2836		set (_dependsFiles "")
2837		foreach (_language ${_languages})
2838			set (_props COTIRE_${_language}_PREFIX_HEADER COTIRE_${_language}_UNITY_SOURCE)
2839			if (NOT CMAKE_${_language}_COMPILER_ID MATCHES "MSVC|Intel")
2840				# Visual Studio and Intel only create precompiled header as a side effect
2841				list (INSERT _props 0 COTIRE_${_language}_PRECOMPILED_HEADER)
2842			endif()
2843			cotire_get_first_set_property_value(_dependsFile TARGET ${_target} ${_props})
2844			if (_dependsFile)
2845				list (APPEND _dependsFiles "${_dependsFile}")
2846			endif()
2847		endforeach()
2848		if (_dependsFiles)
2849			set (_pchTargetName "${_target}${COTIRE_PCH_TARGET_SUFFIX}")
2850			add_custom_target("${_pchTargetName}" DEPENDS ${_dependsFiles})
2851			cotire_init_target("${_pchTargetName}")
2852			cotire_add_to_pch_all_target(${_pchTargetName})
2853		endif()
2854	else()
2855		# for other generators, we add the "clean all" target to clean up the precompiled header
2856		cotire_setup_clean_all_target()
2857	endif()
2858endfunction()
2859
2860function (cotire_collect_unity_target_sources _target _languages _unityTargetSourcesVar)
2861	get_target_property(_targetSourceFiles ${_target} SOURCES)
2862	set (_unityTargetSources ${_targetSourceFiles})
2863	foreach (_language ${_languages})
2864		get_property(_unityFiles TARGET ${_target} PROPERTY COTIRE_${_language}_UNITY_SOURCE)
2865		if (_unityFiles)
2866			# remove source files that are included in the unity source
2867			set (_sourceFiles "")
2868			set (_excludedSources "")
2869			set (_cotiredSources "")
2870			cotire_filter_language_source_files(${_language} ${_target} _sourceFiles _excludedSources _cotiredSources ${_targetSourceFiles})
2871			if (_sourceFiles OR _cotiredSources)
2872				list (REMOVE_ITEM _unityTargetSources ${_sourceFiles} ${_cotiredSources})
2873			endif()
2874			# add unity source files instead
2875			list (APPEND _unityTargetSources ${_unityFiles})
2876		endif()
2877	endforeach()
2878	set (${_unityTargetSourcesVar} ${_unityTargetSources} PARENT_SCOPE)
2879endfunction()
2880
2881function (cotire_setup_unity_target_pch_usage _languages _target)
2882	foreach (_language ${_languages})
2883		get_property(_unityFiles TARGET ${_target} PROPERTY COTIRE_${_language}_UNITY_SOURCE)
2884		if (_unityFiles)
2885			get_property(_userPrefixFile TARGET ${_target} PROPERTY COTIRE_${_language}_PREFIX_HEADER_INIT)
2886			get_property(_prefixFile TARGET ${_target} PROPERTY COTIRE_${_language}_PREFIX_HEADER)
2887			if (_userPrefixFile AND _prefixFile)
2888				# user provided prefix header must be included unconditionally by unity sources
2889				cotire_setup_prefix_file_inclusion(${_language} ${_target} "${_prefixFile}" ${_unityFiles})
2890			endif()
2891		endif()
2892	endforeach()
2893endfunction()
2894
2895function (cotire_setup_unity_build_target _languages _configurations _target)
2896	get_target_property(_unityTargetName ${_target} COTIRE_UNITY_TARGET_NAME)
2897	if (NOT _unityTargetName)
2898		set (_unityTargetName "${_target}${COTIRE_UNITY_BUILD_TARGET_SUFFIX}")
2899	endif()
2900	# determine unity target sub type
2901	get_target_property(_targetType ${_target} TYPE)
2902	if ("${_targetType}" STREQUAL "EXECUTABLE")
2903		set (_unityTargetSubType "")
2904	elseif (_targetType MATCHES "(STATIC|SHARED|MODULE|OBJECT)_LIBRARY")
2905		set (_unityTargetSubType "${CMAKE_MATCH_1}")
2906	else()
2907		message (WARNING "cotire: target ${_target} has unknown target type ${_targetType}.")
2908		return()
2909	endif()
2910	# determine unity target sources
2911	set (_unityTargetSources "")
2912	cotire_collect_unity_target_sources(${_target} "${_languages}" _unityTargetSources)
2913	# handle automatic Qt processing
2914	get_target_property(_targetAutoMoc ${_target} AUTOMOC)
2915	get_target_property(_targetAutoUic ${_target} AUTOUIC)
2916	get_target_property(_targetAutoRcc ${_target} AUTORCC)
2917	if (_targetAutoMoc OR _targetAutoUic OR _targetAutoRcc)
2918		# if the original target sources are subject to CMake's automatic Qt processing,
2919		# also include implicitly generated <targetname>_automoc.cpp file
2920		list (APPEND _unityTargetSources "${_target}_automoc.cpp")
2921		set_property (SOURCE "${_target}_automoc.cpp" PROPERTY GENERATED TRUE)
2922	endif()
2923	# prevent AUTOMOC, AUTOUIC and AUTORCC properties from being set when the unity target is created
2924	set (CMAKE_AUTOMOC OFF)
2925	set (CMAKE_AUTOUIC OFF)
2926	set (CMAKE_AUTORCC OFF)
2927	if (COTIRE_DEBUG)
2928		message (STATUS "add target ${_targetType} ${_unityTargetName} ${_unityTargetSubType} EXCLUDE_FROM_ALL ${_unityTargetSources}")
2929	endif()
2930	# generate unity target
2931	if ("${_targetType}" STREQUAL "EXECUTABLE")
2932		add_executable(${_unityTargetName} ${_unityTargetSubType} EXCLUDE_FROM_ALL ${_unityTargetSources})
2933	else()
2934		add_library(${_unityTargetName} ${_unityTargetSubType} EXCLUDE_FROM_ALL ${_unityTargetSources})
2935	endif()
2936	if (_targetAutoMoc OR _targetAutoUic OR _targetAutoRcc)
2937		# depend on the original target's implicity generated <targetname>_automoc target
2938		add_dependencies(${_unityTargetName} ${_target}_automoc)
2939	endif()
2940	# copy output location properties
2941	set (_outputDirProperties
2942		ARCHIVE_OUTPUT_DIRECTORY ARCHIVE_OUTPUT_DIRECTORY_<CONFIG>
2943		LIBRARY_OUTPUT_DIRECTORY LIBRARY_OUTPUT_DIRECTORY_<CONFIG>
2944		RUNTIME_OUTPUT_DIRECTORY RUNTIME_OUTPUT_DIRECTORY_<CONFIG>)
2945	if (COTIRE_UNITY_OUTPUT_DIRECTORY)
2946		set (_setDefaultOutputDir TRUE)
2947		if (IS_ABSOLUTE "${COTIRE_UNITY_OUTPUT_DIRECTORY}")
2948			set (_outputDir "${COTIRE_UNITY_OUTPUT_DIRECTORY}")
2949		else()
2950			# append relative COTIRE_UNITY_OUTPUT_DIRECTORY to target's actual output directory
2951			cotire_copy_set_properites("${_configurations}" TARGET ${_target} ${_unityTargetName} ${_outputDirProperties})
2952			cotire_resolve_config_properites("${_configurations}" _properties ${_outputDirProperties})
2953			foreach (_property ${_properties})
2954				get_property(_outputDir TARGET ${_target} PROPERTY ${_property})
2955				if (_outputDir)
2956					get_filename_component(_outputDir "${_outputDir}/${COTIRE_UNITY_OUTPUT_DIRECTORY}" ABSOLUTE)
2957					set_property(TARGET ${_unityTargetName} PROPERTY ${_property} "${_outputDir}")
2958					set (_setDefaultOutputDir FALSE)
2959				endif()
2960			endforeach()
2961			if (_setDefaultOutputDir)
2962				get_filename_component(_outputDir "${CMAKE_CURRENT_BINARY_DIR}/${COTIRE_UNITY_OUTPUT_DIRECTORY}" ABSOLUTE)
2963			endif()
2964		endif()
2965		if (_setDefaultOutputDir)
2966			set_target_properties(${_unityTargetName} PROPERTIES
2967				ARCHIVE_OUTPUT_DIRECTORY "${_outputDir}"
2968				LIBRARY_OUTPUT_DIRECTORY "${_outputDir}"
2969				RUNTIME_OUTPUT_DIRECTORY "${_outputDir}")
2970		endif()
2971	else()
2972		cotire_copy_set_properites("${_configurations}" TARGET ${_target} ${_unityTargetName}
2973			${_outputDirProperties})
2974	endif()
2975	# copy output name
2976	cotire_copy_set_properites("${_configurations}" TARGET ${_target} ${_unityTargetName}
2977		ARCHIVE_OUTPUT_NAME ARCHIVE_OUTPUT_NAME_<CONFIG>
2978		LIBRARY_OUTPUT_NAME LIBRARY_OUTPUT_NAME_<CONFIG>
2979		OUTPUT_NAME OUTPUT_NAME_<CONFIG>
2980		RUNTIME_OUTPUT_NAME RUNTIME_OUTPUT_NAME_<CONFIG>
2981		PREFIX <CONFIG>_POSTFIX SUFFIX
2982		IMPORT_PREFIX IMPORT_SUFFIX)
2983	# copy compile stuff
2984	cotire_copy_set_properites("${_configurations}" TARGET ${_target} ${_unityTargetName}
2985		COMPILE_DEFINITIONS COMPILE_DEFINITIONS_<CONFIG>
2986		COMPILE_FLAGS COMPILE_OPTIONS
2987		Fortran_FORMAT Fortran_MODULE_DIRECTORY
2988		INCLUDE_DIRECTORIES
2989		INTERPROCEDURAL_OPTIMIZATION INTERPROCEDURAL_OPTIMIZATION_<CONFIG>
2990		POSITION_INDEPENDENT_CODE
2991		C_COMPILER_LAUNCHER CXX_COMPILER_LAUNCHER
2992		C_INCLUDE_WHAT_YOU_USE CXX_INCLUDE_WHAT_YOU_USE
2993		C_VISIBILITY_PRESET CXX_VISIBILITY_PRESET VISIBILITY_INLINES_HIDDEN)
2994	# copy compile features
2995	cotire_copy_set_properites("${_configurations}" TARGET ${_target} ${_unityTargetName}
2996		C_EXTENSIONS C_STANDARD C_STANDARD_REQUIRED
2997		CXX_EXTENSIONS CXX_STANDARD CXX_STANDARD_REQUIRED
2998		COMPILE_FEATURES)
2999	# copy interface stuff
3000	cotire_copy_set_properites("${_configurations}" TARGET ${_target} ${_unityTargetName}
3001		COMPATIBLE_INTERFACE_BOOL COMPATIBLE_INTERFACE_NUMBER_MAX COMPATIBLE_INTERFACE_NUMBER_MIN
3002		COMPATIBLE_INTERFACE_STRING
3003		INTERFACE_COMPILE_DEFINITIONS INTERFACE_COMPILE_FEATURES INTERFACE_COMPILE_OPTIONS
3004		INTERFACE_INCLUDE_DIRECTORIES INTERFACE_SOURCES
3005		INTERFACE_POSITION_INDEPENDENT_CODE INTERFACE_SYSTEM_INCLUDE_DIRECTORIES
3006		INTERFACE_AUTOUIC_OPTIONS NO_SYSTEM_FROM_IMPORTED)
3007	# copy link stuff
3008	cotire_copy_set_properites("${_configurations}" TARGET ${_target} ${_unityTargetName}
3009		BUILD_WITH_INSTALL_RPATH INSTALL_RPATH INSTALL_RPATH_USE_LINK_PATH SKIP_BUILD_RPATH
3010		LINKER_LANGUAGE LINK_DEPENDS LINK_DEPENDS_NO_SHARED
3011		LINK_FLAGS LINK_FLAGS_<CONFIG>
3012		LINK_INTERFACE_LIBRARIES LINK_INTERFACE_LIBRARIES_<CONFIG>
3013		LINK_INTERFACE_MULTIPLICITY LINK_INTERFACE_MULTIPLICITY_<CONFIG>
3014		LINK_SEARCH_START_STATIC LINK_SEARCH_END_STATIC
3015		STATIC_LIBRARY_FLAGS STATIC_LIBRARY_FLAGS_<CONFIG>
3016		NO_SONAME SOVERSION VERSION)
3017	# copy cmake stuff
3018	cotire_copy_set_properites("${_configurations}" TARGET ${_target} ${_unityTargetName}
3019		IMPLICIT_DEPENDS_INCLUDE_TRANSFORM RULE_LAUNCH_COMPILE RULE_LAUNCH_CUSTOM RULE_LAUNCH_LINK)
3020	# copy Apple platform specific stuff
3021	cotire_copy_set_properites("${_configurations}" TARGET ${_target} ${_unityTargetName}
3022		BUNDLE BUNDLE_EXTENSION FRAMEWORK FRAMEWORK_VERSION INSTALL_NAME_DIR
3023		MACOSX_BUNDLE MACOSX_BUNDLE_INFO_PLIST MACOSX_FRAMEWORK_INFO_PLIST MACOSX_RPATH
3024		OSX_ARCHITECTURES OSX_ARCHITECTURES_<CONFIG> PRIVATE_HEADER PUBLIC_HEADER RESOURCE XCTEST
3025		IOS_INSTALL_COMBINED)
3026	# copy Windows platform specific stuff
3027	cotire_copy_set_properites("${_configurations}" TARGET ${_target} ${_unityTargetName}
3028		GNUtoMS
3029		COMPILE_PDB_NAME COMPILE_PDB_NAME_<CONFIG>
3030		COMPILE_PDB_OUTPUT_DIRECTORY COMPILE_PDB_OUTPUT_DIRECTORY_<CONFIG>
3031		PDB_NAME PDB_NAME_<CONFIG> PDB_OUTPUT_DIRECTORY PDB_OUTPUT_DIRECTORY_<CONFIG>
3032		VS_DESKTOP_EXTENSIONS_VERSION VS_DOTNET_REFERENCES VS_DOTNET_TARGET_FRAMEWORK_VERSION
3033		VS_GLOBAL_KEYWORD VS_GLOBAL_PROJECT_TYPES VS_GLOBAL_ROOTNAMESPACE
3034		VS_IOT_EXTENSIONS_VERSION VS_IOT_STARTUP_TASK
3035		VS_KEYWORD VS_MOBILE_EXTENSIONS_VERSION
3036		VS_SCC_AUXPATH VS_SCC_LOCALPATH VS_SCC_PROJECTNAME VS_SCC_PROVIDER
3037		VS_WINDOWS_TARGET_PLATFORM_MIN_VERSION
3038		VS_WINRT_COMPONENT VS_WINRT_EXTENSIONS VS_WINRT_REFERENCES
3039		WIN32_EXECUTABLE WINDOWS_EXPORT_ALL_SYMBOLS)
3040	# copy Android platform specific stuff
3041	cotire_copy_set_properites("${_configurations}" TARGET ${_target} ${_unityTargetName}
3042		ANDROID_API ANDROID_API_MIN ANDROID_GUI
3043		ANDROID_ANT_ADDITIONAL_OPTIONS ANDROID_ARCH ANDROID_ASSETS_DIRECTORIES
3044		ANDROID_JAR_DEPENDENCIES ANDROID_JAR_DIRECTORIES ANDROID_JAVA_SOURCE_DIR
3045		ANDROID_NATIVE_LIB_DEPENDENCIES ANDROID_NATIVE_LIB_DIRECTORIES
3046		ANDROID_PROCESS_MAX ANDROID_PROGUARD ANDROID_PROGUARD_CONFIG_PATH
3047		ANDROID_SECURE_PROPS_PATH ANDROID_SKIP_ANT_STEP ANDROID_STL_TYPE)
3048	# use output name from original target
3049	get_target_property(_targetOutputName ${_unityTargetName} OUTPUT_NAME)
3050	if (NOT _targetOutputName)
3051		set_property(TARGET ${_unityTargetName} PROPERTY OUTPUT_NAME "${_target}")
3052	endif()
3053	# use export symbol from original target
3054	cotire_get_target_export_symbol("${_target}" _defineSymbol)
3055	if (_defineSymbol)
3056		set_property(TARGET ${_unityTargetName} PROPERTY DEFINE_SYMBOL "${_defineSymbol}")
3057		if ("${_targetType}" STREQUAL "EXECUTABLE")
3058			set_property(TARGET ${_unityTargetName} PROPERTY ENABLE_EXPORTS TRUE)
3059		endif()
3060	endif()
3061	cotire_init_target(${_unityTargetName})
3062	cotire_add_to_unity_all_target(${_unityTargetName})
3063	set_property(TARGET ${_target} PROPERTY COTIRE_UNITY_TARGET_NAME "${_unityTargetName}")
3064endfunction(cotire_setup_unity_build_target)
3065
3066function (cotire_target _target)
3067	set(_options "")
3068	set(_oneValueArgs "")
3069	set(_multiValueArgs LANGUAGES CONFIGURATIONS)
3070	cmake_parse_arguments(_option "${_options}" "${_oneValueArgs}" "${_multiValueArgs}" ${ARGN})
3071	if (NOT _option_LANGUAGES)
3072		get_property (_option_LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES)
3073	endif()
3074	if (NOT _option_CONFIGURATIONS)
3075		cotire_get_configuration_types(_option_CONFIGURATIONS)
3076	endif()
3077	# check if cotire can be applied to target at all
3078	cotire_is_target_supported(${_target} _isSupported)
3079	if (NOT _isSupported)
3080		get_target_property(_imported ${_target} IMPORTED)
3081		get_target_property(_targetType ${_target} TYPE)
3082		if (_imported)
3083			message (WARNING "cotire: imported ${_targetType} target ${_target} cannot be cotired.")
3084		else()
3085			message (STATUS "cotire: ${_targetType} target ${_target} cannot be cotired.")
3086		endif()
3087		return()
3088	endif()
3089	# resolve alias
3090	get_target_property(_aliasName ${_target} ALIASED_TARGET)
3091	if (_aliasName)
3092		if (COTIRE_DEBUG)
3093			message (STATUS "${_target} is an alias. Applying cotire to aliased target ${_aliasName} instead.")
3094		endif()
3095		set (_target ${_aliasName})
3096	endif()
3097	# check if target needs to be cotired for build type
3098	# when using configuration types, the test is performed at build time
3099	cotire_init_cotire_target_properties(${_target})
3100	if (NOT CMAKE_CONFIGURATION_TYPES)
3101		if (CMAKE_BUILD_TYPE)
3102			list (FIND _option_CONFIGURATIONS "${CMAKE_BUILD_TYPE}" _index)
3103		else()
3104			list (FIND _option_CONFIGURATIONS "None" _index)
3105		endif()
3106		if (_index EQUAL -1)
3107			if (COTIRE_DEBUG)
3108				message (STATUS "CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} not cotired (${_option_CONFIGURATIONS})")
3109			endif()
3110			return()
3111		endif()
3112	endif()
3113	# when not using configuration types, immediately create cotire intermediate dir
3114	if (NOT CMAKE_CONFIGURATION_TYPES)
3115		cotire_get_intermediate_dir(_baseDir)
3116		file (MAKE_DIRECTORY "${_baseDir}")
3117	endif()
3118	# choose languages that apply to the target
3119	cotire_choose_target_languages("${_target}" _targetLanguages _wholeTarget ${_option_LANGUAGES})
3120	if (NOT _targetLanguages)
3121		return()
3122	endif()
3123	set (_cmds "")
3124	foreach (_language ${_targetLanguages})
3125		cotire_process_target_language("${_language}" "${_option_CONFIGURATIONS}" ${_target} ${_wholeTarget} _cmd)
3126		if (_cmd)
3127			list (APPEND _cmds ${_cmd})
3128		endif()
3129	endforeach()
3130	get_target_property(_targetAddSCU ${_target} COTIRE_ADD_UNITY_BUILD)
3131	if (_targetAddSCU)
3132		cotire_setup_unity_build_target("${_targetLanguages}" "${_option_CONFIGURATIONS}" ${_target})
3133	endif()
3134	get_target_property(_targetUsePCH ${_target} COTIRE_ENABLE_PRECOMPILED_HEADER)
3135	if (_targetUsePCH)
3136		cotire_setup_target_pch_usage("${_targetLanguages}" ${_target} ${_wholeTarget} ${_cmds})
3137		cotire_setup_pch_target("${_targetLanguages}" "${_option_CONFIGURATIONS}" ${_target})
3138		if (_targetAddSCU)
3139			cotire_setup_unity_target_pch_usage("${_targetLanguages}" ${_target})
3140		endif()
3141	endif()
3142	get_target_property(_targetAddCleanTarget ${_target} COTIRE_ADD_CLEAN)
3143	if (_targetAddCleanTarget)
3144		cotire_setup_clean_target(${_target})
3145	endif()
3146endfunction(cotire_target)
3147
3148function (cotire_map_libraries _strategy _mappedLibrariesVar)
3149	set (_mappedLibraries "")
3150	foreach (_library ${ARGN})
3151		if (_library MATCHES "^\\$<LINK_ONLY:(.+)>$")
3152			set (_libraryName "${CMAKE_MATCH_1}")
3153			set (_linkOnly TRUE)
3154		else()
3155			set (_libraryName "${_library}")
3156			set (_linkOnly FALSE)
3157		endif()
3158		if ("${_strategy}" MATCHES "COPY_UNITY")
3159			cotire_is_target_supported(${_libraryName} _isSupported)
3160			if (_isSupported)
3161				# use target's corresponding unity target, if available
3162				get_target_property(_libraryUnityTargetName ${_libraryName} COTIRE_UNITY_TARGET_NAME)
3163				if (TARGET "${_libraryUnityTargetName}")
3164					if (_linkOnly)
3165						list (APPEND _mappedLibraries "$<LINK_ONLY:${_libraryUnityTargetName}>")
3166					else()
3167						list (APPEND _mappedLibraries "${_libraryUnityTargetName}")
3168					endif()
3169				else()
3170					list (APPEND _mappedLibraries "${_library}")
3171				endif()
3172			else()
3173				list (APPEND _mappedLibraries "${_library}")
3174			endif()
3175		else()
3176			list (APPEND _mappedLibraries "${_library}")
3177		endif()
3178	endforeach()
3179	list (REMOVE_DUPLICATES _mappedLibraries)
3180	set (${_mappedLibrariesVar} ${_mappedLibraries} PARENT_SCOPE)
3181endfunction()
3182
3183function (cotire_target_link_libraries _target)
3184	cotire_is_target_supported(${_target} _isSupported)
3185	if (NOT _isSupported)
3186		return()
3187	endif()
3188	get_target_property(_unityTargetName ${_target} COTIRE_UNITY_TARGET_NAME)
3189	if (TARGET "${_unityTargetName}")
3190		get_target_property(_linkLibrariesStrategy ${_target} COTIRE_UNITY_LINK_LIBRARIES_INIT)
3191		if (COTIRE_DEBUG)
3192			message (STATUS "unity target ${_unityTargetName} link strategy: ${_linkLibrariesStrategy}")
3193		endif()
3194		if ("${_linkLibrariesStrategy}" MATCHES "^(COPY|COPY_UNITY)$")
3195			get_target_property(_linkLibraries ${_target} LINK_LIBRARIES)
3196			if (_linkLibraries)
3197				cotire_map_libraries("${_linkLibrariesStrategy}" _unityLinkLibraries ${_linkLibraries})
3198				set_target_properties(${_unityTargetName} PROPERTIES LINK_LIBRARIES "${_unityLinkLibraries}")
3199				if (COTIRE_DEBUG)
3200					message (STATUS "unity target ${_unityTargetName} link libraries: ${_unityLinkLibraries}")
3201				endif()
3202			endif()
3203			get_target_property(_interfaceLinkLibraries ${_target} INTERFACE_LINK_LIBRARIES)
3204			if (_interfaceLinkLibraries)
3205				cotire_map_libraries("${_linkLibrariesStrategy}" _unityLinkInterfaceLibraries ${_interfaceLinkLibraries})
3206				set_target_properties(${_unityTargetName} PROPERTIES INTERFACE_LINK_LIBRARIES "${_unityLinkInterfaceLibraries}")
3207				if (COTIRE_DEBUG)
3208					message (STATUS "unity target ${_unityTargetName} interface link libraries: ${_unityLinkInterfaceLibraries}")
3209				endif()
3210			endif()
3211		endif()
3212	endif()
3213endfunction(cotire_target_link_libraries)
3214
3215function (cotire_cleanup _binaryDir _cotireIntermediateDirName _targetName)
3216	if (_targetName)
3217		file (GLOB_RECURSE _cotireFiles "${_binaryDir}/${_targetName}*.*")
3218	else()
3219		file (GLOB_RECURSE _cotireFiles "${_binaryDir}/*.*")
3220	endif()
3221	# filter files in intermediate directory
3222	set (_filesToRemove "")
3223	foreach (_file ${_cotireFiles})
3224		get_filename_component(_dir "${_file}" DIRECTORY)
3225		get_filename_component(_dirName "${_dir}" NAME)
3226		if ("${_dirName}" STREQUAL "${_cotireIntermediateDirName}")
3227			list (APPEND _filesToRemove "${_file}")
3228		endif()
3229	endforeach()
3230	if (_filesToRemove)
3231		if (COTIRE_VERBOSE)
3232			message (STATUS "cleaning up ${_filesToRemove}")
3233		endif()
3234		file (REMOVE ${_filesToRemove})
3235	endif()
3236endfunction()
3237
3238function (cotire_init_target _targetName)
3239	if (COTIRE_TARGETS_FOLDER)
3240		set_target_properties(${_targetName} PROPERTIES FOLDER "${COTIRE_TARGETS_FOLDER}")
3241	endif()
3242	set_target_properties(${_targetName} PROPERTIES EXCLUDE_FROM_ALL TRUE)
3243	if (MSVC_IDE)
3244		set_target_properties(${_targetName} PROPERTIES EXCLUDE_FROM_DEFAULT_BUILD TRUE)
3245	endif()
3246endfunction()
3247
3248function (cotire_add_to_pch_all_target _pchTargetName)
3249	set (_targetName "${COTIRE_PCH_ALL_TARGET_NAME}")
3250	if (NOT TARGET "${_targetName}")
3251		add_custom_target("${_targetName}"
3252			WORKING_DIRECTORY "${CMAKE_BINARY_DIR}"
3253			VERBATIM)
3254		cotire_init_target("${_targetName}")
3255	endif()
3256	cotire_setup_clean_all_target()
3257	add_dependencies(${_targetName} ${_pchTargetName})
3258endfunction()
3259
3260function (cotire_add_to_unity_all_target _unityTargetName)
3261	set (_targetName "${COTIRE_UNITY_BUILD_ALL_TARGET_NAME}")
3262	if (NOT TARGET "${_targetName}")
3263		add_custom_target("${_targetName}"
3264			WORKING_DIRECTORY "${CMAKE_BINARY_DIR}"
3265			VERBATIM)
3266		cotire_init_target("${_targetName}")
3267	endif()
3268	cotire_setup_clean_all_target()
3269	add_dependencies(${_targetName} ${_unityTargetName})
3270endfunction()
3271
3272function (cotire_setup_clean_all_target)
3273	set (_targetName "${COTIRE_CLEAN_ALL_TARGET_NAME}")
3274	if (NOT TARGET "${_targetName}")
3275		cotire_set_cmd_to_prologue(_cmds)
3276		list (APPEND _cmds -P "${COTIRE_CMAKE_MODULE_FILE}" "cleanup" "${CMAKE_BINARY_DIR}" "${COTIRE_INTDIR}")
3277		add_custom_target(${_targetName}
3278			COMMAND ${_cmds}
3279			WORKING_DIRECTORY "${CMAKE_BINARY_DIR}"
3280			COMMENT "Cleaning up all cotire generated files"
3281			VERBATIM)
3282		cotire_init_target("${_targetName}")
3283	endif()
3284endfunction()
3285
3286function (cotire)
3287	set(_options "")
3288	set(_oneValueArgs "")
3289	set(_multiValueArgs LANGUAGES CONFIGURATIONS)
3290	cmake_parse_arguments(_option "${_options}" "${_oneValueArgs}" "${_multiValueArgs}" ${ARGN})
3291	set (_targets ${_option_UNPARSED_ARGUMENTS})
3292	foreach (_target ${_targets})
3293		if (TARGET ${_target})
3294			cotire_target(${_target} LANGUAGES ${_option_LANGUAGES} CONFIGURATIONS ${_option_CONFIGURATIONS})
3295		else()
3296			message (WARNING "cotire: ${_target} is not a target.")
3297		endif()
3298	endforeach()
3299	foreach (_target ${_targets})
3300		if (TARGET ${_target})
3301			cotire_target_link_libraries(${_target})
3302		endif()
3303	endforeach()
3304endfunction()
3305
3306if (CMAKE_SCRIPT_MODE_FILE)
3307
3308	# cotire is being run in script mode
3309	# locate -P on command args
3310	set (COTIRE_ARGC -1)
3311	foreach (_index RANGE ${CMAKE_ARGC})
3312		if (COTIRE_ARGC GREATER -1)
3313			set (COTIRE_ARGV${COTIRE_ARGC} "${CMAKE_ARGV${_index}}")
3314			math (EXPR COTIRE_ARGC "${COTIRE_ARGC} + 1")
3315		elseif ("${CMAKE_ARGV${_index}}" STREQUAL "-P")
3316			set (COTIRE_ARGC 0)
3317		endif()
3318	endforeach()
3319
3320	# include target script if available
3321	if ("${COTIRE_ARGV2}" MATCHES "\\.cmake$")
3322		# the included target scripts sets up additional variables relating to the target (e.g., COTIRE_TARGET_SOURCES)
3323		include("${COTIRE_ARGV2}")
3324	endif()
3325
3326	if (COTIRE_DEBUG)
3327		message (STATUS "${COTIRE_ARGV0} ${COTIRE_ARGV1} ${COTIRE_ARGV2} ${COTIRE_ARGV3} ${COTIRE_ARGV4} ${COTIRE_ARGV5}")
3328	endif()
3329
3330	if (NOT COTIRE_BUILD_TYPE)
3331		set (COTIRE_BUILD_TYPE "None")
3332	endif()
3333	string (TOUPPER "${COTIRE_BUILD_TYPE}" _upperConfig)
3334	set (_includeDirs ${COTIRE_TARGET_INCLUDE_DIRECTORIES_${_upperConfig}})
3335	set (_systemIncludeDirs ${COTIRE_TARGET_SYSTEM_INCLUDE_DIRECTORIES_${_upperConfig}})
3336	set (_compileDefinitions ${COTIRE_TARGET_COMPILE_DEFINITIONS_${_upperConfig}})
3337	set (_compileFlags ${COTIRE_TARGET_COMPILE_FLAGS_${_upperConfig}})
3338	# check if target has been cotired for actual build type COTIRE_BUILD_TYPE
3339	list (FIND COTIRE_TARGET_CONFIGURATION_TYPES "${COTIRE_BUILD_TYPE}" _index)
3340	if (_index GREATER -1)
3341		set (_sources ${COTIRE_TARGET_SOURCES})
3342		set (_sourcesDefinitions ${COTIRE_TARGET_SOURCES_COMPILE_DEFINITIONS_${_upperConfig}})
3343	else()
3344		if (COTIRE_DEBUG)
3345			message (STATUS "COTIRE_BUILD_TYPE=${COTIRE_BUILD_TYPE} not cotired (${COTIRE_TARGET_CONFIGURATION_TYPES})")
3346		endif()
3347		set (_sources "")
3348		set (_sourcesDefinitions "")
3349	endif()
3350	set (_targetPreUndefs ${COTIRE_TARGET_PRE_UNDEFS})
3351	set (_targetPostUndefs ${COTIRE_TARGET_POST_UNDEFS})
3352	set (_sourcesPreUndefs ${COTIRE_TARGET_SOURCES_PRE_UNDEFS})
3353	set (_sourcesPostUndefs ${COTIRE_TARGET_SOURCES_POST_UNDEFS})
3354
3355	if ("${COTIRE_ARGV1}" STREQUAL "unity")
3356
3357		if (XCODE)
3358			# executing pre-build action under Xcode, check dependency on target script
3359			set (_dependsOption DEPENDS "${COTIRE_ARGV2}")
3360		else()
3361			# executing custom command, no need to re-check for dependencies
3362			set (_dependsOption "")
3363		endif()
3364
3365		cotire_select_unity_source_files("${COTIRE_ARGV3}" _sources ${_sources})
3366
3367		cotire_generate_unity_source(
3368			"${COTIRE_ARGV3}" ${_sources}
3369			LANGUAGE "${COTIRE_TARGET_LANGUAGE}"
3370			SOURCES_COMPILE_DEFINITIONS ${_sourcesDefinitions}
3371			PRE_UNDEFS ${_targetPreUndefs}
3372			POST_UNDEFS ${_targetPostUndefs}
3373			SOURCES_PRE_UNDEFS ${_sourcesPreUndefs}
3374			SOURCES_POST_UNDEFS ${_sourcesPostUndefs}
3375			${_dependsOption})
3376
3377	elseif ("${COTIRE_ARGV1}" STREQUAL "prefix")
3378
3379		if (XCODE)
3380			# executing pre-build action under Xcode, check dependency on unity file and prefix dependencies
3381			set (_dependsOption DEPENDS "${COTIRE_ARGV4}" ${COTIRE_TARGET_PREFIX_DEPENDS})
3382		else()
3383			# executing custom command, no need to re-check for dependencies
3384			set (_dependsOption "")
3385		endif()
3386
3387		set (_files "")
3388		foreach (_index RANGE 4 ${COTIRE_ARGC})
3389			if (COTIRE_ARGV${_index})
3390				list (APPEND _files "${COTIRE_ARGV${_index}}")
3391			endif()
3392		endforeach()
3393
3394		cotire_generate_prefix_header(
3395			"${COTIRE_ARGV3}" ${_files}
3396			COMPILER_LAUNCHER "${COTIRE_TARGET_${COTIRE_TARGET_LANGUAGE}_COMPILER_LAUNCHER}"
3397			COMPILER_EXECUTABLE "${CMAKE_${COTIRE_TARGET_LANGUAGE}_COMPILER}"
3398			COMPILER_ARG1 ${CMAKE_${COTIRE_TARGET_LANGUAGE}_COMPILER_ARG1}
3399			COMPILER_ID "${CMAKE_${COTIRE_TARGET_LANGUAGE}_COMPILER_ID}"
3400			COMPILER_VERSION "${CMAKE_${COTIRE_TARGET_LANGUAGE}_COMPILER_VERSION}"
3401			LANGUAGE "${COTIRE_TARGET_LANGUAGE}"
3402			IGNORE_PATH "${COTIRE_TARGET_IGNORE_PATH};${COTIRE_ADDITIONAL_PREFIX_HEADER_IGNORE_PATH}"
3403			INCLUDE_PATH ${COTIRE_TARGET_INCLUDE_PATH}
3404			IGNORE_EXTENSIONS "${CMAKE_${COTIRE_TARGET_LANGUAGE}_SOURCE_FILE_EXTENSIONS};${COTIRE_ADDITIONAL_PREFIX_HEADER_IGNORE_EXTENSIONS}"
3405			INCLUDE_PRIORITY_PATH ${COTIRE_TARGET_INCLUDE_PRIORITY_PATH}
3406			INCLUDE_DIRECTORIES ${_includeDirs}
3407			SYSTEM_INCLUDE_DIRECTORIES ${_systemIncludeDirs}
3408			COMPILE_DEFINITIONS ${_compileDefinitions}
3409			COMPILE_FLAGS ${_compileFlags}
3410			${_dependsOption})
3411
3412	elseif ("${COTIRE_ARGV1}" STREQUAL "precompile")
3413
3414		set (_files "")
3415		foreach (_index RANGE 5 ${COTIRE_ARGC})
3416			if (COTIRE_ARGV${_index})
3417				list (APPEND _files "${COTIRE_ARGV${_index}}")
3418			endif()
3419		endforeach()
3420
3421		cotire_precompile_prefix_header(
3422			"${COTIRE_ARGV3}" "${COTIRE_ARGV4}" "${COTIRE_ARGV5}"
3423			COMPILER_LAUNCHER "${COTIRE_TARGET_${COTIRE_TARGET_LANGUAGE}_COMPILER_LAUNCHER}"
3424			COMPILER_EXECUTABLE "${CMAKE_${COTIRE_TARGET_LANGUAGE}_COMPILER}"
3425			COMPILER_ARG1 ${CMAKE_${COTIRE_TARGET_LANGUAGE}_COMPILER_ARG1}
3426			COMPILER_ID "${CMAKE_${COTIRE_TARGET_LANGUAGE}_COMPILER_ID}"
3427			COMPILER_VERSION "${CMAKE_${COTIRE_TARGET_LANGUAGE}_COMPILER_VERSION}"
3428			LANGUAGE "${COTIRE_TARGET_LANGUAGE}"
3429			INCLUDE_DIRECTORIES ${_includeDirs}
3430			SYSTEM_INCLUDE_DIRECTORIES ${_systemIncludeDirs}
3431			COMPILE_DEFINITIONS ${_compileDefinitions}
3432			COMPILE_FLAGS ${_compileFlags})
3433
3434	elseif ("${COTIRE_ARGV1}" STREQUAL "combine")
3435
3436		if (COTIRE_TARGET_LANGUAGE)
3437			set (_combinedFile "${COTIRE_ARGV3}")
3438			set (_startIndex 4)
3439		else()
3440			set (_combinedFile "${COTIRE_ARGV2}")
3441			set (_startIndex 3)
3442		endif()
3443		set (_files "")
3444		foreach (_index RANGE ${_startIndex} ${COTIRE_ARGC})
3445			if (COTIRE_ARGV${_index})
3446				list (APPEND _files "${COTIRE_ARGV${_index}}")
3447			endif()
3448		endforeach()
3449
3450		if (XCODE)
3451			# executing pre-build action under Xcode, check dependency on files to be combined
3452			set (_dependsOption DEPENDS ${_files})
3453		else()
3454			# executing custom command, no need to re-check for dependencies
3455			set (_dependsOption "")
3456		endif()
3457
3458		if (COTIRE_TARGET_LANGUAGE)
3459			cotire_generate_unity_source(
3460				"${_combinedFile}" ${_files}
3461				LANGUAGE "${COTIRE_TARGET_LANGUAGE}"
3462				${_dependsOption})
3463		else()
3464			cotire_generate_unity_source("${_combinedFile}" ${_files} ${_dependsOption})
3465		endif()
3466
3467	elseif ("${COTIRE_ARGV1}" STREQUAL "cleanup")
3468
3469		cotire_cleanup("${COTIRE_ARGV2}" "${COTIRE_ARGV3}" "${COTIRE_ARGV4}")
3470
3471	else()
3472		message (FATAL_ERROR "cotire: unknown command \"${COTIRE_ARGV1}\".")
3473	endif()
3474
3475else()
3476
3477	# cotire is being run in include mode
3478	# set up all variable and property definitions
3479
3480	if (NOT DEFINED COTIRE_DEBUG_INIT)
3481		if (DEFINED COTIRE_DEBUG)
3482			set (COTIRE_DEBUG_INIT ${COTIRE_DEBUG})
3483		else()
3484			set (COTIRE_DEBUG_INIT FALSE)
3485		endif()
3486	endif()
3487	option (COTIRE_DEBUG "Enable cotire debugging output?" ${COTIRE_DEBUG_INIT})
3488
3489	if (NOT DEFINED COTIRE_VERBOSE_INIT)
3490		if (DEFINED COTIRE_VERBOSE)
3491			set (COTIRE_VERBOSE_INIT ${COTIRE_VERBOSE})
3492		else()
3493			set (COTIRE_VERBOSE_INIT FALSE)
3494		endif()
3495	endif()
3496	option (COTIRE_VERBOSE "Enable cotire verbose output?" ${COTIRE_VERBOSE_INIT})
3497
3498	set (COTIRE_ADDITIONAL_PREFIX_HEADER_IGNORE_EXTENSIONS "inc;inl;ipp" CACHE STRING
3499		"Ignore headers with the listed file extensions from the generated prefix header.")
3500
3501	set (COTIRE_ADDITIONAL_PREFIX_HEADER_IGNORE_PATH "" CACHE STRING
3502		"Ignore headers from these directories when generating the prefix header.")
3503
3504	set (COTIRE_UNITY_SOURCE_EXCLUDE_EXTENSIONS "m;mm" CACHE STRING
3505		"Ignore sources with the listed file extensions from the generated unity source.")
3506
3507	set (COTIRE_MINIMUM_NUMBER_OF_TARGET_SOURCES "3" CACHE STRING
3508		"Minimum number of sources in target required to enable use of precompiled header.")
3509
3510	if (NOT DEFINED COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES_INIT)
3511		if (DEFINED COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES)
3512			set (COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES_INIT ${COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES})
3513		elseif ("${CMAKE_GENERATOR}" MATCHES "JOM|Ninja|Visual Studio")
3514			# enable parallelization for generators that run multiple jobs by default
3515			set (COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES_INIT "-j")
3516		else()
3517			set (COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES_INIT "0")
3518		endif()
3519	endif()
3520	set (COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES "${COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES_INIT}" CACHE STRING
3521		"Maximum number of source files to include in a single unity source file.")
3522
3523	if (NOT COTIRE_PREFIX_HEADER_FILENAME_SUFFIX)
3524		set (COTIRE_PREFIX_HEADER_FILENAME_SUFFIX "_prefix")
3525	endif()
3526	if (NOT COTIRE_UNITY_SOURCE_FILENAME_SUFFIX)
3527		set (COTIRE_UNITY_SOURCE_FILENAME_SUFFIX "_unity")
3528	endif()
3529	if (NOT COTIRE_INTDIR)
3530		set (COTIRE_INTDIR "cotire")
3531	endif()
3532	if (NOT COTIRE_PCH_ALL_TARGET_NAME)
3533		set (COTIRE_PCH_ALL_TARGET_NAME "all_pch")
3534	endif()
3535	if (NOT COTIRE_UNITY_BUILD_ALL_TARGET_NAME)
3536		set (COTIRE_UNITY_BUILD_ALL_TARGET_NAME "all_unity")
3537	endif()
3538	if (NOT COTIRE_CLEAN_ALL_TARGET_NAME)
3539		set (COTIRE_CLEAN_ALL_TARGET_NAME "clean_cotire")
3540	endif()
3541	if (NOT COTIRE_CLEAN_TARGET_SUFFIX)
3542		set (COTIRE_CLEAN_TARGET_SUFFIX "_clean_cotire")
3543	endif()
3544	if (NOT COTIRE_PCH_TARGET_SUFFIX)
3545		set (COTIRE_PCH_TARGET_SUFFIX "_pch")
3546	endif()
3547	if (MSVC)
3548		# MSVC default PCH memory scaling factor of 100 percent (75 MB) is too small for template heavy C++ code
3549		# use a bigger default factor of 170 percent (128 MB)
3550		if (NOT DEFINED COTIRE_PCH_MEMORY_SCALING_FACTOR)
3551			set (COTIRE_PCH_MEMORY_SCALING_FACTOR "170")
3552		endif()
3553	endif()
3554	if (NOT COTIRE_UNITY_BUILD_TARGET_SUFFIX)
3555		set (COTIRE_UNITY_BUILD_TARGET_SUFFIX "_unity")
3556	endif()
3557	if (NOT DEFINED COTIRE_TARGETS_FOLDER)
3558		set (COTIRE_TARGETS_FOLDER "cotire")
3559	endif()
3560	if (NOT DEFINED COTIRE_UNITY_OUTPUT_DIRECTORY)
3561		if ("${CMAKE_GENERATOR}" MATCHES "Ninja")
3562			# generated Ninja build files do not work if the unity target produces the same output file as the cotired target
3563			set (COTIRE_UNITY_OUTPUT_DIRECTORY "unity")
3564		else()
3565			set (COTIRE_UNITY_OUTPUT_DIRECTORY "")
3566		endif()
3567	endif()
3568
3569	# define cotire cache variables
3570
3571	define_property(
3572		CACHED_VARIABLE PROPERTY "COTIRE_ADDITIONAL_PREFIX_HEADER_IGNORE_PATH"
3573		BRIEF_DOCS "Ignore headers from these directories when generating the prefix header."
3574		FULL_DOCS
3575			"The variable can be set to a semicolon separated list of include directories."
3576			"If a header file is found in one of these directories or sub-directories, it will be excluded from the generated prefix header."
3577			"If not defined, defaults to empty list."
3578	)
3579
3580	define_property(
3581		CACHED_VARIABLE PROPERTY "COTIRE_ADDITIONAL_PREFIX_HEADER_IGNORE_EXTENSIONS"
3582		BRIEF_DOCS "Ignore includes with the listed file extensions from the generated prefix header."
3583		FULL_DOCS
3584			"The variable can be set to a semicolon separated list of file extensions."
3585			"If a header file extension matches one in the list, it will be excluded from the generated prefix header."
3586			"Includes with an extension in CMAKE_<LANG>_SOURCE_FILE_EXTENSIONS are always ignored."
3587			"If not defined, defaults to inc;inl;ipp."
3588	)
3589
3590	define_property(
3591		CACHED_VARIABLE PROPERTY "COTIRE_UNITY_SOURCE_EXCLUDE_EXTENSIONS"
3592		BRIEF_DOCS "Exclude sources with the listed file extensions from the generated unity source."
3593		FULL_DOCS
3594			"The variable can be set to a semicolon separated list of file extensions."
3595			"If a source file extension matches one in the list, it will be excluded from the generated unity source file."
3596			"Source files with an extension in CMAKE_<LANG>_IGNORE_EXTENSIONS are always excluded."
3597			"If not defined, defaults to m;mm."
3598	)
3599
3600	define_property(
3601		CACHED_VARIABLE PROPERTY "COTIRE_MINIMUM_NUMBER_OF_TARGET_SOURCES"
3602		BRIEF_DOCS "Minimum number of sources in target required to enable use of precompiled header."
3603		FULL_DOCS
3604			"The variable can be set to an integer > 0."
3605			"If a target contains less than that number of source files, cotire will not enable the use of the precompiled header for the target."
3606			"If not defined, defaults to 3."
3607	)
3608
3609	define_property(
3610		CACHED_VARIABLE PROPERTY "COTIRE_MAXIMUM_NUMBER_OF_UNITY_INCLUDES"
3611		BRIEF_DOCS "Maximum number of source files to include in a single unity source file."
3612		FULL_DOCS
3613			"This may be set to an integer >= 0."
3614			"If 0, cotire will only create a single unity source file."
3615			"If a target contains more than that number of source files, cotire will create multiple unity source files for it."
3616			"Can be set to \"-j\" to optimize the count of unity source files for the number of available processor cores."
3617			"Can be set to \"-j jobs\" to optimize the number of unity source files for the given number of simultaneous jobs."
3618			"Is used to initialize the target property COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES."
3619			"Defaults to \"-j\" for the generators Visual Studio, JOM or Ninja. Defaults to 0 otherwise."
3620	)
3621
3622	# define cotire directory properties
3623
3624	define_property(
3625		DIRECTORY PROPERTY "COTIRE_ENABLE_PRECOMPILED_HEADER"
3626		BRIEF_DOCS "Modify build command of cotired targets added in this directory to make use of the generated precompiled header."
3627		FULL_DOCS
3628			"See target property COTIRE_ENABLE_PRECOMPILED_HEADER."
3629	)
3630
3631	define_property(
3632		DIRECTORY PROPERTY "COTIRE_ADD_UNITY_BUILD"
3633		BRIEF_DOCS "Add a new target that performs a unity build for cotired targets added in this directory."
3634		FULL_DOCS
3635			"See target property COTIRE_ADD_UNITY_BUILD."
3636	)
3637
3638	define_property(
3639		DIRECTORY PROPERTY "COTIRE_ADD_CLEAN"
3640		BRIEF_DOCS "Add a new target that cleans all cotire generated files for cotired targets added in this directory."
3641		FULL_DOCS
3642			"See target property COTIRE_ADD_CLEAN."
3643	)
3644
3645	define_property(
3646		DIRECTORY PROPERTY "COTIRE_PREFIX_HEADER_IGNORE_PATH"
3647		BRIEF_DOCS "Ignore headers from these directories when generating the prefix header."
3648		FULL_DOCS
3649			"See target property COTIRE_PREFIX_HEADER_IGNORE_PATH."
3650	)
3651
3652	define_property(
3653		DIRECTORY PROPERTY "COTIRE_PREFIX_HEADER_INCLUDE_PATH"
3654		BRIEF_DOCS "Honor headers from these directories when generating the prefix header."
3655		FULL_DOCS
3656			"See target property COTIRE_PREFIX_HEADER_INCLUDE_PATH."
3657	)
3658
3659	define_property(
3660		DIRECTORY PROPERTY "COTIRE_PREFIX_HEADER_INCLUDE_PRIORITY_PATH"
3661		BRIEF_DOCS "Header paths matching one of these directories are put at the top of the prefix header."
3662		FULL_DOCS
3663			"See target property COTIRE_PREFIX_HEADER_INCLUDE_PRIORITY_PATH."
3664	)
3665
3666	define_property(
3667		DIRECTORY PROPERTY "COTIRE_UNITY_SOURCE_PRE_UNDEFS"
3668		BRIEF_DOCS "Preprocessor undefs to place in the generated unity source file before the inclusion of each source file."
3669		FULL_DOCS
3670			"See target property COTIRE_UNITY_SOURCE_PRE_UNDEFS."
3671	)
3672
3673	define_property(
3674		DIRECTORY PROPERTY "COTIRE_UNITY_SOURCE_POST_UNDEFS"
3675		BRIEF_DOCS "Preprocessor undefs to place in the generated unity source file after the inclusion of each source file."
3676		FULL_DOCS
3677			"See target property COTIRE_UNITY_SOURCE_POST_UNDEFS."
3678	)
3679
3680	define_property(
3681		DIRECTORY PROPERTY "COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES"
3682		BRIEF_DOCS "Maximum number of source files to include in a single unity source file."
3683		FULL_DOCS
3684			"See target property COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES."
3685	)
3686
3687	define_property(
3688		DIRECTORY PROPERTY "COTIRE_UNITY_LINK_LIBRARIES_INIT"
3689		BRIEF_DOCS "Define strategy for setting up the unity target's link libraries."
3690		FULL_DOCS
3691			"See target property COTIRE_UNITY_LINK_LIBRARIES_INIT."
3692	)
3693
3694	# define cotire target properties
3695
3696	define_property(
3697		TARGET PROPERTY "COTIRE_ENABLE_PRECOMPILED_HEADER" INHERITED
3698		BRIEF_DOCS "Modify this target's build command to make use of the generated precompiled header."
3699		FULL_DOCS
3700			"If this property is set to TRUE, cotire will modify the build command to make use of the generated precompiled header."
3701			"Irrespective of the value of this property, cotire will setup custom commands to generate the unity source and prefix header for the target."
3702			"For makefile based generators cotire will also set up a custom target to manually invoke the generation of the precompiled header."
3703			"The target name will be set to this target's name with the suffix _pch appended."
3704			"Inherited from directory."
3705			"Defaults to TRUE."
3706	)
3707
3708	define_property(
3709		TARGET PROPERTY "COTIRE_ADD_UNITY_BUILD" INHERITED
3710		BRIEF_DOCS "Add a new target that performs a unity build for this target."
3711		FULL_DOCS
3712			"If this property is set to TRUE, cotire creates a new target of the same type that uses the generated unity source file instead of the target sources."
3713			"Most of the relevant target properties will be copied from this target to the new unity build target."
3714			"Target dependencies and linked libraries have to be manually set up for the new unity build target."
3715			"The unity target name will be set to this target's name with the suffix _unity appended."
3716			"Inherited from directory."
3717			"Defaults to TRUE."
3718	)
3719
3720	define_property(
3721		TARGET PROPERTY "COTIRE_ADD_CLEAN" INHERITED
3722		BRIEF_DOCS "Add a new target that cleans all cotire generated files for this target."
3723		FULL_DOCS
3724			"If this property is set to TRUE, cotire creates a new target that clean all files (unity source, prefix header, precompiled header)."
3725			"The clean target name will be set to this target's name with the suffix _clean_cotire appended."
3726			"Inherited from directory."
3727			"Defaults to FALSE."
3728	)
3729
3730	define_property(
3731		TARGET PROPERTY "COTIRE_PREFIX_HEADER_IGNORE_PATH" INHERITED
3732		BRIEF_DOCS "Ignore headers from these directories when generating the prefix header."
3733		FULL_DOCS
3734			"The property can be set to a list of directories."
3735			"If a header file is found in one of these directories or sub-directories, it will be excluded from the generated prefix header."
3736			"Inherited from directory."
3737			"If not set, this property is initialized to \${CMAKE_SOURCE_DIR};\${CMAKE_BINARY_DIR}."
3738	)
3739
3740	define_property(
3741		TARGET PROPERTY "COTIRE_PREFIX_HEADER_INCLUDE_PATH" INHERITED
3742		BRIEF_DOCS "Honor headers from these directories when generating the prefix header."
3743		FULL_DOCS
3744			"The property can be set to a list of directories."
3745			"If a header file is found in one of these directories or sub-directories, it will be included in the generated prefix header."
3746			"If a header file is both selected by COTIRE_PREFIX_HEADER_IGNORE_PATH and COTIRE_PREFIX_HEADER_INCLUDE_PATH,"
3747			"the option which yields the closer relative path match wins."
3748			"Inherited from directory."
3749			"If not set, this property is initialized to the empty list."
3750	)
3751
3752	define_property(
3753		TARGET PROPERTY "COTIRE_PREFIX_HEADER_INCLUDE_PRIORITY_PATH" INHERITED
3754		BRIEF_DOCS "Header paths matching one of these directories are put at the top of prefix header."
3755		FULL_DOCS
3756			"The property can be set to a list of directories."
3757			"Header file paths matching one of these directories will be inserted at the beginning of the generated prefix header."
3758			"Header files are sorted according to the order of the directories in the property."
3759			"If not set, this property is initialized to the empty list."
3760	)
3761
3762	define_property(
3763		TARGET PROPERTY "COTIRE_UNITY_SOURCE_PRE_UNDEFS" INHERITED
3764		BRIEF_DOCS "Preprocessor undefs to place in the generated unity source file before the inclusion of each target source file."
3765		FULL_DOCS
3766			"This may be set to a semicolon-separated list of preprocessor symbols."
3767			"cotire will add corresponding #undef directives to the generated unit source file before each target source file."
3768			"Inherited from directory."
3769			"Defaults to empty string."
3770	)
3771
3772	define_property(
3773		TARGET PROPERTY "COTIRE_UNITY_SOURCE_POST_UNDEFS" INHERITED
3774		BRIEF_DOCS "Preprocessor undefs to place in the generated unity source file after the inclusion of each target source file."
3775		FULL_DOCS
3776			"This may be set to a semicolon-separated list of preprocessor symbols."
3777			"cotire will add corresponding #undef directives to the generated unit source file after each target source file."
3778			"Inherited from directory."
3779			"Defaults to empty string."
3780	)
3781
3782	define_property(
3783		TARGET PROPERTY "COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES" INHERITED
3784		BRIEF_DOCS "Maximum number of source files to include in a single unity source file."
3785		FULL_DOCS
3786			"This may be set to an integer > 0."
3787			"If a target contains more than that number of source files, cotire will create multiple unity build files for it."
3788			"If not set, cotire will only create a single unity source file."
3789			"Inherited from directory."
3790			"Defaults to empty."
3791	)
3792
3793	define_property(
3794		TARGET PROPERTY "COTIRE_<LANG>_UNITY_SOURCE_INIT"
3795		BRIEF_DOCS "User provided unity source file to be used instead of the automatically generated one."
3796		FULL_DOCS
3797			"If set, cotire will only add the given file(s) to the generated unity source file."
3798			"If not set, cotire will add all the target source files to the generated unity source file."
3799			"The property can be set to a user provided unity source file."
3800			"Defaults to empty."
3801	)
3802
3803	define_property(
3804		TARGET PROPERTY "COTIRE_<LANG>_PREFIX_HEADER_INIT"
3805		BRIEF_DOCS "User provided prefix header file to be used instead of the automatically generated one."
3806		FULL_DOCS
3807			"If set, cotire will add the given header file(s) to the generated prefix header file."
3808			"If not set, cotire will generate a prefix header by tracking the header files included by the unity source file."
3809			"The property can be set to a user provided prefix header file (e.g., stdafx.h)."
3810			"Defaults to empty."
3811	)
3812
3813	define_property(
3814		TARGET PROPERTY "COTIRE_UNITY_LINK_LIBRARIES_INIT" INHERITED
3815		BRIEF_DOCS "Define strategy for setting up unity target's link libraries."
3816		FULL_DOCS
3817			"If this property is empty or set to NONE, the generated unity target's link libraries have to be set up manually."
3818			"If this property is set to COPY, the unity target's link libraries will be copied from this target."
3819			"If this property is set to COPY_UNITY, the unity target's link libraries will be copied from this target with considering existing unity targets."
3820			"Inherited from directory."
3821			"Defaults to empty."
3822	)
3823
3824	define_property(
3825		TARGET PROPERTY "COTIRE_<LANG>_UNITY_SOURCE"
3826		BRIEF_DOCS "Read-only property. The generated <LANG> unity source file(s)."
3827		FULL_DOCS
3828			"cotire sets this property to the path of the generated <LANG> single computation unit source file for the target."
3829			"Defaults to empty string."
3830	)
3831
3832	define_property(
3833		TARGET PROPERTY "COTIRE_<LANG>_PREFIX_HEADER"
3834		BRIEF_DOCS "Read-only property. The generated <LANG> prefix header file."
3835		FULL_DOCS
3836			"cotire sets this property to the full path of the generated <LANG> language prefix header for the target."
3837			"Defaults to empty string."
3838	)
3839
3840	define_property(
3841		TARGET PROPERTY "COTIRE_<LANG>_PRECOMPILED_HEADER"
3842		BRIEF_DOCS "Read-only property. The generated <LANG> precompiled header file."
3843		FULL_DOCS
3844			"cotire sets this property to the full path of the generated <LANG> language precompiled header binary for the target."
3845			"Defaults to empty string."
3846	)
3847
3848	define_property(
3849		TARGET PROPERTY "COTIRE_UNITY_TARGET_NAME"
3850		BRIEF_DOCS "The name of the generated unity build target corresponding to this target."
3851		FULL_DOCS
3852			"This property can be set to the desired name of the unity target that will be created by cotire."
3853			"If not set, the unity target name will be set to this target's name with the suffix _unity appended."
3854			"After this target has been processed by cotire, the property is set to the actual name of the generated unity target."
3855			"Defaults to empty string."
3856	)
3857
3858	# define cotire source properties
3859
3860	define_property(
3861		SOURCE PROPERTY "COTIRE_EXCLUDED"
3862		BRIEF_DOCS "Do not modify source file's build command."
3863		FULL_DOCS
3864			"If this property is set to TRUE, the source file's build command will not be modified to make use of the precompiled header."
3865			"The source file will also be excluded from the generated unity source file."
3866			"Source files that have their COMPILE_FLAGS property set will be excluded by default."
3867			"Defaults to FALSE."
3868	)
3869
3870	define_property(
3871		SOURCE PROPERTY "COTIRE_DEPENDENCY"
3872		BRIEF_DOCS "Add this source file to dependencies of the automatically generated prefix header file."
3873		FULL_DOCS
3874			"If this property is set to TRUE, the source file is added to dependencies of the generated prefix header file."
3875			"If the file is modified, cotire will re-generate the prefix header source upon build."
3876			"Defaults to FALSE."
3877	)
3878
3879	define_property(
3880		SOURCE PROPERTY "COTIRE_UNITY_SOURCE_PRE_UNDEFS"
3881		BRIEF_DOCS "Preprocessor undefs to place in the generated unity source file before the inclusion of this source file."
3882		FULL_DOCS
3883			"This may be set to a semicolon-separated list of preprocessor symbols."
3884			"cotire will add corresponding #undef directives to the generated unit source file before this file is included."
3885			"Defaults to empty string."
3886	)
3887
3888	define_property(
3889		SOURCE PROPERTY "COTIRE_UNITY_SOURCE_POST_UNDEFS"
3890		BRIEF_DOCS "Preprocessor undefs to place in the generated unity source file after the inclusion of this source file."
3891		FULL_DOCS
3892			"This may be set to a semicolon-separated list of preprocessor symbols."
3893			"cotire will add corresponding #undef directives to the generated unit source file after this file is included."
3894			"Defaults to empty string."
3895	)
3896
3897	define_property(
3898		SOURCE PROPERTY "COTIRE_START_NEW_UNITY_SOURCE"
3899		BRIEF_DOCS "Start a new unity source file which includes this source file as the first one."
3900		FULL_DOCS
3901			"If this property is set to TRUE, cotire will complete the current unity file and start a new one."
3902			"The new unity source file will include this source file as the first one."
3903			"This property essentially works as a separator for unity source files."
3904			"Defaults to FALSE."
3905	)
3906
3907	define_property(
3908		SOURCE PROPERTY "COTIRE_TARGET"
3909		BRIEF_DOCS "Read-only property. Mark this source file as cotired for the given target."
3910		FULL_DOCS
3911			"cotire sets this property to the name of target, that the source file's build command has been altered for."
3912			"Defaults to empty string."
3913	)
3914
3915	message (STATUS "cotire ${COTIRE_CMAKE_MODULE_VERSION} loaded.")
3916
3917endif()
3918