diff options
author | Bill Hoffman <bill.hoffman@kitware.com> | 2009-06-25 20:41:57 (GMT) |
---|---|---|
committer | Bill Hoffman <bill.hoffman@kitware.com> | 2009-06-25 20:41:57 (GMT) |
commit | 7491f52992450bc6853c44c28db646c6176cbfd0 (patch) | |
tree | 3ec314d959220760927dc3741e8e51bc64267471 /Source/cmVisualStudioGeneratorOptions.cxx | |
parent | 953439f738e98b463e2583cdbe1c756a7045eacb (diff) | |
download | CMake-7491f52992450bc6853c44c28db646c6176cbfd0.zip CMake-7491f52992450bc6853c44c28db646c6176cbfd0.tar.gz CMake-7491f52992450bc6853c44c28db646c6176cbfd0.tar.bz2 |
ENH: first pass at VS 10, can bootstrap CMake, but many tests still fail
Diffstat (limited to 'Source/cmVisualStudioGeneratorOptions.cxx')
-rw-r--r-- | Source/cmVisualStudioGeneratorOptions.cxx | 420 |
1 files changed, 420 insertions, 0 deletions
diff --git a/Source/cmVisualStudioGeneratorOptions.cxx b/Source/cmVisualStudioGeneratorOptions.cxx new file mode 100644 index 0000000..179dc5b --- /dev/null +++ b/Source/cmVisualStudioGeneratorOptions.cxx @@ -0,0 +1,420 @@ +#include "cmVisualStudioGeneratorOptions.h" +#include "cmSystemTools.h" +#include <cmsys/System.h> +#include "cmVisualStudio10TargetGenerator.h" + +inline std::string cmVisualStudioGeneratorOptionsEscapeForXML(const char* s) +{ + std::string ret = s; + cmSystemTools::ReplaceString(ret, "&", "&"); + cmSystemTools::ReplaceString(ret, "\"", """); + cmSystemTools::ReplaceString(ret, "<", "<"); + cmSystemTools::ReplaceString(ret, ">", ">"); + cmSystemTools::ReplaceString(ret, "\n", "
"); + return ret; +} + +//---------------------------------------------------------------------------- +cmVisualStudioGeneratorOptions +::cmVisualStudioGeneratorOptions(cmLocalGenerator* lg, + int version, + Tool tool, + cmVS7FlagTable const* table, + cmVS7FlagTable const* extraTable, + cmVisualStudio10TargetGenerator* g): + LocalGenerator(lg), Version(version), CurrentTool(tool), + DoingDefine(false), FlagTable(table), ExtraFlagTable(extraTable), + TargetGenerator(g) +{ +} + +//---------------------------------------------------------------------------- +void cmVisualStudioGeneratorOptions::FixExceptionHandlingDefault() +{ + // 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. + switch (this->Version) + { + case 7: + case 71: + this->FlagMap["ExceptionHandling"] = "FALSE"; + break; + case 10: + // by default VS puts <ExceptionHandling></ExceptionHandling> empty + // for a project, to make our projects look the same put a new line + // and space over for the closing </ExceptionHandling> as the default + // value + this->FlagMap["ExceptionHandling"] = "\n "; + break; + default: + this->FlagMap["ExceptionHandling"] = "0"; + break; + } +} + +//---------------------------------------------------------------------------- +void cmVisualStudioGeneratorOptions::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()) + { + if(this->Version == 10) + { + this->FlagMap["SuppressStartupBanner"] = "false"; + } + else + { + this->FlagMap["SuppressStartupBanner"] = "FALSE"; + } + } +} + +//---------------------------------------------------------------------------- +void cmVisualStudioGeneratorOptions::AddDefine(const std::string& def) +{ + this->Defines.push_back(def); +} + +//---------------------------------------------------------------------------- +void cmVisualStudioGeneratorOptions::AddDefines(const char* defines) +{ + if(defines) + { + // Expand the list of definitions. + cmSystemTools::ExpandListArgument(defines, this->Defines); + } +} + +//---------------------------------------------------------------------------- +void cmVisualStudioGeneratorOptions::AddFlag(const char* flag, + const char* value) +{ + this->FlagMap[flag] = value; +} + + +bool cmVisualStudioGeneratorOptions::IsDebug() +{ + return this->FlagMap.find("DebugInformationFormat") != this->FlagMap.end(); +} + +//---------------------------------------------------------------------------- +bool cmVisualStudioGeneratorOptions::UsingUnicode() +{ + // Look for the a _UNICODE definition. + for(std::vector<std::string>::const_iterator di = this->Defines.begin(); + di != this->Defines.end(); ++di) + { + if(*di == "_UNICODE") + { + return true; + } + } + return false; +} + +//---------------------------------------------------------------------------- +void cmVisualStudioGeneratorOptions::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 cmVisualStudioGeneratorOptions::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] == '/') + { + // Look for preprocessor definitions. + if(this->CurrentTool == Compiler && 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; + } + + // Look through the available flag tables. + bool flag_handled = false; + if(this->FlagTable && + this->CheckFlagTable(this->FlagTable, flag, flag_handled)) + { + return; + } + if(this->ExtraFlagTable && + this->CheckFlagTable(this->ExtraFlagTable, flag, flag_handled)) + { + return; + } + + // If any map entry handled the flag we are done. + if(flag_handled) + { + return; + } + } + // This option is not known. Store it in the output flags. + this->FlagString += " "; + this->FlagString += + cmSystemTools::EscapeWindowsShellArgument( + flag, + cmsysSystem_Shell_Flag_AllowMakeVariables | + cmsysSystem_Shell_Flag_VSIDE); +} + +//---------------------------------------------------------------------------- +bool +cmVisualStudioGeneratorOptions +::CheckFlagTable(cmVS7FlagTable const* table, const char* flag, + bool& flag_handled) +{ + // Look for an entry in the flag table matching this flag. + for(cmVS7FlagTable const* entry = table; entry->IDEName; ++entry) + { + bool entry_found = false; + if(entry->special & cmVS7FlagTable::UserValue) + { + // This flag table entry accepts a user-specified value. If + // the entry specifies UserRequired we must match only if a + // non-empty value is given. + int n = static_cast<int>(strlen(entry->commandFlag)); + if(strncmp(flag+1, entry->commandFlag, n) == 0 && + (!(entry->special & cmVS7FlagTable::UserRequired) || + static_cast<int>(strlen(flag+1)) > n)) + { + if(entry->special & cmVS7FlagTable::UserIgnored) + { + // Ignore the user-specified value. + this->FlagMap[entry->IDEName] = entry->value; + } + else if(entry->special & cmVS7FlagTable::SemicolonAppendable) + { + const char *new_value = flag+1+n; + + std::map<cmStdString,cmStdString>::iterator itr; + 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 + { + // Use the user-specified value. + this->FlagMap[entry->IDEName] = flag+1+n; + } + entry_found = true; + } + } + else if(strcmp(flag+1, entry->commandFlag) == 0) + { + // This flag table entry provides a fixed value. + this->FlagMap[entry->IDEName] = entry->value; + entry_found = true; + } + + // If the flag has been handled by an entry not requesting a + // search continuation we are done. + if(entry_found && !(entry->special & cmVS7FlagTable::Continue)) + { + return true; + } + + // If the entry was found the flag has been handled. + flag_handled = flag_handled || entry_found; + } + + return false; +} + + +void cmVisualStudioGeneratorOptions::SetConfiguration(const char* config) +{ + this->Configuration = config; +} + +//---------------------------------------------------------------------------- +void +cmVisualStudioGeneratorOptions +::OutputPreprocessorDefinitions(std::ostream& fout, + const char* prefix, + const char* suffix) +{ + if(this->Defines.empty()) + { + return; + } + if(this->Version == 10) + { + // if there are configuration specifc flags, then + // use the configuration specific tag for PreprocessorDefinitions + if(this->Configuration.size()) + { + fout << prefix; + this->TargetGenerator->WritePlatformConfigTag( + "PreprocessorDefinitions", + this->Configuration.c_str(), + 0, + 0, 0, &fout); + } + else + { + fout << prefix << "<PreprocessorDefinitions>"; + } + } + else + { + fout << prefix << "PreprocessorDefinitions=\""; + } + const char* comma = ""; + for(std::vector<std::string>::const_iterator di = this->Defines.begin(); + di != this->Defines.end(); ++di) + { + // Escape the definition for the compiler. + std::string define; + if(this->Version != 10) + { + define = + this->LocalGenerator->EscapeForShell(di->c_str(), true); + } + else + { + define = *di; + } + // Escape this flag for the IDE. + if(this->Version != 10) + { + define = cmVisualStudioGeneratorOptionsEscapeForXML(define.c_str()); + } + // Store the flag in the project file. + fout << comma << define; + if(this->Version == 10) + { + comma = ";"; + } + else + { + comma = ","; + } + } + if(this->Version == 10) + { + fout << ";%(PreprocessorDefinitions)</PreprocessorDefinitions>" << suffix; + } + else + { + fout << "\"" << suffix; + } +} + +//---------------------------------------------------------------------------- +void +cmVisualStudioGeneratorOptions +::OutputFlagMap(std::ostream& fout, const char* indent) +{ + if(this->Version == 10) + { + for(std::map<cmStdString, cmStdString>::iterator m = this->FlagMap.begin(); + m != this->FlagMap.end(); ++m) + { + fout << indent; + if(this->Configuration.size()) + { + this->TargetGenerator->WritePlatformConfigTag( + m->first.c_str(), + this->Configuration.c_str(), + 0, + 0, 0, &fout); + } + else + { + fout << "<" << m->first << ">"; + } + fout << m->second << "</" << m->first << ">\n"; + } + } + else + { + for(std::map<cmStdString, cmStdString>::iterator m = this->FlagMap.begin(); + m != this->FlagMap.end(); ++m) + { + fout << indent << m->first << "=\"" << m->second << "\"\n"; + } + } +} + +//---------------------------------------------------------------------------- +void +cmVisualStudioGeneratorOptions +::OutputAdditionalOptions(std::ostream& fout, + const char* prefix, + const char* suffix) +{ + if(!this->FlagString.empty()) + { + if(this->Version == 10) + { + fout << prefix; + if(this->Configuration.size()) + { + this->TargetGenerator->WritePlatformConfigTag( + "AdditionalOptions", + this->Configuration.c_str(), + 0, + 0, 0, &fout); + } + else + { + fout << "<AdditionalOptions>"; + } + fout << this->FlagString.c_str() + << " %(AdditionalOptions)</AdditionalOptions>\n"; + } + else + { + fout << prefix << "AdditionalOptions=\""; + fout << + cmVisualStudioGeneratorOptionsEscapeForXML(this->FlagString.c_str()); + fout << "\"" << suffix; + } + } +} |