Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/core4/cmake/PrecompiledHeaderFiles.cmake @ 3534

Last change on this file since 3534 was 3251, checked in by rgrieder, 15 years ago

Fixed two serious dependency bugs:

  • Only every second file of the tolua bind dependencies was regarded as such (already fixed in trunk)
  • Running cmake still caused complete rebuilds when using PCH
  • Property svn:eol-style set to native
File size: 6.3 KB
Line 
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
24INCLUDE(GetGCCCompilerFlags)
25 
26MACRO(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}PCHDependencyHelper.h")
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    IF(NOT "${_pch_gcc_flags}" STREQUAL "${_INTERNAL_${_target_name}_PCH_GCC_FLAGS}")
113      SET(_INTERNAL_${_target_name}_PCH_GCC_FLAGS "${_pch_gcc_flags}" CACHE INTERNAL "")
114      FILE(WRITE ${_pch_dep_helper_file} "/* ${_pch_gcc_flags} */")
115    ENDIF()
116
117    # Set Compile flags for the other source files
118    FOREACH(_file ${_source_files})
119      GET_SOURCE_FILE_PROPERTY(_is_header ${_file} HEADER_FILE_ONLY)
120      IF(NOT _is_header)
121        GET_SOURCE_FILE_PROPERTY(_old_flags ${_file} COMPILE_FLAGS)
122        IF(NOT _old_flags)
123          SET(_old_flags "")
124        ENDIF()
125        SET_SOURCE_FILES_PROPERTIES(${_file} PROPERTIES
126          COMPILE_FLAGS "${_old_flags} -include ${_pch_header_filename}"
127          OBJECT_DEPENDS "${_pch_header_file};${_pch_file}"
128        )
129      ENDIF(NOT _is_header)
130    ENDFOREACH(_file)
131
132  ENDIF()
133
134ENDMACRO(PRECOMPILED_HEADER_FILES_PRE_TARGET)
135
136FUNCTION(PRECOMPILED_HEADER_FILES_POST_TARGET _target_name)
137    # This macro is only necessary for GCC
138    IF(CMAKE_COMPILER_IS_GNU)
139
140      # Workaround for distcc
141      IF(CMAKE_CXX_COMPILER_ARG1)
142        # remove leading space in compiler argument
143        STRING(REGEX REPLACE "^ +" "" _pch_cmake_cxx_compiler_arg1 "${CMAKE_CXX_COMPILER_ARG1}")
144      ENDIF()
145
146      # Get compiler flags of the source files again (target exists this time)
147      GET_GCC_COMPILER_FLAGS(${_target_name} _pch_gcc_flags)
148
149      # Compile the header file
150      ADD_CUSTOM_COMMAND(
151        OUTPUT ${_pch_file}
152        COMMAND ${CMAKE_CXX_COMPILER}
153        ARGS ${pchsupport_compiler_cxx_arg1} ${_pch_gcc_flags} -c -x c++-header -o ${_pch_file} ${_pch_header_file}
154        WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
155        DEPENDS ${_pch_dep_helper_file}
156        IMPLICIT_DEPENDS CXX ${_pch_header_file}
157        VERBATIM
158      )
159
160    ENDIF(CMAKE_COMPILER_IS_GNU)
161ENDFUNCTION(PRECOMPILED_HEADER_FILES_POST_TARGET)
Note: See TracBrowser for help on using the repository browser.