Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/usability/cmake/tools/PrecompiledHeaderFiles.cmake @ 8002

Last change on this file since 8002 was 7448, checked in by rgrieder, 14 years ago

DEFINE_SYMBOL property is only added to compile flags for an executable.

  • Property svn:eol-style set to native
File size: 6.4 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
73  IF(MSVC)
74
75    # Write and add one source file, which generates the precompiled header file
76    SET(_pch_source_file "${CMAKE_CURRENT_BINARY_DIR}/${_pch_header_filename_we}.cc")
77    IF(NOT EXISTS ${_pch_source_file})
78      FILE(WRITE ${_pch_source_file} "#include \"${_pch_header_file}\"\n")
79    ENDIF()
80    SET_SOURCE_FILES_PROPERTIES(_pch_source_file PROPERTIES GENERATED TRUE)
81    LIST(APPEND ${_sourcefile_var} ${_pch_source_file})
82
83    SET(_pch_file "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${_pch_header_filename}.pch")
84    # Set compile flags for generated source file
85    SET_SOURCE_FILES_PROPERTIES(${_pch_source_file} PROPERTIES COMPILE_FLAGS "/c /Yc\"${_pch_header_file}\" /Fp\"${_pch_file}\"")
86    # Set Compile flags for the other source files
87    FOREACH(_file ${_source_files})
88      GET_SOURCE_FILE_PROPERTY(_is_header ${_file} HEADER_FILE_ONLY)
89      IF(NOT _is_header)
90        GET_SOURCE_FILE_PROPERTY(_old_flags ${_file} COMPILE_FLAGS)
91        IF(NOT _old_flags)
92          SET(_old_flags "")
93        ENDIF()
94        SET_SOURCE_FILES_PROPERTIES(${_file} PROPERTIES COMPILE_FLAGS "${_old_flags} /FI\"${_pch_header_file}\" /Yu\"${_pch_header_file}\" /Fp\"${_pch_file}\"")
95      ENDIF(NOT _is_header)
96    ENDFOREACH(_file)
97
98  ELSEIF(CMAKE_COMPILER_IS_GNU)
99
100    SET(_pch_file "${CMAKE_CURRENT_BINARY_DIR}/${_pch_header_filename}.gch")
101    SET(_pch_dep_helper_file "${CMAKE_CURRENT_BINARY_DIR}/${_target_name}PCHDependencyHelper.h")
102
103    # Append the gch-dir to make sure gcc finds the pch file
104    INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
105
106    # Get compiler flags of the source files (target does not yet exist!)
107    # This is just the best possible opportunity to address this dependency issue
108    GET_GCC_COMPILER_FLAGS(${_target_name} _pch_gcc_flags)
109    # Make sure we recompile the pch file even if only the flags change
110    IF(NOT "${_pch_gcc_flags}" STREQUAL "${_INTERNAL_${_target_name}_PCH_GCC_FLAGS}" OR NOT EXISTS "${_pch_dep_helper_file}")
111      SET(_INTERNAL_${_target_name}_PCH_GCC_FLAGS "${_pch_gcc_flags}" CACHE INTERNAL "")
112      FILE(WRITE ${_pch_dep_helper_file} "/* ${_pch_gcc_flags} */")
113    ENDIF()
114
115    # Set Compile flags for the other source files
116    FOREACH(_file ${_source_files})
117      GET_SOURCE_FILE_PROPERTY(_is_header ${_file} HEADER_FILE_ONLY)
118      IF(NOT _is_header)
119        GET_SOURCE_FILE_PROPERTY(_old_flags ${_file} COMPILE_FLAGS)
120        IF(NOT _old_flags)
121          SET(_old_flags "")
122        ENDIF()
123        SET_SOURCE_FILES_PROPERTIES(${_file} PROPERTIES
124          COMPILE_FLAGS "${_old_flags} -include ${_pch_header_filename}"
125          OBJECT_DEPENDS "${_pch_header_file}"
126        )
127      ENDIF(NOT _is_header)
128    ENDFOREACH(_file)
129
130  ENDIF()
131
132ENDMACRO(PRECOMPILED_HEADER_FILES_PRE_TARGET)
133
134FUNCTION(PRECOMPILED_HEADER_FILES_POST_TARGET _target_name)
135    # This macro is only necessary for GCC
136    IF(CMAKE_COMPILER_IS_GNU)
137
138      # Workaround for distcc
139      IF(CMAKE_CXX_COMPILER_ARG1)
140        # remove leading space in compiler argument
141        STRING(REGEX REPLACE "^ +" "" _pch_cmake_cxx_compiler_arg1 "${CMAKE_CXX_COMPILER_ARG1}")
142      ENDIF()
143
144      # Get compiler flags of the source files again (target exists this time)
145      GET_GCC_COMPILER_FLAGS(${_target_name} _pch_gcc_flags)
146
147      # Compile the header file
148      ADD_CUSTOM_COMMAND(
149        OUTPUT ${_pch_file}
150        COMMAND ${CMAKE_CXX_COMPILER}
151        ARGS ${pchsupport_compiler_cxx_arg1} ${_pch_gcc_flags} -c -x c++-header -o ${_pch_file} ${_pch_header_file}
152        WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
153        DEPENDS ${_pch_dep_helper_file}
154        IMPLICIT_DEPENDS CXX ${_pch_header_file}
155        VERBATIM
156      )
157      ADD_CUSTOM_TARGET(${_target_name}PrecompiledHeader DEPENDS ${_pch_file})
158      ADD_DEPENDENCIES(${_target_name} ${_target_name}PrecompiledHeader)
159
160    ENDIF(CMAKE_COMPILER_IS_GNU)
161ENDFUNCTION(PRECOMPILED_HEADER_FILES_POST_TARGET)
Note: See TracBrowser for help on using the repository browser.