Imported Upstream version 3.25.0
[platform/upstream/cmake.git] / Tests / Preprocess / CMakeLists.txt
1 cmake_minimum_required(VERSION 2.8.12)
2 project(Preprocess)
3
4 # This test is meant both as a test and as a reference for supported
5 # syntax on native tool command lines.
6
7 # Determine the build tool being used.  Not all characters can be
8 # escaped for all build tools.  This test checks all characters known
9 # to work with each tool and documents those known to not work.
10 if("${CMAKE_GENERATOR}" MATCHES "Xcode")
11   set(PP_XCODE 1)
12 endif()
13 if("${CMAKE_GENERATOR}" MATCHES "Unix Makefiles")
14   set(PP_UMAKE 1)
15 endif()
16 if("${CMAKE_GENERATOR}" MATCHES "NMake Makefiles")
17   set(PP_NMAKE 1)
18 endif()
19 if("${CMAKE_GENERATOR}" MATCHES "MinGW Makefiles")
20   set(PP_MINGW 1)
21 endif()
22 if("${CMAKE_GENERATOR}" MATCHES "Borland Makefiles")
23   set(PP_BORLAND 1)
24 endif()
25 if("${CMAKE_GENERATOR}" MATCHES "Watcom WMake")
26   set(PP_WATCOM 1)
27 endif()
28 if("${CMAKE_GENERATOR}" MATCHES "Visual Studio")
29   set(PP_VS 1)
30 endif()
31 if(CMAKE_C_COMPILER_ID STREQUAL "Clang" AND
32    "x${CMAKE_C_SIMULATE_ID}" STREQUAL "xMSVC")
33    set(CLANG_MSVC_WINDOWS 1)
34 endif()
35 if(CLANG_MSVC_WINDOWS AND
36    "x${CMAKE_C_COMPILER_FRONTEND_VARIANT}" STREQUAL "xGNU")
37    set(CLANG_GNULIKE_WINDOWS 1)
38 endif()
39
40 # Some tests below check the PP_* variables set above.  They are meant
41 # to test the case that the build tool is at fault.  Other tests below
42 # check the compiler that will be used when the compiler is at fault
43 # (does not work even from a command shell).
44
45 #-----------------------------------------------------------------------------
46 # Construct a C-string literal to test passing through a definition on
47 # the command line.  We configure the value into a header so it can be
48 # checked in the executable at runtime.  The semicolon is handled
49 # specially because it needs to be escaped in the COMPILE_DEFINITIONS
50 # property value to avoid separating definitions but the string value
51 # must not have it escaped inside the configured header.
52 set(STRING_EXTRA "")
53
54 if(NOT BORLAND)
55   # Borland: ;
56   # The Borland compiler will simply not accept a non-escaped semicolon
57   # on the command line.  If it is escaped \; then the escape character
58   # shows up in the preprocessing output too.
59   set(SEMICOLON "\;")
60 endif()
61
62 string(APPEND STRING_EXTRA " ")
63
64 if(NOT PP_BORLAND AND NOT PP_WATCOM AND NOT CLANG_GNULIKE_WINDOWS)
65   # Borland, WMake: multiple spaces
66   # The make tool seems to remove extra whitespace from inside
67   # quoted strings when passing to the compiler.  It does not have
68   # trouble passing to other tools, and the compiler may be directly
69   # invoked from the command line.
70   string(APPEND STRING_EXTRA " ")
71 endif()
72
73 if(NOT PP_VS)
74   # VS: ,
75   # Visual Studio will not accept a comma in the value of a definition.
76   # The comma-separated list of PreprocessorDefinitions in the project
77   # file seems to be parsed before the content of entries is examined.
78   string(APPEND STRING_EXTRA ",")
79 endif()
80
81 if(NOT PP_MINGW AND NOT CLANG_GNULIKE_WINDOWS)
82   # MinGW: &
83   # When inside -D"FOO=\"a & b\"" MinGW make wants -D"FOO=\"a "&" b\""
84   # but it does not like quoted ampersand elsewhere.
85   string(APPEND STRING_EXTRA "&")
86 endif()
87
88 if(NOT PP_MINGW AND NOT CLANG_GNULIKE_WINDOWS)
89   # MinGW: |
90   # When inside -D"FOO=\"a | b\"" MinGW make wants -D"FOO=\"a "|" b\""
91   # but it does not like quoted pipe elsewhere.
92   string(APPEND STRING_EXTRA "|")
93 endif()
94
95 if(NOT PP_BORLAND AND NOT PP_MINGW AND NOT PP_NMAKE)
96   # Borland, NMake, MinGW: ^
97   # When inside -D"FOO=\"a ^ b\"" the make tools want -D"FOO=\"a "^" b\""
98   # but do not like quoted carrot elsewhere.  In NMake the non-quoted
99   # syntax works when the flags are not in a make variable.
100   string(APPEND STRING_EXTRA "^")
101 endif()
102
103 if(NOT PP_BORLAND AND NOT PP_MINGW AND NOT PP_NMAKE)
104   # Borland, MinGW: < >
105   # Angle-brackets have funny behavior that is hard to escape.
106   string(APPEND STRING_EXTRA "<>")
107 endif()
108
109 set(EXPR_OP1 "/")
110 if((NOT MSVC OR PP_NMAKE) AND
111    NOT CMAKE_C_COMPILER_ID STREQUAL "Intel" AND
112    NOT CLANG_MSVC_WINDOWS)
113   # MSVC cl, Intel icl: %
114   # When the cl compiler is invoked from the command line then % must
115   # be written %% (to distinguish from %ENV% syntax).  However cl does
116   # not seem to accept the syntax when it is invoked from inside a
117   # make tool (nmake, mingw32-make, etc.).  Instead the argument must
118   # be placed inside a response file.  Then cl accepts it because it
119   # parses the response file as it would the normal windows command
120   # line.  Currently only NMake supports running cl with a response
121   # file.  Supporting other make tools would require CMake to generate
122   # response files explicitly for each object file.
123   #
124   # When the icl compiler is invoked from the command line then % must
125   # be written just '%'.  However nmake requires '%%' except when using
126   # response files.  Currently we have no way to affect escaping based
127   # on whether flags go in a response file, so we just have to skip it.
128   string(APPEND STRING_EXTRA "%")
129   set(EXPR_OP1 "%")
130 endif()
131
132 # XL: )(
133 # The XL compiler cannot pass unbalanced parens correctly to a tool
134 # it launches internally.
135 if(CMAKE_C_COMPILER_ID STREQUAL "XL")
136   string(APPEND STRING_EXTRA "()")
137 else()
138   string(APPEND STRING_EXTRA ")(")
139 endif()
140
141 # General: \"
142 # Make tools do not reliably accept \\\" syntax:
143 #  - MinGW and MSYS make tools crash with \\\"
144 #  - Borland make actually wants a mis-matched quote \\"
145 #    or $(BACKSLASH)\" where BACKSLASH is a variable set to \\
146 #  - VS IDE gets confused about the bounds of the definition value \\\"
147 #  - NMake is okay with just \\\"
148 #  - The XL compiler does not re-escape \\\" when launching an
149 #    internal tool to do preprocessing .
150 #  - The IntelLLVM C and C++ compiler drivers do not re-escape the \\\" when
151 #    launching the underlying compiler. FIXME: this bug is expected to be fixed
152 #    in a future release.
153 if((PP_NMAKE OR PP_UMAKE) AND
154     NOT CMAKE_C_COMPILER_ID STREQUAL "XL" AND
155     NOT CMAKE_C_COMPILER_ID STREQUAL "IntelLLVM" AND
156     NOT CMAKE_CXX_COMPILER_ID STREQUAL "IntelLLVM")
157   string(APPEND STRING_EXTRA "\\\"")
158 endif()
159
160 # General: #
161 # MSVC will not accept a # in the value of a string definition on the
162 # command line.  The character seems to be simply replaced by an
163 # equals =.  According to "cl -help" definitions may be specified by
164 # -DMACRO#VALUE as well as -DMACRO=VALUE.  It must be implemented by a
165 # simple search-and-replace.
166 #
167 # The Borland compiler will parse both # and \# as just # but the make
168 # tool seems to want \# sometimes and not others.
169 #
170 # Unix make does not like # in variable settings without extra
171 # escaping.  This could probably be fixed but since MSVC does not
172 # support it and it is not an operator it is not worthwhile.
173
174 # Compose the final test string.
175 set(STRING_VALUE "hello`~!@$*_+-=}{][:'.?/${STRING_EXTRA}world")
176
177 #-----------------------------------------------------------------------------
178 # Function-style macro command-line support:
179 #   - Borland does not support
180 #   - MSVC does not support
181 #   - Watcom does not support
182 #   - GCC supports
183
184 # Too few platforms support this to bother implementing.
185 # People can just configure headers with the macros.
186
187 #-----------------------------------------------------------------------------
188 # Construct a sample expression to pass as a macro definition.
189
190 set(EXPR "x*y+!(x==(y+1*2))*f(x${EXPR_OP1}2)")
191
192 if(NOT WATCOM)
193   # Watcom does not support - or / because it parses them as options.
194   string(APPEND EXPR " + y/x-x")
195 endif()
196
197 #-----------------------------------------------------------------------------
198
199 # Inform the test if the debug configuration is getting built.
200 string(APPEND CMAKE_C_FLAGS_DEBUG " -DPREPROCESS_DEBUG")
201 string(APPEND CMAKE_CXX_FLAGS_DEBUG " -DPREPROCESS_DEBUG")
202 string(APPEND CMAKE_C_FLAGS_RELEASE " -DPREPROCESS_NDEBUG")
203 string(APPEND CMAKE_CXX_FLAGS_RELEASE " -DPREPROCESS_NDEBUG")
204 string(APPEND CMAKE_C_FLAGS_RELWITHDEBINFO " -DPREPROCESS_NDEBUG")
205 string(APPEND CMAKE_CXX_FLAGS_RELWITHDEBINFO " -DPREPROCESS_NDEBUG")
206 string(APPEND CMAKE_C_FLAGS_MINSIZEREL " -DPREPROCESS_NDEBUG")
207 string(APPEND CMAKE_CXX_FLAGS_MINSIZEREL " -DPREPROCESS_NDEBUG")
208
209 # Inform the test if it built from Xcode.
210 if(PP_XCODE)
211   set(PREPROCESS_XCODE 1)
212 endif()
213
214 # Test old-style definitions.
215 add_definitions(-DOLD_DEF -DOLD_EXPR=2)
216
217 # Make sure old-style definitions are converted to directory property.
218 set(OLD_DEFS_EXPECTED "OLD_DEF;OLD_EXPR=2")
219 get_property(OLD_DEFS DIRECTORY PROPERTY COMPILE_DEFINITIONS)
220 if(NOT "${OLD_DEFS}" STREQUAL "${OLD_DEFS_EXPECTED}")
221   message(SEND_ERROR "add_definitions not converted to directory property!")
222 endif()
223
224 add_executable(Preprocess preprocess.c preprocess.cxx)
225
226 set(FILE_PATH "${Preprocess_SOURCE_DIR}/file_def.h")
227 set(TARGET_PATH "${Preprocess_SOURCE_DIR}/target_def.h")
228
229 # Set some definition properties.
230 foreach(c "" "_DEBUG" "_RELEASE" "_RELWITHDEBINFO" "_MINSIZEREL")
231   set(FLAVOR "${c}")
232   # Treat RelWithDebInfo and MinSizeRel as Release to avoid having
233   # an exponentional matrix of inclusions and exclusions of defines
234   if("${c}" STREQUAL "_RELWITHDEBINFO" OR "${c}" STREQUAL "_MINSIZEREL")
235     set(FLAVOR "_RELEASE")
236   endif()
237   set_property(
238     DIRECTORY .
239     APPEND PROPERTY COMPILE_DEFINITIONS${c} "DIRECTORY_DEF${FLAVOR}"
240     )
241   set_property(
242     TARGET Preprocess
243     PROPERTY COMPILE_DEFINITIONS${c} "TARGET_DEF${FLAVOR}"
244     )
245   set_property(
246     SOURCE preprocess.c preprocess.cxx
247     PROPERTY COMPILE_DEFINITIONS${c} "FILE_DEF${FLAVOR}"
248     )
249 endforeach()
250
251 # Add definitions with values.
252 set(DEF_TARGET_PATH "TARGET_PATH=\"${TARGET_PATH}\"")
253 set(DEF_FILE_PATH "FILE_PATH=\"${FILE_PATH}\"")
254 set_property(
255   TARGET Preprocess
256   APPEND PROPERTY COMPILE_DEFINITIONS
257   "TARGET_STRING=\"${STRING_VALUE}${SEMICOLON}\""
258   "TARGET_EXPR=${EXPR}"
259   ${DEF_TARGET_PATH}
260   )
261 set_property(
262   SOURCE preprocess.c preprocess.cxx
263   APPEND PROPERTY COMPILE_DEFINITIONS
264   "FILE_STRING=\"${STRING_VALUE}${SEMICOLON}\""
265   "FILE_EXPR=${EXPR}"
266   ${DEF_FILE_PATH}
267   )
268
269 # Try reading and writing the property value to ensure the string is
270 # preserved.
271 get_property(defs1 TARGET Preprocess PROPERTY COMPILE_DEFINITIONS)
272 set_property(TARGET Preprocess PROPERTY COMPILE_DEFINITIONS "${defs1}")
273 get_property(defs2 TARGET Preprocess PROPERTY COMPILE_DEFINITIONS)
274 if(NOT "x${defs1}" STREQUAL "x${defs2}")
275   message(FATAL_ERROR "get/set/get COMPILE_DEFINITIONS round trip failed.  "
276     "First get:\n"
277     "  ${defs1}\n"
278     "Second get:\n"
279     "  ${defs2}")
280 endif()
281
282 # Helper target for running test manually in build tree.
283 add_custom_target(drive COMMAND Preprocess)
284
285 # Configure the header file with the desired string value.
286 if(SEMICOLON)
287   string(APPEND STRING_VALUE ";")
288 endif()
289 configure_file(${Preprocess_SOURCE_DIR}/preprocess.h.in
290                ${Preprocess_BINARY_DIR}/preprocess.h)
291 include_directories(${Preprocess_BINARY_DIR})