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