Просмотр исходного кода

ENH: second try for handling the linker language with integer priority values (returning a pointer to a string on the stack is no good idea)

Alex
Alexander Neundorf 18 лет назад
Родитель
Сommit
021ceea1b0

+ 1 - 1
Modules/CMakeASMCompiler.cmake.in

@@ -7,5 +7,5 @@ SET(CMAKE_ASM@ASM_DIALECT@_COMPILER_LOADED 1)
 SET(CMAKE_ASM@ASM_DIALECT@_COMPILER_ENV_VAR "@_CMAKE_ASM_COMPILER_ENV_VAR@")
 
 SET(CMAKE_ASM@ASM_DIALECT@_IGNORE_EXTENSIONS h;H;o;O;obj;OBJ;def;DEF;rc;RC)
-SET(CMAKE_ASM@ASM_DIALECT@_LINKER_PREFERENCE None)
+SET(CMAKE_ASM@ASM_DIALECT@_LINKER_PREFERENCE 0)
 

+ 1 - 1
Modules/CMakeCCompiler.cmake.in

@@ -21,7 +21,7 @@ ENDIF(CMAKE_COMPILER_IS_MINGW)
 SET(CMAKE_C_COMPILER_ID_RUN 1)
 SET(CMAKE_C_SOURCE_FILE_EXTENSIONS c)
 SET(CMAKE_C_IGNORE_EXTENSIONS h;H;o;O;obj;OBJ;def;DEF;rc;RC)
-SET(CMAKE_C_LINKER_PREFERENCE None)
+SET(CMAKE_C_LINKER_PREFERENCE 10)
 
 # save the size of void* in case where cache is removed
 # and the this file is still around

+ 1 - 1
Modules/CMakeCXXCompiler.cmake.in

@@ -21,7 +21,7 @@ ENDIF(CMAKE_COMPILER_IS_MINGW)
 SET(CMAKE_CXX_COMPILER_ID_RUN 1)
 SET(CMAKE_CXX_IGNORE_EXTENSIONS inl;h;H;o;O;obj;OBJ;def;DEF;rc;RC)
 SET(CMAKE_CXX_SOURCE_FILE_EXTENSIONS C;M;c++;cc;cpp;cxx;m;mm)
-SET(CMAKE_CXX_LINKER_PREFERENCE Prefered)
+SET(CMAKE_CXX_LINKER_PREFERENCE 30)
 
 # save the size of void* in case where cache is removed
 # and the this file is still around

+ 11 - 0
Modules/CMakeForceCompiler.cmake

@@ -38,6 +38,12 @@ MACRO(CMAKE_FORCE_C_COMPILER compiler id sizeof_void)
   SET(CMAKE_C_COMPILER_ID_RUN TRUE)
   SET(CMAKE_C_COMPILER_ID ${id})
   SET(CMAKE_C_COMPILER_WORKS TRUE)
+
+  # Set old compiler and platform id variables.
+  IF("${CMAKE_C_COMPILER_ID}" MATCHES "GNU")
+    SET(CMAKE_COMPILER_IS_GNUCC 1)
+  ENDIF("${CMAKE_C_COMPILER_ID}" MATCHES "GNU")
+
   SET(CMAKE_SIZEOF_VOID_P ${sizeof_void} CACHE STRING "sizeof void")
   SET(HAVE_CMAKE_SIZEOF_VOID_P TRUE CACHE INTERNAL "have sizeof void")
 ENDMACRO(CMAKE_FORCE_C_COMPILER)
@@ -47,5 +53,10 @@ MACRO(CMAKE_FORCE_CXX_COMPILER compiler id)
   SET(CMAKE_CXX_COMPILER_ID_RUN TRUE)
   SET(CMAKE_CXX_COMPILER_ID ${id})
   SET(CMAKE_CXX_COMPILER_WORKS TRUE)
+
+  IF("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU")
+    SET(CMAKE_COMPILER_IS_GNUCXX 1)
+  ENDIF("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU")
+
 ENDMACRO(CMAKE_FORCE_CXX_COMPILER)
 

+ 1 - 1
Modules/CMakeFortranCompiler.cmake.in

@@ -21,7 +21,7 @@ ENDIF(CMAKE_COMPILER_IS_MINGW)
 SET(CMAKE_Fortran_COMPILER_ID_RUN 1)
 SET(CMAKE_Fortran_SOURCE_FILE_EXTENSIONS f;F;f77;F77;f90;F90;for;f95;F95)
 SET(CMAKE_Fortran_IGNORE_EXTENSIONS h;H;o;O;obj;OBJ;def;DEF;rc;RC)
