mirror of
https://github.com/Kitware/CMake.git
synced 2025-10-14 02:08:27 +08:00

This adds few adjustments for position independent code descriptions. * CheckPIESupported: The output of check_pie_supported() is already logged in details by the try_compile event. To make the example a bit nicer to use in projects the message(VERBOSE) is used instead of the WARNING. In case of MSVC, there isn't anything to warn about as it isn't supported by default. Added intro code block showing how to include this module. Synced descriptions. Fixes: #22360
208 lines
6.8 KiB
CMake
208 lines
6.8 KiB
CMake
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
|
# file LICENSE.rst or https://cmake.org/licensing for details.
|
|
|
|
#[=======================================================================[.rst:
|
|
CheckPIESupported
|
|
-----------------
|
|
|
|
.. versionadded:: 3.14
|
|
|
|
This module provides a command to check whether the linker supports Position
|
|
Independent Code (PIE) or No Position Independent Code (NO_PIE) for
|
|
executables.
|
|
|
|
Load this module in a CMake project with:
|
|
|
|
.. code-block:: cmake
|
|
|
|
include(CheckPIESupported)
|
|
|
|
When setting the :prop_tgt:`POSITION_INDEPENDENT_CODE` target property,
|
|
PIC-related compile and link options are added when building library objects,
|
|
and PIE-related compile options are added when building objects of executable
|
|
targets, regardless of this module. Use this module to ensure that the
|
|
``POSITION_INDEPENDENT_CODE`` target property for executables is also honored
|
|
at link time.
|
|
|
|
Commands
|
|
^^^^^^^^
|
|
|
|
This module provides the following command:
|
|
|
|
.. command:: check_pie_supported
|
|
|
|
Checks for PIE/NO_PIE support and prepares all executables to have link
|
|
time PIE options enabled:
|
|
|
|
.. code-block:: cmake
|
|
|
|
check_pie_supported([OUTPUT_VARIABLE <output>] [LANGUAGES <langs>...])
|
|
|
|
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 <langs>...``
|
|
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.
|
|
|
|
.. note::
|
|
|
|
To use ``check_pie_supported()``, policy :policy:`CMP0083` must be set to
|
|
``NEW``; otherwise, a fatal error will occur.
|
|
|
|
Variables
|
|
^^^^^^^^^
|
|
|
|
For each language checked, the ``check_pie_supported()`` command defines two
|
|
boolean cache variables:
|
|
|
|
``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
|
|
^^^^^^^^
|
|
|
|
To enable PIE on an executable target at link time as well, include this module
|
|
and call ``check_pie_supported()`` before setting the
|
|
``POSITION_INDEPENDENT_CODE`` target property. This will determine whether the
|
|
linker for each checked language supports PIE-related link options. For
|
|
example:
|
|
|
|
.. code-block:: cmake
|
|
|
|
add_executable(foo ...)
|
|
|
|
include(CheckPIESupported)
|
|
check_pie_supported()
|
|
set_property(TARGET foo PROPERTY POSITION_INDEPENDENT_CODE TRUE)
|
|
|
|
Since not all linkers require or support PIE-related link options (for example,
|
|
``MSVC``), retrieving any error messages might be useful for logging purposes:
|
|
|
|
.. code-block:: cmake
|
|
|
|
add_executable(foo ...)
|
|
|
|
message(CHECK_START "Checking for C linker PIE support")
|
|
|
|
include(CheckPIESupported)
|
|
check_pie_supported(OUTPUT_VARIABLE output LANGUAGES C)
|
|
set_property(TARGET foo PROPERTY POSITION_INDEPENDENT_CODE TRUE)
|
|
|
|
if(CMAKE_C_LINK_PIE_SUPPORTED)
|
|
message(CHECK_PASS "yes")
|
|
else()
|
|
message(CHECK_FAIL "no")
|
|
message(VERBOSE "PIE is not supported at link time:\n${output}"
|
|
"PIE link options will not be passed to linker.")
|
|
endif()
|
|
|
|
Setting the ``POSITION_INDEPENDENT_CODE`` target property on an executable
|
|
without this module will set PIE-related compile options but not PIE-related
|
|
link options, which might not be sufficient in certain cases:
|
|
|
|
.. code-block:: cmake
|
|
|
|
add_executable(foo ...)
|
|
set_property(TARGET foo PROPERTY POSITION_INDEPENDENT_CODE TRUE)
|
|
#]=======================================================================]
|
|
|
|
|
|
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)
|
|
|
|
# Isolate the checks below from the project's PIC selection.
|
|
unset(CMAKE_POSITION_INDEPENDENT_CODE)
|
|
|
|
foreach(lang IN LISTS CHECK_PIE_LANGUAGES)
|
|
if(_CMAKE_${lang}_PIE_MAY_BE_SUPPORTED_BY_LINKER)
|
|
if(NOT DEFINED CMAKE_${lang}_LINK_PIE_SUPPORTED)
|
|
# ensure PIE compile flags are also used
|
|
list(JOIN CMAKE_${lang}_COMPILE_OPTIONS_PIE " " CMAKE_REQUIRED_FLAGS)
|
|
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()
|
|
unset(CMAKE_REQUIRED_FLAGS)
|
|
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()
|