From ca2a16c0a221bb0c3be4491125c044c9112836e0 Mon Sep 17 00:00:00 2001 From: David Cole Date: Fri, 15 Feb 2008 11:49:58 -0500 Subject: [PATCH] ENH: Add code to support calling the VS reload macro from Visual Studio 7.1 and 9.0 in addition to 8.0 sp1... Make new macros file with VS 7.1 so that it can be read by 7.1 and later. VS 7.1 does not appear to run the macros while a build is in progress, but does not return any errors either, so for now, the reload macro is not called when using 7.1. If I can figure out how to get 7.1 to execute the macro, I will uncomment the code in cmGlobalVisualStudio71Generator::GetUserMacrosDirectory() to activate executing the macros in VS 7.1, too. --- Source/cmCallVisualStudioMacro.cxx | 36 +++++++++- Source/cmGlobalVisualStudio71Generator.cxx | 75 +++++++++++++++++---- Source/cmGlobalVisualStudio71Generator.h | 13 ++++ Source/cmGlobalVisualStudio8Generator.cxx | 20 +++--- Source/cmGlobalVisualStudio8Generator.h | 6 ++ Source/cmGlobalVisualStudio9Generator.cxx | 7 ++ Source/cmGlobalVisualStudio9Generator.h | 6 ++ Source/cmGlobalVisualStudioGenerator.cxx | 44 +++++++----- Source/cmGlobalVisualStudioGenerator.h | 6 ++ Templates/CMakeVSMacros2.vsmacros | Bin 0 -> 63488 bytes 10 files changed, 172 insertions(+), 41 deletions(-) create mode 100644 Templates/CMakeVSMacros2.vsmacros diff --git a/Source/cmCallVisualStudioMacro.cxx b/Source/cmCallVisualStudioMacro.cxx index 80112840d..247663172 100644 --- a/Source/cmCallVisualStudioMacro.cxx +++ b/Source/cmCallVisualStudioMacro.cxx @@ -94,7 +94,41 @@ HRESULT InstanceCallMacro( hr = vsIDE->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, ¶ms, &result, &excep, &arg); - ReportHRESULT(hr, "Invoke(ExecuteCommand)"); + + std::ostringstream oss; + oss << std::endl; + oss << "Invoke(ExecuteCommand)" << std::endl; + oss << " Macro: " << macro.c_str() << std::endl; + oss << " Args: " << args.c_str() << std::endl; + + if (DISP_E_EXCEPTION == hr) + { + oss << "DISP_E_EXCEPTION EXCEPINFO:" << excep.wCode << std::endl; + oss << " wCode: " << excep.wCode << std::endl; + oss << " wReserved: " << excep.wReserved << std::endl; + if (excep.bstrSource) + { + oss << " bstrSource: " << + (const char*)(_bstr_t)excep.bstrSource << std::endl; + } + if (excep.bstrDescription) + { + oss << " bstrDescription: " << + (const char*)(_bstr_t)excep.bstrDescription << std::endl; + } + if (excep.bstrHelpFile) + { + oss << " bstrHelpFile: " << + (const char*)(_bstr_t)excep.bstrHelpFile << std::endl; + } + oss << " dwHelpContext: " << excep.dwHelpContext << std::endl; + oss << " pvReserved: " << excep.pvReserved << std::endl; + oss << " pfnDeferredFillIn: " << excep.pfnDeferredFillIn << std::endl; + oss << " scode: " << excep.scode << std::endl; + } + + std::string exstr(oss.str()); + ReportHRESULT(hr, exstr.c_str()); VariantClear(&result); } diff --git a/Source/cmGlobalVisualStudio71Generator.cxx b/Source/cmGlobalVisualStudio71Generator.cxx index 26a095ec6..b3abec7a2 100644 --- a/Source/cmGlobalVisualStudio71Generator.cxx +++ b/Source/cmGlobalVisualStudio71Generator.cxx @@ -20,16 +20,14 @@ #include "cmMakefile.h" #include "cmake.h" - - +//---------------------------------------------------------------------------- cmGlobalVisualStudio71Generator::cmGlobalVisualStudio71Generator() { this->FindMakeProgramFile = "CMakeVS71FindMake.cmake"; this->ProjectConfigurationSectionName = "ProjectConfiguration"; } - - +//---------------------------------------------------------------------------- ///! Create a local generator appropriate to this Global Generator cmLocalGenerator *cmGlobalVisualStudio71Generator::CreateLocalGenerator() { @@ -40,12 +38,66 @@ cmLocalGenerator *cmGlobalVisualStudio71Generator::CreateLocalGenerator() return lg; } +//---------------------------------------------------------------------------- void cmGlobalVisualStudio71Generator::AddPlatformDefinitions(cmMakefile* mf) { mf->AddDefinition("MSVC71", "1"); } +//---------------------------------------------------------------------------- +std::string cmGlobalVisualStudio71Generator::GetUserMacrosDirectory() +{ + // Macros not supported on Visual Studio 7.1 and earlier because + // they do not appear to work *during* a build when called by an + // outside agent... + // + return ""; +#if 0 + // + // The COM result from calling a Visual Studio macro with 7.1 indicates + // that the call succeeds, but the macro does not appear to execute... + // + // So, I am leaving this code here to show how to do it, but have not + // yet figured out what the issue is in terms of why the macro does not + // appear to execute... + // + std::string base; + std::string path; + + // base begins with the VisualStudioProjectsLocation reg value... + if (cmSystemTools::ReadRegistryValue( + "HKEY_CURRENT_USER\\Software\\Microsoft\\VisualStudio\\7.1;" + "VisualStudioProjectsLocation", + base)) + { + cmSystemTools::ConvertToUnixSlashes(base); + + // 7.1 macros folder: + path = base + "/VSMacros71"; + } + + // path is (correctly) still empty if we did not read the base value from + // the Registry value + return path; +#endif +} + +//---------------------------------------------------------------------------- +std::string cmGlobalVisualStudio71Generator::GetUserMacrosRegKeyBase() +{ + // Macros not supported on Visual Studio 7.1 and earlier because + // they do not appear to work *during* a build when called by an + // outside agent... + // + return ""; + +#if 0 + return "Software\\Microsoft\\VisualStudio\\7.1\\vsmacros"; +#endif +} + +//---------------------------------------------------------------------------- void cmGlobalVisualStudio71Generator ::WriteSLNFile(std::ostream& fout, cmLocalGenerator* root, @@ -77,7 +129,7 @@ void cmGlobalVisualStudio71Generator this->WriteSLNFooter(fout); } - +//---------------------------------------------------------------------------- void cmGlobalVisualStudio71Generator ::WriteSolutionConfigurations(std::ostream& fout) @@ -91,6 +143,7 @@ cmGlobalVisualStudio71Generator fout << "\tEndGlobalSection\n"; } +//---------------------------------------------------------------------------- // Write a dsp file into the SLN file, // Note, that dependencies from executables to // the libraries it uses are also done here @@ -112,8 +165,7 @@ cmGlobalVisualStudio71Generator::WriteProject(std::ostream& fout, fout <<"EndProject\n"; } - - +//---------------------------------------------------------------------------- // Write a dsp file into the SLN file, // Note, that dependencies from executables to // the libraries it uses are also done here @@ -179,6 +231,7 @@ cmGlobalVisualStudio71Generator } } +//---------------------------------------------------------------------------- // Write a dsp file into the SLN file, Note, that dependencies from // executables to the libraries it uses are also done here void cmGlobalVisualStudio71Generator @@ -219,7 +272,7 @@ void cmGlobalVisualStudio71Generator } - +//---------------------------------------------------------------------------- // Write a dsp file into the SLN file, Note, that dependencies from // executables to the libraries it uses are also done here void cmGlobalVisualStudio71Generator @@ -240,9 +293,7 @@ void cmGlobalVisualStudio71Generator } } - - - +//---------------------------------------------------------------------------- // Standard end of dsw file void cmGlobalVisualStudio71Generator::WriteSLNFooter(std::ostream& fout) { @@ -253,7 +304,7 @@ void cmGlobalVisualStudio71Generator::WriteSLNFooter(std::ostream& fout) << "EndGlobal\n"; } - +//---------------------------------------------------------------------------- // ouput standard header for dsw file void cmGlobalVisualStudio71Generator::WriteSLNHeader(std::ostream& fout) { diff --git a/Source/cmGlobalVisualStudio71Generator.h b/Source/cmGlobalVisualStudio71Generator.h index f357c8f23..9a2bcdba5 100644 --- a/Source/cmGlobalVisualStudio71Generator.h +++ b/Source/cmGlobalVisualStudio71Generator.h @@ -43,6 +43,19 @@ public: ///! Create a local generator appropriate to this Global Generator virtual cmLocalGenerator *CreateLocalGenerator(); + /** + * Where does this version of Visual Studio look for macros for the + * current user? Returns the empty string if this version of Visual + * Studio does not implement support for VB macros. + */ + virtual std::string GetUserMacrosDirectory(); + + /** + * What is the reg key path to "vsmacros" for this version of Visual + * Studio? + */ + virtual std::string GetUserMacrosRegKeyBase(); + protected: virtual void AddPlatformDefinitions(cmMakefile* mf); virtual void WriteSLNFile(std::ostream& fout, diff --git a/Source/cmGlobalVisualStudio8Generator.cxx b/Source/cmGlobalVisualStudio8Generator.cxx index 7a394595d..52225aa64 100644 --- a/Source/cmGlobalVisualStudio8Generator.cxx +++ b/Source/cmGlobalVisualStudio8Generator.cxx @@ -20,8 +20,7 @@ #include "cmMakefile.h" #include "cmake.h" - - +//---------------------------------------------------------------------------- cmGlobalVisualStudio8Generator::cmGlobalVisualStudio8Generator() { this->FindMakeProgramFile = "CMakeVS8FindMake.cmake"; @@ -29,8 +28,7 @@ cmGlobalVisualStudio8Generator::cmGlobalVisualStudio8Generator() this->PlatformName = "Win32"; } - - +//---------------------------------------------------------------------------- ///! Create a local generator appropriate to this Global Generator cmLocalGenerator *cmGlobalVisualStudio8Generator::CreateLocalGenerator() { @@ -40,8 +38,8 @@ cmLocalGenerator *cmGlobalVisualStudio8Generator::CreateLocalGenerator() lg->SetGlobalGenerator(this); return lg; } - +//---------------------------------------------------------------------------- // ouput standard header for dsw file void cmGlobalVisualStudio8Generator::WriteSLNHeader(std::ostream& fout) { @@ -100,12 +98,6 @@ std::string cmGlobalVisualStudio8Generator::GetUserMacrosDirectory() { cmSystemTools::ConvertToUnixSlashes(base); - // 7.0 macros folder: - //path = base + "/VSMacros"; - - // 7.1 macros folder: - //path = base + "/VSMacros71"; - // 8.0 macros folder: path = base + "/VSMacros80"; } @@ -115,6 +107,12 @@ std::string cmGlobalVisualStudio8Generator::GetUserMacrosDirectory() return path; } +//---------------------------------------------------------------------------- +std::string cmGlobalVisualStudio8Generator::GetUserMacrosRegKeyBase() +{ + return "Software\\Microsoft\\VisualStudio\\8.0\\vsmacros"; +} + //---------------------------------------------------------------------------- void cmGlobalVisualStudio8Generator::Generate() { diff --git a/Source/cmGlobalVisualStudio8Generator.h b/Source/cmGlobalVisualStudio8Generator.h index 534258a40..8e6a994da 100644 --- a/Source/cmGlobalVisualStudio8Generator.h +++ b/Source/cmGlobalVisualStudio8Generator.h @@ -57,6 +57,12 @@ public: */ virtual std::string GetUserMacrosDirectory(); + /** + * What is the reg key path to "vsmacros" for this version of Visual + * Studio? + */ + virtual std::string GetUserMacrosRegKeyBase(); + protected: virtual bool VSLinksDependencies() const { return false; } diff --git a/Source/cmGlobalVisualStudio9Generator.cxx b/Source/cmGlobalVisualStudio9Generator.cxx index 9899f9c0e..ffc31af6a 100644 --- a/Source/cmGlobalVisualStudio9Generator.cxx +++ b/Source/cmGlobalVisualStudio9Generator.cxx @@ -33,6 +33,7 @@ void cmGlobalVisualStudio9Generator::AddPlatformDefinitions(cmMakefile* mf) mf->AddDefinition("MSVC90", "1"); } +//---------------------------------------------------------------------------- void cmGlobalVisualStudio9Generator::WriteSLNHeader(std::ostream& fout) { fout << "Microsoft Visual Studio Solution File, Format Version 10.00\n"; @@ -92,3 +93,9 @@ std::string cmGlobalVisualStudio9Generator::GetUserMacrosDirectory() // the Registry value return path; } + +//---------------------------------------------------------------------------- +std::string cmGlobalVisualStudio9Generator::GetUserMacrosRegKeyBase() +{ + return "Software\\Microsoft\\VisualStudio\\9.0\\vsmacros"; +} diff --git a/Source/cmGlobalVisualStudio9Generator.h b/Source/cmGlobalVisualStudio9Generator.h index 66d01806f..0841603b2 100644 --- a/Source/cmGlobalVisualStudio9Generator.h +++ b/Source/cmGlobalVisualStudio9Generator.h @@ -59,5 +59,11 @@ public: * Studio does not implement support for VB macros. */ virtual std::string GetUserMacrosDirectory(); + + /** + * What is the reg key path to "vsmacros" for this version of Visual + * Studio? + */ + virtual std::string GetUserMacrosRegKeyBase(); }; #endif diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx index b824590cb..efa9adfbc 100644 --- a/Source/cmGlobalVisualStudioGenerator.cxx +++ b/Source/cmGlobalVisualStudioGenerator.cxx @@ -68,19 +68,21 @@ void cmGlobalVisualStudioGenerator::Generate() //---------------------------------------------------------------------------- bool IsVisualStudioMacrosFileRegistered(const std::string& macrosFile, + const std::string& regKeyBase, std::string& nextAvailableSubKeyName); -void RegisterVisualStudioMacros(const std::string& macrosFile); +void RegisterVisualStudioMacros(const std::string& macrosFile, + const std::string& regKeyBase); //---------------------------------------------------------------------------- #define CMAKE_VSMACROS_FILENAME \ - "CMakeVSMacros1.vsmacros" + "CMakeVSMacros2.vsmacros" #define CMAKE_VSMACROS_RELOAD_MACRONAME \ - "Macros.CMakeVSMacros1.Macros.ReloadProjects" + "Macros.CMakeVSMacros2.Macros.ReloadProjects" #define CMAKE_VSMACROS_STOP_MACRONAME \ - "Macros.CMakeVSMacros1.Macros.StopBuild" + "Macros.CMakeVSMacros2.Macros.StopBuild" //---------------------------------------------------------------------------- void cmGlobalVisualStudioGenerator::ConfigureCMakeVisualStudioMacros() @@ -113,7 +115,7 @@ void cmGlobalVisualStudioGenerator::ConfigureCMakeVisualStudioMacros() } } - RegisterVisualStudioMacros(dst); + RegisterVisualStudioMacros(dst, this->GetUserMacrosRegKeyBase()); } } @@ -140,7 +142,8 @@ cmGlobalVisualStudioGenerator std::string macrosFile = dir + "/CMakeMacros/" CMAKE_VSMACROS_FILENAME; std::string nextSubkeyName; if (cmSystemTools::FileExists(macrosFile.c_str()) && - IsVisualStudioMacrosFileRegistered(macrosFile, nextSubkeyName) + IsVisualStudioMacrosFileRegistered(macrosFile, + this->GetUserMacrosRegKeyBase(), nextSubkeyName) ) { std::string topLevelSlnName; @@ -194,6 +197,12 @@ std::string cmGlobalVisualStudioGenerator::GetUserMacrosDirectory() return ""; } +//---------------------------------------------------------------------------- +std::string cmGlobalVisualStudioGenerator::GetUserMacrosRegKeyBase() +{ + return ""; +} + //---------------------------------------------------------------------------- void cmGlobalVisualStudioGenerator::FixUtilityDepends() { @@ -396,6 +405,7 @@ cmGlobalVisualStudioGenerator::GetUtilityForTarget(cmTarget& target, //---------------------------------------------------------------------------- bool IsVisualStudioMacrosFileRegistered(const std::string& macrosFile, + const std::string& regKeyBase, std::string& nextAvailableSubKeyName) { bool macrosRegistered = false; @@ -413,8 +423,7 @@ bool IsVisualStudioMacrosFileRegistered(const std::string& macrosFile, LONG result = ERROR_SUCCESS; DWORD index = 0; - keyname = - "Software\\Microsoft\\VisualStudio\\8.0\\vsmacros\\OtherProjects7"; + keyname = regKeyBase + "\\OtherProjects7"; hkey = NULL; result = RegOpenKeyEx(HKEY_CURRENT_USER, keyname.c_str(), 0, KEY_READ, &hkey); @@ -517,8 +526,7 @@ bool IsVisualStudioMacrosFileRegistered(const std::string& macrosFile, nextAvailableSubKeyName = ossNext.str(); - keyname = - "Software\\Microsoft\\VisualStudio\\8.0\\vsmacros\\RecordingProject7"; + keyname = regKeyBase + "\\RecordingProject7"; hkey = NULL; result = RegOpenKeyEx(HKEY_CURRENT_USER, keyname.c_str(), 0, KEY_READ, &hkey); @@ -567,10 +575,10 @@ bool IsVisualStudioMacrosFileRegistered(const std::string& macrosFile, //---------------------------------------------------------------------------- void WriteVSMacrosFileRegistryEntry( const std::string& nextAvailableSubKeyName, - const std::string& macrosFile) + const std::string& macrosFile, + const std::string& regKeyBase) { - std::string keyname = - "Software\\Microsoft\\VisualStudio\\8.0\\vsmacros\\OtherProjects7"; + std::string keyname = regKeyBase + "\\OtherProjects7"; HKEY hkey = NULL; LONG result = RegOpenKeyEx(HKEY_CURRENT_USER, keyname.c_str(), 0, KEY_READ|KEY_WRITE, &hkey); @@ -634,13 +642,14 @@ void WriteVSMacrosFileRegistryEntry( } //---------------------------------------------------------------------------- -void RegisterVisualStudioMacros(const std::string& macrosFile) +void RegisterVisualStudioMacros(const std::string& macrosFile, + const std::string& regKeyBase) { bool macrosRegistered; std::string nextAvailableSubKeyName; macrosRegistered = IsVisualStudioMacrosFileRegistered(macrosFile, - nextAvailableSubKeyName); + regKeyBase, nextAvailableSubKeyName); if (!macrosRegistered) { @@ -681,7 +690,7 @@ void RegisterVisualStudioMacros(const std::string& macrosFile) // if (0 == count) { - IsVisualStudioMacrosFileRegistered(macrosFile, + IsVisualStudioMacrosFileRegistered(macrosFile, regKeyBase, nextAvailableSubKeyName); } } @@ -690,7 +699,8 @@ void RegisterVisualStudioMacros(const std::string& macrosFile) // if (0 == count) { - WriteVSMacrosFileRegistryEntry(nextAvailableSubKeyName, macrosFile); + WriteVSMacrosFileRegistryEntry(nextAvailableSubKeyName, macrosFile, + regKeyBase); } } } diff --git a/Source/cmGlobalVisualStudioGenerator.h b/Source/cmGlobalVisualStudioGenerator.h index 2fbb47847..750418c20 100644 --- a/Source/cmGlobalVisualStudioGenerator.h +++ b/Source/cmGlobalVisualStudioGenerator.h @@ -49,6 +49,12 @@ public: */ virtual std::string GetUserMacrosDirectory(); + /** + * What is the reg key path to "vsmacros" for this version of Visual + * Studio? + */ + virtual std::string GetUserMacrosRegKeyBase(); + enum MacroName {MacroReload, MacroStop}; /** diff --git a/Templates/CMakeVSMacros2.vsmacros b/Templates/CMakeVSMacros2.vsmacros new file mode 100644 index 0000000000000000000000000000000000000000..5ba27991a836866251cd05f6abcdb9ca06ec13da GIT binary patch literal 63488 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
    VEcr&5wW#(MEpuREo*^QTyk8cDN~kL7h?;#%~n zm4BnP!&7>``Ca=9rKgr}pPzcAJsIcE7A+T78Ps~0ajyA)cIddccwg^r(YfaT*`wv+ zDuZh8n+;bA$6a4m}%GTwHvw z+zD|$xqtR(xwy-~&pox`tkpNShIy{rqVhHSvq96vRVwxO{!EpI?j$*vYZSG2TAk~% zD7_1C>*1$gOB<~bTF>>XwT-PToy~Q?=o`6H<8`S&z0g+tCgZ#~uD2eOt$IgGMtAmA zTdPx9=#7ll&h_rFx-Y+$v$-POT9mq!YsV}1>Teoc`jzgJ?U+!`T3H!9doyOA8%EeWT8-&M4BD4nPTT+2J1UcSntH$;2koT%!B66yBy6{TIY zp}Ie-hj(gs;G;6^e%`d{U6FPn>rJ8FBe}ij^=~=QK6C#zR;$SFwk+)fmtOmgb)#14 zy?Zp>^1BQAScN`qKJHO22J z(9UxIR&_Bus-x6+8BzHR<124#l5V~7Zx1HMRW1C)aC#%`-^EmpJau=T_J0f&-|Q*Q zYVq#kon8_SXy?9ms8391m(8(r_xtFV<5Oj;v0b%TeXb{u-M`mvG)5n@=jT!Q=-vTV zD;3=zro#8SAbWG&C386b0e{PT8H7JB&D$u_q2KJLpzR@WPkEg zDT_(-8laTRE^d=l*$q5Lnp zvk{*AG{h~huNAvEd^#s=&WsZAdtz<#Co0a)`J6MOaAMhrX3wiLJL_|1l!*?{DeaS~ zeNyPm(y7mZ=$RFNwx{~3qq9v#HM)Kj=b6roZk3Yi?YTP*b>{SHd{O-@m2#sNWb#&2 zyN=vAWq{mk3{igK%2C-!E9QHSC{@1y*kgN>t;Bu59o=}U8;Q3(KDCk2*gC@&Q>Wgd z_8RY;u)S?pcotD@KzS`#Q724!T-w>Hd4*^hv?HuBdZYoq2b^SYNh7&XTco~0BUpDn z^UP1Lol3v%M>m}|51#*SBpA)>9TA!GoYQz`FX1%ys$UxAp~dm#{2Cj7`LTn?wa1I< zVYSCgcd=?;pLPZ|Hg=jkZjG)r+UT6n-!(pl@~L>9p9;_1x!Kd@nNQjCPJ5Cy6L2@z zx?Mk--AHydHY}|f)I0sS*vk20{GS?^x7&1*%)H!v%AUGfxKaO;`K#sb?cF>}wKiIF zUp(_iwS5|8luGy9%o?>TunTBh=A!L!Eh(#BYTmZ;MnEs4(USG@b~?4<>{Hlyo7>2& U)#t4epH5y&@=`fRuPmGY4-5j`eE