| # Distributed under the OSI-approved BSD 3-Clause License. See accompanying | |
| # file LICENSE.rst or https://cmake.org/licensing for details. | |
| #[=======================================================================[.rst: | |
| CSharpUtilities | |
| --------------- | |
| .. versionadded:: 3.8 | |
| This utility module is intended to simplify the configuration of CSharp/.NET | |
| targets and provides a collection of commands for managing CSharp targets | |
| with :ref:`Visual Studio Generators`, version 2010 and newer. | |
| Load this module in a CMake project with: | |
| .. code-block:: cmake | |
| include(CSharpUtilities) | |
| Commands | |
| ^^^^^^^^ | |
| This module provides the following commands: | |
| .. rubric:: Main Commands | |
| - :command:`csharp_set_windows_forms_properties` | |
| - :command:`csharp_set_designer_cs_properties` | |
| - :command:`csharp_set_xaml_cs_properties` | |
| .. rubric:: Helper Commands | |
| - :command:`csharp_get_filename_keys` | |
| - :command:`csharp_get_filename_key_base` | |
| - :command:`csharp_get_dependentupon_name` | |
| Main Commands | |
| """"""""""""" | |
| .. command:: csharp_set_windows_forms_properties | |
| Sets source file properties for use of Windows Forms: | |
| .. code-block:: cmake | |
| csharp_set_windows_forms_properties([<files>...]) | |
| ``<files>...`` | |
| A list of zero or more source files which are relevant for setting the | |
| :prop_sf:`VS_CSHARP_<tagname>` source file properties. This typically | |
| includes files with ``.cs``, ``.resx``, and ``.Designer.cs`` extensions. | |
| Use this command when a CSharp target in the project uses Windows Forms. | |
| This command searches in the provided list of files for pairs of related | |
| files ending with ``.Designer.cs`` (*designer* files) or ``.resx`` | |
| (*resource* files). For each such file, a corresponding base ``.cs`` | |
| file is searched (with the same base name). When found, the | |
| :prop_sf:`VS_CSHARP_<tagname>` source file properties are set as follows: | |
| For the **.cs** file: | |
| - ``VS_CSHARP_SubType "Form"`` | |
| For the **.Designer.cs** file (if it exists): | |
| - ``VS_CSHARP_DependentUpon <cs-filename>`` | |
| - ``VS_CSHARP_DesignTime ""`` (tag is removed if previously defined) | |
| - ``VS_CSHARP_AutoGen ""`` (tag is removed if previously defined) | |
| For the **.resx** file (if it exists): | |
| - ``VS_RESOURCE_GENERATOR ""`` (tag is removed if previously defined) | |
| - ``VS_CSHARP_DependentUpon <cs-filename>`` | |
| - ``VS_CSHARP_SubType "Designer"`` | |
| .. command:: csharp_set_designer_cs_properties | |
| Sets source file properties for ``.Designer.cs`` files depending on | |
| sibling filenames: | |
| .. code-block:: cmake | |
| csharp_set_designer_cs_properties([<files>...]) | |
| ``<files>...`` | |
| A list of zero or more source files which are relevant for setting the | |
| :prop_sf:`VS_CSHARP_<tagname>` source file properties. This typically | |
| includes files with ``.resx``, ``.settings``, and ``.Designer.cs`` | |
| extensions. | |
| Use this command, if the CSharp target does **not** use Windows Forms | |
| (for Windows Forms use :command:`csharp_set_windows_forms_properties` | |
| instead). | |
| This command searches through the provided list for files ending in | |
| ``.Designer.cs`` (*designer* files). For each such file, it looks for | |
| sibling files with the same base name but different extensions. If a | |
| matching file is found, the appropriate source file properties are set on | |
| the corresponding ``.Designer.cs`` file based on the matched extension: | |
| If match is **.resx** file: | |
| - ``VS_CSHARP_AutoGen "True"`` | |
| - ``VS_CSHARP_DesignTime "True"`` | |
| - ``VS_CSHARP_DependentUpon <resx-filename>`` | |
| If match is **.cs** file: | |
| - ``VS_CSHARP_DependentUpon <cs-filename>`` | |
| If match is **.settings** file: | |
| - ``VS_CSHARP_AutoGen "True"`` | |
| - ``VS_CSHARP_DesignTimeSharedInput "True"`` | |
| - ``VS_CSHARP_DependentUpon <settings-filename>`` | |
| .. note:: | |
| Because the source file properties of the ``.Designer.cs`` file are set | |
| according to the found matches and every match sets the | |
| :prop_sf:`VS_CSHARP_DependentUpon <VS_CSHARP_<tagname>>` | |
| source file property, there should only be one match for | |
| each ``Designer.cs`` file. | |
| .. command:: csharp_set_xaml_cs_properties | |
| Sets source file properties for use of Windows Presentation Foundation (WPF) | |
| and XAML: | |
| .. code-block:: cmake | |
| csharp_set_xaml_cs_properties([<files>...]) | |
| Use this command, if the CSharp target uses WPF/XAML. | |
| ``<files>...`` | |
| A list of zero or more source files which are relevant for setting the | |
| :prop_sf:`VS_CSHARP_<tagname>` source file properties. This typically | |
| includes files with ``.cs``, ``.xaml``, and ``.xaml.cs`` extensions. | |
| This command searches the provided file list for files ending with | |
| ``.xaml.cs``. For each such XAML code-behind file, a corresponding | |
| ``.xaml`` file with the same base name is searched. If found, the | |
| following source file property is set on the ``.xaml.cs`` file: | |
| - ``VS_CSHARP_DependentUpon <xaml-filename>`` | |
| Helper Commands | |
| """"""""""""""" | |
| These commands are used by the above main commands and typically aren't | |
| used directly: | |
| .. command:: csharp_get_filename_keys | |
| Computes a normalized list of key values to identify source files | |
| independently of relative or absolute paths given in CMake and eliminates | |
| case sensitivity: | |
| .. code-block:: cmake | |
| csharp_get_filename_keys(<variable> [<files>...]) | |
| ``<variable>`` | |
| Name of the variable in which the list of computed keys is stored. | |
| ``<files>...`` | |
| Zero or more source file paths as given to CSharp target using commands | |
| like :command:`add_library`, or :command:`add_executable`. | |
| This command canonicalizes file paths to ensure consistent identification | |
| of source files. This is useful when source files are added to a target | |
| using different path forms. Without normalization, CMake may treat paths | |
| like ``myfile.Designer.cs`` and | |
| ``${CMAKE_CURRENT_SOURCE_DIR}/myfile.Designer.cs`` as different files, | |
| which can cause issues when setting source file properties. | |
| For example, the following code will fail to set properties because the | |
| file paths do not match exactly: | |
| .. code-block:: cmake | |
| add_library(lib myfile.cs ${CMAKE_CURRENT_SOURCE_DIR}/myfile.Designer.cs) | |
| set_source_files_properties( | |
| myfile.Designer.cs | |
| PROPERTIES VS_CSHARP_DependentUpon myfile.cs | |
| ) | |
| .. command:: csharp_get_filename_key_base | |
| Returns the full filepath and name **without** extension of a key: | |
| .. code-block:: cmake | |
| csharp_get_filename_key_base(<base> <key>) | |
| ``<base>`` | |
| Name of the variable with the computed base value of the ``<key>`` | |
| without the file extension. | |
| ``<key>`` | |
| The key of which the base will be computed. Expected to be a | |
| uppercase full filename from :command:`csharp_get_filename_keys`. | |
| .. command:: csharp_get_dependentupon_name | |
| Computes a string which can be used as value for the source file property | |
| :prop_sf:`VS_CSHARP_<tagname>` with ``<tagname>`` being ``DependentUpon``: | |
| .. code-block:: cmake | |
| csharp_get_dependentupon_name(<variable> <file>) | |
| ``<variable>`` | |
| Name of the variable with the result value. Value contains the name | |
| of the ``<file>`` without directory. | |
| ``<file>`` | |
| Filename to convert for using in the value of the | |
| ``VS_CSHARP_DependentUpon`` source file property. | |
| #]=======================================================================] | |
| function(csharp_get_filename_keys OUT) | |
| set(${OUT} "") | |
| foreach(f ${ARGN}) | |
| get_filename_component(f ${f} REALPATH) | |
| string(TOUPPER ${f} f) | |
| list(APPEND ${OUT} ${f}) | |
| endforeach() | |
| set(${OUT} "${${OUT}}" PARENT_SCOPE) | |
| endfunction() | |
| function(csharp_get_filename_key_base base key) | |
| get_filename_component(dir ${key} DIRECTORY) | |
| get_filename_component(fil ${key} NAME_WE) | |
| set(${base} "${dir}/${fil}" PARENT_SCOPE) | |
| endfunction() | |
| function(csharp_get_dependentupon_name out in) | |
| get_filename_component(${out} ${in} NAME) | |
| set(${out} ${${out}} PARENT_SCOPE) | |
| endfunction() | |
| function(csharp_set_windows_forms_properties) | |
| csharp_get_filename_keys(fileKeys ${ARGN}) | |
| foreach(key ${fileKeys}) | |
| get_filename_component(ext ${key} EXT) | |
| if(${ext} STREQUAL ".DESIGNER.CS" OR | |
| ${ext} STREQUAL ".RESX") | |
| csharp_get_filename_key_base(NAME_BASE ${key}) | |
| list(FIND fileKeys "${NAME_BASE}.CS" FILE_INDEX) | |
| if(NOT ${FILE_INDEX} EQUAL -1) | |
| list(GET ARGN ${FILE_INDEX} FILE_NAME) | |
| # set properties of main form file | |
| set_source_files_properties("${FILE_NAME}" | |
| PROPERTIES | |
| VS_CSHARP_SubType "Form") | |
| csharp_get_dependentupon_name(LINK "${FILE_NAME}") | |
| # set properties of designer file (if found) | |
| list(FIND fileKeys "${NAME_BASE}.DESIGNER.CS" FILE_INDEX) | |
| if(NOT ${FILE_INDEX} EQUAL -1) | |
| list(GET ARGN ${FILE_INDEX} FILE_NAME) | |
| set_source_files_properties("${FILE_NAME}" | |
| PROPERTIES | |
| VS_CSHARP_DependentUpon "${LINK}" | |
| VS_CSHARP_DesignTime "" | |
| VS_CSHARP_AutoGen "") | |
| endif() | |
| # set properties of corresponding resource file (if found) | |
| list(FIND fileKeys "${NAME_BASE}.RESX" FILE_INDEX) | |
| if(NOT ${FILE_INDEX} EQUAL -1) | |
| list(GET ARGN ${FILE_INDEX} FILE_NAME) | |
| set_source_files_properties("${FILE_NAME}" | |
| PROPERTIES | |
| VS_RESOURCE_GENERATOR "" | |
| VS_CSHARP_DependentUpon "${LINK}" | |
| VS_CSHARP_SubType "Designer") | |
| endif() | |
| endif() | |
| endif() | |
| endforeach() | |
| endfunction() | |
| function(csharp_set_designer_cs_properties) | |
| csharp_get_filename_keys(fileKeys ${ARGN}) | |
| set(INDEX -1) | |
| foreach(key ${fileKeys}) | |
| math(EXPR INDEX "${INDEX}+1") | |
| list(GET ARGN ${INDEX} source) | |
| get_filename_component(ext ${key} EXT) | |
| if(${ext} STREQUAL ".DESIGNER.CS") | |
| csharp_get_filename_key_base(NAME_BASE ${key}) | |
| if("${NAME_BASE}.RESX" IN_LIST fileKeys) | |
| list(FIND fileKeys "${NAME_BASE}.RESX" FILE_INDEX) | |
| list(GET ARGN ${FILE_INDEX} FILE_NAME) | |
| csharp_get_dependentupon_name(LINK "${FILE_NAME}") | |
| set_source_files_properties("${source}" | |
| PROPERTIES | |
| VS_CSHARP_AutoGen "True" | |
| VS_CSHARP_DesignTime "True" | |
| VS_CSHARP_DependentUpon "${LINK}") | |
| elseif("${NAME_BASE}.CS" IN_LIST fileKeys) | |
| list(FIND fileKeys "${NAME_BASE}.CS" FILE_INDEX) | |
| list(GET ARGN ${FILE_INDEX} FILE_NAME) | |
| csharp_get_dependentupon_name(LINK "${FILE_NAME}") | |
| set_source_files_properties("${source}" | |
| PROPERTIES | |
| VS_CSHARP_DependentUpon "${LINK}") | |
| elseif("${NAME_BASE}.SETTINGS" IN_LIST fileKeys) | |
| list(FIND fileKeys "${NAME_BASE}.SETTINGS" FILE_INDEX) | |
| list(GET ARGN ${FILE_INDEX} FILE_NAME) | |
| csharp_get_dependentupon_name(LINK "${FILE_NAME}") | |
| set_source_files_properties("${source}" | |
| PROPERTIES | |
| VS_CSHARP_AutoGen "True" | |
| VS_CSHARP_DesignTimeSharedInput "True" | |
| VS_CSHARP_DependentUpon "${LINK}") | |
| endif() | |
| endif() | |
| endforeach() | |
| endfunction() | |
| function(csharp_set_xaml_cs_properties) | |
| csharp_get_filename_keys(fileKeys ${ARGN}) | |
| set(INDEX -1) | |
| foreach(key ${fileKeys}) | |
| math(EXPR INDEX "${INDEX}+1") | |
| list(GET ARGN ${INDEX} source) | |
| get_filename_component(ext ${key} EXT) | |
| if(${ext} STREQUAL ".XAML.CS") | |
| csharp_get_filename_key_base(NAME_BASE ${key}) | |
| if("${NAME_BASE}.XAML" IN_LIST fileKeys) | |
| list(FIND fileKeys "${NAME_BASE}.XAML" FILE_INDEX) | |
| list(GET ARGN ${FILE_INDEX} FILE_NAME) | |
| csharp_get_dependentupon_name(LINK "${FILE_NAME}") | |
| set_source_files_properties("${source}" | |
| PROPERTIES | |
| VS_CSHARP_DependentUpon "${LINK}") | |
| endif() | |
| endif() | |
| endforeach() | |
| endfunction() |