Przeglądaj źródła

Merge topic 'ipo-clang'

7d057b27 Clang IPO (LTO) support

Acked-by: Kitware Robot <[email protected]>
Merge-request: !717
Brad King 8 lat temu
rodzic
commit
a2a13e8b48

+ 25 - 0
Modules/Compiler/Clang-FindBinUtils.cmake

@@ -0,0 +1,25 @@
+if(NOT DEFINED _CMAKE_PROCESSING_LANGUAGE OR _CMAKE_PROCESSING_LANGUAGE STREQUAL "")
+  message(FATAL_ERROR "Internal error: _CMAKE_PROCESSING_LANGUAGE is not set")
+endif()
+
+# Try to find tools in the same directory as Clang itself
+get_filename_component(__clang_hint_1 "${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER}" REALPATH)
+get_filename_component(__clang_hint_1 "${__clang_hint_1}" DIRECTORY)
+
+get_filename_component(__clang_hint_2 "${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER}" DIRECTORY)
+
+set(__clang_hints ${__clang_hint_1} ${__clang_hint_2})
+
+# http://manpages.ubuntu.com/manpages/precise/en/man1/llvm-ar.1.html
+find_program(CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_AR NAMES
+    "${_CMAKE_TOOLCHAIN_PREFIX}llvm-ar"
+    HINTS ${__clang_hints}
+    DOC "LLVM archiver"
+)
+
+# http://manpages.ubuntu.com/manpages/precise/en/man1/llvm-ranlib.1.html
+find_program(CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_RANLIB NAMES
+    "${_CMAKE_TOOLCHAIN_PREFIX}llvm-ranlib"
+    HINTS ${__clang_hints}
+    DOC "Generate index for LLVM archive"
+)

+ 48 - 6
Modules/Compiler/Clang.cmake

@@ -28,12 +28,54 @@ else()
       set(CMAKE_${lang}_COMPILE_OPTIONS_EXTERNAL_TOOLCHAIN "--gcc-toolchain=")
     endif()
 
-    set(_CMAKE_IPO_SUPPORTED_BY_CMAKE NO)
-    set(_CMAKE_IPO_MAY_BE_SUPPORTED_BY_COMPILER NO)
+    set(_CMAKE_IPO_SUPPORTED_BY_CMAKE YES)
+    set(_CMAKE_IPO_MAY_BE_SUPPORTED_BY_COMPILER YES)
 
-    unset(CMAKE_${lang}_COMPILE_OPTIONS_IPO)
-    unset(CMAKE_${lang}_ARCHIVE_CREATE_IPO)
-    unset(CMAKE_${lang}_ARCHIVE_APPEND_IPO)
-    unset(CMAKE_${lang}_ARCHIVE_FINISH_IPO)
+    string(COMPARE EQUAL "${CMAKE_${lang}_COMPILER_ID}" "AppleClang" __is_apple_clang)
+
+    # '-flto=thin' available since Clang 3.9 and Xcode 8
+    # * http://clang.llvm.org/docs/ThinLTO.html#clang-llvm
+    # * https://trac.macports.org/wiki/XcodeVersionInfo
+    set(_CMAKE_LTO_THIN TRUE)
+    if(__is_apple_clang)
+      if(CMAKE_${lang}_COMPILER_VERSION VERSION_LESS 8.0)
+        set(_CMAKE_LTO_THIN FALSE)
+      endif()
+    else()
+      if(CMAKE_${lang}_COMPILER_VERSION VERSION_LESS 3.9)
+        set(_CMAKE_LTO_THIN FALSE)
+      endif()
+    endif()
+
+    if(_CMAKE_LTO_THIN)
+      set(CMAKE_${lang}_COMPILE_OPTIONS_IPO "-flto=thin")
+    else()
+      set(CMAKE_${lang}_COMPILE_OPTIONS_IPO "-flto")
+    endif()
+
+    if(ANDROID)
+      # https://github.com/android-ndk/ndk/issues/242
+      set(CMAKE_${lang}_LINK_OPTIONS_IPO "-fuse-ld=gold")
+    endif()
+
+    if(ANDROID OR __is_apple_clang)
+      set(__ar "${CMAKE_AR}")
+      set(__ranlib "${CMAKE_RANLIB}")
+    else()
+      set(__ar "${CMAKE_${lang}_COMPILER_AR}")
+      set(__ranlib "${CMAKE_${lang}_COMPILER_RANLIB}")
+    endif()
+
+    set(CMAKE_${lang}_ARCHIVE_CREATE_IPO
+      "${__ar} cr <TARGET> <LINK_FLAGS> <OBJECTS>"
+    )
+
+    set(CMAKE_${lang}_ARCHIVE_APPEND_IPO
+      "${__ar} r <TARGET> <LINK_FLAGS> <OBJECTS>"
+    )
+
+    set(CMAKE_${lang}_ARCHIVE_FINISH_IPO
+      "${__ranlib} <TARGET>"
+    )
   endmacro()
 endif()

