| # Distributed under the OSI-approved BSD 3-Clause License. See accompanying |
| # file Copyright.txt or https://cmake.org/licensing for details. |
| |
| #[=======================================================================[.rst: |
| CheckPIESupported |
| ----------------- |
| |
| .. versionadded:: 3.14 |
| |
| Check whether the linker supports Position Independent Code (PIE) or No |
| Position Independent Code (NO_PIE) for executables. |
| Use this to ensure that the :prop_tgt:`POSITION_INDEPENDENT_CODE` target |
| property for executables will be honored at link time. |
| |
| .. command:: check_pie_supported |
| |
| :: |
| |
| check_pie_supported([OUTPUT_VARIABLE <output>] |
| [LANGUAGES <lang>...]) |
| |
| Options are: |
| |
| ``OUTPUT_VARIABLE <output>`` |
| Set ``<output>`` variable with details about any error. If the check is |
| bypassed because it uses cached results from a previous call, the output |
| will be empty even if errors were present in the previous call. |
| |
| ``LANGUAGES <lang>...`` |
| Check the linkers used for each of the specified languages. |
| If this option is not provided, the command checks all enabled languages. |
| |
| ``C``, ``CXX``, ``Fortran`` are supported. |
| |
| .. versionadded:: 3.23 |
| |
| ``OBJC``, ``OBJCXX``, ``CUDA``, and ``HIP`` are supported. |
| |
| It makes no sense to use this module when :policy:`CMP0083` is set to ``OLD``, |
| so the command will return an error in this case. See policy :policy:`CMP0083` |
| for details. |
| |
| Variables |
| ^^^^^^^^^ |
| |
| For each language checked, two boolean cache variables are defined. |
| |
| ``CMAKE_<lang>_LINK_PIE_SUPPORTED`` |
| Set to true if ``PIE`` is supported by the linker and false otherwise. |
| ``CMAKE_<lang>_LINK_NO_PIE_SUPPORTED`` |
| Set to true if ``NO_PIE`` is supported by the linker and false otherwise. |
| |
| Examples |
| ^^^^^^^^ |
| |
| .. code-block:: cmake |
| |
| check_pie_supported() |
| set_property(TARGET foo PROPERTY POSITION_INDEPENDENT_CODE TRUE) |
| |
| .. code-block:: cmake |
| |
| # Retrieve any error message. |
| check_pie_supported(OUTPUT_VARIABLE output LANGUAGES C) |
| set_property(TARGET foo PROPERTY POSITION_INDEPENDENT_CODE TRUE) |
| if(NOT CMAKE_C_LINK_PIE_SUPPORTED) |
| message(WARNING "PIE is not supported at link time: ${output}.\n" |
| "PIE link options will not be passed to linker.") |
| endif() |
| |
| #]=======================================================================] |
| |
| |
| include (Internal/CheckLinkerFlag) |
| |
| function (check_pie_supported) |
| cmake_policy(GET CMP0083 cmp0083) |
| |
| if (NOT cmp0083) |
| message(FATAL_ERROR "check_pie_supported: Policy CMP0083 is not set") |
| endif() |
| |
| if(cmp0083 STREQUAL "OLD") |
| message(FATAL_ERROR "check_pie_supported: Policy CMP0083 set to OLD") |
| endif() |
| |
| set(optional) |
| set(one OUTPUT_VARIABLE) |
| set(multiple LANGUAGES) |
| |
| cmake_parse_arguments(CHECK_PIE "${optional}" "${one}" "${multiple}" "${ARGN}") |
| if(CHECK_PIE_UNPARSED_ARGUMENTS) |
| message(FATAL_ERROR "check_pie_supported: Unparsed arguments: ${CHECK_PIE_UNPARSED_ARGUMENTS}") |
| endif() |
| |
| if (CHECK_PIE_LANGUAGES) |
| set (unsupported_languages "${CHECK_PIE_LANGUAGES}") |
| list (REMOVE_ITEM unsupported_languages "C" "CXX" "OBJC" "OBJCXX" "Fortran" "CUDA" "HIP") |
| if(unsupported_languages) |
| message(FATAL_ERROR "check_pie_supported: language(s) '${unsupported_languages}' not supported") |
| endif() |
| else() |
| # User did not set any languages, use defaults |
| get_property (enabled_languages GLOBAL PROPERTY ENABLED_LANGUAGES) |
| if (NOT enabled_languages) |
| return() |
| endif() |
| |
| list (FILTER enabled_languages INCLUDE REGEX "^(C|CXX|OBJC|OBJCXX|Fortran|CUDA|HIP)$") |
| if (NOT enabled_languages) |
| return() |
| endif() |
| |
| set (CHECK_PIE_LANGUAGES ${enabled_languages}) |
| endif() |
| |
| set(CMAKE_REQUIRED_QUIET TRUE) |
| set (outputs) |
| |
| foreach(lang IN LISTS CHECK_PIE_LANGUAGES) |
| if(_CMAKE_${lang}_PIE_MAY_BE_SUPPORTED_BY_LINKER) |
| if(NOT DEFINED CMAKE_${lang}_LINK_PIE_SUPPORTED) |
| cmake_check_linker_flag(${lang} |
| "${CMAKE_${lang}_LINK_OPTIONS_PIE}" |
| CMAKE_${lang}_LINK_PIE_SUPPORTED |
| OUTPUT_VARIABLE output) |
| if (NOT CMAKE_${lang}_LINK_PIE_SUPPORTED) |
| string (APPEND outputs "PIE (${lang}): ${output}\n") |
| endif() |
| endif() |
| |
| if(NOT DEFINED CMAKE_${lang}_LINK_NO_PIE_SUPPORTED) |
| cmake_check_linker_flag(${lang} |
| "${CMAKE_${lang}_LINK_OPTIONS_NO_PIE}" |
| CMAKE_${lang}_LINK_NO_PIE_SUPPORTED |
| OUTPUT_VARIABLE output) |
| if (NOT CMAKE_${lang}_LINK_NO_PIE_SUPPORTED) |
| string (APPEND outputs "NO_PIE (${lang}): ${output}\n") |
| endif() |
| endif() |
| else() |
| # no support at link time. Set cache variables to NO |
| set(CMAKE_${lang}_LINK_PIE_SUPPORTED NO CACHE INTERNAL "PIE (${lang})") |
| set(CMAKE_${lang}_LINK_NO_PIE_SUPPORTED NO CACHE INTERNAL "NO_PIE (${lang})") |
| string (APPEND outputs "PIE and NO_PIE are not supported by linker for ${lang}\n") |
| endif() |
| endforeach() |
| |
| if (CHECK_PIE_OUTPUT_VARIABLE) |
| set (${CHECK_PIE_OUTPUT_VARIABLE} "${outputs}" PARENT_SCOPE) |
| endif() |
| endfunction() |