1 | # |
---|
2 | # ORXONOX - the hottest 3D action shooter ever to exist |
---|
3 | # > www.orxonox.net < |
---|
4 | # |
---|
5 | # This program is free software; you can redistribute it and/or |
---|
6 | # modify it under the terms of the GNU General Public License |
---|
7 | # as published by the Free Software Foundation; either version 2 |
---|
8 | # of the License, or (at your option) any later version. |
---|
9 | # |
---|
10 | # This program is distributed in the hope that it will be useful, |
---|
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
13 | # GNU General Public License for more details. |
---|
14 | # |
---|
15 | # You should have received a copy of the GNU General Public License along |
---|
16 | # with this program; if not, write to the Free Software Foundation, |
---|
17 | # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
---|
18 | # |
---|
19 | # |
---|
20 | # Author: |
---|
21 | # Reto Grieder |
---|
22 | # |
---|
23 | |
---|
24 | INCLUDE(GetGCCCompilerFlags) |
---|
25 | |
---|
26 | MACRO(PRECOMPILED_HEADER_FILES_PRE_TARGET _target_name _header_file_arg _sourcefile_var) |
---|
27 | |
---|
28 | GET_FILENAME_COMPONENT(_pch_header_file ${_header_file_arg} ABSOLUTE) |
---|
29 | GET_FILENAME_COMPONENT(_pch_header_filename ${_pch_header_file} NAME) |
---|
30 | GET_FILENAME_COMPONENT(_pch_header_filename_we ${_pch_header_file} NAME_WE) |
---|
31 | |
---|
32 | IF(NOT EXISTS ${_pch_header_file}) |
---|
33 | MESSAGE(FATAL_ERROR "Specified precompiled headerfile '${_header_file_arg}' does not exist.") |
---|
34 | ENDIF() |
---|
35 | |
---|
36 | # Extract arguments from ARGN |
---|
37 | FOREACH(_arg ${ARGN}) |
---|
38 | IF(NOT "${_arg}" STREQUAL "EXCLUDE") |
---|
39 | IF(NOT _arg_second) |
---|
40 | # Source files with PCH support |
---|
41 | SET(_included_files ${_included_files} ${_arg}) |
---|
42 | ELSE() |
---|
43 | # Source files to be excluded from PCH support (easier syntax this way) |
---|
44 | SET(_excluded files ${_excluded_files} ${_arg}) |
---|
45 | ENDIF() |
---|
46 | ELSE() |
---|
47 | SET(_arg_second TRUE) |
---|
48 | ENDIF() |
---|
49 | ENDFOREACH(_arg) |
---|
50 | |
---|
51 | # Use ${_sourcefile_var} if no files were specified explicitely |
---|
52 | IF(NOT _included_files) |
---|
53 | SET(_source_files ${${_sourcefile_var}}) |
---|
54 | ELSE() |
---|
55 | SET(_source_files ${_included_files}) |
---|
56 | ENDIF() |
---|
57 | |
---|
58 | # Exclude files (if specified) |
---|
59 | FOREACH(_file ${_excluded_files}) |
---|
60 | LIST(FIND _source_files ${_file} _list_index) |
---|
61 | IF(_list_index GREATER -1) |
---|
62 | LIST(REMOVE_AT _source_files _list_index) |
---|
63 | ELSE() |
---|
64 | MESSAGE(FATAL_ERROR "Could not exclude file ${_file} in target ${_target_name}") |
---|
65 | ENDIF() |
---|
66 | ENDFOREACH(_file) |
---|
67 | |
---|
68 | LIST(FIND ${_sourcefile_var} ${_pch_header_file} _list_index) |
---|
69 | IF(_list_index EQUAL -1) # Header file could already be included with GET_ALL_HEADER_FILES |
---|
70 | LIST(APPEND ${_sourcefile_var} ${_pch_header_file}) |
---|
71 | ENDIF() |
---|
72 | SOURCE_GROUP("PCH" FILES ${_pch_header_file}) |
---|
73 | |
---|
74 | IF(MSVC) |
---|
75 | |
---|
76 | # Write and add one source file, which generates the precompiled header file |
---|
77 | SET(_pch_source_file "${CMAKE_CURRENT_BINARY_DIR}/${_pch_header_filename_we}.cc") |
---|
78 | IF(NOT EXISTS ${_pch_source_file}) |
---|
79 | FILE(WRITE ${_pch_source_file} "#include \"${_pch_header_file}\"\n") |
---|
80 | ENDIF() |
---|
81 | SET_SOURCE_FILES_PROPERTIES(_pch_source_file PROPERTIES GENERATED TRUE) |
---|
82 | LIST(APPEND ${_sourcefile_var} ${_pch_source_file}) |
---|
83 | SOURCE_GROUP("PCH" FILES ${_pch_source_file}) |
---|
84 | |
---|
85 | SET(_pch_file "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${_pch_header_filename}.pch") |
---|
86 | # Set compile flags for generated source file |
---|
87 | SET_SOURCE_FILES_PROPERTIES(${_pch_source_file} PROPERTIES COMPILE_FLAGS "/c /Yc\"${_pch_header_file}\" /Fp\"${_pch_file}\"") |
---|
88 | # Set Compile flags for the other source files |
---|
89 | FOREACH(_file ${_source_files}) |
---|
90 | GET_SOURCE_FILE_PROPERTY(_is_header ${_file} HEADER_FILE_ONLY) |
---|
91 | IF(NOT _is_header) |
---|
92 | GET_SOURCE_FILE_PROPERTY(_old_flags ${_file} COMPILE_FLAGS) |
---|
93 | IF(NOT _old_flags) |
---|
94 | SET(_old_flags "") |
---|
95 | ENDIF() |
---|
96 | SET_SOURCE_FILES_PROPERTIES(${_file} PROPERTIES COMPILE_FLAGS "${_old_flags} /FI\"${_pch_header_file}\" /Yu\"${_pch_header_file}\" /Fp\"${_pch_file}\"") |
---|
97 | ENDIF(NOT _is_header) |
---|
98 | ENDFOREACH(_file) |
---|
99 | |
---|
100 | ELSEIF(CMAKE_COMPILER_IS_GNU) |
---|
101 | |
---|
102 | SET(_pch_file "${CMAKE_CURRENT_BINARY_DIR}/${_pch_header_filename}.gch") |
---|
103 | SET(_pch_dep_helper_file "${CMAKE_CURRENT_BINARY_DIR}/${_target_name}_pch_dependency_helper.cc") |
---|
104 | |
---|
105 | # Append the gch-dir to make sure gcc finds the pch file |
---|
106 | INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}) |
---|
107 | |
---|
108 | # Get compiler flags of the source files (target does not yet exist!) |
---|
109 | # This is just the best possible opportunity to address this dependency issue |
---|
110 | GET_GCC_COMPILER_FLAGS(${_target_name} _pch_gcc_flags) |
---|
111 | # Make sure we recompile the pch file even if only the flags change |
---|
112 | FILE(WRITE ${_pch_dep_helper_file} "/* ${_pch_gcc_flags} */") |
---|
113 | |
---|
114 | # Set Compile flags for the other source files |
---|
115 | FOREACH(_file ${_source_files}) |
---|
116 | GET_SOURCE_FILE_PROPERTY(_is_header ${_file} HEADER_FILE_ONLY) |
---|
117 | IF(NOT _is_header) |
---|
118 | GET_SOURCE_FILE_PROPERTY(_old_flags ${_file} COMPILE_FLAGS) |
---|
119 | IF(NOT _old_flags) |
---|
120 | SET(_old_flags "") |
---|
121 | ENDIF() |
---|
122 | SET_SOURCE_FILES_PROPERTIES(${_file} PROPERTIES |
---|
123 | COMPILE_FLAGS "${_old_flags} -include ${_pch_header_filename}" |
---|
124 | OBJECT_DEPENDS "${_pch_header_file};${_pch_file}" |
---|
125 | ) |
---|
126 | ENDIF(NOT _is_header) |
---|
127 | ENDFOREACH(_file) |
---|
128 | |
---|
129 | ENDIF() |
---|
130 | |
---|
131 | ENDMACRO(PRECOMPILED_HEADER_FILES_PRE_TARGET) |
---|
132 | |
---|
133 | FUNCTION(PRECOMPILED_HEADER_FILES_POST_TARGET _target_name) |
---|
134 | # This macro is only necessary for GCC |
---|
135 | IF(CMAKE_COMPILER_IS_GNU) |
---|
136 | |
---|
137 | # Workaround for distcc |
---|
138 | IF(CMAKE_CXX_COMPILER_ARG1) |
---|
139 | # remove leading space in compiler argument |
---|
140 | STRING(REGEX REPLACE "^ +" "" _pch_cmake_cxx_compiler_arg1 "${CMAKE_CXX_COMPILER_ARG1}") |
---|
141 | ENDIF() |
---|
142 | |
---|
143 | # Get compiler flags of the source files again (target exists this time) |
---|
144 | GET_GCC_COMPILER_FLAGS(${_target_name} _pch_gcc_flags) |
---|
145 | |
---|
146 | # Compile the header file |
---|
147 | ADD_CUSTOM_COMMAND( |
---|
148 | OUTPUT ${_pch_file} |
---|
149 | COMMAND ${CMAKE_CXX_COMPILER} |
---|
150 | ARGS ${pchsupport_compiler_cxx_arg1} ${_pch_gcc_flags} -c -x c++-header -o ${_pch_file} ${_pch_header_file} |
---|
151 | WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} |
---|
152 | DEPENDS ${_pch_header_file} ${_pch_dep_helper_file} |
---|
153 | IMPLICIT_DEPENDS ${_pch_header_file} |
---|
154 | VERBATIM |
---|
155 | ) |
---|
156 | |
---|
157 | ENDIF(CMAKE_COMPILER_IS_GNU) |
---|
158 | ENDFUNCTION(PRECOMPILED_HEADER_FILES_POST_TARGET) |
---|
159 | |
---|
160 | # TODO: Investigate what happens when we suddenly disable PCH for a library |
---|
161 | # TODO: C and CXX |
---|