CMakeLists.txt 10 KB

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