From fdb2ba2521998397d97d466b10a8ac2458363625 Mon Sep 17 00:00:00 2001 From: Ruslan Baratov Date: Tue, 7 Mar 2017 20:18:28 +0800 Subject: CheckIPOSupported: New module to check for compiler/cmake IPO support --- Help/manual/cmake-modules.7.rst | 1 + Help/module/CheckIPOSupported.rst | 1 + Help/release/dev/CheckIPOSupported.rst | 6 + Modules/CheckIPOSupported.cmake | 215 ++++++++++++++++++++++++ Modules/CheckIPOSupported/CMakeLists-C.txt.in | 8 + Modules/CheckIPOSupported/CMakeLists-CXX.txt.in | 8 + Modules/CheckIPOSupported/foo.c | 4 + Modules/CheckIPOSupported/foo.cpp | 4 + Modules/CheckIPOSupported/main.c | 6 + Modules/CheckIPOSupported/main.cpp | 6 + Modules/Platform/Linux-Intel.cmake | 5 + 11 files changed, 264 insertions(+) create mode 100644 Help/module/CheckIPOSupported.rst create mode 100644 Help/release/dev/CheckIPOSupported.rst create mode 100644 Modules/CheckIPOSupported.cmake create mode 100644 Modules/CheckIPOSupported/CMakeLists-C.txt.in create mode 100644 Modules/CheckIPOSupported/CMakeLists-CXX.txt.in create mode 100644 Modules/CheckIPOSupported/foo.c create mode 100644 Modules/CheckIPOSupported/foo.cpp create mode 100644 Modules/CheckIPOSupported/main.c create mode 100644 Modules/CheckIPOSupported/main.cpp diff --git a/Help/manual/cmake-modules.7.rst b/Help/manual/cmake-modules.7.rst index 5e96d79..1e8342c 100644 --- a/Help/manual/cmake-modules.7.rst +++ b/Help/manual/cmake-modules.7.rst @@ -27,6 +27,7 @@ All Modules /module/CheckFortranFunctionExists /module/CheckFortranSourceCompiles /module/CheckFunctionExists + /module/CheckIPOSupported /module/CheckIncludeFileCXX /module/CheckIncludeFile /module/CheckIncludeFiles diff --git a/Help/module/CheckIPOSupported.rst b/Help/module/CheckIPOSupported.rst new file mode 100644 index 0000000..9c8a77b --- /dev/null +++ b/Help/module/CheckIPOSupported.rst @@ -0,0 +1 @@ +.. cmake-module:: ../../Modules/CheckIPOSupported.cmake diff --git a/Help/release/dev/CheckIPOSupported.rst b/Help/release/dev/CheckIPOSupported.rst new file mode 100644 index 0000000..dbc84e6 --- /dev/null +++ b/Help/release/dev/CheckIPOSupported.rst @@ -0,0 +1,6 @@ +CheckIPOSupported +----------------- + +* A :module:`CheckIPOSupported` module was added to help projects + check whether interprocedural optimization (IPO) is supported by + the current toolchain and CMake version. diff --git a/Modules/CheckIPOSupported.cmake b/Modules/CheckIPOSupported.cmake new file mode 100644 index 0000000..6f7bc82 --- /dev/null +++ b/Modules/CheckIPOSupported.cmake @@ -0,0 +1,215 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +#[=======================================================================[.rst: +CheckIPOSupported +----------------- + +Check whether the compiler supports an interprocedural optimization (IPO/LTO). +Use this before enabling the :prop_tgt:`INTERPROCEDURAL_OPTIMIZATION` target +property. + +.. command:: check_ipo_supported + + :: + + check_ipo_supported([RESULT ] [OUTPUT ] + [LANGUAGES ...]) + + Options are: + + ``RESULT `` + Set ```` variable to ``YES`` if IPO is supported by the + compiler and ``NO`` otherwise. If this option is not given then + the command will issue a fatal error if IPO is not supported. + ``OUTPUT `` + Set ```` variable with details about any error. + ``LANGUAGES ...`` + Specify languages whose compilers to check. + Languages ``C`` and ``CXX`` are supported. + +Examples +^^^^^^^^ + +.. code-block:: cmake + + check_ipo_supported() # fatal error if IPO is not supported + set_property(TARGET foo PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE) + +.. code-block:: cmake + + # Optional IPO. Do not use IPO if it's not supported by compiler. + check_ipo_supported(RESULT result OUTPUT output) + if(result) + set_property(TARGET foo PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE) + else() + message(WARNING "IPO is not supported: ${output}") + endif() + +#]=======================================================================] + +include(CMakeParseArguments) # cmake_parse_arguments + +# X_RESULT - name of the final result variable +# X_OUTPUT - name of the variable with information about error +macro(_ipo_not_supported output) + string(COMPARE EQUAL "${X_RESULT}" "" is_empty) + if(is_empty) + message(FATAL_ERROR "IPO is not supported (${output}).") + endif() + + set("${X_RESULT}" NO PARENT_SCOPE) + set("${X_OUTPUT}" "${output}" PARENT_SCOPE) +endmacro() + +# Run IPO/LTO test +macro(_ipo_run_language_check language) + set(testdir "${CMAKE_CURRENT_BINARY_DIR}/_CMakeLTOTest-${language}") + + file(REMOVE_RECURSE "${testdir}") + file(MAKE_DIRECTORY "${testdir}") + + set(bindir "${testdir}/bin") + set(srcdir "${testdir}/src") + + file(MAKE_DIRECTORY "${bindir}") + file(MAKE_DIRECTORY "${srcdir}") + + set(TRY_COMPILE_PROJECT_NAME "lto-test") + + set(try_compile_src "${CMAKE_ROOT}/Modules/CheckIPOSupported") + + # Use: + # * TRY_COMPILE_PROJECT_NAME + # * CMAKE_VERSION + configure_file( + "${try_compile_src}/CMakeLists-${language}.txt.in" + "${srcdir}/CMakeLists.txt" + @ONLY + ) + + string(COMPARE EQUAL "${language}" "C" is_c) + string(COMPARE EQUAL "${language}" "CXX" is_cxx) + + if(is_c) + set(copy_sources foo.c main.c) + elseif(is_cxx) + set(copy_sources foo.cpp main.cpp) + else() + message(FATAL_ERROR "Language not supported") + endif() + + foreach(x ${copy_sources}) + configure_file( + "${try_compile_src}/${x}" + "${srcdir}/${x}" + COPYONLY + ) + endforeach() + + try_compile( + result + "${bindir}" + "${srcdir}" + "${TRY_COMPILE_PROJECT_NAME}" + CMAKE_FLAGS + "-DCMAKE_VERBOSE_MAKEFILE=ON" + "-DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON" + OUTPUT_VARIABLE output + ) + + if(NOT result) + _ipo_not_supported("${output}") + return() + endif() +endmacro() + +function(check_ipo_supported) + # TODO: IPO policy + + set(optional) + set(one RESULT OUTPUT) + set(multiple LANGUAGES) + + # Introduce: + # * X_RESULT + # * X_OUTPUT + # * X_LANGUAGES + cmake_parse_arguments(X "${optional}" "${one}" "${multiple}" "${ARGV}") + + string(COMPARE NOTEQUAL "${X_UNPARSED_ARGUMENTS}" "" has_unparsed) + if(has_unparsed) + message(FATAL_ERROR "Unparsed arguments: ${X_UNPARSED_ARGUMENTS}") + endif() + + string(COMPARE EQUAL "${X_LANGUAGES}" "" no_languages) + if(no_languages) + # User did not set any languages, use defaults + get_property(enabled_languages GLOBAL PROPERTY ENABLED_LANGUAGES) + string(COMPARE EQUAL "${enabled_languages}" "" no_languages) + if(no_languages) + _ipo_not_supported( + "no languages found in ENABLED_LANGUAGES global property" + ) + return() + endif() + + set(languages "") + list(FIND enabled_languages "CXX" result) + if(NOT result EQUAL -1) + list(APPEND languages "CXX") + endif() + + list(FIND enabled_languages "C" result) + if(NOT result EQUAL -1) + list(APPEND languages "C") + endif() + + list(FIND enabled_languages "Fortran" result) + if(NOT result EQUAL -1) + list(APPEND languages "Fortran") + endif() + + string(COMPARE EQUAL "${languages}" "" no_languages) + if(no_languages) + _ipo_not_supported( + "no C/CXX/Fortran languages found in ENABLED_LANGUAGES global property" + ) + return() + endif() + else() + set(languages "${X_LANGUAGES}") + + set(unsupported_languages "${languages}") + list(REMOVE_ITEM unsupported_languages "C" "CXX" "Fortran") + string(COMPARE NOTEQUAL "${unsupported_languages}" "" has_unsupported) + if(has_unsupported) + _ipo_not_supported( + "language(s) '${unsupported_languages}' not supported" + ) + return() + endif() + endif() + + list(FIND languages "Fortran" result) + if(NOT result EQUAL -1) + _ipo_not_supported("Fortran is not supported") + return() + endif() + + if(NOT _CMAKE_IPO_SUPPORTED_BY_CMAKE) + _ipo_not_supported("CMake doesn't support IPO for current compiler") + return() + endif() + + if(NOT _CMAKE_IPO_MAY_BE_SUPPORTED_BY_COMPILER) + _ipo_not_supported("compiler doesn't support IPO") + return() + endif() + + foreach(x ${languages}) + _ipo_run_language_check(${x}) + endforeach() + + set("${X_RESULT}" YES PARENT_SCOPE) +endfunction() diff --git a/Modules/CheckIPOSupported/CMakeLists-C.txt.in b/Modules/CheckIPOSupported/CMakeLists-C.txt.in new file mode 100644 index 0000000..d20f31f --- /dev/null +++ b/Modules/CheckIPOSupported/CMakeLists-C.txt.in @@ -0,0 +1,8 @@ +cmake_minimum_required(VERSION "@CMAKE_VERSION@") +project("@TRY_COMPILE_PROJECT_NAME@" LANGUAGES C) + +# TODO: IPO policy + +add_library(foo foo.c) +add_executable(boo main.c) +target_link_libraries(boo PUBLIC foo) diff --git a/Modules/CheckIPOSupported/CMakeLists-CXX.txt.in b/Modules/CheckIPOSupported/CMakeLists-CXX.txt.in new file mode 100644 index 0000000..4b55c70 --- /dev/null +++ b/Modules/CheckIPOSupported/CMakeLists-CXX.txt.in @@ -0,0 +1,8 @@ +cmake_minimum_required(VERSION "@CMAKE_VERSION@") +project("@TRY_COMPILE_PROJECT_NAME@" LANGUAGES CXX) + +# TODO: IPO policy + +add_library(foo foo.cpp) +add_executable(boo main.cpp) +target_link_libraries(boo PUBLIC foo) diff --git a/Modules/CheckIPOSupported/foo.c b/Modules/CheckIPOSupported/foo.c new file mode 100644 index 0000000..1e56597 --- /dev/null +++ b/Modules/CheckIPOSupported/foo.c @@ -0,0 +1,4 @@ +int foo() +{ + return 0x42; +} diff --git a/Modules/CheckIPOSupported/foo.cpp b/Modules/CheckIPOSupported/foo.cpp new file mode 100644 index 0000000..1e56597 --- /dev/null +++ b/Modules/CheckIPOSupported/foo.cpp @@ -0,0 +1,4 @@ +int foo() +{ + return 0x42; +} diff --git a/Modules/CheckIPOSupported/main.c b/Modules/CheckIPOSupported/main.c new file mode 100644 index 0000000..5be0864 --- /dev/null +++ b/Modules/CheckIPOSupported/main.c @@ -0,0 +1,6 @@ +int foo(); + +int main() +{ + return foo(); +} diff --git a/Modules/CheckIPOSupported/main.cpp b/Modules/CheckIPOSupported/main.cpp new file mode 100644 index 0000000..5be0864 --- /dev/null +++ b/Modules/CheckIPOSupported/main.cpp @@ -0,0 +1,6 @@ +int foo(); + +int main() +{ + return foo(); +} diff --git a/Modules/Platform/Linux-Intel.cmake b/Modules/Platform/Linux-Intel.cmake index 85a0772..45dc36f 100644 --- a/Modules/Platform/Linux-Intel.cmake +++ b/Modules/Platform/Linux-Intel.cmake @@ -30,12 +30,17 @@ macro(__linux_compiler_intel lang) # executables that use dlopen but do not set ENABLE_EXPORTS. set(CMAKE_SHARED_LIBRARY_LINK_${lang}_FLAGS "-rdynamic") + set(_CMAKE_IPO_SUPPORTED_BY_CMAKE YES) + if(XIAR) # INTERPROCEDURAL_OPTIMIZATION set(CMAKE_${lang}_COMPILE_OPTIONS_IPO -ipo) set(CMAKE_${lang}_CREATE_STATIC_LIBRARY_IPO "${XIAR} cr " "${XIAR} -s ") + set(_CMAKE_IPO_MAY_BE_SUPPORTED_BY_COMPILER YES) + else() + set(_CMAKE_IPO_MAY_BE_SUPPORTED_BY_COMPILER NO) endif() if(NOT CMAKE_${lang}_COMPILER_VERSION VERSION_LESS 12.0) -- cgit v0.12