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()