diff --git a/Modules/CMakeASMCompiler.cmake.in b/Modules/CMakeASMCompiler.cmake.in index f839a3e22..230805bf4 100644 --- a/Modules/CMakeASMCompiler.cmake.in +++ b/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) diff --git a/Modules/CMakeCCompiler.cmake.in b/Modules/CMakeCCompiler.cmake.in index b746abaf8..6a7fef818 100644 --- a/Modules/CMakeCCompiler.cmake.in +++ b/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 diff --git a/Modules/CMakeCXXCompiler.cmake.in b/Modules/CMakeCXXCompiler.cmake.in index f2c53d59c..b3a84dd1d 100644 --- a/Modules/CMakeCXXCompiler.cmake.in +++ b/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 diff --git a/Modules/CMakeForceCompiler.cmake b/Modules/CMakeForceCompiler.cmake index d104ad9c0..751fd7850 100644 --- a/Modules/CMakeForceCompiler.cmake +++ b/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) diff --git a/Modules/CMakeFortranCompiler.cmake.in b/Modules/CMakeFortranCompiler.cmake.in index a4f3941ba..67a0c64a1 100644 --- a/Modules/CMakeFortranCompiler.cmake.in +++ b/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) diff --git a/Modules/CMakeJavaCompiler.cmake.in b/Modules/CMakeJavaCompiler.cmake.in index c9eeb14c8..83c1ee44a 100644 --- a/Modules/CMakeJavaCompiler.cmake.in +++ b/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") diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index cea5b2b04..31adcf158 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/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& lang) } } -const char* cmGlobalGenerator::GetLinkerPreference(const char* lang) +int cmGlobalGenerator::GetLinkerPreference(const char* lang) { - if(this->LanguageToLinkerPreference.count(lang)) + std::map::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() diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index 959945c98..ccf00d7f5 100644 --- a/Source/cmGlobalGenerator.h +++ b/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 OutputExtensions; std::map LanguageToOutputExtension; std::map ExtensionToLanguage; - std::map LanguageToLinkerPreference; + std::map LanguageToLinkerPreference; // this is used to improve performance std::map TotalTargets; diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 70d00352f..3db4add30 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -1477,58 +1477,56 @@ const char* cmTarget::GetLinkerLanguage(cmGlobalGenerator* gg) const_cast(this)->SetProperty("LINKER_LANGUAGE", "CXX"); } const char* linkerLang = this->GetProperty("LINKER_LANGUAGE"); - if(linkerLang) + if (linkerLang==0) { - return linkerLang; - } - std::set languages; - for(std::vector::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 languages; + for(std::vector::const_iterator + i = this->SourceFiles.begin(); i != this->SourceFiles.end(); ++i) { - languages.insert(lang); - } - } - if(languages.size() == 0) - { - return 0; - } - if(languages.size() == 1) - { - const_cast(this)->SetProperty("LINKER_LANGUAGE", - languages.begin()->c_str()); - return this->GetProperty("LINKER_LANGUAGE"); - } - const char* prefLang = 0; - for(std::set::const_iterator s = languages.begin(); - s != languages.end(); ++s) - { - const char* lpref = gg->GetLinkerPreference(s->c_str()); - if(lpref[0] == 'P') - { - if(prefLang && !(*s == prefLang)) + if(const char* lang = (*i)->GetLanguage()) { - 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()); - } - else - { - prefLang = s->c_str(); + languages.insert(lang); } } + + std::string linkerLangList; // only used for the error message + int maxLinkerPref = 0; + bool multiplePreferedLanguages = false; + for(std::set::const_iterator sit = languages.begin(); + sit != languages.end(); ++sit) + { + int linkerPref = gg->GetLinkerPreference(sit->c_str()); + if ((linkerPref > maxLinkerPref) || (linkerLang==0)) + { + maxLinkerPref = linkerPref; + linkerLang = sit->c_str(); + linkerLangList = *sit; + multiplePreferedLanguages = false; + } + else if (linkerPref == maxLinkerPref) + { + linkerLangList += "; "; + linkerLangList += *sit; + multiplePreferedLanguages = true; + } + } + + if (linkerLang!=0) + { + const_cast(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(this)->SetProperty("LINKER_LANGUAGE", prefLang); return this->GetProperty("LINKER_LANGUAGE"); }