CSharpUtilities.cmake 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  1. # Distributed under the OSI-approved BSD 3-Clause License. See accompanying
  2. # file LICENSE.rst or https://cmake.org/licensing for details.
  3. #[=======================================================================[.rst:
  4. CSharpUtilities
  5. ---------------
  6. .. versionadded:: 3.8
  7. This utility module is intended to simplify the configuration of CSharp/.NET
  8. targets and provides a collection of commands for managing CSharp targets
  9. with :ref:`Visual Studio Generators`, version 2010 and newer.
  10. Load this module in a CMake project with:
  11. .. code-block:: cmake
  12. include(CSharpUtilities)
  13. Commands
  14. ^^^^^^^^
  15. This module provides the following commands:
  16. .. rubric:: Main Commands
  17. - :command:`csharp_set_windows_forms_properties`
  18. - :command:`csharp_set_designer_cs_properties`
  19. - :command:`csharp_set_xaml_cs_properties`
  20. .. rubric:: Helper Commands
  21. - :command:`csharp_get_filename_keys`
  22. - :command:`csharp_get_filename_key_base`
  23. - :command:`csharp_get_dependentupon_name`
  24. Main Commands
  25. """""""""""""
  26. .. command:: csharp_set_windows_forms_properties
  27. Sets source file properties for use of Windows Forms:
  28. .. code-block:: cmake
  29. csharp_set_windows_forms_properties([<files>...])
  30. ``<files>...``
  31. A list of zero or more source files which are relevant for setting the
  32. :prop_sf:`VS_CSHARP_<tagname>` source file properties. This typically
  33. includes files with ``.cs``, ``.resx``, and ``.Designer.cs`` extensions.
  34. Use this command when a CSharp target in the project uses Windows Forms.
  35. This command searches in the provided list of files for pairs of related
  36. files ending with ``.Designer.cs`` (*designer* files) or ``.resx``
  37. (*resource* files). For each such file, a corresponding base ``.cs``
  38. file is searched (with the same base name). When found, the
  39. :prop_sf:`VS_CSHARP_<tagname>` source file properties are set as follows:
  40. For the **.cs** file:
  41. - ``VS_CSHARP_SubType "Form"``
  42. For the **.Designer.cs** file (if it exists):
  43. - ``VS_CSHARP_DependentUpon <cs-filename>``
  44. - ``VS_CSHARP_DesignTime ""`` (tag is removed if previously defined)
  45. - ``VS_CSHARP_AutoGen ""`` (tag is removed if previously defined)
  46. For the **.resx** file (if it exists):
  47. - ``VS_RESOURCE_GENERATOR ""`` (tag is removed if previously defined)
  48. - ``VS_CSHARP_DependentUpon <cs-filename>``
  49. - ``VS_CSHARP_SubType "Designer"``
  50. .. command:: csharp_set_designer_cs_properties
  51. Sets source file properties for ``.Designer.cs`` files depending on
  52. sibling filenames:
  53. .. code-block:: cmake
  54. csharp_set_designer_cs_properties([<files>...])
  55. ``<files>...``
  56. A list of zero or more source files which are relevant for setting the
  57. :prop_sf:`VS_CSHARP_<tagname>` source file properties. This typically
  58. includes files with ``.resx``, ``.settings``, and ``.Designer.cs``
  59. extensions.
  60. Use this command, if the CSharp target does **not** use Windows Forms
  61. (for Windows Forms use :command:`csharp_set_windows_forms_properties`
  62. instead).
  63. This command searches through the provided list for files ending in
  64. ``.Designer.cs`` (*designer* files). For each such file, it looks for
  65. sibling files with the same base name but different extensions. If a
  66. matching file is found, the appropriate source file properties are set on
  67. the corresponding ``.Designer.cs`` file based on the matched extension:
  68. If match is **.resx** file:
  69. - ``VS_CSHARP_AutoGen "True"``
  70. - ``VS_CSHARP_DesignTime "True"``
  71. - ``VS_CSHARP_DependentUpon <resx-filename>``
  72. If match is **.cs** file:
  73. - ``VS_CSHARP_DependentUpon <cs-filename>``
  74. If match is **.settings** file:
  75. - ``VS_CSHARP_AutoGen "True"``
  76. - ``VS_CSHARP_DesignTimeSharedInput "True"``
  77. - ``VS_CSHARP_DependentUpon <settings-filename>``
  78. .. note::
  79. Because the source file properties of the ``.Designer.cs`` file are set
  80. according to the found matches and every match sets the
  81. :prop_sf:`VS_CSHARP_DependentUpon <VS_CSHARP_<tagname>>`
  82. source file property, there should only be one match for
  83. each ``Designer.cs`` file.
  84. .. command:: csharp_set_xaml_cs_properties
  85. Sets source file properties for use of Windows Presentation Foundation (WPF)
  86. and XAML:
  87. .. code-block:: cmake
  88. csharp_set_xaml_cs_properties([<files>...])
  89. Use this command, if the CSharp target uses WPF/XAML.
  90. ``<files>...``
  91. A list of zero or more source files which are relevant for setting the
  92. :prop_sf:`VS_CSHARP_<tagname>` source file properties. This typically
  93. includes files with ``.cs``, ``.xaml``, and ``.xaml.cs`` extensions.
  94. This command searches the provided file list for files ending with
  95. ``.xaml.cs``. For each such XAML code-behind file, a corresponding
  96. ``.xaml`` file with the same base name is searched. If found, the
  97. following source file property is set on the ``.xaml.cs`` file:
  98. - ``VS_CSHARP_DependentUpon <xaml-filename>``
  99. Helper Commands
  100. """""""""""""""
  101. These commands are used by the above main commands and typically aren't
  102. used directly:
  103. .. command:: csharp_get_filename_keys
  104. Computes a normalized list of key values to identify source files
  105. independently of relative or absolute paths given in CMake and eliminates
  106. case sensitivity:
  107. .. code-block:: cmake
  108. csharp_get_filename_keys(<variable> [<files>...])
  109. ``<variable>``
  110. Name of the variable in which the list of computed keys is stored.
  111. ``<files>...``
  112. Zero or more source file paths as given to CSharp target using commands
  113. like :command:`add_library`, or :command:`add_executable`.
  114. This command canonicalizes file paths to ensure consistent identification
  115. of source files. This is useful when source files are added to a target
  116. using different path forms. Without normalization, CMake may treat paths
  117. like ``myfile.Designer.cs`` and
  118. ``${CMAKE_CURRENT_SOURCE_DIR}/myfile.Designer.cs`` as different files,
  119. which can cause issues when setting source file properties.
  120. For example, the following code will fail to set properties because the
  121. file paths do not match exactly:
  122. .. code-block:: cmake
  123. add_library(lib myfile.cs ${CMAKE_CURRENT_SOURCE_DIR}/myfile.Designer.cs)
  124. set_source_files_properties(
  125. myfile.Designer.cs
  126. PROPERTIES VS_CSHARP_DependentUpon myfile.cs
  127. )
  128. .. command:: csharp_get_filename_key_base
  129. Returns the full filepath and name **without** extension of a key:
  130. .. code-block:: cmake
  131. csharp_get_filename_key_base(<base> <key>)
  132. ``<base>``
  133. Name of the variable with the computed base value of the ``<key>``
  134. without the file extension.
  135. ``<key>``
  136. The key of which the base will be computed. Expected to be a
  137. uppercase full filename from :command:`csharp_get_filename_keys`.
  138. .. command:: csharp_get_dependentupon_name
  139. Computes a string which can be used as value for the source file property
  140. :prop_sf:`VS_CSHARP_<tagname>` with ``<tagname>`` being ``DependentUpon``:
  141. .. code-block:: cmake
  142. csharp_get_dependentupon_name(<variable> <file>)
  143. ``<variable>``
  144. Name of the variable with the result value. Value contains the name
  145. of the ``<file>`` without directory.
  146. ``<file>``
  147. Filename to convert for using in the value of the
  148. ``VS_CSHARP_DependentUpon`` source file property.
  149. #]=======================================================================]
  150. function(csharp_get_filename_keys OUT)
  151. set(${OUT} "")
  152. foreach(f ${ARGN})
  153. get_filename_component(f ${f} REALPATH)
  154. string(TOUPPER ${f} f)
  155. list(APPEND ${OUT} ${f})
  156. endforeach()
  157. set(${OUT} "${${OUT}}" PARENT_SCOPE)
  158. endfunction()
  159. function(csharp_get_filename_key_base base key)
  160. get_filename_component(dir ${key} DIRECTORY)
  161. get_filename_component(fil ${key} NAME_WE)
  162. set(${base} "${dir}/${fil}" PARENT_SCOPE)
  163. endfunction()
  164. function(csharp_get_dependentupon_name out in)
  165. get_filename_component(${out} ${in} NAME)
  166. set(${out} ${${out}} PARENT_SCOPE)
  167. endfunction()
  168. function(csharp_set_windows_forms_properties)
  169. csharp_get_filename_keys(fileKeys ${ARGN})
  170. foreach(key ${fileKeys})
  171. get_filename_component(ext ${key} EXT)
  172. if(${ext} STREQUAL ".DESIGNER.CS" OR
  173. ${ext} STREQUAL ".RESX")
  174. csharp_get_filename_key_base(NAME_BASE ${key})
  175. list(FIND fileKeys "${NAME_BASE}.CS" FILE_INDEX)
  176. if(NOT ${FILE_INDEX} EQUAL -1)
  177. list(GET ARGN ${FILE_INDEX} FILE_NAME)
  178. # set properties of main form file
  179. set_source_files_properties("${FILE_NAME}"
  180. PROPERTIES
  181. VS_CSHARP_SubType "Form")
  182. csharp_get_dependentupon_name(LINK "${FILE_NAME}")
  183. # set properties of designer file (if found)
  184. list(FIND fileKeys "${NAME_BASE}.DESIGNER.CS" FILE_INDEX)
  185. if(NOT ${FILE_INDEX} EQUAL -1)
  186. list(GET ARGN ${FILE_INDEX} FILE_NAME)
  187. set_source_files_properties("${FILE_NAME}"
  188. PROPERTIES
  189. VS_CSHARP_DependentUpon "${LINK}"
  190. VS_CSHARP_DesignTime ""
  191. VS_CSHARP_AutoGen "")
  192. endif()
  193. # set properties of corresponding resource file (if found)
  194. list(FIND fileKeys "${NAME_BASE}.RESX" FILE_INDEX)
  195. if(NOT ${FILE_INDEX} EQUAL -1)
  196. list(GET ARGN ${FILE_INDEX} FILE_NAME)
  197. set_source_files_properties("${FILE_NAME}"
  198. PROPERTIES
  199. VS_RESOURCE_GENERATOR ""
  200. VS_CSHARP_DependentUpon "${LINK}"
  201. VS_CSHARP_SubType "Designer")
  202. endif()
  203. endif()
  204. endif()
  205. endforeach()
  206. endfunction()
  207. function(csharp_set_designer_cs_properties)
  208. csharp_get_filename_keys(fileKeys ${ARGN})
  209. set(INDEX -1)
  210. foreach(key ${fileKeys})
  211. math(EXPR INDEX "${INDEX}+1")
  212. list(GET ARGN ${INDEX} source)
  213. get_filename_component(ext ${key} EXT)
  214. if(${ext} STREQUAL ".DESIGNER.CS")
  215. csharp_get_filename_key_base(NAME_BASE ${key})
  216. if("${NAME_BASE}.RESX" IN_LIST fileKeys)
  217. list(FIND fileKeys "${NAME_BASE}.RESX" FILE_INDEX)
  218. list(GET ARGN ${FILE_INDEX} FILE_NAME)
  219. csharp_get_dependentupon_name(LINK "${FILE_NAME}")
  220. set_source_files_properties("${source}"
  221. PROPERTIES
  222. VS_CSHARP_AutoGen "True"
  223. VS_CSHARP_DesignTime "True"
  224. VS_CSHARP_DependentUpon "${LINK}")
  225. elseif("${NAME_BASE}.CS" IN_LIST fileKeys)
  226. list(FIND fileKeys "${NAME_BASE}.CS" FILE_INDEX)
  227. list(GET ARGN ${FILE_INDEX} FILE_NAME)
  228. csharp_get_dependentupon_name(LINK "${FILE_NAME}")
  229. set_source_files_properties("${source}"
  230. PROPERTIES
  231. VS_CSHARP_DependentUpon "${LINK}")
  232. elseif("${NAME_BASE}.SETTINGS" IN_LIST fileKeys)
  233. list(FIND fileKeys "${NAME_BASE}.SETTINGS" FILE_INDEX)
  234. list(GET ARGN ${FILE_INDEX} FILE_NAME)
  235. csharp_get_dependentupon_name(LINK "${FILE_NAME}")
  236. set_source_files_properties("${source}"
  237. PROPERTIES
  238. VS_CSHARP_AutoGen "True"
  239. VS_CSHARP_DesignTimeSharedInput "True"
  240. VS_CSHARP_DependentUpon "${LINK}")
  241. endif()
  242. endif()
  243. endforeach()
  244. endfunction()
  245. function(csharp_set_xaml_cs_properties)
  246. csharp_get_filename_keys(fileKeys ${ARGN})
  247. set(INDEX -1)
  248. foreach(key ${fileKeys})
  249. math(EXPR INDEX "${INDEX}+1")
  250. list(GET ARGN ${INDEX} source)
  251. get_filename_component(ext ${key} EXT)
  252. if(${ext} STREQUAL ".XAML.CS")
  253. csharp_get_filename_key_base(NAME_BASE ${key})
  254. if("${NAME_BASE}.XAML" IN_LIST fileKeys)
  255. list(FIND fileKeys "${NAME_BASE}.XAML" FILE_INDEX)
  256. list(GET ARGN ${FILE_INDEX} FILE_NAME)
  257. csharp_get_dependentupon_name(LINK "${FILE_NAME}")
  258. set_source_files_properties("${source}"
  259. PROPERTIES
  260. VS_CSHARP_DependentUpon "${LINK}")
  261. endif()
  262. endif()
  263. endforeach()
  264. endfunction()