Merge topic 'vs-escaping'

09164c63 VS: Encode more content correctly in vcxproj files (#15031)
29a0642b VS: Encode mapped flag values in XML project files (#15031)
8fa087ab cmVisualStudioGeneratorOptions: Simplify XML escaping API
1c209ac1 cmIDEOption: Store mapped flag values as a vector<string>
91c93354 cmVisualStudio10TargetGenerator: Remove dupilcate line
This commit is contained in:
Brad King 2014-07-28 10:35:45 -04:00 committed by CMake Topic Stage
commit 107db681e3
6 changed files with 89 additions and 65 deletions

View File

@ -152,18 +152,7 @@ void cmIDEOptions::FlagMapUpdate(cmIDEFlagTable const* entry,
} }
else if(entry->special & cmIDEFlagTable::SemicolonAppendable) else if(entry->special & cmIDEFlagTable::SemicolonAppendable)
{ {
std::map<std::string,std::string>::iterator itr; this->FlagMap[entry->IDEName].push_back(new_value);
itr = this->FlagMap.find(entry->IDEName);
if(itr != this->FlagMap.end())
{
// Append to old value (if present) with semicolons;
itr->second += ";";
itr->second += new_value;
}
else
{
this->FlagMap[entry->IDEName] = new_value;
}
} }
else else
{ {
@ -199,6 +188,13 @@ void cmIDEOptions::AddFlag(const char* flag, const char* value)
this->FlagMap[flag] = value; this->FlagMap[flag] = value;
} }
//----------------------------------------------------------------------------
void cmIDEOptions::AddFlag(const char* flag,
std::vector<std::string> const& value)
{
this->FlagMap[flag] = value;
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmIDEOptions::RemoveFlag(const char* flag) void cmIDEOptions::RemoveFlag(const char* flag)
{ {
@ -208,10 +204,11 @@ void cmIDEOptions::RemoveFlag(const char* flag)
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
const char* cmIDEOptions::GetFlag(const char* flag) const char* cmIDEOptions::GetFlag(const char* flag)
{ {
std::map<std::string, std::string>::iterator i = this->FlagMap.find(flag); // This method works only for single-valued flags!
if(i != this->FlagMap.end()) std::map<std::string, FlagValue>::iterator i = this->FlagMap.find(flag);
if(i != this->FlagMap.end() && i->second.size() == 1)
{ {
return i->second.c_str(); return i->second[0].c_str();
} }
return 0; return 0;
} }

View File

@ -29,6 +29,7 @@ public:
void AddDefines(const char* defines); void AddDefines(const char* defines);
void AddDefines(const std::vector<std::string> &defines); void AddDefines(const std::vector<std::string> &defines);
void AddFlag(const char* flag, const char* value); void AddFlag(const char* flag, const char* value);
void AddFlag(const char* flag, std::vector<std::string> const& value);
void RemoveFlag(const char* flag); void RemoveFlag(const char* flag);
const char* GetFlag(const char* flag); const char* GetFlag(const char* flag);
@ -40,7 +41,23 @@ protected:
// Then parse the command line flags specified in CMAKE_CXX_FLAGS // Then parse the command line flags specified in CMAKE_CXX_FLAGS
// and CMAKE_C_FLAGS // and CMAKE_C_FLAGS
// and overwrite or add new values to this map // and overwrite or add new values to this map
std::map<std::string, std::string> FlagMap; class FlagValue: public std::vector<std::string>
{
typedef std::vector<std::string> derived;
public:
FlagValue& operator=(std::string const& r)
{
this->resize(1);
this->operator[](0) = r;
return *this;
}
FlagValue& operator=(std::vector<std::string> const& r)
{
this->derived::operator=(r);
return *this;
}
};
std::map<std::string, FlagValue > FlagMap;
// Preprocessor definitions. // Preprocessor definitions.
std::vector<std::string> Defines; std::vector<std::string> Defines;

View File

@ -1013,7 +1013,7 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout,
if(!this->ModuleDefinitionFile.empty()) if(!this->ModuleDefinitionFile.empty())
{ {
std::string defFile = std::string defFile =
this->ConvertToXMLOutputPath(this->ModuleDefinitionFile.c_str()); this->ConvertToOptionallyRelativeOutputPath(this->ModuleDefinitionFile);
linkOptions.AddFlag("ModuleDefinitionFile", defFile.c_str()); linkOptions.AddFlag("ModuleDefinitionFile", defFile.c_str());
} }
switch(target.GetType()) switch(target.GetType())

View File

@ -343,19 +343,20 @@ void cmVisualStudio10TargetGenerator::Generate()
} }
this->WriteString("<Platform>", 2); this->WriteString("<Platform>", 2);
(*this->BuildFileStream) << this->Platform << "</Platform>\n"; (*this->BuildFileStream) << cmVS10EscapeXML(this->Platform)
<< "</Platform>\n";
const char* projLabel = this->Target->GetProperty("PROJECT_LABEL"); const char* projLabel = this->Target->GetProperty("PROJECT_LABEL");
if(!projLabel) if(!projLabel)
{ {
projLabel = this->Name.c_str(); projLabel = this->Name.c_str();
} }
this->WriteString("<ProjectName>", 2); this->WriteString("<ProjectName>", 2);
(*this->BuildFileStream) << projLabel << "</ProjectName>\n"; (*this->BuildFileStream) << cmVS10EscapeXML(projLabel) << "</ProjectName>\n";
if(const char* targetFrameworkVersion = this->Target->GetProperty( if(const char* targetFrameworkVersion = this->Target->GetProperty(
"VS_DOTNET_TARGET_FRAMEWORK_VERSION")) "VS_DOTNET_TARGET_FRAMEWORK_VERSION"))
{ {
this->WriteString("<TargetFrameworkVersion>", 2); this->WriteString("<TargetFrameworkVersion>", 2);
(*this->BuildFileStream) << targetFrameworkVersion (*this->BuildFileStream) << cmVS10EscapeXML(targetFrameworkVersion)
<< "</TargetFrameworkVersion>\n"; << "</TargetFrameworkVersion>\n";
} }
this->WriteString("</PropertyGroup>\n", 1); this->WriteString("</PropertyGroup>\n", 1);
@ -507,7 +508,8 @@ void cmVisualStudio10TargetGenerator::WriteProjectConfigurations()
this->WriteString("<Configuration>", 3); this->WriteString("<Configuration>", 3);
(*this->BuildFileStream ) << *i << "</Configuration>\n"; (*this->BuildFileStream ) << *i << "</Configuration>\n";
this->WriteString("<Platform>", 3); this->WriteString("<Platform>", 3);
(*this->BuildFileStream) << this->Platform << "</Platform>\n"; (*this->BuildFileStream) << cmVS10EscapeXML(this->Platform)
<< "</Platform>\n";
this->WriteString("</ProjectConfiguration>\n", 2); this->WriteString("</ProjectConfiguration>\n", 2);
} }
this->WriteString("</ItemGroup>\n", 1); this->WriteString("</ItemGroup>\n", 1);
@ -700,7 +702,7 @@ cmVisualStudio10TargetGenerator::WriteCustomRule(cmSourceFile const* source,
(*this->BuildFileStream ) << script << "</Command>\n"; (*this->BuildFileStream ) << script << "</Command>\n";
this->WritePlatformConfigTag("AdditionalInputs", i->c_str(), 3); this->WritePlatformConfigTag("AdditionalInputs", i->c_str(), 3);
(*this->BuildFileStream ) << source->GetFullPath(); (*this->BuildFileStream ) << cmVS10EscapeXML(source->GetFullPath());
for(std::vector<std::string>::const_iterator d = for(std::vector<std::string>::const_iterator d =
ccg.GetDepends().begin(); ccg.GetDepends().begin();
d != ccg.GetDepends().end(); d != ccg.GetDepends().end();
@ -710,7 +712,7 @@ cmVisualStudio10TargetGenerator::WriteCustomRule(cmSourceFile const* source,
if(this->LocalGenerator->GetRealDependency(d->c_str(), i->c_str(), dep)) if(this->LocalGenerator->GetRealDependency(d->c_str(), i->c_str(), dep))
{ {
this->ConvertToWindowsSlash(dep); this->ConvertToWindowsSlash(dep);
(*this->BuildFileStream ) << ";" << dep; (*this->BuildFileStream ) << ";" << cmVS10EscapeXML(dep);
} }
} }
(*this->BuildFileStream ) << ";%(AdditionalInputs)</AdditionalInputs>\n"; (*this->BuildFileStream ) << ";%(AdditionalInputs)</AdditionalInputs>\n";
@ -723,7 +725,7 @@ cmVisualStudio10TargetGenerator::WriteCustomRule(cmSourceFile const* source,
{ {
std::string out = *o; std::string out = *o;
this->ConvertToWindowsSlash(out); this->ConvertToWindowsSlash(out);
(*this->BuildFileStream ) << sep << out; (*this->BuildFileStream ) << sep << cmVS10EscapeXML(out);
sep = ";"; sep = ";";
} }
(*this->BuildFileStream ) << "</Outputs>\n"; (*this->BuildFileStream ) << "</Outputs>\n";
@ -824,7 +826,7 @@ void cmVisualStudio10TargetGenerator::WriteGroups()
std::string obj = (*oi)->GetFullPath(); std::string obj = (*oi)->GetFullPath();
this->WriteString("<EmbeddedResource Include=\"", 2); this->WriteString("<EmbeddedResource Include=\"", 2);
this->ConvertToWindowsSlash(obj); this->ConvertToWindowsSlash(obj);
(*this->BuildFileStream ) << obj << "\">\n"; (*this->BuildFileStream ) << cmVS10EscapeXML(obj) << "\">\n";
this->WriteString("<Filter>Resource Files</Filter>\n", 3); this->WriteString("<Filter>Resource Files</Filter>\n", 3);
this->WriteString("</EmbeddedResource>\n", 2); this->WriteString("</EmbeddedResource>\n", 2);
} }
@ -843,7 +845,7 @@ void cmVisualStudio10TargetGenerator::WriteGroups()
std::string obj = *oi; std::string obj = *oi;
this->WriteString("<Object Include=\"", 2); this->WriteString("<Object Include=\"", 2);
this->ConvertToWindowsSlash(obj); this->ConvertToWindowsSlash(obj);
(*this->BuildFileStream ) << obj << "\">\n"; (*this->BuildFileStream ) << cmVS10EscapeXML(obj) << "\">\n";
this->WriteString("<Filter>Object Libraries</Filter>\n", 3); this->WriteString("<Filter>Object Libraries</Filter>\n", 3);
this->WriteString("</Object>\n", 2); this->WriteString("</Object>\n", 2);
} }
@ -978,7 +980,7 @@ WriteGroupSources(const char* name,
std::string path = this->ConvertPath(source, s->RelativePath); std::string path = this->ConvertPath(source, s->RelativePath);
this->ConvertToWindowsSlash(path); this->ConvertToWindowsSlash(path);
(*this->BuildFileStream) << name << " Include=\"" (*this->BuildFileStream) << name << " Include=\""
<< path; << cmVS10EscapeXML(path);
if(strlen(filter)) if(strlen(filter))
{ {
(*this->BuildFileStream) << "\">\n"; (*this->BuildFileStream) << "\">\n";
@ -1033,7 +1035,8 @@ void cmVisualStudio10TargetGenerator::WriteSource(
} }
this->ConvertToWindowsSlash(sourceFile); this->ConvertToWindowsSlash(sourceFile);
this->WriteString("<", 2); this->WriteString("<", 2);
(*this->BuildFileStream ) << tool << " Include=\"" << sourceFile << "\""; (*this->BuildFileStream ) << tool << " Include=\""
<< cmVS10EscapeXML(sourceFile) << "\"";
if(sf->GetExtension() == "h" && if(sf->GetExtension() == "h" &&
this->IsResxHeader(sf->GetFullPath())) this->IsResxHeader(sf->GetFullPath()))
@ -1165,7 +1168,7 @@ void cmVisualStudio10TargetGenerator::WriteAllSources()
std::string obj = *oi; std::string obj = *oi;
this->WriteString("<Object Include=\"", 2); this->WriteString("<Object Include=\"", 2);
this->ConvertToWindowsSlash(obj); this->ConvertToWindowsSlash(obj);
(*this->BuildFileStream ) << obj << "\" />\n"; (*this->BuildFileStream ) << cmVS10EscapeXML(obj) << "\" />\n";
} }
this->WriteString("</ItemGroup>\n", 1); this->WriteString("</ItemGroup>\n", 1);
@ -1735,6 +1738,9 @@ cmVisualStudio10TargetGenerator::ComputeLinkOptions(std::string const& config)
} }
// Replace spaces in libs with ; // Replace spaces in libs with ;
cmSystemTools::ReplaceString(libs, " ", ";"); cmSystemTools::ReplaceString(libs, " ", ";");
std::vector<std::string> libVec;
cmSystemTools::ExpandListArgument(libs, libVec);
cmComputeLinkInformation* pcli = cmComputeLinkInformation* pcli =
this->Target->GetLinkInformation(config.c_str()); this->Target->GetLinkInformation(config.c_str());
if(!pcli) if(!pcli)
@ -1746,28 +1752,21 @@ cmVisualStudio10TargetGenerator::ComputeLinkOptions(std::string const& config)
} }
// add the libraries for the target to libs string // add the libraries for the target to libs string
cmComputeLinkInformation& cli = *pcli; cmComputeLinkInformation& cli = *pcli;
this->AddLibraries(cli, libs); this->AddLibraries(cli, libVec);
linkOptions.AddFlag("AdditionalDependencies", libs.c_str()); linkOptions.AddFlag("AdditionalDependencies", libVec);
std::vector<std::string> const& ldirs = cli.GetDirectories(); std::vector<std::string> const& ldirs = cli.GetDirectories();
const char* sep = ""; std::vector<std::string> linkDirs;
std::string linkDirs;
for(std::vector<std::string>::const_iterator d = ldirs.begin(); for(std::vector<std::string>::const_iterator d = ldirs.begin();
d != ldirs.end(); ++d) d != ldirs.end(); ++d)
{ {
// first just full path // first just full path
linkDirs += sep; linkDirs.push_back(*d);
linkDirs += *d;
sep = ";";
linkDirs += sep;
// next path with configuration type Debug, Release, etc // next path with configuration type Debug, Release, etc
linkDirs += *d; linkDirs.push_back(*d + "/$(Configuration)");
linkDirs += "/$(Configuration)";
linkDirs += sep;
} }
linkDirs += "%(AdditionalLibraryDirectories)"; linkDirs.push_back("%(AdditionalLibraryDirectories)");
linkOptions.AddFlag("AdditionalLibraryDirectories", linkDirs.c_str()); linkOptions.AddFlag("AdditionalLibraryDirectories", linkDirs);
linkOptions.AddFlag("AdditionalDependencies", libs.c_str());
std::string targetName; std::string targetName;
std::string targetNameSO; std::string targetNameSO;
@ -1867,11 +1866,10 @@ cmVisualStudio10TargetGenerator::WriteLinkOptions(std::string const& config)
void cmVisualStudio10TargetGenerator::AddLibraries( void cmVisualStudio10TargetGenerator::AddLibraries(
cmComputeLinkInformation& cli, cmComputeLinkInformation& cli,
std::string& libstring) std::vector<std::string>& libVec)
{ {
typedef cmComputeLinkInformation::ItemVector ItemVector; typedef cmComputeLinkInformation::ItemVector ItemVector;
ItemVector libs = cli.GetItems(); ItemVector libs = cli.GetItems();
const char* sep = ";";
for(ItemVector::const_iterator l = libs.begin(); l != libs.end(); ++l) for(ItemVector::const_iterator l = libs.begin(); l != libs.end(); ++l)
{ {
if(l->IsPath) if(l->IsPath)
@ -1881,14 +1879,12 @@ void cmVisualStudio10TargetGenerator::AddLibraries(
cmLocalGenerator::START_OUTPUT, cmLocalGenerator::START_OUTPUT,
cmLocalGenerator::UNCHANGED); cmLocalGenerator::UNCHANGED);
this->ConvertToWindowsSlash(path); this->ConvertToWindowsSlash(path);
libstring += sep; libVec.push_back(path);
libstring += path;
} }
else if (!l->Target else if (!l->Target
|| l->Target->GetType() != cmTarget::INTERFACE_LIBRARY) || l->Target->GetType() != cmTarget::INTERFACE_LIBRARY)
{ {
libstring += sep; libVec.push_back(l->Value);
libstring += l->Value;
} }
} }
} }
@ -2051,7 +2047,7 @@ void cmVisualStudio10TargetGenerator::WriteProjectReferences()
path += dt->GetName(); path += dt->GetName();
path += ".vcxproj"; path += ".vcxproj";
} }
(*this->BuildFileStream) << path << "\">\n"; (*this->BuildFileStream) << cmVS10EscapeXML(path) << "\">\n";
this->WriteString("<Project>", 3); this->WriteString("<Project>", 3);
(*this->BuildFileStream) (*this->BuildFileStream)
<< this->GlobalGenerator->GetGUID(name.c_str()) << this->GlobalGenerator->GetGUID(name.c_str())

