Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/cmake/FlagUtilities.cmake @ 3177

Last change on this file since 3177 was 2792, checked in by rgrieder, 16 years ago

Finally found the MSVC IntelliSense bug! It wasn't working at all, so there was helping information about any symbol, class, function or macro. That was very annoying…
Turned out the compiler likes "-" to start a compiler switch, but IntelliSense doesn't like that at all. Using "/" instead.

  • Property svn:eol-style set to native
File size: 8.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 #  Description:
23 #    Sets the compiler/linker flags. After the flags you can specify more args:
24 #    Release, Debug, RelWithDebInfo, MinSizeRel: Build configs (inclusive)
25 #    ReleaseAll: Sets the flags of all three release builds
26 #    CACHE: Values are witten with SET_CACHE (see above)
27 #    FORCE: When writing to the cache, the values are set anyway
28 #    Any variable names (like WIN32, MSVC, etc.): Condition (combined with AND)
29 #    You can suffix the condition with a NOT if you wish
30 #  Functions:
31 #    [ADD/SET/REMOVE]_[COMPILER/LINKER]_FLAGS
32 #  Caution: -If you use CACHE after calling the macro without CACHE, the value
33 #            Will not get written unless FORCE is specified.
34 #          - Also be aware to always specify the flags in quotes.
35 #  Example:
36 #    REMOVE_COMPILER_FLAGS("/Gm "asdf" -q"test -foo" CXX ReleaseAll NOT UNIX)
37 #    This will only remove the CXX (C++) flags on a non Unix system for the
38 #    Release, RelWithDebInfo and MinSizeRel configurations. The macros should
39 #    be able to cope with "test -foo" that is like another flag in the string.
40 #
41
42# Write to the cache by force, but only if the user didn't edit the value
43# Additional argument is the value (may also be a list)
44MACRO(SET_CACHE _varname _type _docstring)
45  SET(_value ${ARGN})
46  IF(NOT "${_type}" MATCHES "^(STRING|BOOL|PATH|FILEPATH)$")
47    MESSAGE(FATAL_ERROR "${_type} is not a valid CACHE entry type")
48  ENDIF()
49
50  IF(NOT DEFINED _INTERNAL_${_varname} OR "${_INTERNAL_${_varname}}" STREQUAL "${${_varname}}")
51    SET(${_varname} "${_value}" CACHE ${_type} "${_docstring}" FORCE)
52    SET(_INTERNAL_${_varname} "${_value}" CACHE INTERNAL "Do not edit in any case!")
53  ENDIF()
54ENDMACRO(SET_CACHE)
55
56# Visual studio (esp. IntelliSense) doesn't like dashes to specify arguments
57# Always use foward slashes instead
58IF(MSVC)
59  SET(ARGUMENT_STARTER "/")
60ELSE()
61  SET(ARGUMENT_STARTER "-")
62ENDIF(MSVC)
63
64# Separates a string of flags. " -" or " /" denotes the start of a flag.
65# The same sequence inside double quotation marks is ignored.
66# Spaces not within quotes are cleaned meaningfully.
67# This macro cannot cope with semicolons in the flag string!
68MACRO(SEPARATE_FLAGS _flags _output_variable)
69  SET(_flags_prep " ${_flags} -")
70  STRING(REPLACE " " " ;" _flag_chunks ${_flags_prep}) # Max loop iterations
71  SET(_flag_string)
72  SET(_parsed_flags)
73  # Loop is necessary because the regex engine is greedy
74  FOREACH(_chunk ${_flag_chunks})
75    SET(_flag_string "${_flag_string}${_chunk}")
76    # Replace all " -" and " /" inside quotation marks
77    STRING(REGEX REPLACE "^(([^\"]*\"[^\"]*\")*[^\"]*\"[^\"]*) [/-]([^\"]*\")"
78           "\\1@39535493@\\3" _flag_string "${_flag_string}")
79    # Extract one flag if possible
80    SET(_flag)
81    STRING(REGEX REPLACE "^.* [/-](.+)( [/-].*$)" "${ARGUMENT_STARTER}\\1" _flag "${_flag_string}")
82    STRING(REGEX REPLACE "^.* [/-](.+)( [/-].*$)" "\\2"  _flag_string "${_flag_string}")
83    IF(NOT _flag STREQUAL _flag_string)
84      LIST(APPEND _parsed_flags "${_flag}")
85    ENDIF(NOT _flag STREQUAL _flag_string)
86  ENDFOREACH(_chunk)
87
88  # Re-replace all " -" and " /" inside quotation marks
89  STRING(REGEX REPLACE "@39535493@" " -" ${_output_variable} "${_parsed_flags}")
90ENDMACRO(SEPARATE_FLAGS)
91
92# Internal macro, do not use
93# Modifies the flags according to the mode: set, add or remove
94# Also sets flags according to the CACHE and FORCE parameter.
95# If only CACHE is specified, SET_CACHE() is used.
96MACRO(_INTERNAL_PARSE_FLAGS _mode _flags _varname _write_to_cache _force)
97  SEPARATE_FLAGS("${_flags}" _arg_flag_list)
98
99  IF("${_mode}" STREQUAL "SET")
100    # SET
101    SET(_flag_list "${_arg_flag_list}")
102  ELSE()
103    # ADD or REMOVE
104    SEPARATE_FLAGS("${${_varname}}" _flag_list)
105    FOREACH(_flag ${_arg_flag_list})
106      LIST(${_mode} _flag_list "${_flag}")
107    ENDFOREACH(_flag)
108  ENDIF()
109
110  LIST(REMOVE_DUPLICATES _flag_list)
111  LIST(SORT _flag_list)
112  STRING(REPLACE ";" " " _flag_list "${_flag_list}")
113
114  IF(_write_to_cache)
115    IF(_force)
116      SET(${_varname} "${_flag_list}" CACHE STRING "${${_varname}}" FORCE)
117      SET(${_varname} "${_flag_list}" CACHE STRING "${${_varname}}" FORCE)
118    ELSE()
119      SET_CACHE(${_varname} STRING "${${_varname}}" "${_flag_list}")
120    ENDIF()
121  ELSE()
122    SET(${_varname} "${_flag_list}")
123  ENDIF()
124ENDMACRO(_INTERNAL_PARSE_FLAGS)
125
126# Internal macro, do not use
127# Parses the given additional arguments and sets the flags to the
128# corresponding variables.
129MACRO(_INTERNAL_PARSE_FLAGS_ARGS _mode _keys _key_postfix _flags)
130  SET(_langs)
131  SET(_build_types)
132  SET(_cond TRUE)
133  SET(_invert_condition FALSE)
134  SET(_write_to_cache FALSE)
135  SET(_force FALSE)
136  STRING(REPLACE ";" "|" _key_regex "${_keys}")
137  SET(_key_regex "^(${_key_regex})$")
138
139  FOREACH(_arg ${ARGN})
140    IF(_arg MATCHES "${_key_regex}")
141      LIST(APPEND _langs "${_arg}")
142    ELSEIF(   _arg MATCHES "^(Debug|Release|MinSizeRel|RelWithDebInfo)$"
143           OR _arg MATCHES "^(DEBUG|RELEASE|MINSIZEREL|RELWITHDEBINFO)$")
144      STRING(TOUPPER "${_arg}" _upper_arg)
145      LIST(APPEND _build_types ${_upper_arg})
146    ELSEIF(_arg STREQUAL "ReleaseAll")
147      LIST(APPEND _build_types RELEASE MINSIZEREL RELWITHDEBINFO)
148    ELSEIF(_arg STREQUAL "CACHE")
149      SET(_write_to_cache TRUE)
150    ELSEIF(_arg STREQUAL "FORCE")
151      SET(_force TRUE)
152    ELSEIF(_arg MATCHES "^[Nn][Oo][Tt]$")
153      SET(_invert_condition TRUE)
154    ELSE()
155      IF(_invert_condition)
156        SET(_invert_condition FALSE)
157    IF(${_arg})
158          SET(_arg_cond FALSE)
159    ELSE()
160          SET(_arg_cond TRUE)
161    ENDIF()
162      ELSE()
163        SET(_arg_cond ${${_arg}})
164      ENDIF()
165      IF(_cond AND _arg_cond)
166        SET(_cond TRUE)
167      ELSE()
168        SET(_cond FALSE)
169      ENDIF()
170    ENDIF()
171  ENDFOREACH(_arg)
172
173  # No language specified, use all: C and CXX or EXE, SHARED and MODULE
174  IF(NOT DEFINED _langs)
175    SET(_langs ${_keys})
176  ENDIF()
177
178  IF(_cond)
179    FOREACH(_lang ${_langs})
180      SET(_varname "CMAKE_${_lang}${_key_postfix}_FLAGS")
181      IF(DEFINED _build_types)
182        FOREACH(_build_type ${_build_types})
183          _INTERNAL_PARSE_FLAGS(${_mode} "${_flags}" ${_varname}_${_build_type} ${_write_to_cache} ${_force})
184        ENDFOREACH(_build_type)
185      ELSE()
186        _INTERNAL_PARSE_FLAGS(${_mode} "${_flags}" ${_varname} ${_write_to_cache} ${_force})
187      ENDIF()
188    ENDFOREACH(_lang ${_langs})
189  ENDIF(_cond)
190ENDMACRO(_INTERNAL_PARSE_FLAGS_ARGS)
191
192
193# Compiler flags, additional arguments:
194# C, CXX: Specify a language, default is both
195MACRO(SET_COMPILER_FLAGS _flags)
196  _INTERNAL_PARSE_FLAGS_ARGS(SET "C;CXX" "" "${_flags}" "${ARGN}")
197ENDMACRO(SET_COMPILER_FLAGS)
198# Add flags (flags don't get added twice)
199MACRO(ADD_COMPILER_FLAGS _flags)
200  _INTERNAL_PARSE_FLAGS_ARGS(APPEND "C;CXX" "" "${_flags}" "${ARGN}")
201ENDMACRO(ADD_COMPILER_FLAGS)
202# Remove flags
203MACRO(REMOVE_COMPILER_FLAGS _flags)
204  _INTERNAL_PARSE_FLAGS_ARGS(REMOVE_ITEM "C;CXX" "" "${_flags}" "${ARGN}")
205ENDMACRO(REMOVE_COMPILER_FLAGS)
206
207# Linker flags, additional arguments:
208# EXE, SHARED, MODULE: Specify a linker mode, default is all three
209MACRO(SET_LINKER_FLAGS _flags)
210  _INTERNAL_PARSE_FLAGS_ARGS(SET "EXE;SHARED;MODULE" "_LINKER" "${_flags}" "${ARGN}")
211ENDMACRO(SET_LINKER_FLAGS)
212# Add flags (flags don't get added twice)
213MACRO(ADD_LINKER_FLAGS _flags)
214  _INTERNAL_PARSE_FLAGS_ARGS(APPEND "EXE;SHARED;MODULE" "_LINKER" "${_flags}" "${ARGN}")
215ENDMACRO(ADD_LINKER_FLAGS)
216# Remove flags
217MACRO(REMOVE_LINKER_FLAGS _flags)
218  _INTERNAL_PARSE_FLAGS_ARGS(REMOVE_ITEM "EXE;SHARED;MODULE" "_LINKER" "${_flags}" "${ARGN}")
219ENDMACRO(REMOVE_LINKER_FLAGS)
Note: See TracBrowser for help on using the repository browser.