| /*============================================================================ |
| CMake - Cross Platform Makefile Generator |
| Copyright 2000-2009 Kitware, Inc., Insight Software Consortium |
| |
| Distributed under the OSI-approved BSD License (the "License"); |
| see accompanying file Copyright.txt for details. |
| |
| This software is distributed WITHOUT ANY WARRANTY; without even the |
| implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| See the License for more information. |
| ============================================================================*/ |
| #include "cmGlobalVisualStudio6Generator.h" |
| #include "cmLocalVisualStudio6Generator.h" |
| #include "cmMakefile.h" |
| #include "cmake.h" |
| #include "cmGeneratedFileStream.h" |
| #include <cmsys/FStream.hxx> |
| |
| // Utility function to make a valid VS6 *.dsp filename out |
| // of a CMake target name: |
| // |
| std::string GetVS6TargetName(const std::string& targetName) |
| { |
| std::string name(targetName); |
| |
| // Eliminate hyphens. VS6 cannot handle hyphens in *.dsp filenames... |
| // Replace them with underscores. |
| // |
| cmSystemTools::ReplaceString(name, "-", "_"); |
| |
| return name; |
| } |
| |
| cmGlobalVisualStudio6Generator::cmGlobalVisualStudio6Generator(cmake* cm) |
| : cmGlobalVisualStudioGenerator(cm) |
| { |
| this->MSDevCommandInitialized = false; |
| this->Version = VS6; |
| } |
| |
| void cmGlobalVisualStudio6Generator |
| ::EnableLanguage(std::vector<std::string>const& lang, |
| cmMakefile *mf, |
| bool optional) |
| { |
| mf->AddDefinition("CMAKE_GENERATOR_RC", "rc"); |
| mf->AddDefinition("CMAKE_GENERATOR_NO_COMPILER_ENV", "1"); |
| this->GenerateConfigurations(mf); |
| this->cmGlobalGenerator::EnableLanguage(lang, mf, optional); |
| } |
| |
| void cmGlobalVisualStudio6Generator::GenerateConfigurations(cmMakefile* mf) |
| { |
| std::string fname= mf->GetRequiredDefinition("CMAKE_ROOT"); |
| const char* def= mf->GetDefinition( "MSPROJECT_TEMPLATE_DIRECTORY"); |
| if(def) |
| { |
| fname = def; |
| } |
| else |
| { |
| fname += "/Templates"; |
| } |
| fname += "/CMakeVisualStudio6Configurations.cmake"; |
| if(!mf->ReadDependentFile(fname.c_str())) |
| { |
| cmSystemTools::Error("Cannot open ", fname.c_str(), |
| ". Please copy this file from the main " |
| "CMake/Templates directory and edit it for " |
| "your build configurations."); |
| } |
| else if(!mf->GetDefinition("CMAKE_CONFIGURATION_TYPES")) |
| { |
| cmSystemTools::Error("CMAKE_CONFIGURATION_TYPES not set by ", |
| fname.c_str(), |
| ". Please copy this file from the main " |
| "CMake/Templates directory and edit it for " |
| "your build configurations."); |
| } |
| } |
| |
| //---------------------------------------------------------------------------- |
| void cmGlobalVisualStudio6Generator::FindMakeProgram(cmMakefile* mf) |
| { |
| this->cmGlobalVisualStudioGenerator::FindMakeProgram(mf); |
| mf->AddDefinition("CMAKE_VS_MSDEV_COMMAND", |
| this->GetMSDevCommand().c_str()); |
| } |
| |
| //---------------------------------------------------------------------------- |
| std::string const& cmGlobalVisualStudio6Generator::GetMSDevCommand() |
| { |
| if(!this->MSDevCommandInitialized) |
| { |
| this->MSDevCommandInitialized = true; |
| this->MSDevCommand = this->FindMSDevCommand(); |
| } |
| return this->MSDevCommand; |
| } |
| |
| //---------------------------------------------------------------------------- |
| std::string cmGlobalVisualStudio6Generator::FindMSDevCommand() |
| { |
| std::string vscmd; |
| std::string vskey = this->GetRegistryBase() + "\\Setup;VsCommonDir"; |
| if(cmSystemTools::ReadRegistryValue(vskey.c_str(), vscmd, |
| cmSystemTools::KeyWOW64_32)) |
| { |
| cmSystemTools::ConvertToUnixSlashes(vscmd); |
| vscmd += "/MSDev98/Bin/"; |
| } |
| vscmd += "msdev.exe"; |
| return vscmd; |
| } |
| |
| //---------------------------------------------------------------------------- |
| void |
| cmGlobalVisualStudio6Generator::GenerateBuildCommand( |
| std::vector<std::string>& makeCommand, |
| const std::string& makeProgram, |
| const std::string& projectName, |
| const std::string& /*projectDir*/, |
| const std::string& targetName, |
| const std::string& config, |
| bool /*fast*/, bool /*verbose*/, |
| std::vector<std::string> const& makeOptions |
| ) |
| { |
| // now build the test |
| makeCommand.push_back( |
| this->SelectMakeProgram(makeProgram, this->GetMSDevCommand()) |
| ); |
| |
| makeCommand.push_back(std::string(projectName)+".dsw"); |
| makeCommand.push_back("/MAKE"); |
| std::string targetArg; |
| bool clean = false; |
| std::string realTarget = targetName; |
| if ( realTarget == "clean" ) |
| { |
| clean = true; |
| realTarget = "ALL_BUILD"; |
| } |
| if (!realTarget.empty()) |
| { |
| targetArg += realTarget; |
| } |
| else |
| { |
| targetArg += "ALL_BUILD"; |
| } |
| targetArg += " - "; |
| if(!config.empty()) |
| { |
| targetArg += config; |
| } |
| else |
| { |
| targetArg += "Debug"; |
| } |
| makeCommand.push_back(targetArg); |
| if(clean) |
| { |
| makeCommand.push_back("/CLEAN"); |
| } |
| else |
| { |
| makeCommand.push_back("/BUILD"); |
| } |
| makeCommand.insert(makeCommand.end(), |
| makeOptions.begin(), makeOptions.end()); |
| } |
| |
| ///! Create a local generator appropriate to this Global Generator |
| cmLocalGenerator * |
| cmGlobalVisualStudio6Generator::CreateLocalGenerator(cmLocalGenerator* parent, |
| cmState::Snapshot snapshot) |
| { |
| return new cmLocalVisualStudio6Generator(this, parent, snapshot); |
| } |
| |
| |
| void cmGlobalVisualStudio6Generator::Generate() |
| { |
| // first do the superclass method |
| this->cmGlobalVisualStudioGenerator::Generate(); |
| |
| // Now write out the DSW |
| this->OutputDSWFile(); |
| |
| if (!this->CMakeInstance->GetIsInTryCompile()) |
| { |
| const char* cmakeWarnVS6 = |
| this->CMakeInstance->GetState()->GetCacheEntryValue("CMAKE_WARN_VS6"); |
| if (!cmakeWarnVS6 || !cmSystemTools::IsOff(cmakeWarnVS6)) |
| { |
| this->CMakeInstance->IssueMessage( |
| cmake::WARNING, |
| "The \"Visual Studio 6\" generator is deprecated " |
| "and will be removed in a future version of CMake." |
| "\n" |
| "Add CMAKE_WARN_VS6=OFF to the cache to disable this warning." |
| ); |
| } |
| } |
| } |
| |
| // Write a DSW file to the stream |
| void cmGlobalVisualStudio6Generator |
| ::WriteDSWFile(std::ostream& fout,cmLocalGenerator* root, |
| std::vector<cmLocalGenerator*>& generators) |
| { |
| // Write out the header for a DSW file |
| this->WriteDSWHeader(fout); |
| |
| // Collect all targets under this root generator and the transitive |
| // closure of their dependencies. |
| TargetDependSet projectTargets; |
| TargetDependSet originalTargets; |
| this->GetTargetSets(projectTargets, originalTargets, root, generators); |
| OrderedTargetDependSet orderedProjectTargets(projectTargets); |
| |
| for(OrderedTargetDependSet::const_iterator |
| tt = orderedProjectTargets.begin(); |
| tt != orderedProjectTargets.end(); ++tt) |
| { |
| cmTarget const* target = *tt; |
| if(target->GetType() == cmTarget::INTERFACE_LIBRARY) |
| { |
| continue; |
| } |
| // Write the project into the DSW file |
| const char* expath = target->GetProperty("EXTERNAL_MSPROJECT"); |
| if(expath) |
| { |
| std::string project = target->GetName(); |
| std::string location = expath; |
| this->WriteExternalProject(fout, project.c_str(), |
| location.c_str(), target->GetUtilities()); |
| } |
| else |
| { |
| std::string dspname = GetVS6TargetName(target->GetName()); |
| std::string dir = target->GetMakefile()->GetCurrentBinaryDirectory(); |
| dir = root->Convert(dir.c_str(), cmLocalGenerator::START_OUTPUT); |
| this->WriteProject(fout, dspname.c_str(), dir.c_str(), *target); |
| } |
| } |
| |
| // Write the footer for the DSW file |
| this->WriteDSWFooter(fout); |
| } |
| |
| void cmGlobalVisualStudio6Generator |
| ::OutputDSWFile(cmLocalGenerator* root, |
| std::vector<cmLocalGenerator*>& generators) |
| { |
| if(generators.size() == 0) |
| { |
| return; |
| } |
| std::string fname = root->GetMakefile()->GetCurrentBinaryDirectory(); |
| fname += "/"; |
| fname += root->GetMakefile()->GetProjectName(); |
| fname += ".dsw"; |
| cmsys::ofstream fout(fname.c_str()); |
| if(!fout) |
| { |
| cmSystemTools::Error("Error can not open DSW file for write: ", |
| fname.c_str()); |
| cmSystemTools::ReportLastSystemError(""); |
| return; |
| } |
| this->WriteDSWFile(fout, root, generators); |
| } |
| |
| // output the DSW file |
| void cmGlobalVisualStudio6Generator::OutputDSWFile() |
| { |
| std::map<std::string, std::vector<cmLocalGenerator*> >::iterator it; |
| for(it = this->ProjectMap.begin(); it!= this->ProjectMap.end(); ++it) |
| { |
| this->OutputDSWFile(it->second[0], it->second); |
| } |
| } |
| |
| // Write a dsp file into the DSW file, |
| // Note, that dependencies from executables to |
| // the libraries it uses are also done here |
| void cmGlobalVisualStudio6Generator::WriteProject(std::ostream& fout, |
| const std::string& dspname, |
| const char* dir, |
| cmTarget const& target) |
| { |
| fout << "#########################################################" |
| "######################\n\n"; |
| fout << "Project: \"" << dspname << "\"=" |
| << dir << "\\" << dspname << ".dsp - Package Owner=<4>\n\n"; |
| fout << "Package=<5>\n{{{\n}}}\n\n"; |
| fout << "Package=<4>\n"; |
| fout << "{{{\n"; |
| VSDependSet const& depends = this->VSTargetDepends[&target]; |
| for(VSDependSet::const_iterator di = depends.begin(); |
| di != depends.end(); ++di) |
| { |
| const char* name = di->c_str(); |
| fout << "Begin Project Dependency\n"; |
| fout << "Project_Dep_Name " << GetVS6TargetName(name) << "\n"; |
| fout << "End Project Dependency\n"; |
| } |
| fout << "}}}\n\n"; |
| |
| UtilityDependsMap::iterator ui = this->UtilityDepends.find(&target); |
| if(ui != this->UtilityDepends.end()) |
| { |
| const char* uname = ui->second.c_str(); |
| fout << "Project: \"" << uname << "\"=" |
| << dir << "\\" << uname << ".dsp - Package Owner=<4>\n\n"; |
| fout << |
| "Package=<5>\n{{{\n}}}\n\n" |
| "Package=<4>\n" |
| "{{{\n" |
| "Begin Project Dependency\n" |
| "Project_Dep_Name " << dspname << "\n" |
| "End Project Dependency\n" |
| "}}}\n\n"; |
| ; |
| } |
| } |
| |
| |
| // Write a dsp file into the DSW file, |
| // Note, that dependencies from executables to |
| // the libraries it uses are also done here |
| void cmGlobalVisualStudio6Generator::WriteExternalProject(std::ostream& fout, |
| const std::string& name, |
| const char* location, |
| const std::set<std::string>& dependencies) |
| { |
| fout << "#########################################################" |
| "######################\n\n"; |
| fout << "Project: \"" << name << "\"=" |
| << location << " - Package Owner=<4>\n\n"; |
| fout << "Package=<5>\n{{{\n}}}\n\n"; |
| fout << "Package=<4>\n"; |
| fout << "{{{\n"; |
| |
| |
| std::set<std::string>::const_iterator i, end; |
| // write dependencies. |
| i = dependencies.begin(); |
| end = dependencies.end(); |
| for(;i!= end; ++i) |
| { |
| fout << "Begin Project Dependency\n"; |
| fout << "Project_Dep_Name " << GetVS6TargetName(*i) << "\n"; |
| fout << "End Project Dependency\n"; |
| } |
| fout << "}}}\n\n"; |
| } |
| |
| |
| |
| // Standard end of dsw file |
| void cmGlobalVisualStudio6Generator::WriteDSWFooter(std::ostream& fout) |
| { |
| fout << "######################################################" |
| "#########################\n\n"; |
| fout << "Global:\n\n"; |
| fout << "Package=<5>\n{{{\n}}}\n\n"; |
| fout << "Package=<3>\n{{{\n}}}\n\n"; |
| fout << "#####################################################" |
| "##########################\n\n"; |
| } |
| |
| |
| // ouput standard header for dsw file |
| void cmGlobalVisualStudio6Generator::WriteDSWHeader(std::ostream& fout) |
| { |
| fout << "Microsoft Developer Studio Workspace File, Format Version 6.00\n"; |
| fout << "# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!\n\n"; |
| } |
| |
| //---------------------------------------------------------------------------- |
| std::string |
| cmGlobalVisualStudio6Generator::WriteUtilityDepend(cmTarget const* target) |
| { |
| std::string pname = target->GetName(); |
| pname += "_UTILITY"; |
| pname = GetVS6TargetName(pname.c_str()); |
| std::string fname = target->GetMakefile()->GetCurrentBinaryDirectory(); |
| fname += "/"; |
| fname += pname; |
| fname += ".dsp"; |
| cmGeneratedFileStream fout(fname.c_str()); |
| fout.SetCopyIfDifferent(true); |
| fout << |
| "# Microsoft Developer Studio Project File - Name=\"" |
| << pname << "\" - Package Owner=<4>\n" |
| "# Microsoft Developer Studio Generated Build File, Format Version 6.00\n" |
| "# ** DO NOT EDIT **\n" |
| "\n" |
| "# TARGTYPE \"Win32 (x86) Generic Project\" 0x010a\n" |
| "\n" |
| "CFG=" << pname << " - Win32 Debug\n" |
| "!MESSAGE \"" << pname << " - Win32 Debug\"" |
| " (based on \"Win32 (x86) Generic Project\")\n" |
| "!MESSAGE \"" << pname << " - Win32 Release\" " |
| "(based on \"Win32 (x86) Generic Project\")\n" |
| "!MESSAGE \"" << pname << " - Win32 MinSizeRel\" " |
| "(based on \"Win32 (x86) Generic Project\")\n" |
| "!MESSAGE \"" << pname << " - Win32 RelWithDebInfo\" " |
| "(based on \"Win32 (x86) Generic Project\")\n" |
| "\n" |
| "# Begin Project\n" |
| "# Begin Target\n" |
| "# Name \"" << pname << " - Win32 Debug\"\n" |
| "# Name \"" << pname << " - Win32 Release\"\n" |
| "# Name \"" << pname << " - Win32 MinSizeRel\"\n" |
| "# Name \"" << pname << " - Win32 RelWithDebInfo\"\n" |
| "# End Target\n" |
| "# End Project\n" |
| ; |
| return pname; |
| } |
| |
| //---------------------------------------------------------------------------- |
| void cmGlobalVisualStudio6Generator |
| ::GetDocumentation(cmDocumentationEntry& entry) |
| { |
| entry.Name = cmGlobalVisualStudio6Generator::GetActualName(); |
| entry.Brief = "Deprecated. Generates Visual Studio 6 project files."; |
| } |
| |
| //---------------------------------------------------------------------------- |
| void |
| cmGlobalVisualStudio6Generator |
| ::AppendDirectoryForConfig(const std::string& prefix, |
| const std::string& config, |
| const std::string& suffix, |
| std::string& dir) |
| { |
| if(!config.empty()) |
| { |
| dir += prefix; |
| dir += config; |
| dir += suffix; |
| } |
| } |