+ 37 - 3
Source/cmLocalGenerator.cxx

@@ -915,6 +915,9 @@ void cmLocalGenerator::GetTargetFlags(
   const char* libraryLinkVariable =
     "CMAKE_SHARED_LINKER_FLAGS"; // default to shared library
 
+  const std::string linkLanguage =
+    linkLineComputer->GetLinkerLanguage(target, buildType);
+
   switch (target->GetType()) {
     case cmStateEnums::STATIC_LIBRARY:
       this->GetStaticLibraryFlags(linkFlags, buildType, target);
@@ -976,9 +979,6 @@ void cmLocalGenerator::GetTargetFlags(
         linkFlags += this->Makefile->GetSafeDefinition(build);
         linkFlags += " ";
       }
-
-      const std::string linkLanguage =
-        linkLineComputer->GetLinkerLanguage(target, buildType);
       if (linkLanguage.empty()) {
         cmSystemTools::Error(
           "CMake can not determine linker language for target: ",
@@ -1040,6 +1040,8 @@ void cmLocalGenerator::GetTargetFlags(
     default:
       break;
   }
+
+  this->AppendIPOLinkerFlags(linkFlags, target, config, linkLanguage);
 }
 
 void cmLocalGenerator::GetTargetCompileFlags(cmGeneratorTarget* target,
@@ -1769,6 +1771,38 @@ void cmLocalGenerator::AppendFlagEscape(std::string& flags,
   this->AppendFlags(flags, this->EscapeForShell(rawFlag));
 }
 
+void cmLocalGenerator::AppendIPOLinkerFlags(std::string& flags,
+                                            cmGeneratorTarget* target,
+                                            const std::string& config,
+                                            const std::string& lang)
+{
+  if (!target->IsIPOEnabled(config)) {
+    return;
+  }
+
+  switch (target->GetType()) {
+    case cmStateEnums::EXECUTABLE:
+    case cmStateEnums::SHARED_LIBRARY:
+    case cmStateEnums::MODULE_LIBRARY:
+      break;
+    default:
+      return;
+  }
+
+  const std::string name = "CMAKE_" + lang + "_LINK_OPTIONS_IPO";
+  const char* rawFlagsList = this->Makefile->GetDefinition(name);
+  if (rawFlagsList == CM_NULLPTR) {
+    return;
+  }
+
+  std::vector<std::string> flagsList;
+  cmSystemTools::ExpandListArgument(rawFlagsList, flagsList);
+  for (std::vector<std::string>::const_iterator oi = flagsList.begin();
+       oi != flagsList.end(); ++oi) {
+    this->AppendFlagEscape(flags, *oi);
+  }
+}
+
 void cmLocalGenerator::AppendDefines(std::set<std::string>& defines,
                                      const char* defines_list) const
 {

+ 3 - 0
Source/cmLocalGenerator.h

@@ -115,6 +115,9 @@ public:
   virtual void AppendFlags(std::string& flags, const char* newFlags);
   virtual void AppendFlagEscape(std::string& flags,
                                 const std::string& rawFlag);
+  void AppendIPOLinkerFlags(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,

+ 3 - 0
Source/cmMakefileExecutableTargetGenerator.cxx

@@ -457,6 +457,9 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
     this->AddModuleDefinitionFlag(linkLineComputer.get(), linkFlags);
   }
 
+  this->LocalGenerator->AppendIPOLinkerFlags(linkFlags, this->GeneratorTarget,
+                                             this->ConfigName, linkLanguage);
+
   // Construct a list of files associated with this executable that
   // may need to be cleaned.
   std::vector<std::string> exeCleanFiles;

+ 2 - 0
Source/cmMakefileLibraryTargetGenerator.cxx

@@ -494,6 +494,8 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
   // Create set of linking flags.
   std::string linkFlags;
   this->LocalGenerator->AppendFlags(linkFlags, extraFlags);
+  this->LocalGenerator->AppendIPOLinkerFlags(linkFlags, this->GeneratorTarget,
+                                             this->ConfigName, linkLanguage);
 
   // Add OSX version flags, if any.
   if (this->GeneratorTarget->GetType() == cmStateEnums::SHARED_LIBRARY ||