ENH: Reimplemented parsing and mapping of flags into vcproj file attribute options. This cleans up and centralizes a few things. It is in preparation for dealing with precompiled header flags for bug #3512 since they require some special handling.

This commit is contained in:
Brad King 2007-02-01 11:49:27 -05:00
parent d37abb6b5d
commit d8aa12178d
2 changed files with 378 additions and 282 deletions

View File

@ -24,8 +24,11 @@
#include "cmCacheManager.h"
#include "cmake.h"
#include <cmsys/System.h>
#include <ctype.h> // for isspace
//----------------------------------------------------------------------------
cmLocalVisualStudio7Generator::cmLocalVisualStudio7Generator()
{
this->Version = 7;
@ -290,6 +293,11 @@ struct cmVS7FlagTable
const char* value; // string value
};
// A statically allocated string so that user value options can be
// identified with a single pointer comparison and can never be
// confused with actual values.
static const char CMFLAG_USER_VALUE[] = "<USER_VALUE>";
// fill the table here currently the comment field is not used for
// anything other than documentation NOTE: Make sure the longer
// commandFlag comes FIRST!
@ -368,22 +376,47 @@ cmVS7FlagTable cmLocalVisualStudio7GeneratorLinkFlagTable[] =
{"GenerateManifest", "MANIFEST", "enable manifest generation", "TRUE"},
{"LinkIncremental", "INCREMENTAL:NO", "link incremental", "1"},
{"LinkIncremental", "INCREMENTAL:YES", "link incremental", "2"},
{"IgnoreDefaultLibraryNames", "NODEFAULTLIB:", "USER_VALUE", ""},
{"IgnoreDefaultLibraryNames", "NODEFAULTLIB:", "default libs to ignore",
CMFLAG_USER_VALUE},
{0,0,0,0 }
};
void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout,
const char* configName,
const char *libName,
cmTarget &target)
//----------------------------------------------------------------------------
class cmLocalVisualStudio7GeneratorOptions
{
public:
// Construct an options table for a given tool.
enum Tool
{
Compiler,
Linker
};
cmLocalVisualStudio7GeneratorOptions(Tool tool);
// Store options from command line flags.
void Parse(const char* flags);
// Store options for verbose builds.
void SetVerboseMakefile(bool verbose);
// Store definitions and flags.
void AddDefine(const std::string& define);
void AddFlag(const char* flag, const char* value);
// Check for specific options.
bool UsingUnicode();
bool UsingDebugPDB();
// Write options to output.
void OutputPreprocessorDefinitions(std::ostream& fout,
const char* prefix,
const char* suffix);
void OutputFlagMap(std::ostream& fout, const char* indent);
void OutputAdditionalOptions(std::ostream& fout,
const char* prefix,
const char* suffix);
private:
// create a map of xml tags to the values they should have in the output
// for example, "BufferSecurityCheck" = "TRUE"
// first fill this table with the values for the configuration
@ -391,11 +424,24 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout,
// Then parse the command line flags specified in CMAKE_CXX_FLAGS
// and CMAKE_C_FLAGS
// and overwrite or add new values to this map
std::map<cmStdString, cmStdString> flagMap;
// since the default is on for this, but if /EHsc is found
// in the flags it will be turned on and we have /EHSC on by
// default in the CXX flags, then this is the only way to turn this off
flagMap["ExceptionHandling"] = "FALSE";
std::map<cmStdString, cmStdString> FlagMap;
// Preprocessor definitions.
std::vector<cmStdString> Defines;
// Unrecognized flags that get no special handling.
cmStdString FlagString;
bool DoingDefine;
cmVS7FlagTable const* FlagTable;
void HandleFlag(const char* flag);
};
void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout,
const char* configName,
const char *libName,
cmTarget &target)
{
const char* mfcFlag = this->Makefile->GetDefinition("CMAKE_MFC_FLAG");
if(!mfcFlag)
{
@ -470,6 +516,51 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout,
flags += targetFlags;
}
// Get preprocessor definitions for this directory.
std::string defineFlags = this->Makefile->GetDefineFlags();
// Construct a set of build options for this target.
Options targetOptions(Options::Compiler);
targetOptions.Parse(flags.c_str());
targetOptions.Parse(defineFlags.c_str());
targetOptions.SetVerboseMakefile(
this->Makefile->IsOn("CMAKE_VERBOSE_MAKEFILE"));
// Add a definition for the configuration name.
std::string configDefine = "CMAKE_INTDIR=\\\"";
configDefine += configName;
configDefine += "\\\"";
targetOptions.AddDefine(configDefine);
// Add a definition for the export macro.
if(target.GetType() == cmTarget::SHARED_LIBRARY ||
target.GetType() == cmTarget::MODULE_LIBRARY)
{
std::string exportSymbol;
if(const char* custom_export_name = target.GetProperty("DEFINE_SYMBOL"))
{
exportSymbol = custom_export_name;
}
else
{
std::string id = libName;
id += "_EXPORTS";
exportSymbol = cmSystemTools::MakeCindentifier(id.c_str());
}
targetOptions.AddDefine(exportSymbol);
}
// Override the flag map with cmake-specific settings.
if(this->Makefile->IsOn("CMAKE_CXX_USE_RTTI"))
{
targetOptions.AddFlag("RuntimeTypeInfo", "TRUE");
}
if(const char* warningLevel =
this->Makefile->GetDefinition("CMAKE_CXX_WARNING_LEVEL"))
{
targetOptions.AddFlag("WarningLevel", warningLevel);
}
// The intermediate directory name consists of a directory for the
// target and a subdirectory for the configuration name.
std::string intermediateDir = this->GetTargetDirectory(target);
@ -481,12 +572,10 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout,
<< "\t\t\tConfigurationType=\"" << configType << "\"\n"
<< "\t\t\tUseOfMFC=\"" << mfcFlag << "\"\n"
<< "\t\t\tATLMinimizesCRunTimeLibraryUsage=\"FALSE\"\n";
// if -D_UNICODE or /D_UNICODE is found in the flags
// change the character set to unicode, if not then
// default to MBCS
std::string defs = this->Makefile->GetDefineFlags();
if(flags.find("D_UNICODE") != flags.npos ||
defs.find("D_UNICODE") != flags.npos)
// If unicode is enabled change the character set to unicode, if not
// then default to MBCS.
if(targetOptions.UsingUnicode())
{
fout << "\t\t\tCharacterSet=\"1\">\n";
}
@ -496,25 +585,8 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout,
}
fout << "\t\t\t<Tool\n"
<< "\t\t\t\tName=\"VCCLCompilerTool\"\n"
<< "\t\t\t\tAdditionalOptions=\"";
// now fill the flagMap from the command line flags, and
// if a flag is used, it will be removed from the flags string by
// this function call
this->FillFlagMapFromCommandFlags
(flagMap, &cmLocalVisualStudio7GeneratorFlagTable[0], flags);
std::string defineFlags = this->Makefile->GetDefineFlags();
// now check the define flags for flags other than -D and
// put them in the map, the -D flags will be left in the defineFlags
// variable as -D is not in the flagMap
this->FillFlagMapFromCommandFlags
(flagMap, &cmLocalVisualStudio7GeneratorFlagTable[0], defineFlags);
// output remaining flags that were not mapped to anything
fout << this->EscapeForXML(flags.c_str()).c_str();
fout << " -DCMAKE_INTDIR=\\&quot;" << configName << "\\&quot;"
<< "\"\n";
<< "\t\t\t\tName=\"VCCLCompilerTool\"\n";
targetOptions.OutputAdditionalOptions(fout, "\t\t\t\t", "\n");
fout << "\t\t\t\tAdditionalIncludeDirectories=\"";
std::vector<std::string> includes;
this->GetIncludeDirectories(includes);
@ -525,48 +597,11 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout,
fout << ipath << ";";
}
fout << "\"\n";
// set a few cmake specific flags
if(this->Makefile->IsOn("CMAKE_CXX_USE_RTTI"))
{
flagMap["RuntimeTypeInfo"] = "TRUE";
}
if ( this->Makefile->GetDefinition("CMAKE_CXX_WARNING_LEVEL") )
{
flagMap["WarningLevel"] =
this->Makefile->GetDefinition("CMAKE_CXX_WARNING_LEVEL");
}
// Now copy the flag map into the xml for the file
for(std::map<cmStdString, cmStdString>::iterator m = flagMap.begin();
m != flagMap.end(); ++m)
{
fout << "\t\t\t\t" << m->first << "=\"" << m->second << "\"\n";
}
fout << "\t\t\t\tPreprocessorDefinitions=\"";
if(target.GetType() == cmTarget::SHARED_LIBRARY
|| target.GetType() == cmTarget::MODULE_LIBRARY)
{
std::string exportSymbol;
if (const char* custom_export_name =
target.GetProperty("DEFINE_SYMBOL"))
{
exportSymbol = custom_export_name;
}
else
{
std::string id = libName;
id += "_EXPORTS";
exportSymbol = cmSystemTools::MakeCindentifier(id.c_str());
}
fout << "," << exportSymbol;
}
this->OutputDefineFlags(defineFlags.c_str(), fout);
fout << "\"\n";
targetOptions.OutputFlagMap(fout, "\t\t\t\t");
targetOptions.OutputPreprocessorDefinitions(fout, "\t\t\t\t", "\n");
fout << "\t\t\t\tAssemblerListingLocation=\"" << configName << "\"\n";
fout << "\t\t\t\tObjectFile=\"$(IntDir)\\\"\n";
std::map<cmStdString, cmStdString>::iterator mi =
flagMap.find("DebugInformationFormat");
if(mi != flagMap.end() && mi->second != "1")
if(targetOptions.UsingDebugPDB())
{
if(target.GetType() == cmTarget::EXECUTABLE)
{
@ -605,15 +640,12 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout,
fout << ipath << ";";
}
// add the -D flags to the RC tool
fout << "\"\n"
<< "\t\t\t\tPreprocessorDefinitions=\"";
this->OutputDefineFlags(defineFlags.c_str(), fout);
fout << "\" />\n";
fout << "\"";
targetOptions.OutputPreprocessorDefinitions(fout, "\n\t\t\t\t", "");
fout << "/>\n";
fout << "\t\t\t<Tool\n\t\t\t\tName=\"VCMIDLTool\"\n";
fout << "\t\t\t\tPreprocessorDefinitions=\"";
this->OutputDefineFlags(defineFlags.c_str(), fout);
fout << "\"\n";
targetOptions.OutputPreprocessorDefinitions(fout, "\t\t\t\t", "\n");
fout << "\t\t\t\tMkTypLibCompatible=\"FALSE\"\n";
if( this->PlatformName == "x64" )
{
@ -651,84 +683,6 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout,
this->OutputBuildTool(fout, configName, target);
fout << "\t\t</Configuration>\n";
}
void cmLocalVisualStudio7Generator::ReplaceFlagSetMap(std::string& flags,
cmVS7FlagTable*
flagTable,
std::map<cmStdString,
cmStdString>& flagMap,
std::string& option,
std::string::size_type
pos)
{
std::string value = flagTable->value;
if(strcmp(flagTable->comment, "USER_VALUE") == 0)
{
std::string::size_type len = flags.find(" ", pos);
if(len != flags.npos)
{
len -= option.size();
}
value = flags.substr(pos+option.size(), len);
std::string fullflag = option;
fullflag += value;
// remove everything
cmSystemTools::ReplaceString(flags, fullflag.c_str(), "");
}
else
{
cmSystemTools::ReplaceString(flags, option.c_str(), "");
}
// now put value into flag map
flagMap[flagTable->IDEName] = value;
}
void cmLocalVisualStudio7Generator::FillFlagMapFromCommandFlags(
std::map<cmStdString, cmStdString>& flagMap,
cmVS7FlagTable* flagTable,
std::string& flags)
{
std::string replace;
std::string option;
while(flagTable->IDEName)
{
option.reserve(strlen(flagTable->commandFlag)+2);
// first do the - version
option = "-";
option += flagTable->commandFlag;
std::string::size_type pos = flags.find(option);
while(pos != flags.npos)
{
this->ReplaceFlagSetMap(flags, flagTable, flagMap,
option, pos);
pos = flags.find(option);
}
// now do the / version
option[0] = '/';
pos = flags.find(option);
while(pos != flags.npos)
{
this->ReplaceFlagSetMap(flags, flagTable, flagMap,
option, pos);
pos = flags.find(option);
}
// move to next flag
flagTable++;
}
// If verbose makefiles have been requested and the /nologo option
// was not given explicitly in the flags we want to add an attribute
// to the generated project to disable logo suppression. Otherwise
// the GUI default is to enable suppression.
if(this->Makefile->IsOn("CMAKE_VERBOSE_MAKEFILE"))
{
if(flagMap.find("SuppressStartupBanner") == flagMap.end())
{
flagMap["SuppressStartupBanner"] = "FALSE";
}
}
}
//----------------------------------------------------------------------------
std::string
@ -789,10 +743,8 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout,
extraLinkOptions += " ";
extraLinkOptions += targetLinkFlags;
}
std::map<cmStdString, cmStdString> flagMap;
this->FillFlagMapFromCommandFlags
(flagMap, &cmLocalVisualStudio7GeneratorLinkFlagTable[0],
extraLinkOptions);
Options linkOptions(Options::Linker);
linkOptions.Parse(extraLinkOptions.c_str());
switch(target.GetType())
{
case cmTarget::STATIC_LIBRARY:
@ -855,17 +807,11 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout,
standardLibsVar += "_STANDARD_LIBRARIES";
fout << "\t\t\t<Tool\n"
<< "\t\t\t\tName=\"VCLinkerTool\"\n"
<< "\t\t\t\tAdditionalOptions=\"/MACHINE:I386";
if(extraLinkOptions.size())
{
fout << " " << cmLocalVisualStudio7Generator::EscapeForXML(
extraLinkOptions.c_str()).c_str();
}
<< "\t\t\t\tName=\"VCLinkerTool\"\n";
linkOptions.OutputAdditionalOptions(fout, "\t\t\t\t", "\n");
// Use the NOINHERIT macro to avoid getting VS project default
// libraries which may be set by the user to something bad.
fout << "\"\n"
<< "\t\t\t\tAdditionalDependencies=\"$(NOINHERIT) "
fout << "\t\t\t\tAdditionalDependencies=\"$(NOINHERIT) "
<< this->Makefile->GetSafeDefinition(standardLibsVar.c_str())
<< " ";
this->OutputLibraries(fout, linkLibs);
@ -877,11 +823,7 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout,
fout << "\t\t\t\tOutputFile=\""
<< this->ConvertToXMLOutputPathSingle(temp.c_str()) << "\"\n";
this->WriteTargetVersionAttribute(fout, target);
for(std::map<cmStdString, cmStdString>::iterator i = flagMap.begin();
i != flagMap.end(); ++i)
{
fout << "\t\t\t\t" << i->first << "=\"" << i->second << "\"\n";
}
linkOptions.OutputFlagMap(fout, "\t\t\t\t");
fout << "\t\t\t\tAdditionalLibraryDirectories=\"";
this->OutputLibraryDirectories(fout, linkDirs);
fout << "\"\n";
@ -943,17 +885,11 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout,
standardLibsVar += "_STANDARD_LIBRARIES";
fout << "\t\t\t<Tool\n"
<< "\t\t\t\tName=\"VCLinkerTool\"\n"
<< "\t\t\t\tAdditionalOptions=\"";
if(extraLinkOptions.size())
{
fout << " " << cmLocalVisualStudio7Generator::EscapeForXML(
extraLinkOptions.c_str()).c_str();
}
<< "\t\t\t\tName=\"VCLinkerTool\"\n";
linkOptions.OutputAdditionalOptions(fout, "\t\t\t\t", "\n");
// Use the NOINHERIT macro to avoid getting VS project default
// libraries which may be set by the user to something bad.
fout << "\"\n"
<< "\t\t\t\tAdditionalDependencies=\"$(NOINHERIT) "
fout << "\t\t\t\tAdditionalDependencies=\"$(NOINHERIT) "
<< this->Makefile->GetSafeDefinition(standardLibsVar.c_str())
<< " ";
this->OutputLibraries(fout, linkLibs);
@ -965,11 +901,7 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout,
fout << "\t\t\t\tOutputFile=\""
<< this->ConvertToXMLOutputPathSingle(temp.c_str()) << "\"\n";
this->WriteTargetVersionAttribute(fout, target);
for(std::map<cmStdString, cmStdString>::iterator i = flagMap.begin();
i != flagMap.end(); ++i)
{
fout << "\t\t\t\t" << i->first << "=\"" << i->second << "\"\n";
}
linkOptions.OutputFlagMap(fout, "\t\t\t\t");
fout << "\t\t\t\tAdditionalLibraryDirectories=\"";
this->OutputLibraryDirectories(fout, linkDirs);
fout << "\"\n";
@ -1087,63 +1019,6 @@ cmLocalVisualStudio7Generator
}
}
//----------------------------------------------------------------------------
void cmLocalVisualStudio7Generator::OutputDefineFlags(const char* flags,
std::ostream& fout)
{
std::string defs = flags;
cmSystemTools::ReplaceString(defs, "/D","-D");
std::string::size_type pos = defs.find("-D");
bool done = pos == std::string::npos;
if(!done)
{
fout << ",";
}
while(!done)
{
std::string::size_type nextpos = defs.find("-D", pos+2);
std::string define;
if(nextpos != std::string::npos)
{
define = defs.substr(pos+2, nextpos - pos -3);
}
else
{
define = defs.substr(pos+2);
done = true;
}
// Remove trailing whitespace from the definition.
while(!define.empty() && isspace(define[define.size()-1]))
{
define = define.substr(0, define.size()-1);
}
// Double-quotes in the value of the definition must be escaped
// with a backslash. The entire definition should be quoted in
// the generated xml attribute to avoid confusing the VS parser.
define = this->EscapeForXML(define.c_str());
// if the define has something in it that is not a letter or a number
// then quote it
if(define.
find_first_not_of(
"-_abcdefghigklmnopqrstuvwxyz1234567890ABCDEFGHIGKLMNOPQRSTUVWXYZ")
!= define.npos)
{
fout << "&quot;" << define << "&quot;,";
}
else
{
fout << define << ",";
}
if(!done)
{
pos = defs.find("-D", nextpos);
}
}
}
void cmLocalVisualStudio7Generator::WriteVCProjFile(std::ostream& fout,
const char *libName,
cmTarget &target)
@ -1342,28 +1217,14 @@ void cmLocalVisualStudio7Generator
fout << ">\n";
fout << "\t\t\t\t\t<Tool\n"
<< "\t\t\t\t\tName=\"" << aCompilerTool << "\"\n";
if(compileFlags.size())
{
std::string compileFlagsCopy = compileFlags;
std::map<cmStdString, cmStdString> fileFlagMap;
this->FillFlagMapFromCommandFlags
(fileFlagMap,
&cmLocalVisualStudio7GeneratorFlagTable[0],
compileFlagsCopy);
if(compileFlagsCopy.size() &&
compileFlagsCopy.find_first_not_of(" ")
!= compileFlagsCopy.npos)
{
fout << "\t\t\t\t\tAdditionalOptions=\""
<< this->EscapeForXML(compileFlagsCopy.c_str()) << "\"\n";
}
for(std::map<cmStdString,
cmStdString>::iterator m = fileFlagMap.begin();
m != fileFlagMap.end(); ++m)
{
fout << "\t\t\t\t\t" << m->first << "=\""
<< m->second << "\"\n";
}
if(!compileFlags.empty())
{
Options fileOptions(Options::Compiler);
fileOptions.Parse(compileFlags.c_str());
fileOptions.OutputAdditionalOptions(fout, "\t\t\t\t\t", "\n");
fileOptions.OutputFlagMap(fout, "\t\t\t\t\t");
fileOptions.OutputPreprocessorDefinitions(fout,
"\t\t\t\t\t", "\n");
}
if(additionalDeps.length())
{
@ -1649,8 +1510,7 @@ void cmLocalVisualStudio7Generator::WriteVCProjFooter(std::ostream& fout)
<< "</VisualStudioProject>\n";
}
std::string cmLocalVisualStudio7Generator::EscapeForXML(const char* s)
std::string cmLocalVisualStudio7GeneratorEscapeForXML(const char* s)
{
std::string ret = s;
cmSystemTools::ReplaceString(ret, "&", "&amp;");
@ -1661,6 +1521,11 @@ std::string cmLocalVisualStudio7Generator::EscapeForXML(const char* s)
return ret;
}
std::string cmLocalVisualStudio7Generator::EscapeForXML(const char* s)
{
return cmLocalVisualStudio7GeneratorEscapeForXML(s);
}
std::string cmLocalVisualStudio7Generator
::ConvertToXMLOutputPath(const char* path)
{
@ -1794,3 +1659,233 @@ std::string cmLocalVisualStudio7Generator
dir += ".dir";
return dir;
}
//----------------------------------------------------------------------------
cmLocalVisualStudio7GeneratorOptions
::cmLocalVisualStudio7GeneratorOptions(Tool tool):
DoingDefine(false), FlagTable(0)
{
// Choose the flag table for the requested tool.
switch(tool)
{
case Compiler:
this->FlagTable = cmLocalVisualStudio7GeneratorFlagTable; break;
case Linker:
this->FlagTable = cmLocalVisualStudio7GeneratorLinkFlagTable; break;
default: break;
}
// Exception handling is on by default because the platform file has
// "/EHsc" in the flags. Normally, that will override this
// initialization to off, but the user has the option of removing
// the flag to disable exception handling. When the user does
// remove the flag we need to override the IDE default of on.
this->FlagMap["ExceptionHandling"] = "FALSE";
}
//----------------------------------------------------------------------------
void cmLocalVisualStudio7GeneratorOptions::SetVerboseMakefile(bool verbose)
{
// If verbose makefiles have been requested and the /nologo option
// was not given explicitly in the flags we want to add an attribute
// to the generated project to disable logo suppression. Otherwise
// the GUI default is to enable suppression.
if(verbose &&
this->FlagMap.find("SuppressStartupBanner") == this->FlagMap.end())
{
this->FlagMap["SuppressStartupBanner"] = "FALSE";
}
}
//----------------------------------------------------------------------------
void cmLocalVisualStudio7GeneratorOptions::AddDefine(const std::string& def)
{
this->Defines.push_back(def);
}
//----------------------------------------------------------------------------
void cmLocalVisualStudio7GeneratorOptions::AddFlag(const char* flag,
const char* value)
{
this->FlagMap[flag] = value;
}
//----------------------------------------------------------------------------
bool cmLocalVisualStudio7GeneratorOptions::UsingUnicode()
{
// Look for the a _UNICODE definition.
bool use_unicode = false;
for(std::vector<cmStdString>::const_iterator di = this->Defines.begin();
di != this->Defines.end(); ++di)
{
if(*di == "_UNICODE")
{
return true;
}
}
return false;
}
//----------------------------------------------------------------------------
bool cmLocalVisualStudio7GeneratorOptions::UsingDebugPDB()
{
std::map<cmStdString, cmStdString>::iterator mi =
this->FlagMap.find("DebugInformationFormat");
if(mi != this->FlagMap.end() && mi->second != "1")
{
return true;
}
else
{
return false;
}
}
//----------------------------------------------------------------------------
void cmLocalVisualStudio7GeneratorOptions::Parse(const char* flags)
{
// Parse the input string as a windows command line since the string
// is intended for writing directly into the build files.
std::vector<std::string> args;
cmSystemTools::ParseWindowsCommandLine(flags, args);
// Process flags that need to be represented specially in the IDE
// project file.
for(std::vector<std::string>::iterator ai = args.begin();
ai != args.end(); ++ai)
{
this->HandleFlag(ai->c_str());
}
}
//----------------------------------------------------------------------------
void cmLocalVisualStudio7GeneratorOptions::HandleFlag(const char* flag)
{
// If the last option was -D then this option is the definition.
if(this->DoingDefine)
{
this->DoingDefine = false;
this->Defines.push_back(flag);
return;
}
// Look for known arguments.
if(flag[0] == '-' || flag[0] == '/')
{
if(flag[1] == 'D')
{
if(flag[2] == '\0')
{
// The next argument will have the definition.
this->DoingDefine = true;
}
else
{
// Store this definition.
this->Defines.push_back(flag+2);
}
return;
}
else if(this->FlagTable)
{
// Look for an entry in the flag table matching this flag.
for(cmVS7FlagTable const* entry = this->FlagTable;
entry->IDEName; ++entry)
{
if(entry->value == CMFLAG_USER_VALUE)
{
// This flag table entry accepts a user value.
int n = static_cast<int>(strlen(entry->commandFlag));
if(strncmp(flag+1, entry->commandFlag, n) == 0)
{
this->FlagMap[entry->IDEName] = flag+1+n;
return;
}
}
else if(strcmp(flag+1, entry->commandFlag) == 0)
{
// This flag table entry provides a fixed value.
this->FlagMap[entry->IDEName] = entry->value;
return;
}
}
}
}
// This option is not known. Store it in the output flags.
this->FlagString += " ";
this->FlagString +=
cmSystemTools::EscapeWindowsShellArgument(flag,
cmsysSystem_Shell_Flag_VSIDE);
}
//----------------------------------------------------------------------------
void
cmLocalVisualStudio7GeneratorOptions
::OutputPreprocessorDefinitions(std::ostream& fout,
const char* prefix,
const char* suffix)
{
if(this->Defines.empty())
{
return;
}
fout << prefix << "PreprocessorDefinitions=\"";
const char* comma = "";
for(std::vector<cmStdString>::const_iterator di = this->Defines.begin();
di != this->Defines.end(); ++di)
{
// Escape this flag for the IDE.
std::string define =
cmLocalVisualStudio7GeneratorEscapeForXML(di->c_str());
// Old comment:
// Double-quotes in the value of the definition must be escaped
// with a backslash. The entire definition should be quoted in
// the generated xml attribute to avoid confusing the VS parser.
// Write this flag. Quote it if the definition is not
// alphanumeric.
if(define.find_first_not_of(
"-_abcdefghigklmnopqrstuvwxyz1234567890ABCDEFGHIGKLMNOPQRSTUVWXYZ")
!= define.npos)
{
fout << comma << "&quot;" << define << "&quot;";
}
else
{
fout << comma << define;
}
comma = ",";
}
fout << "\"" << suffix;
}
//----------------------------------------------------------------------------
void
cmLocalVisualStudio7GeneratorOptions
::OutputFlagMap(std::ostream& fout, const char* indent)
{
for(std::map<cmStdString, cmStdString>::iterator m = this->FlagMap.begin();
m != this->FlagMap.end(); ++m)
{
fout << indent << m->first << "=\"" << m->second << "\"\n";
}
}
//----------------------------------------------------------------------------
void
cmLocalVisualStudio7GeneratorOptions
::OutputAdditionalOptions(std::ostream& fout,
const char* prefix,
const char* suffix)
{
if(!this->FlagString.empty())
{
fout << prefix << "AdditionalOptions=\"";
fout <<
cmLocalVisualStudio7GeneratorEscapeForXML(this->FlagString.c_str());
fout << "\"" << suffix;
}
}

View File

@ -26,6 +26,8 @@ class cmCustomCommand;
class cmSourceGroup;
struct cmVS7FlagTable;
class cmLocalVisualStudio7GeneratorOptions;
/** \class cmLocalVisualStudio7Generator
* \brief Write Visual Studio .NET project files.
*
@ -65,6 +67,7 @@ public:
void SetPlatformName(const char* n) { this->PlatformName = n;}
virtual void ConfigureFinalPass();
private:
typedef cmLocalVisualStudio7GeneratorOptions Options;
void ReadAndStoreExternalGUID(const char* name,
const char* path);
void ReplaceFlagSetMap(std::string& flags,
@ -96,8 +99,6 @@ private:
std::string EscapeForXML(const char* s);
std::string ConvertToXMLOutputPath(const char* path);
std::string ConvertToXMLOutputPathSingle(const char* path);
void OutputDefineFlags(const char* flags,
std::ostream& fout);
void OutputTargetRules(std::ostream& fout, cmTarget &target,
const char *libName);
void OutputBuildTool(std::ostream& fout, const char* configName,