-SET(CMAKE_Fortran_LINKER_PREFERENCE Prefered)
+SET(CMAKE_Fortran_LINKER_PREFERENCE 20)
 IF(UNIX)
   SET(CMAKE_Fortran_OUTPUT_EXTENSION .o)
 ELSE(UNIX)

+ 1 - 1
Modules/CMakeJavaCompiler.cmake.in

@@ -5,7 +5,7 @@ SET(CMAKE_Java_ARCHIVE  "@CMAKE_Java_ARCHIVE@")
 SET(CMAKE_Java_COMPILER_LOADED 1)
 
 SET(CMAKE_Java_SOURCE_FILE_EXTENSIONS java)
-SET(CMAKE_Java_LINKER_PREFERENCE Prefered)
+SET(CMAKE_Java_LINKER_PREFERENCE 40)
 SET(CMAKE_Java_OUTPUT_EXTENSION .class)
 SET(CMAKE_STATIC_LIBRARY_PREFIX_Java "")
 SET(CMAKE_STATIC_LIBRARY_SUFFIX_Java ".jar")

+ 31 - 11
Source/cmGlobalGenerator.cxx

@@ -570,12 +570,35 @@ void cmGlobalGenerator::SetLanguageEnabledMaps(const char* l, cmMakefile* mf)
   std::string linkerPrefVar = std::string("CMAKE_") +
     std::string(l) + std::string("_LINKER_PREFERENCE");
   const char* linkerPref = mf->GetDefinition(linkerPrefVar.c_str());
-  if(!linkerPref)
+  int preference = 0;
+  if(linkerPref)
     {
-    linkerPref = "None";
+    if (sscanf(linkerPref, "%d", &preference)!=1)
+      {
+      // backward compatibility: before 2.6 LINKER_PREFERENCE
+      // was either "None" or "Prefered", and only the first character was 
+      // tested. So if there is a custom language out there and it is 
+      // "Prefered", set its preference high
+      if (linkerPref[0]=='P')
+        {
+        preference = 100;
+        }
+      else
+        {
+        preference = 0;
+        }
+      }
     }
-  this->LanguageToLinkerPreference[l] = linkerPref;
 
+  if (preference < 0)
+    {
+    std::string msg = linkerPrefVar;
+    msg += " is negative, adjusting it to 0";
+    cmSystemTools::Message(msg.c_str(), "Warning");
+    preference = 0;
+    }
+
+  this->LanguageToLinkerPreference[l] = preference;
 
   std::string outputExtensionVar = std::string("CMAKE_") +
     std::string(l) + std::string("_OUTPUT_EXTENSION");
@@ -752,10 +775,6 @@ void cmGlobalGenerator::Configure()
         }
       notFoundVars += "\n";
       }
-    cmSystemTools::Error("This project requires some variables to be set,\n"
-                         "and cmake can not find them.\n"
-                         "Please set the following variables:\n",
-                         notFoundVars.c_str());
     }
   // at this point this->LocalGenerators has been filled,
   // so create the map from project name to vector of local generators
@@ -1120,13 +1139,14 @@ void cmGlobalGenerator::GetEnabledLanguages(std::vector<std::string>& lang)
     }
 }
 
-const char* cmGlobalGenerator::GetLinkerPreference(const char* lang)
+int cmGlobalGenerator::GetLinkerPreference(const char* lang)
 {
-  if(this->LanguageToLinkerPreference.count(lang))
+  std::map<cmStdString, int>::const_iterator it = this->LanguageToLinkerPreference.find(lang);
+  if (it != this->LanguageToLinkerPreference.end())
     {
-    return this->LanguageToLinkerPreference[lang].c_str();
+    return it->second;
     }
-  return "None";
+  return 0;
 }
 
 void cmGlobalGenerator::FillProjectMap()

+ 2 - 2
Source/cmGlobalGenerator.h

@@ -153,7 +153,7 @@ public:
   ///! is an extension to be ignored
   bool IgnoreFile(const char* ext);
   ///! What is the preference for linkers and this language (None or Prefered)
-  const char* GetLinkerPreference(const char* lang);
+  int GetLinkerPreference(const char* lang);
   ///! What is the object file extension for a given source file?
   const char* GetLanguageOutputExtension(cmSourceFile const&);
 
