1 /*============================================================================
2 CMake - Cross Platform Makefile Generator
3 Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
5 Distributed under the OSI-approved BSD License (the "License");
6 see accompanying file Copyright.txt for details.
8 This software is distributed WITHOUT ANY WARRANTY; without even the
9 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10 See the License for more information.
11 ============================================================================*/
12 #include "cmGlobalVisualStudio6Generator.h"
13 #include "cmLocalVisualStudio6Generator.h"
14 #include "cmMakefile.h"
16 #include "cmGeneratedFileStream.h"
18 // Utility function to make a valid VS6 *.dsp filename out
19 // of a CMake target name:
21 std::string GetVS6TargetName(const std::string& targetName)
23 std::string name(targetName);
25 // Eliminate hyphens. VS6 cannot handle hyphens in *.dsp filenames...
26 // Replace them with underscores.
28 cmSystemTools::ReplaceString(name, "-", "_");
33 cmGlobalVisualStudio6Generator::cmGlobalVisualStudio6Generator()
35 this->FindMakeProgramFile = "CMakeVS6FindMake.cmake";
38 void cmGlobalVisualStudio6Generator
39 ::EnableLanguage(std::vector<std::string>const& lang,
43 cmGlobalVisualStudioGenerator::AddPlatformDefinitions(mf);
44 mf->AddDefinition("CMAKE_GENERATOR_RC", "rc");
45 mf->AddDefinition("CMAKE_GENERATOR_NO_COMPILER_ENV", "1");
46 this->GenerateConfigurations(mf);
47 this->cmGlobalGenerator::EnableLanguage(lang, mf, optional);
50 void cmGlobalVisualStudio6Generator::GenerateConfigurations(cmMakefile* mf)
52 std::string fname= mf->GetRequiredDefinition("CMAKE_ROOT");
53 const char* def= mf->GetDefinition( "MSPROJECT_TEMPLATE_DIRECTORY");
60 fname += "/Templates";
62 fname += "/CMakeVisualStudio6Configurations.cmake";
63 if(!mf->ReadListFile(mf->GetCurrentListFile(), fname.c_str()))
65 cmSystemTools::Error("Cannot open ", fname.c_str(),
66 ". Please copy this file from the main "
67 "CMake/Templates directory and edit it for "
68 "your build configurations.");
70 else if(!mf->GetDefinition("CMAKE_CONFIGURATION_TYPES"))
72 cmSystemTools::Error("CMAKE_CONFIGURATION_TYPES not set by ",
74 ". Please copy this file from the main "
75 "CMake/Templates directory and edit it for "
76 "your build configurations.");
80 std::string cmGlobalVisualStudio6Generator
81 ::GenerateBuildCommand(const char* makeProgram,
82 const char *projectName,
83 const char *projectDir,
84 const char* additionalOptions,
85 const char *targetName,
90 // Visual studio 6 doesn't need project dir
92 // Ingoring errors is not implemented in visual studio 6
96 std::vector<std::string> mp;
97 mp.push_back("[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio"
98 "\\6.0\\Setup;VsCommonDir]/MSDev98/Bin");
99 cmSystemTools::ExpandRegistryValues(mp[0]);
100 std::string originalCommand = makeProgram;
101 std::string makeCommand =
102 cmSystemTools::FindProgram(makeProgram, mp);
103 if(makeCommand.size() == 0)
105 std::string e = "Generator cannot find Visual Studio 6 msdev program \"";
106 e += originalCommand;
107 e += "\" specified by CMAKE_MAKE_PROGRAM cache entry. ";
108 e += "Please fix the setting.";
109 cmSystemTools::Error(e.c_str());
112 makeCommand = cmSystemTools::ConvertToOutputPath(makeCommand.c_str());
114 // if there are spaces in the makeCommand, assume a full path
115 // and convert it to a path with no spaces in it as the
116 // RunSingleCommand does not like spaces
117 #if defined(_WIN32) && !defined(__CYGWIN__)
118 if(makeCommand.find(' ') != std::string::npos)
120 cmSystemTools::GetShortPath(makeCommand.c_str(), makeCommand);
124 makeCommand += projectName;
125 makeCommand += ".dsw /MAKE \"";
127 if ( targetName && strcmp(targetName, "clean") == 0 )
130 targetName = "ALL_BUILD";
132 if (targetName && strlen(targetName))
134 makeCommand += targetName;
138 makeCommand += "ALL_BUILD";
140 makeCommand += " - ";
141 if(config && strlen(config))
143 makeCommand += config;
147 makeCommand += "Debug";
151 makeCommand += "\" /CLEAN";
155 makeCommand += "\" /BUILD";
157 if ( additionalOptions )
160 makeCommand += additionalOptions;
165 ///! Create a local generator appropriate to this Global Generator
166 cmLocalGenerator *cmGlobalVisualStudio6Generator::CreateLocalGenerator()
168 cmLocalGenerator *lg = new cmLocalVisualStudio6Generator;
169 lg->SetGlobalGenerator(this);
174 void cmGlobalVisualStudio6Generator::Generate()
176 // first do the superclass method
177 this->cmGlobalVisualStudioGenerator::Generate();
179 // Now write out the DSW
180 this->OutputDSWFile();
183 // Write a DSW file to the stream
184 void cmGlobalVisualStudio6Generator
185 ::WriteDSWFile(std::ostream& fout,cmLocalGenerator* root,
186 std::vector<cmLocalGenerator*>& generators)
188 // Write out the header for a DSW file
189 this->WriteDSWHeader(fout);
191 // Collect all targets under this root generator and the transitive
192 // closure of their dependencies.
193 TargetDependSet projectTargets;
194 TargetDependSet originalTargets;
195 this->GetTargetSets(projectTargets, originalTargets, root, generators);
196 OrderedTargetDependSet orderedProjectTargets(projectTargets);
198 for(OrderedTargetDependSet::const_iterator
199 tt = orderedProjectTargets.begin();
200 tt != orderedProjectTargets.end(); ++tt)
202 cmTarget* target = *tt;
203 // Write the project into the DSW file
204 const char* expath = target->GetProperty("EXTERNAL_MSPROJECT");
207 std::string project = target->GetName();
208 std::string location = expath;
209 this->WriteExternalProject(fout, project.c_str(),
210 location.c_str(), target->GetUtilities());
214 std::string dspname = GetVS6TargetName(target->GetName());
215 std::string dir = target->GetMakefile()->GetStartOutputDirectory();
216 dir = root->Convert(dir.c_str(), cmLocalGenerator::START_OUTPUT);
217 this->WriteProject(fout, dspname.c_str(), dir.c_str(), *target);
221 // Write the footer for the DSW file
222 this->WriteDSWFooter(fout);
225 void cmGlobalVisualStudio6Generator
226 ::OutputDSWFile(cmLocalGenerator* root,
227 std::vector<cmLocalGenerator*>& generators)
229 if(generators.size() == 0)
233 std::string fname = root->GetMakefile()->GetStartOutputDirectory();
235 fname += root->GetMakefile()->GetProjectName();
237 std::ofstream fout(fname.c_str());
240 cmSystemTools::Error("Error can not open DSW file for write: ",
242 cmSystemTools::ReportLastSystemError("");
245 this->WriteDSWFile(fout, root, generators);
248 // output the DSW file
249 void cmGlobalVisualStudio6Generator::OutputDSWFile()
251 std::map<cmStdString, std::vector<cmLocalGenerator*> >::iterator it;
252 for(it = this->ProjectMap.begin(); it!= this->ProjectMap.end(); ++it)
254 this->OutputDSWFile(it->second[0], it->second);
258 // Write a dsp file into the DSW file,
259 // Note, that dependencies from executables to
260 // the libraries it uses are also done here
261 void cmGlobalVisualStudio6Generator::WriteProject(std::ostream& fout,
266 fout << "#########################################################"
267 "######################\n\n";
268 fout << "Project: \"" << dspname << "\"="
269 << dir << "\\" << dspname << ".dsp - Package Owner=<4>\n\n";
270 fout << "Package=<5>\n{{{\n}}}\n\n";
271 fout << "Package=<4>\n";
273 VSDependSet const& depends = this->VSTargetDepends[&target];
274 for(VSDependSet::const_iterator di = depends.begin();
275 di != depends.end(); ++di)
277 const char* name = di->c_str();
278 fout << "Begin Project Dependency\n";
279 fout << "Project_Dep_Name " << GetVS6TargetName(name) << "\n";
280 fout << "End Project Dependency\n";
284 UtilityDependsMap::iterator ui = this->UtilityDepends.find(&target);
285 if(ui != this->UtilityDepends.end())
287 const char* uname = ui->second.c_str();
288 fout << "Project: \"" << uname << "\"="
289 << dir << "\\" << uname << ".dsp - Package Owner=<4>\n\n";
291 "Package=<5>\n{{{\n}}}\n\n"
294 "Begin Project Dependency\n"
295 "Project_Dep_Name " << dspname << "\n"
296 "End Project Dependency\n"
303 // Write a dsp file into the DSW file,
304 // Note, that dependencies from executables to
305 // the libraries it uses are also done here
306 void cmGlobalVisualStudio6Generator::WriteExternalProject(std::ostream& fout,
308 const char* location,
309 const std::set<cmStdString>& dependencies)
311 fout << "#########################################################"
312 "######################\n\n";
313 fout << "Project: \"" << name << "\"="
314 << location << " - Package Owner=<4>\n\n";
315 fout << "Package=<5>\n{{{\n}}}\n\n";
316 fout << "Package=<4>\n";
320 std::set<cmStdString>::const_iterator i, end;
321 // write dependencies.
322 i = dependencies.begin();
323 end = dependencies.end();
326 fout << "Begin Project Dependency\n";
327 fout << "Project_Dep_Name " << GetVS6TargetName(*i) << "\n";
328 fout << "End Project Dependency\n";
335 // Standard end of dsw file
336 void cmGlobalVisualStudio6Generator::WriteDSWFooter(std::ostream& fout)
338 fout << "######################################################"
339 "#########################\n\n";
340 fout << "Global:\n\n";
341 fout << "Package=<5>\n{{{\n}}}\n\n";
342 fout << "Package=<3>\n{{{\n}}}\n\n";
343 fout << "#####################################################"
344 "##########################\n\n";
348 // ouput standard header for dsw file
349 void cmGlobalVisualStudio6Generator::WriteDSWHeader(std::ostream& fout)
351 fout << "Microsoft Developer Studio Workspace File, Format Version 6.00\n";
352 fout << "# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!\n\n";
355 //----------------------------------------------------------------------------
357 cmGlobalVisualStudio6Generator::WriteUtilityDepend(cmTarget* target)
359 std::string pname = target->GetName();
361 pname = GetVS6TargetName(pname.c_str());
362 std::string fname = target->GetMakefile()->GetStartOutputDirectory();
366 cmGeneratedFileStream fout(fname.c_str());
367 fout.SetCopyIfDifferent(true);
369 "# Microsoft Developer Studio Project File - Name=\""
370 << pname << "\" - Package Owner=<4>\n"
371 "# Microsoft Developer Studio Generated Build File, Format Version 6.00\n"
372 "# ** DO NOT EDIT **\n"
374 "# TARGTYPE \"Win32 (x86) Generic Project\" 0x010a\n"
376 "CFG=" << pname << " - Win32 Debug\n"
377 "!MESSAGE \"" << pname << " - Win32 Debug\""
378 " (based on \"Win32 (x86) Generic Project\")\n"
379 "!MESSAGE \"" << pname << " - Win32 Release\" "
380 "(based on \"Win32 (x86) Generic Project\")\n"
381 "!MESSAGE \"" << pname << " - Win32 MinSizeRel\" "
382 "(based on \"Win32 (x86) Generic Project\")\n"
383 "!MESSAGE \"" << pname << " - Win32 RelWithDebInfo\" "
384 "(based on \"Win32 (x86) Generic Project\")\n"
388 "# Name \"" << pname << " - Win32 Debug\"\n"
389 "# Name \"" << pname << " - Win32 Release\"\n"
390 "# Name \"" << pname << " - Win32 MinSizeRel\"\n"
391 "# Name \"" << pname << " - Win32 RelWithDebInfo\"\n"
398 //----------------------------------------------------------------------------
399 void cmGlobalVisualStudio6Generator
400 ::GetDocumentation(cmDocumentationEntry& entry)
402 entry.Name = cmGlobalVisualStudio6Generator::GetActualName();
403 entry.Brief = "Generates Visual Studio 6 project files.";
407 //----------------------------------------------------------------------------
409 cmGlobalVisualStudio6Generator
410 ::AppendDirectoryForConfig(const char* prefix,