View File

@ -90,7 +90,8 @@ private:
void WriteGroups(); void WriteGroups();
void WriteProjectReferences(); void WriteProjectReferences();
bool OutputSourceSpecificFlags(cmSourceFile const* source); bool OutputSourceSpecificFlags(cmSourceFile const* source);
void AddLibraries(cmComputeLinkInformation& cli, std::string& libstring); void AddLibraries(cmComputeLinkInformation& cli,
std::vector<std::string>& libVec);
void WriteLibOptions(std::string const& config); void WriteLibOptions(std::string const& config);
void WriteEvents(std::string const& configName); void WriteEvents(std::string const& configName);
void WriteEvent(const char* name, void WriteEvent(const char* name,

View File

@ -3,9 +3,9 @@
#include <cmsys/System.h> #include <cmsys/System.h>
#include "cmVisualStudio10TargetGenerator.h" #include "cmVisualStudio10TargetGenerator.h"
inline std::string cmVisualStudio10GeneratorOptionsEscapeForXML(const char* s) static
std::string cmVisualStudio10GeneratorOptionsEscapeForXML(std::string ret)
{ {
std::string ret = s;
cmSystemTools::ReplaceString(ret, ";", "%3B"); cmSystemTools::ReplaceString(ret, ";", "%3B");
cmSystemTools::ReplaceString(ret, "&", "&amp;"); cmSystemTools::ReplaceString(ret, "&", "&amp;");
cmSystemTools::ReplaceString(ret, "<", "&lt;"); cmSystemTools::ReplaceString(ret, "<", "&lt;");
@ -13,9 +13,9 @@ inline std::string cmVisualStudio10GeneratorOptionsEscapeForXML(const char* s)
return ret; return ret;
} }
inline std::string cmVisualStudioGeneratorOptionsEscapeForXML(const char* s) static
std::string cmVisualStudioGeneratorOptionsEscapeForXML(std::string ret)
{ {
std::string ret = s;
cmSystemTools::ReplaceString(ret, "&", "&amp;"); cmSystemTools::ReplaceString(ret, "&", "&amp;");
cmSystemTools::ReplaceString(ret, "\"", "&quot;"); cmSystemTools::ReplaceString(ret, "\"", "&quot;");
cmSystemTools::ReplaceString(ret, "<", "&lt;"); cmSystemTools::ReplaceString(ret, "<", "&lt;");
@ -269,7 +269,7 @@ cmVisualStudioGeneratorOptions
// Escape this flag for the IDE. // Escape this flag for the IDE.
if(this->Version >= cmLocalVisualStudioGenerator::VS10) if(this->Version >= cmLocalVisualStudioGenerator::VS10)
{ {
define = cmVisualStudio10GeneratorOptionsEscapeForXML(define.c_str()); define = cmVisualStudio10GeneratorOptionsEscapeForXML(define);
if(lang == "RC") if(lang == "RC")
{ {
@ -278,7 +278,7 @@ cmVisualStudioGeneratorOptions
} }
else else
{ {
define = cmVisualStudioGeneratorOptionsEscapeForXML(define.c_str()); define = cmVisualStudioGeneratorOptionsEscapeForXML(define);
} }
// Store the flag in the project file. // Store the flag in the project file.
fout << sep << define; fout << sep << define;
@ -301,7 +301,7 @@ cmVisualStudioGeneratorOptions
{ {
if(this->Version >= cmLocalVisualStudioGenerator::VS10) if(this->Version >= cmLocalVisualStudioGenerator::VS10)
{ {
for(std::map<std::string, std::string>::iterator m = this->FlagMap.begin(); for(std::map<std::string, FlagValue>::iterator m = this->FlagMap.begin();
m != this->FlagMap.end(); ++m) m != this->FlagMap.end(); ++m)
{ {
fout << indent; fout << indent;
@ -317,20 +317,34 @@ cmVisualStudioGeneratorOptions
{ {
fout << "<" << m->first << ">"; fout << "<" << m->first << ">";
} }
fout << m->second; const char* sep = "";
for(std::vector<std::string>::iterator i = m->second.begin();
i != m->second.end(); ++i)
{
fout << sep << cmVisualStudio10GeneratorOptionsEscapeForXML(*i);
sep = ";";
}
if (m->first == "AdditionalIncludeDirectories") if (m->first == "AdditionalIncludeDirectories")
{ {
fout << ";%(AdditionalIncludeDirectories)"; fout << sep << "%(AdditionalIncludeDirectories)";
} }
fout << "</" << m->first << ">\n"; fout << "</" << m->first << ">\n";
} }
} }
else else
{ {
for(std::map<std::string, std::string>::iterator m = this->FlagMap.begin(); for(std::map<std::string, FlagValue>::iterator m = this->FlagMap.begin();
m != this->FlagMap.end(); ++m) m != this->FlagMap.end(); ++m)
{ {
fout << indent << m->first << "=\"" << m->second << "\"\n"; fout << indent << m->first << "=\"";
const char* sep = "";
for(std::vector<std::string>::iterator i = m->second.begin();
i != m->second.end(); ++i)
{
fout << sep << cmVisualStudioGeneratorOptionsEscapeForXML(*i);
sep = ";";
}
fout << "\"\n";
} }
} }
} }
@ -359,14 +373,13 @@ cmVisualStudioGeneratorOptions
{ {
fout << "<AdditionalOptions>"; fout << "<AdditionalOptions>";
} }
fout << this->FlagString.c_str() fout << cmVisualStudio10GeneratorOptionsEscapeForXML(this->FlagString)
<< " %(AdditionalOptions)</AdditionalOptions>\n"; << " %(AdditionalOptions)</AdditionalOptions>\n";
} }
else else
{ {
fout << prefix << "AdditionalOptions=\""; fout << prefix << "AdditionalOptions=\"";
fout << fout << cmVisualStudioGeneratorOptionsEscapeForXML(this->FlagString);
cmVisualStudioGeneratorOptionsEscapeForXML(this->FlagString.c_str());
fout << "\"" << suffix; fout << "\"" << suffix;
} }
} }