mirror of
https://github.com/reactos/CMake.git
synced 2024-11-23 11:39:48 +00:00
POSITION_INDEPENDENT_CODE: Manage link flags for executables
Fixes: #14983, #16561
This commit is contained in:
parent
724a0346f7
commit
c4b4d8b3a6
@ -57,6 +57,7 @@ Policies Introduced by CMake 3.14
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
CMP0083: Add PIE options when linking executable. </policy/CMP0083>
|
||||
CMP0082: Install rules from add_subdirectory() are interleaved with those in caller. </policy/CMP0082>
|
||||
|
||||
Policies Introduced by CMake 3.13
|
||||
|
24
Help/policy/CMP0083.rst
Normal file
24
Help/policy/CMP0083.rst
Normal file
@ -0,0 +1,24 @@
|
||||
CMP0083
|
||||
-------
|
||||
|
||||
To control generation of Position Independent Executable (``PIE``) or not, some
|
||||
flags are required at link time.
|
||||
|
||||
CMake 3.13 and lower did not add these link flags when
|
||||
:prop_tgt:`POSITION_INDEPENDENT_CODE` is set.
|
||||
|
||||
The ``OLD`` behavior for this policy is to not manage ``PIE`` link flags. The
|
||||
``NEW`` behavior is to add link flags if :prop_tgt:`POSITION_INDEPENDENT_CODE`
|
||||
is set:
|
||||
|
||||
* Set to ``TRUE``: flags to produce a position independent executable are
|
||||
passed to the linker step. For example ``-pie`` for ``GCC``.
|
||||
* Set to ``FALSE``: flags not to produce a position independent executable are
|
||||
passed to the linker step. For example ``-no-pie`` for ``GCC``.
|
||||
* Not set: no flags are passed to the linker step.
|
||||
|
||||
This policy was introduced in CMake version 3.14. CMake version
|
||||
|release| warns when the policy is not set and uses ``OLD`` behavior. Use
|
||||
the :command:`cmake_policy` command to set it to ``OLD`` or ``NEW`` explicitly.
|
||||
|
||||
.. include:: DEPRECATED.txt
|
6
Help/release/dev/link-option-PIE.rst
Normal file
6
Help/release/dev/link-option-PIE.rst
Normal file
@ -0,0 +1,6 @@
|
||||
link-option-PIE
|
||||
---------------
|
||||
|
||||
* Required link options to manage Position Independent Executable are now
|
||||
added when :prop_tgt:`POSITION_INDEPENDENT_CODE` is set. These flags are
|
||||
controlled by policy :policy:`CMP0083`.
|
@ -105,6 +105,12 @@ endif()
|
||||
if(NOT CMAKE_CXX_COMPILE_OPTIONS_PIE)
|
||||
set(CMAKE_CXX_COMPILE_OPTIONS_PIE ${CMAKE_C_COMPILE_OPTIONS_PIE})
|
||||
endif()
|
||||
if(NOT CMAKE_CXX_LINK_OPTIONS_PIE)
|
||||
set(CMAKE_CXX_LINK_OPTIONS_PIE ${CMAKE_C_LINK_OPTIONS_PIE})
|
||||
endif()
|
||||
if(NOT CMAKE_CXX_LINK_OPTIONS_NO_PIE)
|
||||
set(CMAKE_CXX_LINK_OPTIONS_NO_PIE ${CMAKE_C_LINK_OPTIONS_NO_PIE})
|
||||
endif()
|
||||
|
||||
if(NOT CMAKE_CXX_COMPILE_OPTIONS_DLL)
|
||||
set(CMAKE_CXX_COMPILE_OPTIONS_DLL ${CMAKE_C_COMPILE_OPTIONS_DLL})
|
||||
@ -269,4 +275,3 @@ CMAKE_VERBOSE_MAKEFILE
|
||||
)
|
||||
|
||||
set(CMAKE_CXX_INFORMATION_LOADED 1)
|
||||
|
||||
|
@ -74,6 +74,12 @@ endif()
|
||||
if(NOT CMAKE_Fortran_COMPILE_OPTIONS_PIE)
|
||||
set(CMAKE_Fortran_COMPILE_OPTIONS_PIE ${CMAKE_C_COMPILE_OPTIONS_PIE})
|
||||
endif()
|
||||
if(NOT CMAKE_Fortran_LINK_OPTIONS_PIE)
|
||||
set(CMAKE_Fortran_LINK_OPTIONS_PIE ${CMAKE_C_LINK_OPTIONS_PIE})
|
||||
endif()
|
||||
if(NOT CMAKE_Fortran_LINK_OPTIONS_NO_PIE)
|
||||
set(CMAKE_Fortran_LINK_OPTIONS_NO_PIE ${CMAKE_C_LINK_OPTIONS_NO_PIE})
|
||||
endif()
|
||||
|
||||
if(NOT CMAKE_Fortran_COMPILE_OPTIONS_DLL)
|
||||
set(CMAKE_Fortran_COMPILE_OPTIONS_DLL ${CMAKE_C_COMPILE_OPTIONS_DLL})
|
||||
|
@ -1,6 +1,9 @@
|
||||
include(Compiler/Clang)
|
||||
__compiler_clang(C)
|
||||
|
||||
set(CMAKE_C_LINK_OPTIONS_PIE ${CMAKE_C_COMPILE_OPTIONS_PIE} -Xlinker -pie)
|
||||
set(CMAKE_C_LINK_OPTIONS_NO_PIE -Xlinker -no_pie)
|
||||
|
||||
if(NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.0)
|
||||
set(CMAKE_C90_STANDARD_COMPILE_OPTION "-std=c90")
|
||||
set(CMAKE_C90_EXTENSION_COMPILE_OPTION "-std=gnu90")
|
||||
|
@ -1,6 +1,9 @@
|
||||
include(Compiler/Clang)
|
||||
__compiler_clang(CXX)
|
||||
|
||||
set(CMAKE_CXX_LINK_OPTIONS_PIE ${CMAKE_CXX_COMPILE_OPTIONS_PIE} -Xlinker -pie)
|
||||
set(CMAKE_CXX_LINK_OPTIONS_NO_PIE -Xlinker -no_pie)
|
||||
|
||||
if(NOT "x${CMAKE_CXX_SIMULATE_ID}" STREQUAL "xMSVC")
|
||||
set(CMAKE_CXX_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN "-fvisibility-inlines-hidden")
|
||||
endif()
|
||||
|
@ -21,6 +21,26 @@ else()
|
||||
macro(__compiler_clang lang)
|
||||
__compiler_gnu(${lang})
|
||||
set(CMAKE_${lang}_COMPILE_OPTIONS_PIE "-fPIE")
|
||||
# Link options for PIE are already set in 'Compiler/GNU.cmake'
|
||||
# but clang may require alternate syntax on some platforms
|
||||
if (NOT CMAKE_${lang}_FLAG_PIE)
|
||||
cmake_check_compiler_flag(${lang} "${CMAKE_${lang}_COMPILE_OPTIONS_PIE};-Xlinker;-pie"
|
||||
CMAKE_${lang}_FLAG_XLINKER_PIE)
|
||||
if (CMAKE_${lang}_FLAG_XLINKER_PIE)
|
||||
set(CMAKE_${lang}_LINK_OPTIONS_PIE ${CMAKE_${lang}_COMPILE_OPTIONS_PIE} "-Xlinker" "-pie")
|
||||
else()
|
||||
set(CMAKE_${lang}_LINK_OPTIONS_PIE "")
|
||||
endif()
|
||||
endif()
|
||||
if (NOT CMAKE_${lang}_FLAG_NO_PIE)
|
||||
cmake_check_compiler_flag(${lang} "-Xlinker;-no_pie"
|
||||
CMAKE_${lang}_FLAG_XLINKER_NO_PIE)
|
||||
if (CMAKE_${lang}_FLAG_XLINKER_NO_PIE)
|
||||
set(CMAKE_${lang}_LINK_OPTIONS_NO_PIE "-Xlinker" "-no_pie")
|
||||
else()
|
||||
set(CMAKE_${lang}_LINK_OPTIONS_NO_PIE "")
|
||||
endif()
|
||||
endif()
|
||||
set(CMAKE_INCLUDE_SYSTEM_FLAG_${lang} "-isystem ")
|
||||
set(CMAKE_${lang}_COMPILE_OPTIONS_VISIBILITY "-fvisibility=")
|
||||
if(CMAKE_${lang}_COMPILER_VERSION VERSION_LESS 3.4.0)
|
||||
|
@ -9,6 +9,7 @@ endif()
|
||||
set(__COMPILER_GNU 1)
|
||||
|
||||
include(Compiler/CMakeCommonCompilerMacros)
|
||||
include(Internal/CMakeCheckCompilerFlag)
|
||||
|
||||
macro(__compiler_gnu lang)
|
||||
# Feature flags.
|
||||
@ -16,6 +17,21 @@ macro(__compiler_gnu lang)
|
||||
set(CMAKE_${lang}_COMPILE_OPTIONS_PIC "-fPIC")
|
||||
if(NOT CMAKE_${lang}_COMPILER_VERSION VERSION_LESS 3.4)
|
||||
set(CMAKE_${lang}_COMPILE_OPTIONS_PIE "-fPIE")
|
||||
# Support of PIE at link stage depends on various elements : platform, compiler, linker
|
||||
# so the easiest way is to check if compiler supports these flags
|
||||
cmake_check_compiler_flag(${lang} "${CMAKE_${lang}_COMPILE_OPTIONS_PIE};-pie"
|
||||
CMAKE_${lang}_FLAG_PIE)
|
||||
if (CMAKE_${lang}_FLAG_PIE)
|
||||
set(CMAKE_${lang}_LINK_OPTIONS_PIE ${CMAKE_${lang}_COMPILE_OPTIONS_PIE} "-pie")
|
||||
else()
|
||||
set(CMAKE_${lang}_LINK_OPTIONS_PIE "")
|
||||
endif()
|
||||
cmake_check_compiler_flag(${lang} "-no-pie" CMAKE_${lang}_FLAG_NO_PIE)
|
||||
if (CMAKE_${lang}_FLAG_NO_PIE)
|
||||
set(CMAKE_${lang}_LINK_OPTIONS_NO_PIE "-no-pie")
|
||||
else()
|
||||
set(CMAKE_${lang}_LINK_OPTIONS_NO_PIE "")
|
||||
endif()
|
||||
endif()
|
||||
if(NOT CMAKE_${lang}_COMPILER_VERSION VERSION_LESS 4.0)
|
||||
set(CMAKE_${lang}_COMPILE_OPTIONS_VISIBILITY "-fvisibility=")
|
||||
|
@ -7,6 +7,8 @@ set(CMAKE_C_VERBOSE_FLAG "-#")
|
||||
|
||||
set(CMAKE_C_COMPILE_OPTIONS_PIC -KPIC)
|
||||
set(CMAKE_C_COMPILE_OPTIONS_PIE "")
|
||||
set(CMAKE_C_LINK_OPTIONS_PIE "")
|
||||
set(CMAKE_C_LINK_OPTIONS_NO_PIE "")
|
||||
set(CMAKE_SHARED_LIBRARY_C_FLAGS "-KPIC")
|
||||
set(CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS "-G")
|
||||
set(CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG "-R")
|
||||
|
@ -7,6 +7,8 @@ set(CMAKE_CXX_VERBOSE_FLAG "-v")
|
||||
|
||||
set(CMAKE_CXX_COMPILE_OPTIONS_PIC -KPIC)
|
||||
set(CMAKE_CXX_COMPILE_OPTIONS_PIE "")
|
||||
set(CMAKE_CXX_LINK_OPTIONS_PIE "")
|
||||
set(CMAKE_CXX_LINK_OPTIONS_NO_PIE "")
|
||||
set(CMAKE_SHARED_LIBRARY_CXX_FLAGS "-KPIC")
|
||||
set(CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS "-G")
|
||||
set(CMAKE_SHARED_LIBRARY_RUNTIME_CXX_FLAG "-R")
|
||||
|
@ -4,6 +4,8 @@ set(CMAKE_Fortran_FORMAT_FREE_FLAG "-free")
|
||||
|
||||
set(CMAKE_Fortran_COMPILE_OPTIONS_PIC "-KPIC")
|
||||
set(CMAKE_Fortran_COMPILE_OPTIONS_PIE "")
|
||||
set(CMAKE_Fortran_LINK_OPTIONS_PIE "")
|
||||
set(CMAKE_Fortran_LINK_OPTIONS_NO_PIE "")
|
||||
set(CMAKE_SHARED_LIBRARY_Fortran_FLAGS "-KPIC")
|
||||
set(CMAKE_SHARED_LIBRARY_CREATE_Fortran_FLAGS "-G")
|
||||
set(CMAKE_SHARED_LIBRARY_RUNTIME_Fortran_FLAG "-R")
|
||||
|
146
Modules/Internal/CMakeCheckCompilerFlag.cmake
Normal file
146
Modules/Internal/CMakeCheckCompilerFlag.cmake
Normal file
@ -0,0 +1,146 @@
|
||||
# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
# file Copyright.txt or https://cmake.org/licensing for details.
|
||||
|
||||
#[=[
|
||||
|
||||
NOTE: This function is used internally by CMake. Projects should not include
|
||||
this file directly.
|
||||
|
||||
The cmake_check_compiler_flag() function can be used to compile and link a
|
||||
source file to check whether a specific compiler or linker flag is supported.
|
||||
The function does not use the try_compile() command so as to avoid infinite
|
||||
recursion. It may not work for all platforms or toolchains, the caller is
|
||||
responsible for ensuring it is only called in valid situations.
|
||||
|
||||
Parameters:
|
||||
lang - Language to check.
|
||||
flag - The flag to add to the compile/link command line.
|
||||
result - Boolean output variable. It will be stored in the cache as an
|
||||
internal variable and if true, will cause future tests that assign
|
||||
to that variable to be bypassed.
|
||||
|
||||
Optional parameters:
|
||||
SRC_EXT - Overrides the extension of the source file used for the
|
||||
check. Defaults are 'c' (C), 'cxx' (CXX), 'F' (Fortran).
|
||||
COMMAND_PATTERN - Pattern to be used for the command line. The default is
|
||||
'<FLAG> -o <OUTPUT> <SOURCE>'
|
||||
FAIL_REGEX - List of additional regular expressions that, if matched by
|
||||
the output, give a failed result for the check. A common
|
||||
set of regular expressions will be included in addition to
|
||||
those given by FAIL_REGEX.
|
||||
|
||||
#]=]
|
||||
|
||||
include_guard(GLOBAL)
|
||||
include(CMakeCheckCompilerFlagCommonPatterns)
|
||||
|
||||
function(CMAKE_CHECK_COMPILER_FLAG lang flag result)
|
||||
# Cache results between runs similar to check_<lang>_source_compiles()
|
||||
if(DEFINED ${result})
|
||||
return()
|
||||
endif()
|
||||
|
||||
set(comment "Is the '${flag}' option(s) supported")
|
||||
string(REPLACE ";" " " comment "${comment}")
|
||||
|
||||
if (NOT lang MATCHES "^(C|CXX|Fortran|ASM)$")
|
||||
# other possible languages are not supported
|
||||
# log message to keep trace of this problem...
|
||||
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
|
||||
"Function 'CMAKE_CHECK_COMPILER_FLAG' called with unsupported language: ${lang}\n")
|
||||
set(${result} FALSE CACHE INTERNAL ${comment})
|
||||
return()
|
||||
endif()
|
||||
if (lang STREQUAL "ASM")
|
||||
# assume ASM compiler is a multi-language compiler, so supports C language as well
|
||||
set(check_lang C)
|
||||
else()
|
||||
set(check_lang ${lang})
|
||||
endif()
|
||||
|
||||
cmake_parse_arguments(CCCF "" "SRC_EXT;COMMAND_PATTERN" "FAIL_REGEX" ${ARGN})
|
||||
|
||||
if (NOT CCCF_COMMAND_PATTERN)
|
||||
set (CCCF_COMMAND_PATTERN "<FLAG> -o <OUTPUT> <SOURCE>")
|
||||
endif()
|
||||
|
||||
list (APPEND CCCF_FAIL_REGEX "argument unused during compilation") # clang
|
||||
if (check_lang STREQUAL "C")
|
||||
list(APPEND CCCF_FAIL_REGEX
|
||||
"command line option .* is valid for .* but not for C") # GNU
|
||||
elseif(check_lang STREQUAL "CXX")
|
||||
list(APPEND CCCF_FAIL_REGEX
|
||||
"command line option .* is valid for .* but not for C\\+\\+") # GNU
|
||||
elseif(check_lang STREQUAL "Fortran")
|
||||
list(APPEND CCCF_FAIL_REGEX
|
||||
"command line option .* is valid for .* but not for Fortran") # GNU
|
||||
endif()
|
||||
|
||||
# Add patterns for common errors
|
||||
check_compiler_flag_common_patterns(COMPILER_FLAG_COMMON_PATTERNS)
|
||||
foreach(arg IN LISTS COMPILER_FLAG_COMMON_PATTERNS)
|
||||
if(arg MATCHES "^FAIL_REGEX$")
|
||||
continue()
|
||||
endif()
|
||||
list(APPEND CCCF_FAIL_REGEX "${arg}")
|
||||
endforeach()
|
||||
|
||||
if(NOT CCCF_SRC_EXT)
|
||||
if (check_lang STREQUAL "C")
|
||||
set(CCCF_SRC_EXT c)
|
||||
elseif(check_lang STREQUAL "CXX")
|
||||
set(CCCF_SRC_EXT cxx)
|
||||
elseif(check_lang STREQUAL "Fortran")
|
||||
set(CCCF_SRC_EXT F)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Compute the directory in which to run the test.
|
||||
set(COMPILER_FLAG_DIR "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp")
|
||||
# Compute source and output files.
|
||||
set(COMPILER_FLAG_SRC
|
||||
"${COMPILER_FLAG_DIR}/CompilerFlag${lang}.${CCCF_SRC_EXT}")
|
||||
if(check_lang STREQUAL "Fortran")
|
||||
file(WRITE "${COMPILER_FLAG_SRC}"
|
||||
" program simple\n end program simple\n")
|
||||
else()
|
||||
file(WRITE "${COMPILER_FLAG_SRC}" "int main (void)\n{ return 0; }\n")
|
||||
endif()
|
||||
get_filename_component(COMPILER_FLAG_EXE "${COMPILER_FLAG_SRC}" NAME_WE)
|
||||
string(APPEND COMPILER_FLAG_EXE "${CMAKE_EXECUTABLE_SUFFIX}")
|
||||
|
||||
# Build command line
|
||||
separate_arguments(CCCF_COMMAND_PATTERN UNIX_COMMAND
|
||||
"${CCCF_COMMAND_PATTERN}")
|
||||
list(TRANSFORM CCCF_COMMAND_PATTERN REPLACE "<SOURCE>" "${COMPILER_FLAG_SRC}")
|
||||
list(TRANSFORM CCCF_COMMAND_PATTERN REPLACE "<OUTPUT>" "${COMPILER_FLAG_EXE}")
|
||||
list(TRANSFORM CCCF_COMMAND_PATTERN REPLACE "<FLAG>" "${flag}")
|
||||
|
||||
execute_process(
|
||||
COMMAND "${CMAKE_COMMAND}" -E env LC_ALL=C LC_MESSAGES=C LANG=C
|
||||
"${CMAKE_${lang}_COMPILER}" ${CCCF_COMMAND_PATTERN}
|
||||
WORKING_DIRECTORY "${COMPILER_FLAG_DIR}"
|
||||
OUTPUT_VARIABLE COMPILER_FLAG_OUTPUT
|
||||
ERROR_VARIABLE COMPILER_FLAG_OUTPUT
|
||||
RESULT_VARIABLE COMPILER_FLAG_RESULT)
|
||||
|
||||
# Record result in the cache so we can avoid re-testing every CMake run
|
||||
if (COMPILER_FLAG_RESULT)
|
||||
set(${result} FALSE CACHE INTERNAL ${comment})
|
||||
else()
|
||||
foreach(regex IN LISTS CCCF_FAIL_REGEX)
|
||||
if(COMPILER_FLAG_OUTPUT MATCHES "${regex}")
|
||||
set(${result} FALSE CACHE INTERNAL ${comment})
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
if (DEFINED ${result})
|
||||
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
|
||||
"Determining if the ${flag} option "
|
||||
"is supported for ${lang} language failed with the following output:\n"
|
||||
"${COMPILER_FLAG_OUTPUT}\n")
|
||||
return()
|
||||
endif()
|
||||
|
||||
set(${result} TRUE CACHE INTERNAL ${comment})
|
||||
endfunction()
|
@ -12,10 +12,6 @@ if(NOT DEFINED CMAKE_POSITION_INDEPENDENT_CODE
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
endif()
|
||||
|
||||
if(CMAKE_POSITION_INDEPENDENT_CODE)
|
||||
string(APPEND _ANDROID_ABI_INIT_EXE_LDFLAGS " -fPIE -pie")
|
||||
endif()
|
||||
|
||||
string(APPEND _ANDROID_ABI_INIT_EXE_LDFLAGS " -Wl,--gc-sections")
|
||||
|
||||
if(NOT _ANDROID_ABI_INIT_EXE_LDFLAGS_NO_nocopyreloc)
|
||||
|
@ -27,6 +27,8 @@ macro(__cygwin_compiler_gnu lang)
|
||||
# No -fPIC on cygwin
|
||||
set(CMAKE_${lang}_COMPILE_OPTIONS_PIC "")
|
||||
set(CMAKE_${lang}_COMPILE_OPTIONS_PIE "")
|
||||
set(CMAKE_${lang}_LINK_OPTIONS_PIE "")
|
||||
set(CMAKE_${lang}_LINK_OPTIONS_NO_PIE "")
|
||||
set(CMAKE_SHARED_LIBRARY_${lang}_FLAGS "")
|
||||
|
||||
# Initialize C link type selection flags. These flags are used when
|
||||
|
@ -1,6 +1,7 @@
|
||||
set(CMAKE_DL_LIBS "")
|
||||
set(CMAKE_C_COMPILE_OPTIONS_PIC "-fPIC")
|
||||
set(CMAKE_C_COMPILE_OPTIONS_PIE "-fPIE")
|
||||
# PIE link options are managed in Compiler/<compiler>.cmake file
|
||||
set(CMAKE_SHARED_LIBRARY_C_FLAGS "-fPIC") # -pic
|
||||
set(CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS "-shared") # -shared
|
||||
set(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "") # +s, flag for exe link to use shared lib
|
||||
|
@ -3,6 +3,8 @@ set(FUCHSIA 1)
|
||||
set(CMAKE_DL_LIBS "")
|
||||
set(CMAKE_C_COMPILE_OPTIONS_PIC "-fPIC")
|
||||
set(CMAKE_C_COMPILE_OPTIONS_PIE "-fPIE")
|
||||
set(CMAKE_C_LINK_OPTIONS_PIE ${CMAKE_C_COMPILE_OPTIONS_PIE} "-pie")
|
||||
set(CMAKE_C_LINK_OPTIONS_NO_PIE "-no-pie")
|
||||
set(CMAKE_SHARED_LIBRARY_C_FLAGS "-fPIC")
|
||||
set(CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS "-shared")
|
||||
set(CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG "-Wl,-rpath,")
|
||||
|
@ -23,6 +23,10 @@ endif()
|
||||
macro(__linux_compiler_intel lang)
|
||||
set(CMAKE_${lang}_COMPILE_OPTIONS_PIC "-fPIC")
|
||||
set(CMAKE_${lang}_COMPILE_OPTIONS_PIE "-fPIE")
|
||||
if (NOT CMAKE_${lang}_COMPILER_VERSION VERSION_LESS 13.0)
|
||||
set(CMAKE_${lang}_LINK_OPTIONS_PIE ${CMAKE_${lang}_COMPILE_OPTIONS_PIE} "-pie")
|
||||
set(CMAKE_${lang}_LINK_OPTIONS_NO_PIE "-no-pie")
|
||||
endif()
|
||||
set(CMAKE_SHARED_LIBRARY_${lang}_FLAGS "-fPIC")
|
||||
set(CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS "-shared")
|
||||
|
||||
|
@ -12,6 +12,8 @@ macro(__linux_compiler_pgi lang)
|
||||
# Shared library compile and link flags.
|
||||
set(CMAKE_${lang}_COMPILE_OPTIONS_PIC "-fPIC")
|
||||
set(CMAKE_${lang}_COMPILE_OPTIONS_PIE "")
|
||||
set(CMAKE_${lang}_LINK_OPTIONS_PIE "")
|
||||
set(CMAKE_${lang}_LINK_OPTIONS_NO_PIE "")
|
||||
set(CMAKE_SHARED_LIBRARY_${lang}_FLAGS "-fPIC")
|
||||
set(CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS "-shared")
|
||||
set(CMAKE_SHARED_LIBRARY_LINK_${lang}_FLAGS " ")
|
||||
|
@ -1,6 +1,7 @@
|
||||
set(CMAKE_DL_LIBS "")
|
||||
set(CMAKE_C_COMPILE_OPTIONS_PIC "-fPIC")
|
||||
set(CMAKE_C_COMPILE_OPTIONS_PIE "-fPIE")
|
||||
# PIE link options are managed in Compiler/<compiler>.cmake file
|
||||
set(CMAKE_SHARED_LIBRARY_C_FLAGS "-fPIC") # -pic
|
||||
set(CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS "-shared") # -shared
|
||||
set(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "") # +s, flag for exe link to use shared lib
|
||||
|
@ -1,4 +1,6 @@
|
||||
set(CMAKE_C_COMPILE_OPTIONS_PIC -K PIC)
|
||||
set(CMAKE_C_COMPILE_OPTIONS_PIE "")
|
||||
set(CMAKE_C_LINK_OPTIONS_PIE "")
|
||||
set(CMAKE_C_LINK_OPTIONS_NO_PIE "")
|
||||
set(CMAKE_SHARED_LIBRARY_C_FLAGS "-K PIC")
|
||||
include(Platform/UnixPaths)
|
||||
|
@ -1,5 +1,7 @@
|
||||
set(CMAKE_C_COMPILE_OPTIONS_PIC -K PIC)
|
||||
set(CMAKE_C_COMPILE_OPTIONS_PIE "")
|
||||
set(CMAKE_C_LINK_OPTIONS_PIE "")
|
||||
set(CMAKE_C_LINK_OPTIONS_NO_PIE "")
|
||||
set(CMAKE_SHARED_LIBRARY_C_FLAGS "-K PIC")
|
||||
set(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "-Wl,-Bexport")
|
||||
include(Platform/UnixPaths)
|
||||
|
@ -1,5 +1,7 @@
|
||||
set(CMAKE_C_COMPILE_OPTIONS_PIC -K PIC)
|
||||
set(CMAKE_C_COMPILE_OPTIONS_PIE "")
|
||||
set(CMAKE_C_LINK_OPTIONS_PIE "")
|
||||
set(CMAKE_C_LINK_OPTIONS_NO_PIE "")
|
||||
set(CMAKE_SHARED_LIBRARY_C_FLAGS "-K PIC")
|
||||
set(CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS "-Wl,-Bexport")
|
||||
include(Platform/UnixPaths)
|
||||
|
@ -72,6 +72,8 @@ macro(__windows_compiler_gnu lang)
|
||||
# No -fPIC on Windows
|
||||
set(CMAKE_${lang}_COMPILE_OPTIONS_PIC "")
|
||||
set(CMAKE_${lang}_COMPILE_OPTIONS_PIE "")
|
||||
set(CMAKE_${lang}_LINK_OPTIONS_PIE "")
|
||||
set(CMAKE_${lang}_LINK_OPTIONS_NO_PIE "")
|
||||
set(CMAKE_SHARED_LIBRARY_${lang}_FLAGS "")
|
||||
|
||||
set(CMAKE_${lang}_USE_RESPONSE_FILE_FOR_OBJECTS ${__WINDOWS_GNU_LD_RESPONSE})
|
||||
|
@ -495,6 +495,36 @@ const char* cmGeneratorTarget::GetFeature(const std::string& feature,
|
||||
return this->LocalGenerator->GetFeature(feature, config);
|
||||
}
|
||||
|
||||
const char* cmGeneratorTarget::GetLinkPIEProperty(
|
||||
const std::string& config) const
|
||||
{
|
||||
static std::string PICValue;
|
||||
|
||||
PICValue = this->GetLinkInterfaceDependentStringAsBoolProperty(
|
||||
"POSITION_INDEPENDENT_CODE", config);
|
||||
|
||||
if (PICValue == "(unset)") {
|
||||
// POSITION_INDEPENDENT_CODE is not set
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
switch (this->GetPolicyStatusCMP0083()) {
|
||||
case cmPolicies::WARN: {
|
||||
std::ostringstream e;
|
||||
e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0083);
|
||||
this->LocalGenerator->IssueMessage(cmake::AUTHOR_WARNING, e.str());
|
||||
CM_FALLTHROUGH;
|
||||
}
|
||||
case cmPolicies::OLD:
|
||||
return nullptr;
|
||||
default:
|
||||
// nothing to do
|
||||
break;
|
||||
}
|
||||
|
||||
return PICValue.c_str();
|
||||
}
|
||||
|
||||
bool cmGeneratorTarget::IsIPOEnabled(std::string const& lang,
|
||||
std::string const& config) const
|
||||
{
|
||||
@ -4237,6 +4267,29 @@ void cmGeneratorTarget::CheckPropertyCompatibility(
|
||||
}
|
||||
}
|
||||
|
||||
template <typename PropertyType>
|
||||
std::string valueAsString(PropertyType);
|
||||
template <>
|
||||
std::string valueAsString<bool>(bool value)
|
||||
{
|
||||
return value ? "TRUE" : "FALSE";
|
||||
}
|
||||
template <>
|
||||
std::string valueAsString<const char*>(const char* value)
|
||||
{
|
||||
return value ? value : "(unset)";
|
||||
}
|
||||
template <>
|
||||
std::string valueAsString<std::string>(std::string value)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
template <>
|
||||
std::string valueAsString<std::nullptr_t>(std::nullptr_t /*unused*/)
|
||||
{
|
||||
return "(unset)";
|
||||
}
|
||||
|
||||
std::string compatibilityType(CompatibleType t)
|
||||
{
|
||||
switch (t) {
|
||||
@ -4299,17 +4352,18 @@ const char* getTypedProperty<const char*>(
|
||||
return genexInterpreter->Evaluate(value, prop).c_str();
|
||||
}
|
||||
|
||||
template <typename PropertyType>
|
||||
std::string valueAsString(PropertyType);
|
||||
template <>
|
||||
std::string valueAsString<bool>(bool value)
|
||||
std::string getTypedProperty<std::string>(
|
||||
cmGeneratorTarget const* tgt, const std::string& prop,
|
||||
cmGeneratorExpressionInterpreter* genexInterpreter)
|
||||
{
|
||||
return value ? "TRUE" : "FALSE";
|
||||
}
|
||||
template <>
|
||||
std::string valueAsString<const char*>(const char* value)
|
||||
{
|
||||
return value ? value : "(unset)";
|
||||
const char* value = tgt->GetProperty(prop);
|
||||
|
||||
if (genexInterpreter == nullptr) {
|
||||
return valueAsString(value);
|
||||
}
|
||||
|
||||
return genexInterpreter->Evaluate(value, prop);
|
||||
}
|
||||
|
||||
template <typename PropertyType>
|
||||
@ -4324,6 +4378,12 @@ const char* impliedValue<const char*>(const char* /*unused*/)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
template <>
|
||||
std::string impliedValue<std::string>(
|
||||
std::string /*unused*/) // NOLINT(clang-tidy)
|
||||
{
|
||||
return std::string();
|
||||
}
|
||||
|
||||
template <typename PropertyType>
|
||||
std::pair<bool, PropertyType> consistentProperty(PropertyType lhs,
|
||||
@ -4344,6 +4404,13 @@ std::pair<bool, const char*> consistentStringProperty(const char* lhs,
|
||||
return std::make_pair(b, b ? lhs : nullptr);
|
||||
}
|
||||
|
||||
std::pair<bool, std::string> consistentStringProperty(const std::string& lhs,
|
||||
const std::string& rhs)
|
||||
{
|
||||
const bool b = lhs == rhs;
|
||||
return std::make_pair(b, b ? lhs : valueAsString(nullptr));
|
||||
}
|
||||
|
||||
std::pair<bool, const char*> consistentNumberProperty(const char* lhs,
|
||||
const char* rhs,
|
||||
CompatibleType t)
|
||||
@ -4386,9 +4453,10 @@ std::pair<bool, const char*> consistentProperty(const char* lhs,
|
||||
const char* const null_ptr = nullptr;
|
||||
|
||||
switch (t) {
|
||||
case BoolType:
|
||||
assert(false && "consistentProperty for strings called with BoolType");
|
||||
return std::pair<bool, const char*>(false, null_ptr);
|
||||
case BoolType: {
|
||||
bool same = cmSystemTools::IsOn(lhs) == cmSystemTools::IsOn(rhs);
|
||||
return std::make_pair(same, same ? lhs : nullptr);
|
||||
}
|
||||
case StringType:
|
||||
return consistentStringProperty(lhs, rhs);
|
||||
case NumberMinType:
|
||||
@ -4399,6 +4467,40 @@ std::pair<bool, const char*> consistentProperty(const char* lhs,
|
||||
return std::pair<bool, const char*>(false, null_ptr);
|
||||
}
|
||||
|
||||
std::pair<bool, std::string> consistentProperty(const std::string& lhs,
|
||||
const std::string& rhs,
|
||||
CompatibleType t)
|
||||
{
|
||||
const std::string null_ptr = valueAsString(nullptr);
|
||||
|
||||
if (lhs == null_ptr && rhs == null_ptr) {
|
||||
return std::make_pair(true, lhs);
|
||||
}
|
||||
if (lhs == null_ptr) {
|
||||
return std::make_pair(true, rhs);
|
||||
}
|
||||
if (rhs == null_ptr) {
|
||||
return std::make_pair(true, lhs);
|
||||
}
|
||||
|
||||
switch (t) {
|
||||
case BoolType: {
|
||||
bool same = cmSystemTools::IsOn(lhs) == cmSystemTools::IsOn(rhs);
|
||||
return std::make_pair(same, same ? lhs : null_ptr);
|
||||
}
|
||||
case StringType:
|
||||
return consistentStringProperty(lhs, rhs);
|
||||
case NumberMinType:
|
||||
case NumberMaxType: {
|
||||
auto value = consistentNumberProperty(lhs.c_str(), rhs.c_str(), t);
|
||||
return std::make_pair(
|
||||
value.first, value.first ? std::string(value.second) : null_ptr);
|
||||
}
|
||||
}
|
||||
assert(false && "Unreachable!");
|
||||
return std::pair<bool, std::string>(false, null_ptr);
|
||||
}
|
||||
|
||||
template <typename PropertyType>
|
||||
PropertyType checkInterfacePropertyCompatibility(cmGeneratorTarget const* tgt,
|
||||
const std::string& p,
|
||||
@ -4408,6 +4510,7 @@ PropertyType checkInterfacePropertyCompatibility(cmGeneratorTarget const* tgt,
|
||||
PropertyType* /*unused*/)
|
||||
{
|
||||
PropertyType propContent = getTypedProperty<PropertyType>(tgt, p);
|
||||
|
||||
std::vector<std::string> headPropKeys = tgt->GetPropertyKeys();
|
||||
const bool explicitlySet =
|
||||
std::find(headPropKeys.begin(), headPropKeys.end(), p) !=
|
||||
@ -4552,6 +4655,13 @@ bool cmGeneratorTarget::GetLinkInterfaceDependentBoolProperty(
|
||||
BoolType, nullptr);
|
||||
}
|
||||
|
||||
std::string cmGeneratorTarget::GetLinkInterfaceDependentStringAsBoolProperty(
|
||||
const std::string& p, const std::string& config) const
|
||||
{
|
||||
return checkInterfacePropertyCompatibility<std::string>(
|
||||
this, p, config, "FALSE", BoolType, nullptr);
|
||||
}
|
||||
|
||||
const char* cmGeneratorTarget::GetLinkInterfaceDependentStringProperty(
|
||||
const std::string& p, const std::string& config) const
|
||||
{
|
||||
|
@ -173,6 +173,8 @@ public:
|
||||
const char* GetFeature(const std::string& feature,
|
||||
const std::string& config) const;
|
||||
|
||||
const char* GetLinkPIEProperty(const std::string& config) const;
|
||||
|
||||
bool IsIPOEnabled(std::string const& lang, std::string const& config) const;
|
||||
|
||||
bool IsLinkInterfaceDependentBoolProperty(const std::string& p,
|
||||
@ -789,6 +791,9 @@ private:
|
||||
cmHeadToLinkInterfaceMap& GetHeadToLinkInterfaceUsageRequirementsMap(
|
||||
std::string const& config) const;
|
||||
|
||||
std::string GetLinkInterfaceDependentStringAsBoolProperty(
|
||||
const std::string& p, const std::string& config) const;
|
||||
|
||||
// Cache import information from properties for each configuration.
|
||||
struct ImportInfo
|
||||
{
|
||||
|
@ -1755,6 +1755,26 @@ void cmGlobalXCodeGenerator::CreateCustomRulesMakefile(
|
||||
}
|
||||
}
|
||||
|
||||
void cmGlobalXCodeGenerator::AddPositionIndependentLinkAttribute(
|
||||
cmGeneratorTarget* target, cmXCodeObject* buildSettings,
|
||||
const std::string& configName)
|
||||
{
|
||||
// For now, only EXECUTABLE is concerned
|
||||
if (target->GetType() != cmStateEnums::EXECUTABLE) {
|
||||
return;
|
||||
}
|
||||
|
||||
const char* PICValue = target->GetLinkPIEProperty(configName);
|
||||
if (PICValue == nullptr) {
|
||||
// POSITION_INDEPENDENT_CODE is not set
|
||||
return;
|
||||
}
|
||||
|
||||
buildSettings->AddAttribute(
|
||||
"LD_NO_PIE",
|
||||
this->CreateString(cmSystemTools::IsOn(PICValue) ? "NO" : "YES"));
|
||||
}
|
||||
|
||||
void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
|
||||
cmXCodeObject* buildSettings,
|
||||
const std::string& configName)
|
||||
@ -1806,6 +1826,9 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
|
||||
buildSettings->AddAttribute("LLVM_LTO", this->CreateString(ltoValue));
|
||||
}
|
||||
|
||||
// Handle PIE linker configuration
|
||||
this->AddPositionIndependentLinkAttribute(gtgt, buildSettings, configName);
|
||||
|
||||
// Add define flags
|
||||
this->CurrentLocalGenerator->AppendFlags(
|
||||
defFlags, this->CurrentMakefile->GetDefineFlags());
|
||||
|
@ -171,6 +171,9 @@ private:
|
||||
const std::string& configName);
|
||||
cmXCodeObject* CreateUtilityTarget(cmGeneratorTarget* gtgt);
|
||||
void AddDependAndLinkInformation(cmXCodeObject* target);
|
||||
void AddPositionIndependentLinkAttribute(cmGeneratorTarget* target,
|
||||
cmXCodeObject* buildSettings,
|
||||
const std::string& configName);
|
||||
void CreateBuildSettings(cmGeneratorTarget* gtgt,
|
||||
cmXCodeObject* buildSettings,
|
||||
const std::string& buildType);
|
||||
|
@ -1201,6 +1201,8 @@ void cmLocalGenerator::GetTargetFlags(
|
||||
break;
|
||||
}
|
||||
|
||||
this->AppendPositionIndependentLinkerFlags(linkFlags, target, config,
|
||||
linkLanguage);
|
||||
this->AppendIPOLinkerFlags(linkFlags, target, config, linkLanguage);
|
||||
}
|
||||
|
||||
@ -2027,6 +2029,36 @@ void cmLocalGenerator::AppendIPOLinkerFlags(std::string& flags,
|
||||
}
|
||||
}
|
||||
|
||||
void cmLocalGenerator::AppendPositionIndependentLinkerFlags(
|
||||
std::string& flags, cmGeneratorTarget* target, const std::string& config,
|
||||
const std::string& lang)
|
||||
{
|
||||
// For now, only EXECUTABLE is concerned
|
||||
if (target->GetType() != cmStateEnums::EXECUTABLE) {
|
||||
return;
|
||||
}
|
||||
|
||||
const char* PICValue = target->GetLinkPIEProperty(config);
|
||||
if (PICValue == nullptr) {
|
||||
// POSITION_INDEPENDENT_CODE is not set
|
||||
return;
|
||||
}
|
||||
|
||||
std::string name = "CMAKE_" + lang + "_LINK_OPTIONS_";
|
||||
name += cmSystemTools::IsOn(PICValue) ? "PIE" : "NO_PIE";
|
||||
|
||||
auto pieFlags = this->Makefile->GetSafeDefinition(name);
|
||||
if (pieFlags.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<std::string> flagsList;
|
||||
cmSystemTools::ExpandListArgument(pieFlags, flagsList);
|
||||
for (const auto& flag : flagsList) {
|
||||
this->AppendFlagEscape(flags, flag);
|
||||
}
|
||||
}
|
||||
|
||||
void cmLocalGenerator::AppendCompileOptions(std::string& options,
|
||||
const char* options_list,
|
||||
const char* regex) const
|
||||
|
@ -126,6 +126,10 @@ public:
|
||||
void AppendIPOLinkerFlags(std::string& flags, cmGeneratorTarget* target,
|
||||
const std::string& config,
|
||||
const std::string& lang);
|
||||
void AppendPositionIndependentLinkerFlags(std::string& flags,
|
||||
cmGeneratorTarget* target,
|
||||
const std::string& config,
|
||||
const std::string& lang);
|
||||
///! Get the include flags for the current makefile and language
|
||||
std::string GetIncludeFlags(const std::vector<std::string>& includes,
|
||||
cmGeneratorTarget* target,
|
||||
|
@ -97,6 +97,9 @@ void cmMakefileTargetGenerator::GetTargetLinkFlags(
|
||||
this->GeneratorTarget->GetLinkOptions(opts, this->ConfigName, linkLanguage);
|
||||
// LINK_OPTIONS are escaped.
|
||||
this->LocalGenerator->AppendCompileOptions(flags, opts);
|
||||
|
||||
this->LocalGenerator->AppendPositionIndependentLinkerFlags(
|
||||
flags, this->GeneratorTarget, this->ConfigName, linkLanguage);
|
||||
}
|
||||
|
||||
void cmMakefileTargetGenerator::CreateRuleFile()
|
||||
|
@ -244,7 +244,9 @@ class cmMakefile;
|
||||
SELECT(POLICY, CMP0082, \
|
||||
"Install rules from add_subdirectory() are interleaved with those " \
|
||||
"in caller.", \
|
||||
3, 14, 0, cmPolicies::WARN)
|
||||
3, 14, 0, cmPolicies::WARN) \
|
||||
SELECT(POLICY, CMP0083, "Add PIE options when linking executable.", 3, 14, \
|
||||
0, cmPolicies::WARN)
|
||||
|
||||
#define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1)
|
||||
#define CM_FOR_EACH_POLICY_ID(POLICY) \
|
||||
@ -271,7 +273,8 @@ class cmMakefile;
|
||||
F(CMP0069) \
|
||||
F(CMP0073) \
|
||||
F(CMP0076) \
|
||||
F(CMP0081)
|
||||
F(CMP0081) \
|
||||
F(CMP0083)
|
||||
|
||||
/** \class cmPolicies
|
||||
* \brief Handles changes in CMake behavior and policies
|
||||
|
@ -190,7 +190,8 @@ add_RunCMake_test(PolicyScope)
|
||||
add_RunCMake_test(WriteCompilerDetectionHeader)
|
||||
add_RunCMake_test(SourceProperties)
|
||||
if(NOT WIN32)
|
||||
add_RunCMake_test(PositionIndependentCode)
|
||||
add_RunCMake_test(PositionIndependentCode -DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME}
|
||||
-DCMAKE_CXX_COMPILER_ID=${CMAKE_CXX_COMPILER_ID})
|
||||
endif()
|
||||
if(NOT CMAKE_GENERATOR MATCHES "Visual Studio")
|
||||
add_RunCMake_test(VisibilityPreset)
|
||||
|
@ -0,0 +1,22 @@
|
||||
|
||||
include ("${RunCMake_TEST_BINARY_DIR}/${RunCMake_TEST_CONFIG}/CMP0083_config.cmake")
|
||||
|
||||
|
||||
# retrieve default type of executable
|
||||
check_executable ("${cmp0083_ref}" ref)
|
||||
|
||||
if (ref STREQUAL "PIE")
|
||||
# check no_pie executable is really no position independent
|
||||
check_executable ("${cmp0083_new_no_pie}" new_no_pie)
|
||||
if (NOT new_no_pie STREQUAL "NO_PIE")
|
||||
set (RunCMake_TEST_FAILED "CMP0083(NEW) do not produce expected executable.")
|
||||
endif()
|
||||
elseif (ref STREQUAL "NO_PIE")
|
||||
# check pie executable is really position independent
|
||||
check_executable ("${cmp0083_new_pie}" new_pie)
|
||||
if (NOT new_pie MATCHES "PIE")
|
||||
set (RunCMake_TEST_FAILED "CMP0083(NEW) do not produce expected executable.")
|
||||
endif()
|
||||
else()
|
||||
set (RunCMake_TEST_FAILED "CMP0083(NEW) unexpected result.")
|
||||
endif()
|
@ -0,0 +1,20 @@
|
||||
|
||||
include ("${RunCMake_TEST_BINARY_DIR}/${RunCMake_TEST_CONFIG}/CMP0083_config.cmake")
|
||||
|
||||
|
||||
# retrieve default type of executable
|
||||
check_executable ("${cmp0083_ref}" ref)
|
||||
|
||||
# POSITION_INDEPENDENT_CODE must not have influence on executable
|
||||
# pie and no_pie executable must have same type as reference
|
||||
check_executable ("${cmp0083_old_pie}" old_pie)
|
||||
if (NOT old_pie STREQUAL ref)
|
||||
set (RunCMake_TEST_FAILED "CMP0083(OLD) do not produce expected executable.")
|
||||
return()
|
||||
endif()
|
||||
|
||||
check_executable ("${cmp0083_old_no_pie}" old_no_pie)
|
||||
if (NOT old_no_pie STREQUAL ref)
|
||||
set (RunCMake_TEST_FAILED "CMP0083(OLD) do not produce expected executable.")
|
||||
return()
|
||||
endif()
|
45
Tests/RunCMake/PositionIndependentCode/CMP0083.cmake
Normal file
45
Tests/RunCMake/PositionIndependentCode/CMP0083.cmake
Normal file
@ -0,0 +1,45 @@
|
||||
|
||||
# create reference to detect default : PIE or not
|
||||
add_executable (cmp0083_ref main.cpp)
|
||||
|
||||
|
||||
set (CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
|
||||
cmake_policy(SET CMP0083 NEW)
|
||||
add_executable (cmp0083_new_pie main.cpp)
|
||||
|
||||
|
||||
cmake_policy(SET CMP0083 OLD)
|
||||
add_executable (cmp0083_old_pie main.cpp)
|
||||
|
||||
|
||||
set (CMAKE_POSITION_INDEPENDENT_CODE OFF)
|
||||
|
||||
cmake_policy(SET CMP0083 NEW)
|
||||
add_executable (cmp0083_new_no_pie main.cpp)
|
||||
|
||||
|
||||
cmake_policy(SET CMP0083 OLD)
|
||||
add_executable (cmp0083_old_no_pie main.cpp)
|
||||
|
||||
# high-level targets
|
||||
add_custom_target(cmp0083_new)
|
||||
add_dependencies(cmp0083_new cmp0083_ref cmp0083_new_pie cmp0083_new_no_pie)
|
||||
|
||||
# high-level targets
|
||||
add_custom_target(cmp0083_old)
|
||||
add_dependencies(cmp0083_old cmp0083_ref cmp0083_old_pie cmp0083_old_no_pie)
|
||||
|
||||
|
||||
# generate file holding paths to executables
|
||||
file (GENERATE OUTPUT "${CMAKE_BINARY_DIR}/$<CONFIG>/CMP0083_config.cmake"
|
||||
CONTENT
|
||||
[==[
|
||||
include ("${RunCMake_TEST_SOURCE_DIR}/PIE_validator.cmake")
|
||||
|
||||
set (cmp0083_ref "$<TARGET_FILE:cmp0083_ref>")
|
||||
set (cmp0083_new_pie "$<TARGET_FILE:cmp0083_new_pie>")
|
||||
set (cmp0083_old_pie "$<TARGET_FILE:cmp0083_old_pie>")
|
||||
set (cmp0083_new_no_pie "$<TARGET_FILE:cmp0083_new_no_pie>")
|
||||
set (cmp0083_old_no_pie "$<TARGET_FILE:cmp0083_old_no_pie>")
|
||||
]==])
|
@ -0,0 +1,12 @@
|
||||
|
||||
if (CMAKE_CXX_LINK_OPTIONS_PIE)
|
||||
file(WRITE "${PIE_SUPPORTED}" "\nset(PIE_SUPPORTED TRUE)\n")
|
||||
else()
|
||||
file(WRITE "${PIE_SUPPORTED}" "\nset(PIE_SUPPORTED FALSE)\n")
|
||||
endif()
|
||||
|
||||
if (CMAKE_CXX_LINK_OPTIONS_NO_PIE)
|
||||
file(APPEND "${PIE_SUPPORTED}" "\nset(NO_PIE_SUPPORTED TRUE)\n")
|
||||
else()
|
||||
file(APPEND "${PIE_SUPPORTED}" "\nset(NO_PIE_SUPPORTED FALSE)\n")
|
||||
endif()
|
@ -0,0 +1,7 @@
|
||||
|
||||
include ("${RunCMake_TEST_BINARY_DIR}/${RunCMake_TEST_CONFIG}/PIE_config.cmake")
|
||||
|
||||
check_executable ("${pie_off}" status)
|
||||
if (NOT status STREQUAL "NO_PIE")
|
||||
set (RunCMake_TEST_FAILED "Executable is NOT 'no PIE' (${status}).")
|
||||
endif()
|
@ -0,0 +1,7 @@
|
||||
|
||||
include ("${RunCMake_TEST_BINARY_DIR}/${RunCMake_TEST_CONFIG}/PIE_config.cmake")
|
||||
|
||||
check_executable ("${pie_on}" status)
|
||||
if (NOT status STREQUAL "PIE")
|
||||
set (RunCMake_TEST_FAILED "Executable is NOT 'PIE' (${status}).")
|
||||
endif()
|
19
Tests/RunCMake/PositionIndependentCode/PIE.cmake
Normal file
19
Tests/RunCMake/PositionIndependentCode/PIE.cmake
Normal file
@ -0,0 +1,19 @@
|
||||
|
||||
cmake_policy(SET CMP0083 NEW)
|
||||
|
||||
add_executable (pie_on main.cpp)
|
||||
set_property(TARGET pie_on PROPERTY POSITION_INDEPENDENT_CODE ON)
|
||||
|
||||
add_executable (pie_off main.cpp)
|
||||
set_property(TARGET pie_off PROPERTY POSITION_INDEPENDENT_CODE OFF)
|
||||
|
||||
|
||||
# generate file holding paths to executables
|
||||
file (GENERATE OUTPUT "${CMAKE_BINARY_DIR}/$<CONFIG>/PIE_config.cmake"
|
||||
CONTENT
|
||||
[==[
|
||||
include ("${RunCMake_TEST_SOURCE_DIR}/PIE_validator.cmake")
|
||||
|
||||
set (pie_on "$<TARGET_FILE:pie_on>")
|
||||
set (pie_off "$<TARGET_FILE:pie_off>")
|
||||
]==])
|
32
Tests/RunCMake/PositionIndependentCode/PIE_validator.cmake
Normal file
32
Tests/RunCMake/PositionIndependentCode/PIE_validator.cmake
Normal file
@ -0,0 +1,32 @@
|
||||
|
||||
include_guard(GLOBAL)
|
||||
|
||||
function (CHECK_EXECUTABLE executable result)
|
||||
set (${result} "UNKNOWN" PARENT_SCOPE)
|
||||
|
||||
if (CMAKE_SYSTEM_NAME STREQUAL "Darwin")
|
||||
set (tool otool -hv)
|
||||
else()
|
||||
set (tool "${CMAKE_COMMAND}" -E env LANG=C LC_ALL=C readelf -lW)
|
||||
endif()
|
||||
|
||||
execute_process(COMMAND ${tool} "${executable}"
|
||||
OUTPUT_VARIABLE output
|
||||
ERROR_VARIABLE output)
|
||||
|
||||
if (CMAKE_SYSTEM_NAME STREQUAL "Darwin")
|
||||
if (output MATCHES "( |\t)PIE( |\n|$)")
|
||||
set (${result} "PIE" PARENT_SCOPE)
|
||||
else()
|
||||
set (${result} "NO_PIE" PARENT_SCOPE)
|
||||
endif()
|
||||
else()
|
||||
if (output MATCHES "Elf file type is DYN")
|
||||
set (${result} "PIE" PARENT_SCOPE)
|
||||
elseif (output MATCHES "Elf file type is EXEC")
|
||||
set (${result} "NO_PIE" PARENT_SCOPE)
|
||||
else()
|
||||
message(SEND_ERROR "Did not find a known file type")
|
||||
endif()
|
||||
endif()
|
||||
endfunction()
|
@ -9,3 +9,65 @@ run_cmake(Conflict6)
|
||||
run_cmake(Debug)
|
||||
run_cmake(Genex1)
|
||||
run_cmake(Genex2)
|
||||
|
||||
set(RunCMake_TEST_OPTIONS "-DPIE_SUPPORTED=${RunCMake_BINARY_DIR}/PIESupported.cmake")
|
||||
run_cmake(CheckPIESupported)
|
||||
include ("${RunCMake_BINARY_DIR}/PIESupported.cmake" OPTIONAL)
|
||||
|
||||
if (PIE_SUPPORTED OR NO_PIE_SUPPORTED)
|
||||
if (CMAKE_SYSTEM_NAME MATCHES "^(Linux|(Free|Net|Open)BSD)$")
|
||||
# try to locate readelf needed for validation
|
||||
find_program (READELF NAMES readelf)
|
||||
endif()
|
||||
if (CMAKE_SYSTEM_NAME STREQUAL "Darwin")
|
||||
# try to locate otool needed for validation
|
||||
find_program (OTOOL NAMES otool)
|
||||
endif()
|
||||
|
||||
if ((READELF OR OTOOL) AND
|
||||
(CMAKE_CXX_COMPILER_ID STREQUAL "GNU"
|
||||
OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang"
|
||||
OR CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang"))
|
||||
macro(run_cmake_target test subtest)
|
||||
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${test}-build)
|
||||
set(RunCMake_TEST_NO_CLEAN 1)
|
||||
set(RunCMake_TEST_CONFIG Release)
|
||||
run_cmake_command(${test}-${subtest} ${CMAKE_COMMAND} --build . --config Release --target ${subtest} ${ARGN})
|
||||
|
||||
unset(RunCMake_TEST_BINARY_DIR)
|
||||
unset(RunCMake_TEST_NO_CLEAN)
|
||||
endmacro()
|
||||
|
||||
set(RunCMake_TEST_SOURCE_DIR "${RunCMake_SOURCE_DIR}")
|
||||
set(RunCMake_TEST_OUTPUT_MERGE TRUE)
|
||||
if (NOT RunCMake_GENERATOR_IS_MULTI_CONFIG)
|
||||
set(RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE=Release)
|
||||
endif()
|
||||
|
||||
run_cmake(PIE)
|
||||
if (PIE_SUPPORTED)
|
||||
run_cmake_target(PIE pie_on)
|
||||
endif()
|
||||
if (NO_PIE_SUPPORTED)
|
||||
run_cmake_target(PIE pie_off)
|
||||
endif()
|
||||
|
||||
run_cmake(CMP0083)
|
||||
run_cmake_target(CMP0083 cmp0083_ref)
|
||||
|
||||
# retrieve default mode
|
||||
include("${RunCMake_SOURCE_DIR}/PIE_validator.cmake")
|
||||
include("${RunCMake_BINARY_DIR}/CMP0083-build/Release/CMP0083_config.cmake")
|
||||
check_executable("${cmp0083_ref}" cmp0083_ref_mode)
|
||||
|
||||
if ((cmp0083_ref_mode STREQUAL "PIE" AND NO_PIE_SUPPORTED)
|
||||
OR (cmp0083_ref_mode STREQUAL "NO_PIE" AND PIE_SUPPORTED))
|
||||
run_cmake_target(CMP0083 cmp0083_new)
|
||||
endif()
|
||||
run_cmake_target(CMP0083 cmp0083_old)
|
||||
|
||||
unset(RunCMake_TEST_SOURCE_DIR)
|
||||
unset(RunCMake_TEST_OPTIONS)
|
||||
unset(RunCMake_TEST_OUTPUT_MERGE)
|
||||
endif()
|
||||
endif()
|
||||
|
@ -26,6 +26,7 @@
|
||||
\* CMP0073
|
||||
\* CMP0076
|
||||
\* CMP0081
|
||||
\* CMP0083
|
||||
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:3 \(include\)
|
||||
|
Loading…
Reference in New Issue
Block a user