diff options
Diffstat (limited to 'Source/cmVisualStudio10TargetGenerator.cxx')
-rw-r--r-- | Source/cmVisualStudio10TargetGenerator.cxx | 256 |
1 files changed, 121 insertions, 135 deletions
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 2442841..d289695 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -65,7 +65,7 @@ cmVisualStudio10TargetGenerator(cmTarget* target, this->Target = target; this->GeneratorTarget = gg->GetGeneratorTarget(target); this->Makefile = target->GetMakefile(); - this->LocalGenerator = + this->LocalGenerator = (cmLocalVisualStudio7Generator*) this->Makefile->GetLocalGenerator(); this->Name = this->Target->GetName(); @@ -108,9 +108,9 @@ void cmVisualStudio10TargetGenerator::WritePlatformConfigTag( stream = this->BuildFileStream; } stream->fill(' '); - stream->width(indentLevel*2 ); + stream->width(indentLevel*2 ); (*stream ) << ""; - (*stream ) << "<" << tag + (*stream ) << "<" << tag << " Condition=\"'$(Configuration)|$(Platform)'=='"; (*stream ) << config << "|" << this->Platform << "'\""; if(attribute) @@ -164,7 +164,7 @@ void cmVisualStudio10TargetGenerator::Generate() new cmGeneratedFileStream(path.c_str()); this->PathToVcxproj = path; this->BuildFileStream->SetCopyIfDifferent(true); - + // Write the encoding header into the file char magic[] = {0xEF,0xBB, 0xBF}; this->BuildFileStream->write(magic, 3); @@ -370,9 +370,9 @@ void cmVisualStudio10TargetGenerator::WriteProjectConfigurationValues() break; } configType += "</ConfigurationType>\n"; - this->WriteString(configType.c_str(), 2); + this->WriteString(configType.c_str(), 2); - const char* mfcFlag = + const char* mfcFlag = this->Target->GetMakefile()->GetDefinition("CMAKE_MFC_FLAG"); std::string mfcFlagValue = mfcFlag ? mfcFlag : "0"; @@ -454,14 +454,15 @@ void cmVisualStudio10TargetGenerator::WriteCustomCommand(cmSourceFile* sf) } } -void +void cmVisualStudio10TargetGenerator::WriteCustomRule(cmSourceFile* source, - cmCustomCommand const & + cmCustomCommand const & command) { std::string sourcePath = source->GetFullPath(); - // the rule file seems to need to exist for vs10 - if (source->GetExtension() == "rule") + // VS 10 will always rebuild a custom command attached to a .rule + // file that doesn't exist so create the file explicitly. + if (source->GetPropertyAsBool("__CMAKE_RULE")) { if(!cmSystemTools::FileExists(sourcePath.c_str())) { @@ -490,15 +491,10 @@ cmVisualStudio10TargetGenerator::WriteCustomRule(cmSourceFile* source, comment = cmVS10EscapeComment(comment); std::vector<std::string> *configs = static_cast<cmGlobalVisualStudio7Generator *> - (this->GlobalGenerator)->GetConfigurations(); - this->WriteString("<CustomBuild Include=\"", 2); - // custom command have to use relative paths or they do not - // show up in the GUI - std::string path = cmSystemTools::RelativePath( - this->Makefile->GetCurrentOutputDirectory(), - sourcePath.c_str()); - this->ConvertToWindowsSlash(path); - (*this->BuildFileStream ) << path << "\">\n"; + (this->GlobalGenerator)->GetConfigurations(); + + this->WriteSource("CustomBuild", source, ">\n"); + for(std::vector<std::string>::iterator i = configs->begin(); i != configs->end(); ++i) { @@ -509,11 +505,11 @@ cmVisualStudio10TargetGenerator::WriteCustomRule(cmSourceFile* source, this->WritePlatformConfigTag("Command", i->c_str(), 3); (*this->BuildFileStream ) << script << "</Command>\n"; this->WritePlatformConfigTag("AdditionalInputs", i->c_str(), 3); - + (*this->BuildFileStream ) << source->GetFullPath(); - for(std::vector<std::string>::const_iterator d = + for(std::vector<std::string>::const_iterator d = command.GetDepends().begin(); - d != command.GetDepends().end(); + d != command.GetDepends().end(); ++d) { std::string dep; @@ -526,9 +522,9 @@ cmVisualStudio10TargetGenerator::WriteCustomRule(cmSourceFile* source, (*this->BuildFileStream ) << ";%(AdditionalInputs)</AdditionalInputs>\n"; this->WritePlatformConfigTag("Outputs", i->c_str(), 3); const char* sep = ""; - for(std::vector<std::string>::const_iterator o = + for(std::vector<std::string>::const_iterator o = command.GetOutputs().begin(); - o != command.GetOutputs().end(); + o != command.GetOutputs().end(); ++o) { std::string out = *o; @@ -541,6 +537,18 @@ cmVisualStudio10TargetGenerator::WriteCustomRule(cmSourceFile* source, this->WriteString("</CustomBuild>\n", 2); } +std::string +cmVisualStudio10TargetGenerator::ConvertPath(std::string const& path, + bool forceRelative) +{ + return forceRelative + ? cmSystemTools::RelativePath( + this->Makefile->GetCurrentOutputDirectory(), path.c_str()) + : this->LocalGenerator->Convert(path.c_str(), + cmLocalGenerator::START_OUTPUT, + cmLocalGenerator::UNCHANGED); +} + void cmVisualStudio10TargetGenerator::ConvertToWindowsSlash(std::string& s) { // first convert all of the slashes @@ -552,62 +560,21 @@ void cmVisualStudio10TargetGenerator::ConvertToWindowsSlash(std::string& s) } } void cmVisualStudio10TargetGenerator::WriteGroups() -{ +{ // collect up group information - std::vector<cmSourceGroup> sourceGroups = + std::vector<cmSourceGroup> sourceGroups = this->Makefile->GetSourceGroups(); std::vector<cmSourceFile*> classes = this->Target->GetSourceFiles(); - + std::set<cmSourceGroup*> groupsUsed; - std::vector<cmSourceFile*> clCompile; - std::vector<cmSourceFile*> customBuild; - std::vector<cmSourceFile*> none; - std::vector<cmSourceFile*> headers; - std::vector<cmSourceFile*> idls; - std::vector<cmSourceFile*> resource; - - for(std::vector<cmSourceFile*>::const_iterator s = classes.begin(); + for(std::vector<cmSourceFile*>::const_iterator s = classes.begin(); s != classes.end(); s++) { - cmSourceFile* sf = *s; + cmSourceFile* sf = *s; std::string const& source = sf->GetFullPath(); - cmSourceGroup& sourceGroup = + cmSourceGroup& sourceGroup = this->Makefile->FindSourceGroup(source.c_str(), sourceGroups); groupsUsed.insert(&sourceGroup); - const char* lang = sf->GetLanguage(); - bool header = (*s)->GetPropertyAsBool("HEADER_FILE_ONLY") - || this->GlobalGenerator->IgnoreFile - ((*s)->GetExtension().c_str()); - std::string ext = - cmSystemTools::LowerCase((*s)->GetExtension()); - if(!lang) - { - lang = "None"; - } - if(header) - { - headers.push_back(sf); - } - else if(lang[0] == 'C') - { - clCompile.push_back(sf); - } - else if(strcmp(lang, "RC") == 0) - { - resource.push_back(sf); - } - else if(sf->GetCustomCommand()) - { - customBuild.push_back(sf); - } - else if(ext == "idl") - { - idls.push_back(sf); - } - else - { - none.push_back(sf); - } } this->AddMissingSourceGroups(groupsUsed, sourceGroups); @@ -629,11 +596,11 @@ void cmVisualStudio10TargetGenerator::WriteGroups() "xmlns=\"http://schemas.microsoft.com/" "developer/msbuild/2003\">\n", 0); - this->WriteGroupSources("ClCompile", clCompile, sourceGroups); - this->WriteGroupSources("ClInclude", headers, sourceGroups); - this->WriteGroupSources("ResourceCompile", resource, sourceGroups); - this->WriteGroupSources("Midl", idls, sourceGroups); - this->WriteGroupSources("CustomBuild", customBuild, sourceGroups); + for(ToolSourceMap::const_iterator ti = this->Tools.begin(); + ti != this->Tools.end(); ++ti) + { + this->WriteGroupSources(ti->first.c_str(), ti->second, sourceGroups); + } // Add object library contents as external objects. std::vector<std::string> objs; @@ -668,9 +635,9 @@ void cmVisualStudio10TargetGenerator::WriteGroups() guidName += name; this->GlobalGenerator->CreateGUID(guidName.c_str()); this->WriteString("<UniqueIdentifier>", 3); - std::string guid + std::string guid = this->GlobalGenerator->GetGUID(guidName.c_str()); - (*this->BuildFileStream) + (*this->BuildFileStream) << "{" << guid << "}" << "</UniqueIdentifier>\n"; @@ -690,7 +657,6 @@ void cmVisualStudio10TargetGenerator::WriteGroups() this->WriteString("</Filter>\n", 2); } this->WriteString("</ItemGroup>\n", 1); - this->WriteGroupSources("None", none, sourceGroups); this->WriteString("</Project>\n", 0); // restore stream pointer this->BuildFileStream = save; @@ -750,32 +716,20 @@ cmVisualStudio10TargetGenerator::AddMissingSourceGroups( void cmVisualStudio10TargetGenerator:: WriteGroupSources(const char* name, - std::vector<cmSourceFile*> const& sources, + ToolSources const& sources, std::vector<cmSourceGroup>& sourceGroups) { this->WriteString("<ItemGroup>\n", 1); - for(std::vector<cmSourceFile*>::const_iterator s = sources.begin(); + for(ToolSources::const_iterator s = sources.begin(); s != sources.end(); ++s) { - cmSourceFile* sf = *s; - if(sf->GetExtension() == "obj") - { - continue; - } + cmSourceFile* sf = s->SourceFile; std::string const& source = sf->GetFullPath(); - cmSourceGroup& sourceGroup = + cmSourceGroup& sourceGroup = this->Makefile->FindSourceGroup(source.c_str(), sourceGroups); const char* filter = sourceGroup.GetFullName(); - this->WriteString("<", 2); - std::string path = source; - // custom command sources must use relative paths or they will - // not show up in the GUI. - if(sf->GetCustomCommand()) - { - path = cmSystemTools::RelativePath( - this->Makefile->GetCurrentOutputDirectory(), - source.c_str()); - } + this->WriteString("<", 2); + std::string path = this->ConvertPath(source, s->RelativePath); this->ConvertToWindowsSlash(path); (*this->BuildFileStream) << name << " Include=\"" << path; @@ -796,15 +750,47 @@ WriteGroupSources(const char* name, } void cmVisualStudio10TargetGenerator::WriteSource( - const char* tool, cmSourceFile* sf, bool end) + const char* tool, cmSourceFile* sf, const char* end) { - std::string sourceFile = sf->GetFullPath(); - // do not use a relative path here because it means that you - // can not use as long a path to the file. + // Visual Studio tools append relative paths to the current dir, as in: + // + // c:\path\to\current\dir\..\..\..\relative\path\to\source.c + // + // and fail if this exceeds the maximum allowed path length. Our path + // conversion uses full paths outside the build tree to allow deeper trees. + bool forceRelative = false; + std::string sourceFile = this->ConvertPath(sf->GetFullPath(), false); + if(this->LocalGenerator->GetVersion() == cmLocalVisualStudioGenerator::VS10 + && cmSystemTools::FileIsFullPath(sourceFile.c_str())) + { + // Normal path conversion resulted in a full path. VS 10 (but not 11) + // refuses to show the property page in the IDE for a source file with a + // full path (not starting in a '.' or '/' AFAICT). CMake <= 2.8.4 used a + // relative path but to allow deeper build trees CMake 2.8.[5678] used a + // full path except for custom commands. Custom commands do not work + // without a relative path, but they do not seem to be involved in tools + // with the above behavior. For other sources we now use a relative path + // when the combined path will not be too long so property pages appear. + std::string sourceRel = this->ConvertPath(sf->GetFullPath(), true); + size_t const maxLen = 250; + if(sf->GetCustomCommand() || + ((strlen(this->Makefile->GetCurrentOutputDirectory()) + 1 + + sourceRel.length()) <= maxLen)) + { + forceRelative = true; + sourceFile = sourceRel; + } + else + { + this->GlobalGenerator->PathTooLong(this->Target, sf, sourceRel); + } + } this->ConvertToWindowsSlash(sourceFile); this->WriteString("<", 2); (*this->BuildFileStream ) << tool << - " Include=\"" << sourceFile << (end? "\" />\n" : "\" "); + " Include=\"" << sourceFile << "\"" << (end? end : " />\n"); + ToolSource toolSource = {sf, forceRelative}; + this->Tools[tool].push_back(toolSource); } void cmVisualStudio10TargetGenerator::WriteSources( @@ -836,7 +822,7 @@ void cmVisualStudio10TargetGenerator::WriteAllSources() bool cl = strcmp(lang, "C") == 0 || strcmp(lang, "CXX") == 0; bool rc = strcmp(lang, "RC") == 0; const char* tool = cl? "ClCompile" : (rc? "ResourceCompile" : "None"); - this->WriteSource(tool, *si, false); + this->WriteSource(tool, *si, " "); // ouput any flags specific to this source file if(cl && this->OutputSourceSpecificFlags(*si)) { @@ -883,7 +869,7 @@ void cmVisualStudio10TargetGenerator::WriteAllSources() bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags( cmSourceFile* source) -{ +{ cmSourceFile& sf = *source; cmLocalVisualStudio7Generator* lg = this->LocalGenerator; @@ -898,7 +884,7 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags( if(const char* cflags = sf.GetProperty("COMPILE_FLAGS")) { flags += cflags; - } + } if(const char* cdefs = sf.GetProperty("COMPILE_DEFINITIONS")) { defines += cdefs; @@ -914,7 +900,7 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags( { needForceLang = true; lang = sourceLang; - } + } // if the source file does not match the linker language // then force c or c++ if(needForceLang || (linkLanguage && lang @@ -938,7 +924,7 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags( if(objectName.size()) { (*this->BuildFileStream ) << firstString; - firstString = ""; + firstString = ""; hasFlags = true; this->WriteString("<ObjectFileName>", 3); (*this->BuildFileStream ) @@ -949,7 +935,7 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags( (this->GlobalGenerator)->GetConfigurations(); for( std::vector<std::string>::iterator config = configs->begin(); config != configs->end(); ++config) - { + { std::string configUpper = cmSystemTools::UpperCase(*config); std::string configDefines = defines; std::string defPropName = "COMPILE_DEFINITIONS_"; @@ -962,14 +948,14 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags( } configDefines += ccdefs; } - // if we have flags or defines for this config then + // if we have flags or defines for this config then // use them if(flags.size() || configDefines.size()) { (*this->BuildFileStream ) << firstString; firstString = ""; // only do firstString once hasFlags = true; - cmVisualStudioGeneratorOptions + cmVisualStudioGeneratorOptions clOptions(this->LocalGenerator, cmVisualStudioGeneratorOptions::Compiler, cmVS10CLFlagTable, 0, this); @@ -977,7 +963,7 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags( clOptions.AddDefines(configDefines.c_str()); clOptions.SetConfiguration((*config).c_str()); clOptions.OutputAdditionalOptions(*this->BuildFileStream, " ", ""); - clOptions.OutputFlagMap(*this->BuildFileStream, " "); + clOptions.OutputFlagMap(*this->BuildFileStream, " "); clOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, " ", "\n", lang); } @@ -1060,10 +1046,10 @@ void cmVisualStudio10TargetGenerator::WritePathAndIncrementalLinkOptions() -void +void cmVisualStudio10TargetGenerator:: OutputLinkIncremental(std::string const& configName) -{ +{ std::string CONFIG = cmSystemTools::UpperCase(configName); // static libraries and things greater than modules do not need // to set this option @@ -1077,7 +1063,7 @@ OutputLinkIncremental(std::string const& configName) { linkType = "EXE"; } - + // assume incremental linking const char* incremental = "true"; const char* linkLanguage = @@ -1106,9 +1092,9 @@ OutputLinkIncremental(std::string const& configName) flags += this-> Target->GetMakefile()->GetRequiredDefinition(baseFlagVar.c_str()); std::string flagVar = baseFlagVar + std::string("_") + CONFIG; - flags += + flags += Target->GetMakefile()->GetRequiredDefinition(flagVar.c_str()); - } + } const char* targetLinkFlags = this->Target->GetProperty("LINK_FLAGS"); if(targetLinkFlags) { @@ -1128,7 +1114,7 @@ OutputLinkIncremental(std::string const& configName) } this->WritePlatformConfigTag("LinkIncremental", configName.c_str(), 3); *this->BuildFileStream << incremental - << "</LinkIncremental>\n"; + << "</LinkIncremental>\n"; const char* manifest = "true"; if(flags.find("MANIFEST:NO") != flags.npos) @@ -1170,7 +1156,7 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions( Options& clOptions = *pOptions; std::string flags; - // collect up flags for + // collect up flags for if(this->Target->GetType() < cmTarget::UTILITY) { const char* linkLanguage = @@ -1263,10 +1249,10 @@ void cmVisualStudio10TargetGenerator::WriteClOptions( "</DebugInformationFormat>\n", 3); } - clOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, " ", + clOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, " ", "\n", "CXX"); this->WriteString("<AssemblerListingLocation>", 3); - *this->BuildFileStream << configName + *this->BuildFileStream << configName << "</AssemblerListingLocation>\n"; this->WriteString("<ObjectFileName>$(IntDir)</ObjectFileName>\n", 3); if(this->Target->GetType() != cmTarget::OBJECT_LIBRARY) @@ -1293,7 +1279,7 @@ OutputIncludes(std::vector<std::string> const & includes) this->WriteString("%(AdditionalIncludeDirectories)" "</AdditionalIncludeDirectories>\n", 0); } - + void cmVisualStudio10TargetGenerator:: @@ -1331,7 +1317,7 @@ cmVisualStudio10TargetGenerator::WriteLibOptions(std::string const& config) libOptions.Parse(libflags?libflags:""); libOptions.Parse(libflagsConfig?libflagsConfig:""); libOptions.OutputAdditionalOptions(*this->BuildFileStream, " ", ""); - libOptions.OutputFlagMap(*this->BuildFileStream, " "); + libOptions.OutputFlagMap(*this->BuildFileStream, " "); this->WriteString("</Lib>\n", 2); } } @@ -1340,7 +1326,7 @@ cmVisualStudio10TargetGenerator::WriteLibOptions(std::string const& config) void cmVisualStudio10TargetGenerator::WriteLinkOptions(std::string const& config) { - + // static libraries and things greater than modules do not need // to set this option if(this->Target->GetType() == cmTarget::STATIC_LIBRARY @@ -1360,7 +1346,7 @@ void cmVisualStudio10TargetGenerator::WriteLinkOptions(std::string const& this->WriteString("<Link>\n", 2); std::string CONFIG = cmSystemTools::UpperCase(config); - + const char* linkType = "SHARED"; if(this->Target->GetType() == cmTarget::MODULE_LIBRARY) { @@ -1421,7 +1407,7 @@ void cmVisualStudio10TargetGenerator::WriteLinkOptions(std::string const& std::string standardLibsVar = "CMAKE_"; standardLibsVar += linkLanguage; standardLibsVar += "_STANDARD_LIBRARIES"; - std::string + std::string libs = this->Makefile->GetSafeDefinition(standardLibsVar.c_str()); // Remove trailing spaces from libs std::string::size_type pos = libs.size()-1; @@ -1479,7 +1465,7 @@ void cmVisualStudio10TargetGenerator::WriteLinkOptions(std::string const& else { linkOptions.AddFlag("GenerateDebugInformation", "false"); - } + } std::string targetName; std::string targetNameSO; std::string targetNameFull; @@ -1488,13 +1474,13 @@ void cmVisualStudio10TargetGenerator::WriteLinkOptions(std::string const& if(this->Target->GetType() == cmTarget::EXECUTABLE) { this->Target->GetExecutableNames(targetName, targetNameFull, - targetNameImport, targetNamePDB, + targetNameImport, targetNamePDB, config.c_str()); } else { this->Target->GetLibraryNames(targetName, targetNameSO, targetNameFull, - targetNameImport, targetNamePDB, + targetNameImport, targetNamePDB, config.c_str()); } @@ -1518,7 +1504,7 @@ void cmVisualStudio10TargetGenerator::WriteLinkOptions(std::string const& linkOptions.RemoveFlag("GenerateManifest"); linkOptions.OutputAdditionalOptions(*this->BuildFileStream, " ", ""); linkOptions.OutputFlagMap(*this->BuildFileStream, " "); - + this->WriteString("</Link>\n", 2); if(!this->GlobalGenerator->NeedLinkLibraryDependencies(*this->Target)) { @@ -1532,7 +1518,7 @@ void cmVisualStudio10TargetGenerator::WriteLinkOptions(std::string const& void cmVisualStudio10TargetGenerator::AddLibraries( cmComputeLinkInformation& cli, std::string& libstring) -{ +{ typedef cmComputeLinkInformation::ItemVector ItemVector; ItemVector libs = cli.GetItems(); const char* sep = ";"; @@ -1598,15 +1584,15 @@ void cmVisualStudio10TargetGenerator::WriteItemDefinitionGroups() this->WriteMidlOptions(*i, includes); // write events this->WriteEvents(*i); - // output link flags <Link></Link> + // output link flags <Link></Link> this->WriteLinkOptions(*i); - // output lib flags <Lib></Lib> + // output lib flags <Lib></Lib> this->WriteLibOptions(*i); this->WriteString("</ItemDefinitionGroup>\n", 1); } } -void +void cmVisualStudio10TargetGenerator::WriteEvents(std::string const& configName) { this->WriteEvent("PreLinkEvent", @@ -1634,7 +1620,7 @@ void cmVisualStudio10TargetGenerator::WriteEvent( std::string comment; for(std::vector<cmCustomCommand>::iterator i = commands.begin(); i != commands.end(); ++i) - { + { cmCustomCommand& command = *i; comment += pre; comment += lg->ConstructComment(command); @@ -1691,7 +1677,7 @@ void cmVisualStudio10TargetGenerator::WriteProjectReferences() } (*this->BuildFileStream) << path << "\">\n"; this->WriteString("<Project>", 3); - (*this->BuildFileStream) + (*this->BuildFileStream) << this->GlobalGenerator->GetGUID(name.c_str()) << "</Project>\n"; this->WriteString("</ProjectReference>\n", 2); |