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