From fb38af53c0536de7abda7f9a5eea2527f087caf1 Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 12 Mar 2007 12:35:11 -0400 Subject: BUG: Split precompiled header flags into a separate per-global-generator flag map. This is needed because the flag mappings differ across VS IDE versions. This fixes bug#3512 for VS8 where as the previous fix only worked for VS7. --- Source/cmGlobalVisualStudio71Generator.cxx | 1 + Source/cmGlobalVisualStudio7Generator.cxx | 25 +++- Source/cmGlobalVisualStudio7Generator.h | 2 + Source/cmGlobalVisualStudio8Generator.cxx | 19 +++ Source/cmGlobalVisualStudio8Generator.h | 1 + Source/cmGlobalVisualStudio8Win64Generator.cxx | 1 + Source/cmLocalVisualStudio7Generator.cxx | 167 +++++++++++++------------ Source/cmLocalVisualStudio7Generator.h | 23 ++++ Tests/PrecompiledHeader/CMakeLists.txt | 6 +- 9 files changed, 157 insertions(+), 88 deletions(-) diff --git a/Source/cmGlobalVisualStudio71Generator.cxx b/Source/cmGlobalVisualStudio71Generator.cxx index bc02e16..e29227d 100644 --- a/Source/cmGlobalVisualStudio71Generator.cxx +++ b/Source/cmGlobalVisualStudio71Generator.cxx @@ -35,6 +35,7 @@ cmLocalGenerator *cmGlobalVisualStudio71Generator::CreateLocalGenerator() { cmLocalVisualStudio7Generator *lg = new cmLocalVisualStudio7Generator; lg->SetVersion71(); + lg->SetExtraFlagTable(this->GetExtraFlagTableVS7()); lg->SetGlobalGenerator(this); return lg; } diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx index 701137f..8caf90b 100644 --- a/Source/cmGlobalVisualStudio7Generator.cxx +++ b/Source/cmGlobalVisualStudio7Generator.cxx @@ -21,7 +21,6 @@ #include "cmMakefile.h" #include "cmake.h" - cmGlobalVisualStudio7Generator::cmGlobalVisualStudio7Generator() { this->FindMakeProgramFile = "CMakeVS7FindMake.cmake"; @@ -138,7 +137,8 @@ std::string cmGlobalVisualStudio7Generator ///! Create a local generator appropriate to this Global Generator cmLocalGenerator *cmGlobalVisualStudio7Generator::CreateLocalGenerator() { - cmLocalGenerator *lg = new cmLocalVisualStudio7Generator; + cmLocalVisualStudio7Generator *lg = new cmLocalVisualStudio7Generator; + lg->SetExtraFlagTable(this->GetExtraFlagTableVS7()); lg->SetGlobalGenerator(this); return lg; } @@ -821,3 +821,24 @@ bool cmGlobalVisualStudio7Generator::IsPartOfDefaultBuild(const char* project, // default is to be part of the build return true; } + +//---------------------------------------------------------------------------- +static cmVS7FlagTable cmVS7ExtraFlagTable[] = +{ + // Precompiled header and related options. Note that the + // UsePrecompiledHeader entries are marked as "Continue" so that the + // corresponding PrecompiledHeaderThrough entry can be found. + {"UsePrecompiledHeader", "YX", "Automatically Generate", "2", + cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue}, + {"PrecompiledHeaderThrough", "YX", "Precompiled Header Name", "", + cmVS7FlagTable::UserValueRequired}, + {"UsePrecompiledHeader", "Yu", "Use Precompiled Header", "3", + cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue}, + {"PrecompiledHeaderThrough", "Yu", "Precompiled Header Name", "", + cmVS7FlagTable::UserValueRequired}, + {0,0,0,0,0} +}; +cmVS7FlagTable const* cmGlobalVisualStudio7Generator::GetExtraFlagTableVS7() +{ + return cmVS7ExtraFlagTable; +} diff --git a/Source/cmGlobalVisualStudio7Generator.h b/Source/cmGlobalVisualStudio7Generator.h index 7e36cf2..7719cd9 100644 --- a/Source/cmGlobalVisualStudio7Generator.h +++ b/Source/cmGlobalVisualStudio7Generator.h @@ -20,6 +20,7 @@ #include "cmGlobalGenerator.h" class cmTarget; +struct cmVS7FlagTable; /** \class cmGlobalVisualStudio7Generator * \brief Write a Unix makefiles. @@ -97,6 +98,7 @@ public: virtual const char* GetCMakeCFGInitDirectory() { return "$(OutDir)"; } protected: + static cmVS7FlagTable const* GetExtraFlagTableVS7(); virtual void OutputSLNFile(cmLocalGenerator* root, std::vector& generators); virtual void WriteSLNFile(std::ostream& fout, cmLocalGenerator* root, diff --git a/Source/cmGlobalVisualStudio8Generator.cxx b/Source/cmGlobalVisualStudio8Generator.cxx index f2f29b5..c512e07 100644 --- a/Source/cmGlobalVisualStudio8Generator.cxx +++ b/Source/cmGlobalVisualStudio8Generator.cxx @@ -36,6 +36,7 @@ cmLocalGenerator *cmGlobalVisualStudio8Generator::CreateLocalGenerator() { cmLocalVisualStudio7Generator *lg = new cmLocalVisualStudio7Generator; lg->SetVersion8(); + lg->SetExtraFlagTable(this->GetExtraFlagTableVS8()); lg->SetGlobalGenerator(this); return lg; } @@ -245,3 +246,21 @@ cmGlobalVisualStudio8Generator } } } + +//---------------------------------------------------------------------------- +static cmVS7FlagTable cmVS8ExtraFlagTable[] = +{ + // Precompiled header and related options. Note that the + // UsePrecompiledHeader entries are marked as "Continue" so that the + // corresponding PrecompiledHeaderThrough entry can be found. + {"UsePrecompiledHeader", "Yu", "Use Precompiled Header", "2", + cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue}, + {"PrecompiledHeaderThrough", "Yu", "Precompiled Header Name", "", + cmVS7FlagTable::UserValueRequired}, + // There is no YX option in the VS8 IDE. + {0,0,0,0,0} +}; +cmVS7FlagTable const* cmGlobalVisualStudio8Generator::GetExtraFlagTableVS8() +{ + return cmVS8ExtraFlagTable; +} diff --git a/Source/cmGlobalVisualStudio8Generator.h b/Source/cmGlobalVisualStudio8Generator.h index 68a2335..486c885 100644 --- a/Source/cmGlobalVisualStudio8Generator.h +++ b/Source/cmGlobalVisualStudio8Generator.h @@ -50,6 +50,7 @@ public: virtual void Configure(); virtual void Generate(); protected: + static cmVS7FlagTable const* GetExtraFlagTableVS8(); virtual void AddPlatformDefinitions(cmMakefile* mf); virtual void WriteSLNFile(std::ostream& fout, cmLocalGenerator* root, std::vector& generators); diff --git a/Source/cmGlobalVisualStudio8Win64Generator.cxx b/Source/cmGlobalVisualStudio8Win64Generator.cxx index 2571704..71639e8 100644 --- a/Source/cmGlobalVisualStudio8Win64Generator.cxx +++ b/Source/cmGlobalVisualStudio8Win64Generator.cxx @@ -33,6 +33,7 @@ cmLocalGenerator *cmGlobalVisualStudio8Win64Generator::CreateLocalGenerator() cmLocalVisualStudio7Generator *lg = new cmLocalVisualStudio7Generator; lg->SetVersion8(); lg->SetPlatformName(this->PlatformName.c_str()); + lg->SetExtraFlagTable(this->GetExtraFlagTableVS8()); lg->SetGlobalGenerator(this); return lg; } diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index 3ddc2d5..80d257b 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -28,11 +28,14 @@ #include // for isspace +extern cmVS7FlagTable cmLocalVisualStudio7GeneratorFlagTable[]; + //---------------------------------------------------------------------------- cmLocalVisualStudio7Generator::cmLocalVisualStudio7Generator() { this->Version = 7; this->PlatformName = "Win32"; + this->ExtraFlagTable = 0; } cmLocalVisualStudio7Generator::~cmLocalVisualStudio7Generator() @@ -255,26 +258,6 @@ void cmLocalVisualStudio7Generator::WriteConfigurations(std::ostream& fout, fout << "\t\n"; } -// This is a table mapping XML tag IDE names to command line options -struct cmVS7FlagTable -{ - const char* IDEName; // name used in the IDE xml file - const char* commandFlag; // command line flag - const char* comment; // comment - const char* value; // string value - unsigned int special; // flags for special handling requests - enum - { - UserValue = (1<<0), // flag contains a user-specified value - UserIgnored = (1<<1), // ignore any user value - UserRequired = (1<<2), // match only when user value is non-empty - Continue = (1<<3), // continue looking for matching entries - - UserValueIgnored = UserValue | UserIgnored, - UserValueRequired = UserValue | UserRequired - }; -}; - // fill the table here currently the comment field is not used for // anything other than documentation NOTE: Make sure the longer // commandFlag comes FIRST! @@ -334,16 +317,10 @@ cmVS7FlagTable cmLocalVisualStudio7GeneratorFlagTable[] = cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue}, {"PrecompiledHeaderThrough", "Yc", "Precompiled Header Name", "", cmVS7FlagTable::UserValueRequired}, - {"UsePrecompiledHeader", "YX", "Automatically Generate", "2", - cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue}, - {"PrecompiledHeaderThrough", "YX", "Precompiled Header Name", "", - cmVS7FlagTable::UserValueRequired}, - {"UsePrecompiledHeader", "Yu", "Use Precompiled Header", "3", - cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue}, - {"PrecompiledHeaderThrough", "Yu", "Precompiled Header Name", "", - cmVS7FlagTable::UserValueRequired}, {"PrecompiledHeaderFile", "Fp", "Generated Precompiled Header", "", cmVS7FlagTable::UserValue}, + // The YX and Yu options are in a per-global-generator table because + // their values differ based on the VS IDE version. {"ForcedIncludeFiles", "FI", "Forced include files", "", cmVS7FlagTable::UserValueRequired}, @@ -395,7 +372,8 @@ public: Compiler, Linker }; - cmLocalVisualStudio7GeneratorOptions(Tool tool); + cmLocalVisualStudio7GeneratorOptions(Tool tool, + cmVS7FlagTable const* extraTable = 0); // Store options from command line flags. void Parse(const char* flags); @@ -441,7 +419,10 @@ private: bool DoingDefine; cmVS7FlagTable const* FlagTable; + cmVS7FlagTable const* ExtraFlagTable; void HandleFlag(const char* flag); + bool CheckFlagTable(cmVS7FlagTable const* table, const char* flag, + bool& flag_handled); }; void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout, @@ -527,7 +508,7 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout, std::string defineFlags = this->Makefile->GetDefineFlags(); // Construct a set of build options for this target. - Options targetOptions(Options::Compiler); + Options targetOptions(Options::Compiler, this->ExtraFlagTable); targetOptions.FixExceptionHandlingDefault(); targetOptions.Parse(flags.c_str()); targetOptions.Parse(defineFlags.c_str()); @@ -1204,7 +1185,7 @@ void cmLocalVisualStudio7Generator << "\t\t\t\t\tName=\"" << aCompilerTool << "\"\n"; if(!compileFlags.empty()) { - Options fileOptions(Options::Compiler); + Options fileOptions(Options::Compiler, this->ExtraFlagTable); fileOptions.Parse(compileFlags.c_str()); fileOptions.OutputAdditionalOptions(fout, "\t\t\t\t\t", "\n"); fileOptions.OutputFlagMap(fout, "\t\t\t\t\t"); @@ -1648,8 +1629,9 @@ std::string cmLocalVisualStudio7Generator //---------------------------------------------------------------------------- cmLocalVisualStudio7GeneratorOptions -::cmLocalVisualStudio7GeneratorOptions(Tool tool): - DoingDefine(false), FlagTable(0) +::cmLocalVisualStudio7GeneratorOptions(Tool tool, + cmVS7FlagTable const* extraTable): + DoingDefine(false), FlagTable(0), ExtraFlagTable(extraTable) { // Choose the flag table for the requested tool. switch(tool) @@ -1761,6 +1743,7 @@ void cmLocalVisualStudio7GeneratorOptions::HandleFlag(const char* flag) // Look for known arguments. if(flag[0] == '-' || flag[0] == '/') { + // Look for preprocessor definitions. if(flag[1] == 'D') { if(flag[2] == '\0') @@ -1775,68 +1758,86 @@ void cmLocalVisualStudio7GeneratorOptions::HandleFlag(const char* flag) } return; } - else if(this->FlagTable) + + // 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)) { - // Look for an entry in the flag table matching this flag. - bool flag_handled = false; - for(cmVS7FlagTable const* entry = this->FlagTable; - entry->IDEName; ++entry) + 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_VSIDE); +} + +//---------------------------------------------------------------------------- +bool +cmLocalVisualStudio7GeneratorOptions +::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(strlen(entry->commandFlag)); + if(strncmp(flag+1, entry->commandFlag, n) == 0 && + (!(entry->special & cmVS7FlagTable::UserRequired) || + static_cast(strlen(flag+1)) > n)) { - bool entry_found = false; - if(entry->special & cmVS7FlagTable::UserValue) + if(entry->special & cmVS7FlagTable::UserIgnored) { - // 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(strlen(entry->commandFlag)); - if(strncmp(flag+1, entry->commandFlag, n) == 0 && - (!(entry->special & cmVS7FlagTable::UserRequired) || - static_cast(strlen(flag+1)) > n)) - { - if(entry->special & cmVS7FlagTable::UserIgnored) - { - // Ignore the user-specified value. - this->FlagMap[entry->IDEName] = entry->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. + // Ignore the user-specified 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)) + else { - return; + // Use the user-specified value. + this->FlagMap[entry->IDEName] = flag+1+n; } - - // If the entry was found the flag has been handled. - flag_handled = flag_handled || entry_found; + 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 any map entry handled the flag we are done. - if(flag_handled) - { - return; - } + // 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; } - // This option is not known. Store it in the output flags. - this->FlagString += " "; - this->FlagString += - cmSystemTools::EscapeWindowsShellArgument(flag, - cmsysSystem_Shell_Flag_VSIDE); + return false; } //---------------------------------------------------------------------------- diff --git a/Source/cmLocalVisualStudio7Generator.h b/Source/cmLocalVisualStudio7Generator.h index 820b69b..64a29c5 100644 --- a/Source/cmLocalVisualStudio7Generator.h +++ b/Source/cmLocalVisualStudio7Generator.h @@ -72,6 +72,8 @@ public: // return the source name for the object file virtual std::string GetSourceObjectName(cmSourceFile& ); + void SetExtraFlagTable(cmVS7FlagTable const* table) + { this->ExtraFlagTable = table; } private: typedef cmLocalVisualStudio7GeneratorOptions Options; void ReadAndStoreExternalGUID(const char* name, @@ -124,11 +126,32 @@ private: const char *libName, std::vector *configs); virtual std::string GetTargetDirectory(cmTarget&); + cmVS7FlagTable const* ExtraFlagTable; std::vector CreatedProjectNames; std::string ModuleDefinitionFile; int Version; std::string PlatformName; // Win32 or x64 }; +// This is a table mapping XML tag IDE names to command line options +struct cmVS7FlagTable +{ + const char* IDEName; // name used in the IDE xml file + const char* commandFlag; // command line flag + const char* comment; // comment + const char* value; // string value + unsigned int special; // flags for special handling requests + enum + { + UserValue = (1<<0), // flag contains a user-specified value + UserIgnored = (1<<1), // ignore any user value + UserRequired = (1<<2), // match only when user value is non-empty + Continue = (1<<3), // continue looking for matching entries + + UserValueIgnored = UserValue | UserIgnored, + UserValueRequired = UserValue | UserRequired + }; +}; + #endif diff --git a/Tests/PrecompiledHeader/CMakeLists.txt b/Tests/PrecompiledHeader/CMakeLists.txt index ac0e515..14bd277 100644 --- a/Tests/PrecompiledHeader/CMakeLists.txt +++ b/Tests/PrecompiledHeader/CMakeLists.txt @@ -14,9 +14,9 @@ ENDIF(CMAKE_CONFIGURATION_TYPES) FILE(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/PCH) # Choose between an explicit include path and using /I during -# precompilation. The /I form is provided as an example. In practice -# the include path form would be used. -SET(PCH_USE_INCLUDE_DIR 1) +# precompilation. The /I form is used to test that the PCH is +# actually used. In practice the include path form would be used. +SET(PCH_USE_INCLUDE_DIR 0) IF(PCH_USE_INCLUDE_DIR) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/include) ELSE(PCH_USE_INCLUDE_DIR) -- cgit v0.12