1# Distributed under the OSI-approved BSD 3-Clause License. See accompanying 2# file Copyright.txt or https://cmake.org/licensing for details. 3 4#[=======================================================================[.rst: 5CheckPIESupported 6----------------- 7 8.. versionadded:: 3.14 9 10Check whether the linker supports Position Independent Code (PIE) or No 11Position Independent Code (NO_PIE) for executables. 12Use this to ensure that the :prop_tgt:`POSITION_INDEPENDENT_CODE` target 13property for executables will be honored at link time. 14 15.. command:: check_pie_supported 16 17 :: 18 19 check_pie_supported([OUTPUT_VARIABLE <output>] 20 [LANGUAGES <lang>...]) 21 22 Options are: 23 24 ``OUTPUT_VARIABLE <output>`` 25 Set ``<output>`` variable with details about any error. 26 ``LANGUAGES <lang>...`` 27 Check the linkers used for each of the specified languages. 28 Supported languages are ``C``, ``CXX``, and ``Fortran``. 29 30It makes no sense to use this module when :policy:`CMP0083` is set to ``OLD``, 31so the command will return an error in this case. See policy :policy:`CMP0083` 32for details. 33 34Variables 35^^^^^^^^^ 36 37For each language checked, two boolean cache variables are defined. 38 39 ``CMAKE_<lang>_LINK_PIE_SUPPORTED`` 40 Set to ``YES`` if ``PIE`` is supported by the linker and ``NO`` otherwise. 41 ``CMAKE_<lang>_LINK_NO_PIE_SUPPORTED`` 42 Set to ``YES`` if ``NO_PIE`` is supported by the linker and ``NO`` otherwise. 43 44Examples 45^^^^^^^^ 46 47.. code-block:: cmake 48 49 check_pie_supported() 50 set_property(TARGET foo PROPERTY POSITION_INDEPENDENT_CODE TRUE) 51 52.. code-block:: cmake 53 54 # Retrieve any error message. 55 check_pie_supported(OUTPUT_VARIABLE output LANGUAGES C) 56 set_property(TARGET foo PROPERTY POSITION_INDEPENDENT_CODE TRUE) 57 if(NOT CMAKE_C_LINK_PIE_SUPPORTED) 58 message(WARNING "PIE is not supported at link time: ${output}.\n" 59 "PIE link options will not be passed to linker.") 60 endif() 61 62#]=======================================================================] 63 64 65include (Internal/CMakeTryCompilerOrLinkerFlag) 66 67function (check_pie_supported) 68 cmake_policy(GET CMP0083 cmp0083) 69 70 if (NOT cmp0083) 71 message(FATAL_ERROR "check_pie_supported: Policy CMP0083 is not set") 72 endif() 73 74 if(cmp0083 STREQUAL "OLD") 75 message(FATAL_ERROR "check_pie_supported: Policy CMP0083 set to OLD") 76 endif() 77 78 set(optional) 79 set(one OUTPUT_VARIABLE) 80 set(multiple LANGUAGES) 81 82 cmake_parse_arguments(CHECK_PIE "${optional}" "${one}" "${multiple}" "${ARGN}") 83 if(CHECK_PIE_UNPARSED_ARGUMENTS) 84 message(FATAL_ERROR "check_pie_supported: Unparsed arguments: ${CHECK_PIE_UNPARSED_ARGUMENTS}") 85 endif() 86 87 if (CHECK_PIE_LANGUAGES) 88 set (unsupported_languages "${CHECK_PIE_LANGUAGES}") 89 list (REMOVE_ITEM unsupported_languages "C" "CXX" "Fortran") 90 if(unsupported_languages) 91 message(FATAL_ERROR "check_pie_supported: language(s) '${unsupported_languages}' not supported") 92 endif() 93 else() 94 # User did not set any languages, use defaults 95 get_property (enabled_languages GLOBAL PROPERTY ENABLED_LANGUAGES) 96 if (NOT enabled_languages) 97 return() 98 endif() 99 100 list (FILTER enabled_languages INCLUDE REGEX "^(C|CXX|Fortran)$") 101 if (NOT enabled_languages) 102 return() 103 endif() 104 105 set (CHECK_PIE_LANGUAGES ${enabled_languages}) 106 endif() 107 108 set (outputs) 109 110 foreach(lang IN LISTS CHECK_PIE_LANGUAGES) 111 if(_CMAKE_${lang}_PIE_MAY_BE_SUPPORTED_BY_LINKER) 112 cmake_try_compiler_or_linker_flag(${lang} 113 "${CMAKE_${lang}_LINK_OPTIONS_PIE}" 114 CMAKE_${lang}_LINK_PIE_SUPPORTED 115 OUTPUT_VARIABLE output) 116 if (NOT CMAKE_${lang}_LINK_PIE_SUPPORTED) 117 string (APPEND outputs "PIE (${lang}): ${output}\n") 118 endif() 119 120 cmake_try_compiler_or_linker_flag(${lang} 121 "${CMAKE_${lang}_LINK_OPTIONS_NO_PIE}" 122 CMAKE_${lang}_LINK_NO_PIE_SUPPORTED 123 OUTPUT_VARIABLE output) 124 if (NOT CMAKE_${lang}_LINK_NO_PIE_SUPPORTED) 125 string (APPEND outputs "NO_PIE (${lang}): ${output}\n") 126 endif() 127 else() 128 # no support at link time. Set cache variables to NO 129 set(CMAKE_${lang}_LINK_PIE_SUPPORTED NO CACHE INTERNAL "PIE (${lang})") 130 set(CMAKE_${lang}_LINK_NO_PIE_SUPPORTED NO CACHE INTERNAL "NO_PIE (${lang})") 131 string (APPEND outputs "PIE and NO_PIE are not supported by linker for ${lang}") 132 endif() 133 endforeach() 134 135 if (CHECK_PIE_OUTPUT_VARIABLE) 136 set (${CHECK_PIE_OUTPUT_VARIABLE} "${outputs}" PARENT_SCOPE) 137 endif() 138endfunction() 139