diff --git a/Modules/CMakeDetermineFortranCompiler.cmake b/Modules/CMakeDetermineFortranCompiler.cmake index cff5ba4d1..53a1c7591 100644 --- a/Modules/CMakeDetermineFortranCompiler.cmake +++ b/Modules/CMakeDetermineFortranCompiler.cmake @@ -48,7 +48,7 @@ IF(NOT CMAKE_Fortran_COMPILER) # CMake/Source/CMakeLists.txt, IF YOU CHANGE THIS LIST, # PLEASE UPDATE THAT FILE AS WELL! SET(CMAKE_Fortran_COMPILER_LIST ifort ifc efc f95 pgf95 - lf95 xlf95 fort gfortran f90 pgf90 xlf90 epcf90 f77 fort77 frt pgf77 xlf fl32 af77 g77 ) + lf95 xlf95 fort gfortran f90 pgf90 xlf90 epcf90 fort77 frt pgf77 xlf fl32 af77 g77 f77 ) FIND_PROGRAM(CMAKE_Fortran_COMPILER_FULLPATH NAMES ${CMAKE_Fortran_COMPILER_LIST} ) GET_FILENAME_COMPONENT(CMAKE_Fortran_COMPILER_INIT ${CMAKE_Fortran_COMPILER_FULLPATH} NAME) diff --git a/Modules/Platform/Windows-g77.cmake b/Modules/Platform/Windows-g77.cmake new file mode 100644 index 000000000..7ab664b17 --- /dev/null +++ b/Modules/Platform/Windows-g77.cmake @@ -0,0 +1,15 @@ +SET(CMAKE_LINK_LIBRARY_SUFFIX "") +SET(CMAKE_STATIC_LIBRARY_PREFIX "lib") +SET(CMAKE_STATIC_LIBRARY_SUFFIX ".a") +SET(CMAKE_SHARED_LIBRARY_PREFIX "lib") # lib +SET(CMAKE_SHARED_LIBRARY_SUFFIX ".dll") # .so +SET(CMAKE_SHARED_MODULE_PREFIX "lib") # lib +SET(CMAKE_SHARED_MODULE_SUFFIX ".dll") # .so +SET(CMAKE_DL_LIBS "") +SET(CMAKE_SHARED_LIBRARY_C_FLAGS "") # -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 +SET(CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG "") # -rpath +SET(CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG_SEP "") # : or empty +SET(CMAKE_LIBRARY_PATH_FLAG "-L") +SET(CMAKE_LINK_LIBRARY_FLAG "-l") diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index fa4f3d80f..e91f579b6 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -19,6 +19,7 @@ #include "cmake.h" #include "cmMakefile.h" #include "cmGeneratedFileStream.h" +#include "cmSourceFile.h" cmLocalGenerator::cmLocalGenerator() { @@ -26,6 +27,9 @@ cmLocalGenerator::cmLocalGenerator() m_Makefile->SetLocalGenerator(this); m_ExcludeFromAll = false; m_Parent = 0; + m_WindowsShell = false; + m_IgnoreLibPrefix = false; + m_UseRelativePaths = false; } cmLocalGenerator::~cmLocalGenerator() @@ -339,32 +343,31 @@ std::string cmLocalGenerator::GetFullTargetName(const char* n, { const char* targetPrefix = t.GetProperty("PREFIX"); const char* targetSuffix = t.GetProperty("SUFFIX"); - const char* prefixVar = 0; - const char* suffixVar = 0; - switch(t.GetType()) + if(!targetSuffix && t.GetType() == cmTarget::EXECUTABLE) { - case cmTarget::STATIC_LIBRARY: - prefixVar = "CMAKE_STATIC_LIBRARY_PREFIX"; - suffixVar = "CMAKE_STATIC_LIBRARY_SUFFIX"; - break; - case cmTarget::SHARED_LIBRARY: - prefixVar = "CMAKE_SHARED_LIBRARY_PREFIX"; - suffixVar = "CMAKE_SHARED_LIBRARY_SUFFIX"; - break; - case cmTarget::MODULE_LIBRARY: - prefixVar = "CMAKE_SHARED_MODULE_PREFIX"; - suffixVar = "CMAKE_SHARED_MODULE_SUFFIX"; - break; - case cmTarget::EXECUTABLE: targetSuffix = cmSystemTools::GetExecutableExtension(); - case cmTarget::UTILITY: - case cmTarget::INSTALL_FILES: - case cmTarget::INSTALL_PROGRAMS: - break; } + const char* prefixVar = t.GetPrefixVariable(); + const char* suffixVar = t.GetSuffixVariable(); + const char* ll = t.GetLinkerLanguage(this->GetGlobalGenerator()); + // first try language specific suffix + if(ll) + { + if(!targetSuffix) + { + std::string langSuff = suffixVar + std::string("_") + ll; + targetSuffix = m_Makefile->GetDefinition(langSuff.c_str()); + } + if(!targetPrefix) + { + std::string langPrefix = prefixVar + std::string("_") + ll; + targetPrefix = m_Makefile->GetDefinition(langPrefix.c_str()); + } + } + // if there is no prefix on the target use the cmake definition if(!targetPrefix && prefixVar) - { + { targetPrefix = m_Makefile->GetSafeDefinition(prefixVar); } // if there is no suffix on the target use the cmake definition @@ -451,5 +454,780 @@ std::string cmLocalGenerator::ConvertToRelativeOutputPath(const char* p) return ret; } +void cmLocalGenerator::AddCustomCommandToCreateObject(const char* ofname, + const char* lang, + cmSourceFile& source, + cmTarget& target) +{ + std::string objectFile = this->ConvertToRelativeOutputPath(ofname); + std::string sourceFile = this->ConvertToRelativeOutputPath(source.GetFullPath().c_str()); + std::string varString = "CMAKE_"; + varString += lang; + varString += "_COMPILE_OBJECT"; + std::vector rules; + rules.push_back(m_Makefile->GetRequiredDefinition(varString.c_str())); + varString = "CMAKE_"; + varString += lang; + varString += "_FLAGS"; + std::string flags; + flags += m_Makefile->GetSafeDefinition(varString.c_str()); + flags += " "; + flags += this->GetIncludeFlags(lang); + std::vector commands; + cmSystemTools::ExpandList(rules, commands); + for(std::vector::iterator i = commands.begin(); + i != commands.end(); ++i) + { + this->ExpandRuleVariables(*i, + lang, + 0, // no objects + 0, // no target + 0, // no link libs + sourceFile.c_str(), + objectFile.c_str(), + flags.c_str()); + } + std::vector sourceAndDeps; + sourceAndDeps.push_back(sourceFile); + if(commands.size() > 1) + { + cmSystemTools::Error("Currently custom rules can only have one command sorry "); + } + // Check for extra object-file dependencies. + std::vector depends; + const char* additionalDeps = source.GetProperty("OBJECT_DEPENDS"); + if(additionalDeps) + { + cmSystemTools::ExpandListArgument(additionalDeps, depends); + for(std::vector::iterator i = depends.begin(); + i != depends.end(); ++i) + { + sourceAndDeps.push_back(this->ConvertToRelativeOutputPath(i->c_str())); + } + } + std::string command; + std::string args; + cmSystemTools::SplitProgramFromArgs(commands[0].c_str(), command, args); + std::vector argsv; + argsv.push_back(args); + m_Makefile->AddCustomCommandToOutput(ofname, + command.c_str(), + argsv, + source.GetFullPath().c_str(), + sourceAndDeps, + "build from source"); +} + +void cmLocalGenerator::AddBuildTargetRule(const char* llang, cmTarget& target) +{ + cmStdString objs; + std::vector objVector; + // Add all the sources outputs to the depends of the target + std::vector& classes = target.GetSourceFiles(); + for(std::vector::iterator i = classes.begin(); + i != classes.end(); ++i) + { + if(!(*i)->GetPropertyAsBool("HEADER_FILE_ONLY") && + !(*i)->GetCustomCommand()) + { + std::string outExt = + m_GlobalGenerator->GetLanguageOutputExtensionFromExtension( + (*i)->GetSourceExtension().c_str()); + if(outExt.size() && !(*i)->GetPropertyAsBool("EXTERNAL_OBJECT") ) + { + std::string ofname = m_Makefile->GetCurrentOutputDirectory(); + ofname += "/"; + ofname += (*i)->GetSourceName() + outExt; + objVector.push_back(ofname); + this->AddCustomCommandToCreateObject(ofname.c_str(), llang, *(*i), target); + objs += this->ConvertToRelativeOutputPath(ofname.c_str()); + objs += " "; + } + } + } + std::string createRule = "CMAKE_"; + createRule += llang; + createRule += target.GetCreateRuleVariable(); + std::string targetName = this->GetFullTargetName(target.GetName(), target); + // Executable : + // Shared Library: + // Static Library: + // Shared Module: + std::string linkLibs; // should be set + std::string flags; // should be set + std::string linkFlags; // should be set + this->GetTargetFlags(linkLibs, flags, linkFlags, target); + // Change the type to utility +// target.SetType(cmTarget::UTILITY, target.GetName()); + std::string rule = m_Makefile->GetRequiredDefinition(createRule.c_str()); + this->ExpandRuleVariables(rule, + llang, // language + objs.c_str(), // objects + targetName.c_str(), // target + linkLibs.c_str(), // link libs + 0, // source + 0, // object + flags.c_str(), // flags + 0, // objects quoted + 0, // target base name + 0, // target so name, + linkFlags.c_str() // link flags + ); + std::string command; + std::string args; + cmSystemTools::SplitProgramFromArgs(rule.c_str(), command, args); + // Just like ADD_CUSTOM_TARGET(foo ALL DEPENDS a.o b.o) + // Add a custom command for generating each .o file + cmCustomCommand cc(command.c_str(), args.c_str(), objVector, targetName.c_str()); + target.GetPostBuildCommands().push_back(cc); +} +void cmLocalGenerator::CreateCustomTargetsAndCommands(std::set const& lang) +{ + cmTargets &tgts = m_Makefile->GetTargets(); + for(cmTargets::iterator l = tgts.begin(); + l != tgts.end(); l++) + { + cmTarget& target = l->second; + switch(target.GetType()) + { + case cmTarget::STATIC_LIBRARY: + case cmTarget::SHARED_LIBRARY: + case cmTarget::MODULE_LIBRARY: + case cmTarget::EXECUTABLE: + { + const char* llang = target.GetLinkerLanguage(this->GetGlobalGenerator()); + // if the language is not in the set lang then create custom + // commands to build the target + if(lang.count(llang) == 0) + { + this->AddBuildTargetRule(llang, target); + } + } + break; + } + } +} + + +struct RuleVariables +{ + const char* variable; +}; + + +// List of variables that are replaced when +// rules are expanced. These variables are +// replaced in the form with GetSafeDefinition(var). +// ${LANG} is replaced in the variable first with all enabled +// languages. +static const char* ruleReplaceVars[] = +{ + "CMAKE_SHARED_LIBRARY_CREATE_${LANG}_FLAGS", + "CMAKE_SHARED_MODULE_CREATE_${LANG}_FLAGS", + "CMAKE_SHARED_MODULE_${LANG}_FLAGS", + "CMAKE_SHARED_LIBRARY_${LANG}_FLAGS", + "CMAKE_${LANG}_LINK_FLAGS", + "CMAKE_SHARED_LIBRARY_SONAME_${LANG}_FLAG", + "CMAKE_${LANG}_ARCHIVE", + "CMAKE_${LANG}_COMPILER", + "CMAKE_AR", + "CMAKE_CURRENT_SOURCE_DIR", + "CMAKE_CURRENT_BINARY_DIR", + "CMAKE_RANLIB", + 0 +}; + + + + +void +cmLocalGenerator::ExpandRuleVariables(std::string& s, + const char* lang, + const char* objects, + const char* target, + const char* linkLibs, + const char* source, + const char* object, + const char* flags, + const char* objectsquoted, + const char* targetBase, + const char* targetSOName, + const char* linkFlags) +{ + std::vector enabledLanguages; + m_GlobalGenerator->GetEnabledLanguages(enabledLanguages); + + if(linkFlags) + { + cmSystemTools::ReplaceString(s, "", linkFlags); + } + if(flags) + { + cmSystemTools::ReplaceString(s, "", flags); + } + + if(source) + { + cmSystemTools::ReplaceString(s, "", source); + } + if(object) + { + cmSystemTools::ReplaceString(s, "", object); + } + if(objects) + { + cmSystemTools::ReplaceString(s, "", objects); + } + if(objectsquoted) + { + cmSystemTools::ReplaceString(s, "", objectsquoted); + } + if(target) + { + std::string targetQuoted = target; + if(targetQuoted.size() && targetQuoted[0] != '\"') + { + targetQuoted = '\"'; + targetQuoted += target; + targetQuoted += '\"'; + } + cmSystemTools::ReplaceString(s, "", targetQuoted.c_str()); + cmSystemTools::ReplaceString(s, "", target); + } + if(targetBase) + { + // special case for quoted paths with spaces + // if you see .lib then put the .lib inside + // the quotes, same for .dll + if((strlen(targetBase) > 1) && targetBase[0] == '\"') + { + std::string base = targetBase; + base[base.size()-1] = '.'; + std::string baseLib = base + "lib\""; + std::string baseDll = base + "dll\""; + cmSystemTools::ReplaceString(s, ".lib", baseLib.c_str()); + cmSystemTools::ReplaceString(s, ".dll", baseDll.c_str()); + } + cmSystemTools::ReplaceString(s, "", targetBase); + } + if(targetSOName) + { + bool replaced = false; + if(lang) + { + std::string name = "CMAKE_SHARED_LIBRARY_SONAME_"; + name += lang; + name += "_FLAG"; + if(m_Makefile->GetDefinition(name.c_str())) + { + replaced = true; + cmSystemTools::ReplaceString(s, "", targetSOName); + } + } + if(!replaced) + { + cmSystemTools::ReplaceString(s, "", ""); + } + } + if(linkLibs) + { + cmSystemTools::ReplaceString(s, "", linkLibs); + } + + // loop over language specific replace variables + int pos = 0; + while(ruleReplaceVars[pos]) + { + for(std::vector::iterator i = enabledLanguages.begin(); + i != enabledLanguages.end(); ++i) + { + lang = i->c_str(); + std::string replace = "<"; + replace += ruleReplaceVars[pos]; + replace += ">"; + std::string replaceWith = ruleReplaceVars[pos]; + std::string actualReplace = replace; + cmSystemTools::ReplaceString(actualReplace, "${LANG}", lang); + std::string actualReplaceWith = replaceWith; + cmSystemTools::ReplaceString(actualReplaceWith, "${LANG}", lang); + replace = m_Makefile->GetSafeDefinition(actualReplaceWith.c_str()); + // if the variable is not a FLAG then treat it like a path + if(actualReplaceWith.find("_FLAG") == actualReplaceWith.npos) + { + replace = this->ConvertToOutputForExisting(replace.c_str()); + } + if(actualReplace.size()) + { + cmSystemTools::ReplaceString(s, actualReplace.c_str(), replace.c_str()); + } + } + pos++; + } +} + + +std::string +cmLocalGenerator::ConvertToOutputForExisting(const char* p) +{ + std::string ret = this->ConvertToRelativeOutputPath(p); + // if there are spaces in the path, then get the short path version + // if there is one + if(ret.find(' ') != std::string::npos) + { + if(cmSystemTools::FileExists(p)) + { + if(!cmSystemTools::GetShortPath(ret.c_str(), ret)) + { + ret = this->ConvertToRelativeOutputPath(p); + } + } + } + return ret; +} + +const char* cmLocalGenerator::GetIncludeFlags(const char* lang) +{ + if(!lang) + { + return ""; + } + if(m_LanguageToIncludeFlags.count(lang)) + { + return m_LanguageToIncludeFlags[lang].c_str(); + } + // Output Include paths + cmOStringStream includeFlags; + std::vector& includes = m_Makefile->GetIncludeDirectories(); + std::vector::iterator i; + std::map implicitIncludes; + + // CMake versions below 2.0 would add the source tree to the -I path + // automatically. Preserve compatibility. + bool includeSourceDir = false; + const char* versionValue = + m_Makefile->GetDefinition("CMAKE_BACKWARDS_COMPATIBILITY"); + if(versionValue) + { + int major = 0; + int minor = 0; + if(sscanf(versionValue, "%d.%d", &major, &minor) == 2 && major < 2) + { + includeSourceDir = true; + } + } + const char* vtkSourceDir = + m_Makefile->GetDefinition("VTK_SOURCE_DIR"); + if(vtkSourceDir) + { + // Special hack for VTK 4.0 - 4.4. + const char* vtk_major = m_Makefile->GetDefinition("VTK_MAJOR_VERSION"); + const char* vtk_minor = m_Makefile->GetDefinition("VTK_MINOR_VERSION"); + vtk_major = vtk_major? vtk_major : "4"; + vtk_minor = vtk_minor? vtk_minor : "4"; + int major = 0; + int minor = 0; + if(sscanf(vtk_major, "%d", &major) && sscanf(vtk_minor, "%d", &minor) && + major == 4 && minor <= 4) + { + includeSourceDir = true; + } + } + std::string flagVar = "CMAKE_INCLUDE_FLAG_"; + flagVar += lang; + const char* includeFlag = m_Makefile->GetDefinition(flagVar.c_str()); + flagVar = "CMAKE_INCLUDE_FLAG_SEP_"; + flagVar += lang; + const char* sep = m_Makefile->GetDefinition(flagVar.c_str()); + + bool repeatFlag = true; // should the include flag be repeated like ie. -IA -IB + if(!sep) + { + sep = " "; + } + else + { + // if there is a separator then the flag is not repeated but is only given once + // i.e. -classpath a:b:c + repeatFlag = false; + } + bool flagUsed = false; + if(includeSourceDir) + { + includeFlags << includeFlag + << this->ConvertToOutputForExisting(m_Makefile->GetStartDirectory()) + << sep; + flagUsed = true; + } + + implicitIncludes["/usr/include"] = "/usr/include"; + if(m_Makefile->GetDefinition("CMAKE_PLATFORM_IMPLICIT_INCLUDE_DIRECTORIES")) + { + std::string arg = m_Makefile->GetDefinition("CMAKE_PLATFORM_IMPLICIT_INCLUDE_DIRECTORIES"); + std::vector implicitIncludeVec; + cmSystemTools::ExpandListArgument(arg, implicitIncludeVec); + for(unsigned int k =0; k < implicitIncludeVec.size(); k++) + { + implicitIncludes[implicitIncludeVec[k]] = implicitIncludeVec[k]; + } + } + + for(i = includes.begin(); i != includes.end(); ++i) + { + std::string include = *i; + // Don't output a -I for the standard include path "/usr/include". + // This can cause problems with certain standard library + // implementations because the wrong headers may be found first. + if(implicitIncludes.find(include) == implicitIncludes.end()) + { + if(!flagUsed || repeatFlag) + { + includeFlags << includeFlag; + flagUsed = true; + } + includeFlags << this->ConvertToOutputForExisting(i->c_str()) << sep; + } + } + std::string flags = includeFlags.str(); + // remove trailing separators + if((sep[0] != ' ') && flags[flags.size()-1] == sep[0]) + { + flags[flags.size()-1] = ' '; + } + flags += m_Makefile->GetDefineFlags(); + m_LanguageToIncludeFlags[lang] = flags; + return m_LanguageToIncludeFlags[lang].c_str(); + +} + + +void cmLocalGenerator::GetTargetFlags(std::string& linkLibs, + std::string& flags, + std::string& linkFlags, + cmTarget& target) +{ + std::string buildType = m_Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"); + buildType = cmSystemTools::UpperCase(buildType); + const char* libraryLinkVariable = "CMAKE_SHARED_LINKER_FLAGS"; // default to shared library + + switch(target.GetType()) + { + case cmTarget::STATIC_LIBRARY: + { + const char* targetLinkFlags = target.GetProperty("STATIC_LIBRARY_FLAGS"); + if(targetLinkFlags) + { + linkFlags += targetLinkFlags; + linkFlags += " "; + } + } + break; + case cmTarget::MODULE_LIBRARY: + libraryLinkVariable = "CMAKE_MODULE_LINKER_FLAGS"; + case cmTarget::SHARED_LIBRARY: + { + linkFlags = m_Makefile->GetSafeDefinition(libraryLinkVariable); + linkFlags += " "; + if(buildType.size()) + { + std::string build = libraryLinkVariable; + build += "_"; + build += buildType; + linkFlags += m_Makefile->GetSafeDefinition(build.c_str()); + linkFlags += " "; + } + if(m_Makefile->IsOn("WIN32") && !(m_Makefile->IsOn("CYGWIN") || m_Makefile->IsOn("MINGW"))) + { + const std::vector& sources = target.GetSourceFiles(); + for(std::vector::const_iterator i = sources.begin(); + i != sources.end(); ++i) + { + if((*i)->GetSourceExtension() == "def") + { + linkFlags += m_Makefile->GetSafeDefinition("CMAKE_LINK_DEF_FILE_FLAG"); + linkFlags += this->ConvertToRelativeOutputPath((*i)->GetFullPath().c_str()); + linkFlags += " "; + } + } + } + const char* targetLinkFlags = target.GetProperty("LINK_FLAGS"); + if(targetLinkFlags) + { + linkFlags += targetLinkFlags; + linkFlags += " "; + } + cmOStringStream linklibsStr; + this->OutputLinkLibraries(linklibsStr, target.GetName(), target); + linkLibs = linklibsStr.str(); + } + break; + case cmTarget::EXECUTABLE: + { + linkFlags += m_Makefile->GetSafeDefinition("CMAKE_EXE_LINKER_FLAGS"); + linkFlags += " "; + if(buildType.size()) + { + std::string build = "CMAKE_EXE_LINKER_FLAGS_"; + build += buildType; + linkFlags += m_Makefile->GetSafeDefinition(build.c_str()); + linkFlags += " "; + } + const char* linkLanguage = target.GetLinkerLanguage(this->GetGlobalGenerator()); + std::string langVar = "CMAKE_"; + langVar += linkLanguage; + std::string flagsVar = langVar + "_FLAGS"; + std::string sharedFlagsVar = "CMAKE_SHARED_LIBRARY_"; + sharedFlagsVar += langVar; + sharedFlagsVar += "_FLAGS"; + flags += m_Makefile->GetSafeDefinition(flagsVar.c_str()); + flags += " "; + flags += m_Makefile->GetSafeDefinition(sharedFlagsVar.c_str()); + flags += " "; + cmOStringStream linklibs; + this->OutputLinkLibraries(linklibs, 0, target); + linkLibs = linklibs.str(); + if(cmSystemTools::IsOn(m_Makefile->GetDefinition("BUILD_SHARED_LIBS"))) + { + std::string sFlagVar = std::string("CMAKE_SHARED_BUILD_") + linkLanguage + + std::string("_FLAGS"); + linkFlags += m_Makefile->GetSafeDefinition(sFlagVar.c_str()); + linkFlags += " "; + } + if ( target.GetPropertyAsBool("WIN32_EXECUTABLE") ) + { + linkFlags += m_Makefile->GetSafeDefinition("CMAKE_CREATE_WIN32_EXE"); + linkFlags += " "; + } + else + { + linkFlags += m_Makefile->GetSafeDefinition("CMAKE_CREATE_CONSOLE_EXE"); + linkFlags += " "; + } + const char* targetLinkFlags = target.GetProperty("LINK_FLAGS"); + if(targetLinkFlags) + { + linkFlags += targetLinkFlags; + linkFlags += " "; + } + } + break; + } +} + + +/** + * Output the linking rules on a command line. For executables, + * targetLibrary should be a NULL pointer. For libraries, it should point + * to the name of the library. This will not link a library against itself. + */ +void cmLocalGenerator::OutputLinkLibraries(std::ostream& fout, + const char* targetLibrary, + const cmTarget &tgt) +{ + // Try to emit each search path once + std::set emitted; + + // Embed runtime search paths if possible and if required. + bool outputRuntime = true; + std::string runtimeFlag; + std::string runtimeSep; + std::vector runtimeDirs; + + std::string buildType = m_Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"); + buildType = cmSystemTools::UpperCase(buildType); + + const char* linkLanguage = tgt.GetLinkerLanguage(this->GetGlobalGenerator()); + std::string runTimeFlagVar = "CMAKE_SHARED_LIBRARY_RUNTIME_"; + runTimeFlagVar += linkLanguage; + runTimeFlagVar += "_FLAG"; + std::string runTimeFlagSepVar = runTimeFlagVar + "_SEP"; + runtimeFlag = m_Makefile->GetSafeDefinition(runTimeFlagVar.c_str()); + runtimeSep = m_Makefile->GetSafeDefinition(runTimeFlagSepVar.c_str()); + + // concatenate all paths or no? + bool runtimeConcatenate = ( runtimeSep!="" ); + if(runtimeFlag == "" || m_Makefile->IsOn("CMAKE_SKIP_RPATH") ) + { + outputRuntime = false; + } + + // Some search paths should never be emitted + emitted.insert(""); + emitted.insert("/usr/lib"); + std::string libPathFlag = m_Makefile->GetRequiredDefinition("CMAKE_LIBRARY_PATH_FLAG"); + std::string libLinkFlag = m_Makefile->GetSafeDefinition("CMAKE_LINK_LIBRARY_FLAG"); + // collect all the flags needed for linking libraries + std::string linkLibs; + + // Flags to link an executable to shared libraries. + std::string linkFlagsVar = "CMAKE_SHARED_LIBRARY_LINK_"; + linkFlagsVar += linkLanguage; + linkFlagsVar += "_FLAGS"; + if( tgt.GetType() == cmTarget::EXECUTABLE ) + { + linkLibs = m_Makefile->GetSafeDefinition(linkFlagsVar.c_str()); + linkLibs += " "; + } + + const std::vector& libdirs = tgt.GetLinkDirectories(); + for(std::vector::const_iterator libDir = libdirs.begin(); + libDir != libdirs.end(); ++libDir) + { + std::string libpath = this->ConvertToOutputForExisting(libDir->c_str()); + if(emitted.insert(libpath).second) + { + std::string fullLibPath; + if(!m_WindowsShell && m_UseRelativePaths) + { + fullLibPath = "\"`cd "; + } + fullLibPath += libpath; + if(!m_WindowsShell && m_UseRelativePaths) + { + fullLibPath += ";pwd`\""; + } + std::string::size_type pos = libDir->find(libPathFlag.c_str()); + if((pos == std::string::npos || pos > 0) + && libDir->find("${") == std::string::npos) + { + linkLibs += libPathFlag; + if(outputRuntime) + { + runtimeDirs.push_back( fullLibPath ); + } + } + linkLibs += fullLibPath; + linkLibs += " "; + } + } + + std::string linkSuffix = m_Makefile->GetSafeDefinition("CMAKE_LINK_LIBRARY_SUFFIX"); + std::string regexp = ".*\\"; + regexp += linkSuffix; + regexp += "$"; + cmsys::RegularExpression hasSuffix(regexp.c_str()); + std::string librariesLinked; + const cmTarget::LinkLibraries& libs = tgt.GetLinkLibraries(); + for(cmTarget::LinkLibraries::const_iterator lib = libs.begin(); + lib != libs.end(); ++lib) + { + // Don't link the library against itself! + if(targetLibrary && (lib->first == targetLibrary)) continue; + // use the correct lib for the current configuration + if (lib->second == cmTarget::DEBUG && buildType != "DEBUG") + { + continue; + } + if (lib->second == cmTarget::OPTIMIZED && buildType == "DEBUG") + { + continue; + } + // skip zero size library entries, this may happen + // if a variable expands to nothing. + if (lib->first.size() == 0) continue; + // if it is a full path break it into -L and -l + cmsys::RegularExpression reg("^([ \t]*\\-[lWRB])|([ \t]*\\-framework)|(\\${)|([ \t]*\\-pthread)|([ \t]*`)"); + if(lib->first.find('/') != std::string::npos + && !reg.find(lib->first)) + { + std::string dir, file; + cmSystemTools::SplitProgramPath(lib->first.c_str(), + dir, file); + std::string libpath = this->ConvertToOutputForExisting(dir.c_str()); + if(emitted.insert(libpath).second) + { + linkLibs += libPathFlag; + linkLibs += libpath; + linkLibs += " "; + if(outputRuntime) + { + runtimeDirs.push_back( libpath ); + } + } + cmsys::RegularExpression libname("^lib([^/]*)(\\.so|\\.lib|\\.dll|\\.sl|\\.a|\\.dylib).*"); + cmsys::RegularExpression libname_noprefix("([^/]*)(\\.so|\\.lib|\\.dll|\\.sl|\\.a|\\.dylib).*"); + if(libname.find(file)) + { + // Library had "lib" prefix. + librariesLinked += libLinkFlag; + file = libname.match(1); + // if ignore libprefix is on, + // then add the lib prefix back into the name + if(m_IgnoreLibPrefix) + { + file = "lib" + file; + } + librariesLinked += file; + if(linkSuffix.size() && !hasSuffix.find(file)) + { + librariesLinked += linkSuffix; + } + librariesLinked += " "; + } + else if(libname_noprefix.find(file)) + { + // Library had no "lib" prefix. + librariesLinked += libLinkFlag; + file = libname_noprefix.match(1); + librariesLinked += file; + if(linkSuffix.size() && !hasSuffix.find(file)) + { + librariesLinked += linkSuffix; + } + librariesLinked += " "; + } + else + { + // Error parsing the library name. Just use the full path. + // The linker will give an error if it is invalid. + librariesLinked += lib->first; + librariesLinked += " "; + } + } + // not a full path, so add -l name + else + { + if(!reg.find(lib->first)) + { + librariesLinked += libLinkFlag; + } + librariesLinked += lib->first; + if(linkSuffix.size() && !hasSuffix.find(lib->first)) + { + librariesLinked += linkSuffix; + } + librariesLinked += " "; + } + } + + linkLibs += librariesLinked; + + fout << linkLibs; + + if(outputRuntime && runtimeDirs.size()>0) + { + // For the runtime search directories, do a "-Wl,-rpath,a:b:c" or + // a "-R a -R b -R c" type link line + fout << runtimeFlag; + std::vector::iterator itr = runtimeDirs.begin(); + fout << *itr; + ++itr; + for( ; itr != runtimeDirs.end(); ++itr ) + { + if(runtimeConcatenate) + { + fout << runtimeSep << *itr; + } + else + { + fout << " " << runtimeFlag << *itr; + } + } + fout << " "; + } + if(m_Makefile->GetDefinition("CMAKE_STANDARD_LIBRARIES")) + { + fout << m_Makefile->GetDefinition("CMAKE_STANDARD_LIBRARIES") << " "; + } +} diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index 792d8e13c..02f902edc 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -22,6 +22,8 @@ class cmMakefile; class cmGlobalGenerator; class cmTarget; +class cmSourceFile; + /** \class cmLocalGenerator * \brief Create required build files for a directory. @@ -92,6 +94,46 @@ public: void SetParent(cmLocalGenerator* g) { m_Parent = g;} protected: + ///! Fill out these strings for the given target. Libraries to link, flags, and linkflags. + void GetTargetFlags(std::string& linkLibs, + std::string& flags, + std::string& linkFlags, + cmTarget&target); + + ///! put all the libraries for a target on into the given stream + virtual void OutputLinkLibraries(std::ostream&, const char* name, const cmTarget &); + + ///! Get the include flags for the current makefile and language + const char* GetIncludeFlags(const char* lang); + ///! for existing files convert to output path and short path if spaces + std::string ConvertToOutputForExisting(const char* p); + + // Expand rule variables in CMake of the type found in language rules + void ExpandRuleVariables(std::string& string, + const char* language, + const char* objects=0, + const char* target=0, + const char* linkLibs=0, + const char* source=0, + const char* object =0, + const char* flags = 0, + const char* objectsquoted = 0, + const char* targetBase = 0, + const char* targetSOName = 0, + const char* linkFlags = 0); + ///! Convert a target to a utility target for unsupported languages of a generator + void AddBuildTargetRule(const char* llang, cmTarget& target); + ///! add a custom command to build a .o file that is part of a target + void AddCustomCommandToCreateObject(const char* ofname, + const char* lang, + cmSourceFile& source, + cmTarget& target); + // Create Custom Targets and commands for unsupported languages + // The set passed in should contain the languages supported by the + // generator directly. Any targets containing files that are not + // of the types listed will be compiled as custom commands and added + // to a custom target. + void CreateCustomTargetsAndCommands(std::set const&); virtual void AddInstallRule(std::ostream& fout, const char* dest, int type, const char* files, bool optional = false, const char* properties = 0); @@ -107,6 +149,10 @@ protected: std::string m_HomeOutputDirectoryNoSlash; bool m_ExcludeFromAll; cmLocalGenerator* m_Parent; + std::map m_LanguageToIncludeFlags; + bool m_WindowsShell; + bool m_UseRelativePaths; + bool m_IgnoreLibPrefix; }; #endif diff --git a/Source/cmLocalUnixMakefileGenerator.cxx b/Source/cmLocalUnixMakefileGenerator.cxx index 53ab42551..80fee9362 100644 --- a/Source/cmLocalUnixMakefileGenerator.cxx +++ b/Source/cmLocalUnixMakefileGenerator.cxx @@ -322,24 +322,7 @@ std::string cmLocalUnixMakefileGenerator::GetBaseTargetName(const char* n, #endif const char* targetPrefix = t.GetProperty("PREFIX"); - const char* prefixVar = 0; - switch(t.GetType()) - { - case cmTarget::STATIC_LIBRARY: - prefixVar = "CMAKE_STATIC_LIBRARY_PREFIX"; - break; - case cmTarget::SHARED_LIBRARY: - prefixVar = "CMAKE_SHARED_LIBRARY_PREFIX"; - break; - case cmTarget::MODULE_LIBRARY: - prefixVar = "CMAKE_SHARED_MODULE_PREFIX"; - break; - case cmTarget::EXECUTABLE: - case cmTarget::UTILITY: - case cmTarget::INSTALL_FILES: - case cmTarget::INSTALL_PROGRAMS: - break; - } + const char* prefixVar = t.GetPrefixVariable(); // if there is no prefix on the target use the cmake definition if(!targetPrefix && prefixVar) { @@ -361,49 +344,6 @@ std::string cmLocalUnixMakefileGenerator::GetBaseTargetName(const char* n, return name; } -std::string cmLocalUnixMakefileGenerator::GetFullTargetName(const char* n, - const cmTarget& t) -{ - const char* targetSuffix = t.GetProperty("SUFFIX"); - std::string suffixVar; - switch(t.GetType()) - { - case cmTarget::STATIC_LIBRARY: - suffixVar = "CMAKE_STATIC_LIBRARY_SUFFIX"; - break; - case cmTarget::SHARED_LIBRARY: - suffixVar = "CMAKE_SHARED_LIBRARY_SUFFIX"; - break; - case cmTarget::MODULE_LIBRARY: - suffixVar = "CMAKE_SHARED_MODULE_SUFFIX"; - break; - case cmTarget::EXECUTABLE: - targetSuffix = cmSystemTools::GetExecutableExtension(); - case cmTarget::UTILITY: - case cmTarget::INSTALL_FILES: - case cmTarget::INSTALL_PROGRAMS: - break; - } - // if there is no suffix on the target use the cmake definition - if(!targetSuffix && suffixVar.size()) - { - // first check for a language specific suffix var - const char* ll = t.GetLinkerLanguage(this->GetGlobalGenerator()); - if(ll) - { - std::string langSuff = suffixVar + std::string("_") + ll; - targetSuffix = m_Makefile->GetDefinition(langSuff.c_str()); - } - // if there not a language specific suffix then use the general one - if(!targetSuffix) - { - targetSuffix = m_Makefile->GetSafeDefinition(suffixVar.c_str()); - } - } - std::string name = this->GetBaseTargetName(n, t); - name += targetSuffix?targetSuffix:""; - return name; -} // Output the rules for any targets void cmLocalUnixMakefileGenerator::OutputEcho(std::ostream& fout, @@ -683,221 +623,6 @@ void cmLocalUnixMakefileGenerator::OutputTargetRules(std::ostream& fout) } -/** - * Output the linking rules on a command line. For executables, - * targetLibrary should be a NULL pointer. For libraries, it should point - * to the name of the library. This will not link a library against itself. - */ -void cmLocalUnixMakefileGenerator::OutputLinkLibraries(std::ostream& fout, - const char* targetLibrary, - const cmTarget &tgt) -{ - // Try to emit each search path once - std::set emitted; - - // Embed runtime search paths if possible and if required. - bool outputRuntime = true; - std::string runtimeFlag; - std::string runtimeSep; - std::vector runtimeDirs; - - std::string buildType = m_Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"); - buildType = cmSystemTools::UpperCase(buildType); - - const char* linkLanguage = tgt.GetLinkerLanguage(this->GetGlobalGenerator()); - std::string runTimeFlagVar = "CMAKE_SHARED_LIBRARY_RUNTIME_"; - runTimeFlagVar += linkLanguage; - runTimeFlagVar += "_FLAG"; - std::string runTimeFlagSepVar = runTimeFlagVar + "_SEP"; - runtimeFlag = m_Makefile->GetSafeDefinition(runTimeFlagVar.c_str()); - runtimeSep = m_Makefile->GetSafeDefinition(runTimeFlagSepVar.c_str()); - - // concatenate all paths or no? - bool runtimeConcatenate = ( runtimeSep!="" ); - if(runtimeFlag == "" || m_Makefile->IsOn("CMAKE_SKIP_RPATH") ) - { - outputRuntime = false; - } - - // Some search paths should never be emitted - emitted.insert(""); - emitted.insert("/usr/lib"); - std::string libPathFlag = m_Makefile->GetRequiredDefinition("CMAKE_LIBRARY_PATH_FLAG"); - std::string libLinkFlag = m_Makefile->GetSafeDefinition("CMAKE_LINK_LIBRARY_FLAG"); - // collect all the flags needed for linking libraries - std::string linkLibs; - - // Flags to link an executable to shared libraries. - std::string linkFlagsVar = "CMAKE_SHARED_LIBRARY_LINK_"; - linkFlagsVar += linkLanguage; - linkFlagsVar += "_FLAGS"; - if( tgt.GetType() == cmTarget::EXECUTABLE ) - { - linkLibs = m_Makefile->GetSafeDefinition(linkFlagsVar.c_str()); - linkLibs += " "; - } - - const std::vector& libdirs = tgt.GetLinkDirectories(); - for(std::vector::const_iterator libDir = libdirs.begin(); - libDir != libdirs.end(); ++libDir) - { - std::string libpath = this->ConvertToOutputForExisting(libDir->c_str()); - if(emitted.insert(libpath).second) - { - std::string fullLibPath; - if(!m_WindowsShell && m_UseRelativePaths) - { - fullLibPath = "\"`cd "; - } - fullLibPath += libpath; - if(!m_WindowsShell && m_UseRelativePaths) - { - fullLibPath += ";pwd`\""; - } - std::string::size_type pos = libDir->find(libPathFlag.c_str()); - if((pos == std::string::npos || pos > 0) - && libDir->find("${") == std::string::npos) - { - linkLibs += libPathFlag; - if(outputRuntime) - { - runtimeDirs.push_back( fullLibPath ); - } - } - linkLibs += fullLibPath; - linkLibs += " "; - } - } - - std::string linkSuffix = m_Makefile->GetSafeDefinition("CMAKE_LINK_LIBRARY_SUFFIX"); - std::string regexp = ".*\\"; - regexp += linkSuffix; - regexp += "$"; - cmsys::RegularExpression hasSuffix(regexp.c_str()); - std::string librariesLinked; - const cmTarget::LinkLibraries& libs = tgt.GetLinkLibraries(); - for(cmTarget::LinkLibraries::const_iterator lib = libs.begin(); - lib != libs.end(); ++lib) - { - // Don't link the library against itself! - if(targetLibrary && (lib->first == targetLibrary)) continue; - // use the correct lib for the current configuration - if (lib->second == cmTarget::DEBUG && buildType != "DEBUG") - { - continue; - } - if (lib->second == cmTarget::OPTIMIZED && buildType == "DEBUG") - { - continue; - } - // skip zero size library entries, this may happen - // if a variable expands to nothing. - if (lib->first.size() == 0) continue; - // if it is a full path break it into -L and -l - cmsys::RegularExpression reg("^([ \t]*\\-[lWRB])|([ \t]*\\-framework)|(\\${)|([ \t]*\\-pthread)|([ \t]*`)"); - if(lib->first.find('/') != std::string::npos - && !reg.find(lib->first)) - { - std::string dir, file; - cmSystemTools::SplitProgramPath(lib->first.c_str(), - dir, file); - std::string libpath = this->ConvertToOutputForExisting(dir.c_str()); - if(emitted.insert(libpath).second) - { - linkLibs += libPathFlag; - linkLibs += libpath; - linkLibs += " "; - if(outputRuntime) - { - runtimeDirs.push_back( libpath ); - } - } - cmsys::RegularExpression libname("^lib([^/]*)(\\.so|\\.lib|\\.dll|\\.sl|\\.a|\\.dylib).*"); - cmsys::RegularExpression libname_noprefix("([^/]*)(\\.so|\\.lib|\\.dll|\\.sl|\\.a|\\.dylib).*"); - if(libname.find(file)) - { - // Library had "lib" prefix. - librariesLinked += libLinkFlag; - file = libname.match(1); - // if ignore libprefix is on, - // then add the lib prefix back into the name - if(m_IgnoreLibPrefix) - { - file = "lib" + file; - } - librariesLinked += file; - if(linkSuffix.size() && !hasSuffix.find(file)) - { - librariesLinked += linkSuffix; - } - librariesLinked += " "; - } - else if(libname_noprefix.find(file)) - { - // Library had no "lib" prefix. - librariesLinked += libLinkFlag; - file = libname_noprefix.match(1); - librariesLinked += file; - if(linkSuffix.size() && !hasSuffix.find(file)) - { - librariesLinked += linkSuffix; - } - librariesLinked += " "; - } - else - { - // Error parsing the library name. Just use the full path. - // The linker will give an error if it is invalid. - librariesLinked += lib->first; - librariesLinked += " "; - } - } - // not a full path, so add -l name - else - { - if(!reg.find(lib->first)) - { - librariesLinked += libLinkFlag; - } - librariesLinked += lib->first; - if(linkSuffix.size() && !hasSuffix.find(lib->first)) - { - librariesLinked += linkSuffix; - } - librariesLinked += " "; - } - } - - linkLibs += librariesLinked; - - fout << linkLibs; - - if(outputRuntime && runtimeDirs.size()>0) - { - // For the runtime search directories, do a "-Wl,-rpath,a:b:c" or - // a "-R a -R b -R c" type link line - fout << runtimeFlag; - std::vector::iterator itr = runtimeDirs.begin(); - fout << *itr; - ++itr; - for( ; itr != runtimeDirs.end(); ++itr ) - { - if(runtimeConcatenate) - { - fout << runtimeSep << *itr; - } - else - { - fout << " " << runtimeFlag << *itr; - } - } - fout << " "; - } - if(m_Makefile->GetDefinition("CMAKE_STANDARD_LIBRARIES")) - { - fout << m_Makefile->GetDefinition("CMAKE_STANDARD_LIBRARIES") << " "; - } -} std::string cmLocalUnixMakefileGenerator::CreatePreBuildRules( const cmTarget &target, const char* /* targetName */) @@ -974,163 +699,6 @@ std::string cmLocalUnixMakefileGenerator::CreatePostBuildRules( return customRuleCode; } -struct RuleVariables -{ - const char* variable; -}; - - -// List of variables that are replaced when -// rules are expanced. These variables are -// replaced in the form with GetSafeDefinition(var). -// ${LANG} is replaced in the variable first with all enabled -// languages. -static const char* ruleReplaceVars[] = -{ - "CMAKE_SHARED_LIBRARY_CREATE_${LANG}_FLAGS", - "CMAKE_SHARED_MODULE_CREATE_${LANG}_FLAGS", - "CMAKE_SHARED_MODULE_${LANG}_FLAGS", - "CMAKE_SHARED_LIBRARY_${LANG}_FLAGS", - "CMAKE_${LANG}_LINK_FLAGS", - "CMAKE_SHARED_LIBRARY_SONAME_${LANG}_FLAG", - "CMAKE_${LANG}_ARCHIVE", - "CMAKE_${LANG}_COMPILER", - "CMAKE_AR", - "CMAKE_CURRENT_SOURCE_DIR", - "CMAKE_CURRENT_BINARY_DIR", - "CMAKE_RANLIB", - 0 -}; - - - - -void -cmLocalUnixMakefileGenerator::ExpandRuleVariables(std::string& s, - const char* lang, - const char* objects, - const char* target, - const char* linkLibs, - const char* source, - const char* object, - const char* flags, - const char* objectsquoted, - const char* targetBase, - const char* targetSOName, - const char* linkFlags) -{ - std::vector enabledLanguages; - m_GlobalGenerator->GetEnabledLanguages(enabledLanguages); - - if(linkFlags) - { - cmSystemTools::ReplaceString(s, "", linkFlags); - } - if(flags) - { - cmSystemTools::ReplaceString(s, "", flags); - } - - if(source) - { - cmSystemTools::ReplaceString(s, "", source); - } - if(object) - { - cmSystemTools::ReplaceString(s, "", object); - } - if(objects) - { - cmSystemTools::ReplaceString(s, "", objects); - } - if(objectsquoted) - { - cmSystemTools::ReplaceString(s, "", objectsquoted); - } - if(target) - { - std::string targetQuoted = target; - if(targetQuoted.size() && targetQuoted[0] != '\"') - { - targetQuoted = '\"'; - targetQuoted += target; - targetQuoted += '\"'; - } - cmSystemTools::ReplaceString(s, "", targetQuoted.c_str()); - cmSystemTools::ReplaceString(s, "", target); - } - if(targetBase) - { - // special case for quoted paths with spaces - // if you see .lib then put the .lib inside - // the quotes, same for .dll - if((strlen(targetBase) > 1) && targetBase[0] == '\"') - { - std::string base = targetBase; - base[base.size()-1] = '.'; - std::string baseLib = base + "lib\""; - std::string baseDll = base + "dll\""; - cmSystemTools::ReplaceString(s, ".lib", baseLib.c_str()); - cmSystemTools::ReplaceString(s, ".dll", baseDll.c_str()); - } - cmSystemTools::ReplaceString(s, "", targetBase); - } - if(targetSOName) - { - bool replaced = false; - if(lang) - { - std::string name = "CMAKE_SHARED_LIBRARY_SONAME_"; - name += lang; - name += "_FLAG"; - if(m_Makefile->GetDefinition(name.c_str())) - { - replaced = true; - cmSystemTools::ReplaceString(s, "", targetSOName); - } - } - if(!replaced) - { - cmSystemTools::ReplaceString(s, "", ""); - } - } - if(linkLibs) - { - cmSystemTools::ReplaceString(s, "", linkLibs); - } - - // loop over language specific replace variables - int pos = 0; - while(ruleReplaceVars[pos]) - { - for(std::vector::iterator i = enabledLanguages.begin(); - i != enabledLanguages.end(); ++i) - { - lang = i->c_str(); - std::string replace = "<"; - replace += ruleReplaceVars[pos]; - replace += ">"; - std::string replaceWith = ruleReplaceVars[pos]; - std::string actualReplace = replace; - cmSystemTools::ReplaceString(actualReplace, "${LANG}", lang); - std::string actualReplaceWith = replaceWith; - cmSystemTools::ReplaceString(actualReplaceWith, "${LANG}", lang); - replace = m_Makefile->GetSafeDefinition(actualReplaceWith.c_str()); - // if the variable is not a FLAG then treat it like a path - if(actualReplaceWith.find("_FLAG") == actualReplaceWith.npos) - { - replace = this->ConvertToOutputForExisting(replace.c_str()); - } - if(actualReplace.size()) - { - cmSystemTools::ReplaceString(s, actualReplace.c_str(), replace.c_str()); - } - } - pos++; - } -} - - void cmLocalUnixMakefileGenerator::OutputLibraryRule(std::ostream& fout, const char* name, @@ -2459,25 +2027,6 @@ void cmLocalUnixMakefileGenerator::OutputCustomRules(std::ostream& fout) } } -std::string -cmLocalUnixMakefileGenerator::ConvertToOutputForExisting(const char* p) -{ - std::string ret = this->ConvertToRelativeOutputPath(p); - // if there are spaces in the path, then get the short path version - // if there is one - if(ret.find(' ') != std::string::npos) - { - if(cmSystemTools::FileExists(p)) - { - if(!cmSystemTools::GetShortPath(ret.c_str(), ret)) - { - ret = this->ConvertToRelativeOutputPath(p); - } - } - } - return ret; -} - void cmLocalUnixMakefileGenerator::OutputMakeVariables(std::ostream& fout) { @@ -2532,118 +2081,6 @@ void cmLocalUnixMakefileGenerator::OutputMakeVariables(std::ostream& fout) fout << "\n\n"; } -const char* cmLocalUnixMakefileGenerator::GetIncludeFlags(const char* lang) -{ - if(!lang) - { - return ""; - } - if(m_LanguageToIncludeFlags.count(lang)) - { - return m_LanguageToIncludeFlags[lang].c_str(); - } - // Output Include paths - cmOStringStream includeFlags; - std::vector& includes = m_Makefile->GetIncludeDirectories(); - std::vector::iterator i; - std::map implicitIncludes; - - // CMake versions below 2.0 would add the source tree to the -I path - // automatically. Preserve compatibility. - bool includeSourceDir = false; - const char* versionValue = - m_Makefile->GetDefinition("CMAKE_BACKWARDS_COMPATIBILITY"); - if(versionValue) - { - int major = 0; - int minor = 0; - if(sscanf(versionValue, "%d.%d", &major, &minor) == 2 && major < 2) - { - includeSourceDir = true; - } - } - const char* vtkSourceDir = - m_Makefile->GetDefinition("VTK_SOURCE_DIR"); - if(vtkSourceDir) - { - // Special hack for VTK 4.0 - 4.4. - const char* vtk_major = m_Makefile->GetDefinition("VTK_MAJOR_VERSION"); - const char* vtk_minor = m_Makefile->GetDefinition("VTK_MINOR_VERSION"); - vtk_major = vtk_major? vtk_major : "4"; - vtk_minor = vtk_minor? vtk_minor : "4"; - int major = 0; - int minor = 0; - if(sscanf(vtk_major, "%d", &major) && sscanf(vtk_minor, "%d", &minor) && - major == 4 && minor <= 4) - { - includeSourceDir = true; - } - } - std::string flagVar = "CMAKE_INCLUDE_FLAG_"; - flagVar += lang; - const char* includeFlag = m_Makefile->GetDefinition(flagVar.c_str()); - flagVar = "CMAKE_INCLUDE_FLAG_SEP_"; - flagVar += lang; - const char* sep = m_Makefile->GetDefinition(flagVar.c_str()); - - bool repeatFlag = true; // should the include flag be repeated like ie. -IA -IB - if(!sep) - { - sep = " "; - } - else - { - // if there is a separator then the flag is not repeated but is only given once - // i.e. -classpath a:b:c - repeatFlag = false; - } - bool flagUsed = false; - if(includeSourceDir) - { - includeFlags << includeFlag - << this->ConvertToOutputForExisting(m_Makefile->GetStartDirectory()) - << sep; - flagUsed = true; - } - - implicitIncludes["/usr/include"] = "/usr/include"; - if(m_Makefile->GetDefinition("CMAKE_PLATFORM_IMPLICIT_INCLUDE_DIRECTORIES")) - { - std::string arg = m_Makefile->GetDefinition("CMAKE_PLATFORM_IMPLICIT_INCLUDE_DIRECTORIES"); - std::vector implicitIncludeVec; - cmSystemTools::ExpandListArgument(arg, implicitIncludeVec); - for(unsigned int k =0; k < implicitIncludeVec.size(); k++) - { - implicitIncludes[implicitIncludeVec[k]] = implicitIncludeVec[k]; - } - } - - for(i = includes.begin(); i != includes.end(); ++i) - { - std::string include = *i; - // Don't output a -I for the standard include path "/usr/include". - // This can cause problems with certain standard library - // implementations because the wrong headers may be found first. - if(implicitIncludes.find(include) == implicitIncludes.end()) - { - if(!flagUsed || repeatFlag) - { - includeFlags << includeFlag; - flagUsed = true; - } - includeFlags << this->ConvertToOutputForExisting(i->c_str()) << sep; - } - } - std::string flags = includeFlags.str(); - // remove trailing separators - if((sep[0] != ' ') && flags[flags.size()-1] == sep[0]) - { - flags[flags.size()-1] = ' '; - } - flags += m_Makefile->GetDefineFlags(); - m_LanguageToIncludeFlags[lang] = flags; - return m_LanguageToIncludeFlags[lang].c_str(); -} void cmLocalUnixMakefileGenerator::OutputMakeRules(std::ostream& fout) { diff --git a/Source/cmLocalUnixMakefileGenerator.h b/Source/cmLocalUnixMakefileGenerator.h index 1e37209c9..020ea5719 100644 --- a/Source/cmLocalUnixMakefileGenerator.h +++ b/Source/cmLocalUnixMakefileGenerator.h @@ -95,7 +95,6 @@ protected: virtual void ProcessDepends(const cmMakeDepend &md); virtual void OutputMakefile(const char* file, bool withDepends); virtual void OutputTargetRules(std::ostream& fout); - virtual void OutputLinkLibraries(std::ostream&, const char* name, const cmTarget &); void OutputLibraryRule(std::ostream& fout, const char* name, const cmTarget &t, @@ -103,18 +102,7 @@ protected: const char* comment, const char* linkFlags ); - void ExpandRuleVariables(std::string& string, - const char* language, - const char* objects=0, - const char* target=0, - const char* linkLibs=0, - const char* source=0, - const char* object =0, - const char* flags = 0, - const char* objectsquoted = 0, - const char* targetBase = 0, - const char* targetSOName = 0, - const char* linkFlags = 0); + virtual void OutputSharedLibraryRule(std::ostream&, const char* name, const cmTarget &); virtual void OutputModuleLibraryRule(std::ostream&, const char* name, @@ -211,16 +199,10 @@ protected: ///! if the OS is case insensitive then return a lower case of the path. virtual std::string LowerCasePath(const char* path); - ///! for existing files convert to output path and short path if spaces - std::string ConvertToOutputForExisting(const char*); - /** Convert path to a format vaild for the left or right side of a target: dependencies line in a makefile. */ virtual std::string ConvertToMakeTarget(const char*); - /** Get the full name of the target's file, without path. */ - std::string GetFullTargetName(const char* n, const cmTarget& t); - /** Get the base name of the target's file, without path or extension. */ std::string GetBaseTargetName(const char* n, const cmTarget& t); @@ -240,20 +222,15 @@ protected: */ std::string& CreateSafeUniqueObjectFileName(const char* sin); - const char* GetIncludeFlags(const char* lang); protected: int m_MakefileVariableSize; std::map m_MakeVariableMap; std::map m_ShortMakeVariableMap; std::map m_UniqueObjectNamesMap; - std::map m_LanguageToIncludeFlags; - bool m_IgnoreLibPrefix; std::string m_IncludeDirective; std::string m_MakeSilentFlag; std::string m_ExecutableOutputPath; std::string m_LibraryOutputPath; - bool m_WindowsShell; - bool m_UseRelativePaths; bool m_PassMakeflags; private: }; diff --git a/Source/cmLocalVisualStudio6Generator.cxx b/Source/cmLocalVisualStudio6Generator.cxx index 20a79277c..56308e3cf 100644 --- a/Source/cmLocalVisualStudio6Generator.cxx +++ b/Source/cmLocalVisualStudio6Generator.cxx @@ -34,7 +34,11 @@ cmLocalVisualStudio6Generator::~cmLocalVisualStudio6Generator() void cmLocalVisualStudio6Generator::Generate(bool /* fromTheTop */) -{ +{ + std::set lang; + lang.insert("C"); + lang.insert("CXX"); + this->CreateCustomTargetsAndCommands(lang); this->OutputDSPFile(); } diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index e0cd55acb..0087b3e47 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -34,6 +34,10 @@ cmLocalVisualStudio7Generator::~cmLocalVisualStudio7Generator() void cmLocalVisualStudio7Generator::Generate(bool /* fromTheTop */) { + std::set lang; + lang.insert("C"); + lang.insert("CXX"); + this->CreateCustomTargetsAndCommands(lang); this->OutputVCProjFile(); } diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 39f450ed5..aa75573bf 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -769,10 +769,7 @@ const char* cmTarget::GetLinkerLanguage(cmGlobalGenerator* gg) const } if(languages.size() == 0) { - std::string m = "Error Target: "; - m += m_Name + " contains no source files with an enabled languages."; - cmSystemTools::Error(m.c_str()); - return "(NullLanguage)"; + return 0; } if(languages.size() == 1) { @@ -809,3 +806,71 @@ const char* cmTarget::GetLinkerLanguage(cmGlobalGenerator* gg) const const_cast(this)->SetProperty("LINKER_LANGUAGE", prefLang); return this->GetProperty("LINKER_LANGUAGE"); } + +const char* cmTarget::GetCreateRuleVariable() +{ + switch(this->GetType()) + { + case cmTarget::STATIC_LIBRARY: + return "_CREATE_STATIC_LIBRARY"; + break; + case cmTarget::SHARED_LIBRARY: + return "_CREATE_SHARED_LIBRARY"; + break; + case cmTarget::MODULE_LIBRARY: + return "_CREATE_SHARED_MODULE"; + break; + case cmTarget::EXECUTABLE: + return "_LINK_EXECUTABLE"; + break; + } + return ""; +} + + +const char* cmTarget::GetSuffixVariable() const +{ + switch(this->GetType()) + { + case cmTarget::STATIC_LIBRARY: + return "CMAKE_STATIC_LIBRARY_SUFFIX"; + break; + case cmTarget::SHARED_LIBRARY: + return "CMAKE_SHARED_LIBRARY_SUFFIX"; + break; + case cmTarget::MODULE_LIBRARY: + return "CMAKE_SHARED_MODULE_SUFFIX"; + break; + case cmTarget::EXECUTABLE: + return cmSystemTools::GetExecutableExtension(); + case cmTarget::UTILITY: + case cmTarget::INSTALL_FILES: + case cmTarget::INSTALL_PROGRAMS: + break; + } + return ""; +} + + +const char* cmTarget::GetPrefixVariable() const +{ + switch(this->GetType()) + { + case cmTarget::STATIC_LIBRARY: + return "CMAKE_STATIC_LIBRARY_PREFIX"; + break; + case cmTarget::SHARED_LIBRARY: + return "CMAKE_SHARED_LIBRARY_PREFIX"; + break; + case cmTarget::MODULE_LIBRARY: + return "CMAKE_SHARED_MODULE_PREFIX"; + break; + case cmTarget::EXECUTABLE: + return cmSystemTools::GetExecutableExtension(); + case cmTarget::UTILITY: + case cmTarget::INSTALL_FILES: + case cmTarget::INSTALL_PROGRAMS: + break; + } + return ""; +} diff --git a/Source/cmTarget.h b/Source/cmTarget.h index 85991893a..631de5558 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -55,9 +55,9 @@ public: /** * Indicate whether the target is part of the all target */ - bool IsInAll() const { return m_InAll; } - bool GetInAll() const { return m_InAll; } - void SetInAll(bool f) { m_InAll = f; } + bool IsInAll() const { return this->GetPropertyAsBool("IN_ALL"); } + bool GetInAll() const { return this->GetPropertyAsBool("IN_ALL"); } + void SetInAll(bool f) { this->SetProperty("IN_ALL", (f) ? "TRUE" : "FALSE"); } /** * Get the list of the custom commands for this target @@ -157,6 +157,14 @@ public: ///! Return the prefered linker language for this target const char* GetLinkerLanguage(cmGlobalGenerator*) const; + + ///! Return the rule variable used to create this type of target, + // need to add CMAKE_(LANG) for full name. + const char* GetCreateRuleVariable(); + ///! Return the name of the variable to look up the target suffix + const char* GetSuffixVariable() const; + ///! Return the name of the variable to look up the target suffix + const char* GetPrefixVariable() const; private: /** * A list of direct dependencies. Use in conjunction with DependencyMap. @@ -223,7 +231,6 @@ private: LinkLibraries m_LinkLibraries; LinkLibraries m_PrevLinkedLibraries; std::vector m_LinkDirectories; - bool m_InAll; std::string m_InstallPath; std::string m_RuntimeInstallPath; std::set m_Utilities;