@@ -257,7 +257,7 @@ private:
   std::map<cmStdString, cmStdString> OutputExtensions;
   std::map<cmStdString, cmStdString> LanguageToOutputExtension;
   std::map<cmStdString, cmStdString> ExtensionToLanguage;
-  std::map<cmStdString, cmStdString> LanguageToLinkerPreference; 
+  std::map<cmStdString, int> LanguageToLinkerPreference; 
 
   // this is used to improve performance 
   std::map<cmStdString,cmTarget *> TotalTargets;

+ 40 - 42
Source/cmTarget.cxx

@@ -1477,58 +1477,56 @@ const char* cmTarget::GetLinkerLanguage(cmGlobalGenerator* gg)
     const_cast<cmTarget*>(this)->SetProperty("LINKER_LANGUAGE", "CXX");
     }
   const char* linkerLang = this->GetProperty("LINKER_LANGUAGE");
-  if(linkerLang)
+  if (linkerLang==0)
     {
-    return linkerLang;
-    }
-  std::set<cmStdString> languages;
-  for(std::vector<cmSourceFile*>::const_iterator i
-        = this->SourceFiles.begin();
-      i != this->SourceFiles.end(); ++i)
-    {
-    if(const char* lang = (*i)->GetLanguage())
+    // if the property has not yet been set, collect all languages in the
+    // target and then find the language with the highest preference value
+    std::set<cmStdString> languages;
+    for(std::vector<cmSourceFile*>::const_iterator 
+        i = this->SourceFiles.begin(); i != this->SourceFiles.end(); ++i)
       {
-      languages.insert(lang);
+      if(const char* lang = (*i)->GetLanguage())
+        {
+        languages.insert(lang);
+        }
       }
-    }
-  if(languages.size() == 0)
-    {
-    return 0;
-    }
-  if(languages.size() == 1)
-    {
-    const_cast<cmTarget*>(this)->SetProperty("LINKER_LANGUAGE",
-                                             languages.begin()->c_str());
-    return this->GetProperty("LINKER_LANGUAGE");
-    }
-  const char* prefLang = 0;
-  for(std::set<cmStdString>::const_iterator s = languages.begin();
-      s != languages.end(); ++s)
-    {
-    const char* lpref = gg->GetLinkerPreference(s->c_str());
-    if(lpref[0] == 'P')
+
+    std::string linkerLangList;              // only used for the error message
+    int maxLinkerPref = 0;
+    bool multiplePreferedLanguages = false;
+    for(std::set<cmStdString>::const_iterator sit = languages.begin();
+        sit != languages.end(); ++sit)
       {
-      if(prefLang && !(*s == prefLang))
+      int linkerPref = gg->GetLinkerPreference(sit->c_str());
+      if ((linkerPref > maxLinkerPref) || (linkerLang==0))
         {
-        std::string m = "Error Target: ";
-        m += this->Name + " Contains more than one Prefered language: ";
-        m += *s;
-        m += " and ";
-        m += prefLang;
-        m += "\nYou must set the LINKER_LANGUAGE property for this target.";
-        cmSystemTools::Error(m.c_str());
+        maxLinkerPref = linkerPref;
+        linkerLang = sit->c_str();
+        linkerLangList = *sit;
+        multiplePreferedLanguages = false;
         }
-      else
+      else if (linkerPref == maxLinkerPref)
         {
-        prefLang = s->c_str();
+        linkerLangList += "; ";
+        linkerLangList += *sit;
+        multiplePreferedLanguages = true;
         }
       }
+
+    if (linkerLang!=0)
+      {
+      const_cast<cmTarget*>(this)->SetProperty("LINKER_LANGUAGE", linkerLang);
+      }
+    if (multiplePreferedLanguages)
+      {
+      cmOStringStream err;
+      err << "Error: Target " << this->Name << " contains multiple languages "
+          << "with the highest linker preference (" << maxLinkerPref << "): " 
+          << linkerLangList << "\n"
+          << "You must set the LINKER_LANGUAGE property for this target.";
+      cmSystemTools::Error(err.str().c_str());
+      }
     }
-  if(!prefLang)
-    {
-    prefLang = languages.begin()->c_str();
-    }
-  const_cast<cmTarget*>(this)->SetProperty("LINKER_LANGUAGE", prefLang);
   return this->GetProperty("LINKER_LANGUAGE");
 }