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 mf->AddDefinition("CMAKE_GENERATOR_CC", "cl");
44 mf->AddDefinition("CMAKE_GENERATOR_CXX", "cl");
45 mf->AddDefinition("CMAKE_GENERATOR_RC", "rc");
46 mf->AddDefinition("CMAKE_GENERATOR_NO_COMPILER_ENV", "1");
47 mf->AddDefinition("CMAKE_GENERATOR_Fortran", "ifort");
48 mf->AddDefinition("MSVC_C_ARCHITECTURE_ID", "X86");
49 mf->AddDefinition("MSVC_CXX_ARCHITECTURE_ID", "X86");
50 mf->AddDefinition("MSVC60", "1");
51 this->GenerateConfigurations(mf);
52 this->cmGlobalGenerator::EnableLanguage(lang, mf, optional);
55 void cmGlobalVisualStudio6Generator::GenerateConfigurations(cmMakefile* mf)
57 std::string fname= mf->GetRequiredDefinition("CMAKE_ROOT");
58 const char* def= mf->GetDefinition( "MSPROJECT_TEMPLATE_DIRECTORY");
65 fname += "/Templates";
67 fname += "/CMakeVisualStudio6Configurations.cmake";
68 if(!mf->ReadListFile(mf->GetCurrentListFile(), fname.c_str()))
70 cmSystemTools::Error("Cannot open ", fname.c_str(),
71 ". Please copy this file from the main "
72 "CMake/Templates directory and edit it for "
73 "your build configurations.");
75 else if(!mf->GetDefinition("CMAKE_CONFIGURATION_TYPES"))
77 cmSystemTools::Error("CMAKE_CONFIGURATION_TYPES not set by ",
79 ". Please copy this file from the main "
80 "CMake/Templates directory and edit it for "
81 "your build configurations.");
85 std::string cmGlobalVisualStudio6Generator
86 ::GenerateBuildCommand(const char* makeProgram,
87 const char *projectName,
88 const char* additionalOptions,
89 const char *targetName,
94 // Ingoring errors is not implemented in visual studio 6
98 std::vector<std::string> mp;
99 mp.push_back("[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio"
100 "\\6.0\\Setup;VsCommonDir]/MSDev98/Bin");
101 cmSystemTools::ExpandRegistryValues(mp[0]);
102 std::string originalCommand = makeProgram;
103 std::string makeCommand =
104 cmSystemTools::FindProgram(makeProgram, mp);
105 if(makeCommand.size() == 0)
107 std::string e = "Generator cannot find Visual Studio 6 msdev program \"";
108 e += originalCommand;
109 e += "\" specified by CMAKE_MAKE_PROGRAM cache entry. ";
110 e += "Please fix the setting.";
111 cmSystemTools::Error(e.c_str());
114 makeCommand = cmSystemTools::ConvertToOutputPath(makeCommand.c_str());
116 // if there are spaces in the makeCommand, assume a full path
117 // and convert it to a path with no spaces in it as the
118 // RunSingleCommand does not like spaces
119 #if defined(_WIN32) && !defined(__CYGWIN__)
120 if(makeCommand.find(' ') != std::string::npos)
122 cmSystemTools::GetShortPath(makeCommand.c_str(), makeCommand);
126 makeCommand += projectName;
127 makeCommand += ".dsw /MAKE \"";
129 if ( targetName && strcmp(targetName, "clean") == 0 )
132 targetName = "ALL_BUILD";
134 if (targetName && strlen(targetName))
136 makeCommand += targetName;
140 makeCommand += "ALL_BUILD";
142 makeCommand += " - ";
143 if(config && strlen(config))
145 makeCommand += config;
149 makeCommand += "Debug";
153 makeCommand += "\" /CLEAN";
157 makeCommand += "\" /BUILD";
159 if ( additionalOptions )
162 makeCommand += additionalOptions;
167 ///! Create a local generator appropriate to this Global Generator
168 cmLocalGenerator *cmGlobalVisualStudio6Generator::CreateLocalGenerator()
170 cmLocalGenerator *lg = new cmLocalVisualStudio6Generator;
171 lg->SetGlobalGenerator(this);
176 void cmGlobalVisualStudio6Generator::Generate()
178 // first do the superclass method
179 this->cmGlobalVisualStudioGenerator::Generate();
181 // Now write out the DSW
182 this->OutputDSWFile();
185 // Write a DSW file to the stream
186 void cmGlobalVisualStudio6Generator
187 ::WriteDSWFile(std::ostream& fout,cmLocalGenerator* root,
188 std::vector<cmLocalGenerator*>& generators)
190 // Write out the header for a DSW file
191 this->WriteDSWHeader(fout);
193 // Collect all targets under this root generator and the transitive
194 // closure of their dependencies.
195 TargetDependSet projectTargets;
196 TargetDependSet originalTargets;
197 this->GetTargetSets(projectTargets, originalTargets, root, generators);
198 OrderedTargetDependSet orderedProjectTargets(projectTargets);
200 for(OrderedTargetDependSet::const_iterator
201 tt = orderedProjectTargets.begin();
202 tt != orderedProjectTargets.end(); ++tt)
204 cmTarget* target = *tt;
205 cmMakefile* mf = target->GetMakefile();
206 // Write the project into the DSW file
207 const char* expath = target->GetProperty("EXTERNAL_MSPROJECT");
210 std::string project = target->GetName();
211 std::string location = expath;
212 this->WriteExternalProject(fout, project.c_str(),
213 location.c_str(), target->GetUtilities());
217 std::string dspname = GetVS6TargetName(target->GetName());
218 std::string dir = target->GetMakefile()->GetStartOutputDirectory();
219 dir = root->Convert(dir.c_str(), cmLocalGenerator::START_OUTPUT);
220 this->WriteProject(fout, dspname.c_str(), dir.c_str(), *target);
224 // Write the footer for the DSW file
225 this->WriteDSWFooter(fout);
228 void cmGlobalVisualStudio6Generator
229 ::OutputDSWFile(cmLocalGenerator* root,
230 std::vector<cmLocalGenerator*>& generators)
232 if(generators.size() == 0)
236 std::string fname = root->GetMakefile()->GetStartOutputDirectory();
238 fname += root->GetMakefile()->GetProjectName();
240 std::ofstream fout(fname.c_str());
243 cmSystemTools::Error("Error can not open DSW file for write: ",
245 cmSystemTools::ReportLastSystemError("");
248 this->WriteDSWFile(fout, root, generators);
251 // output the DSW file
252 void cmGlobalVisualStudio6Generator::OutputDSWFile()
254 std::map<cmStdString, std::vector<cmLocalGenerator*> >::iterator it;
255 for(it = this->ProjectMap.begin(); it!= this->ProjectMap.end(); ++it)
257 this->OutputDSWFile(it->second[0], it->second);
261 // Write a dsp file into the DSW file,
262 // Note, that dependencies from executables to
263 // the libraries it uses are also done here
264 void cmGlobalVisualStudio6Generator::WriteProject(std::ostream& fout,
269 fout << "#########################################################"
270 "######################\n\n";
271 fout << "Project: \"" << dspname << "\"="
272 << dir << "\\" << dspname << ".dsp - Package Owner=<4>\n\n";
273 fout << "Package=<5>\n{{{\n}}}\n\n";
274 fout << "Package=<4>\n";
276 VSDependSet const& depends = this->VSTargetDepends[&target];
277 for(VSDependSet::const_iterator di = depends.begin();
278 di != depends.end(); ++di)
280 const char* name = di->c_str();
281 fout << "Begin Project Dependency\n";
282 fout << "Project_Dep_Name " << GetVS6TargetName(name) << "\n";
283 fout << "End Project Dependency\n";
287 UtilityDependsMap::iterator ui = this->UtilityDepends.find(&target);
288 if(ui != this->UtilityDepends.end())
290 const char* uname = ui->second.c_str();
291 fout << "Project: \"" << uname << "\"="
292 << dir << "\\" << uname << ".dsp - Package Owner=<4>\n\n";
294 "Package=<5>\n{{{\n}}}\n\n"
297 "Begin Project Dependency\n"
298 "Project_Dep_Name " << dspname << "\n"
299 "End Project Dependency\n"
306 // Write a dsp file into the DSW file,
307 // Note, that dependencies from executables to
308 // the libraries it uses are also done here
309 void cmGlobalVisualStudio6Generator::WriteExternalProject(std::ostream& fout,
311 const char* location,
312 const std::set<cmStdString>& dependencies)
314 fout << "#########################################################"
315 "######################\n\n";
316 fout << "Project: \"" << name << "\"="
317 << location << " - Package Owner=<4>\n\n";
318 fout << "Package=<5>\n{{{\n}}}\n\n";
319 fout << "Package=<4>\n";
323 std::set<cmStdString>::const_iterator i, end;
324 // write dependencies.
325 i = dependencies.begin();
326 end = dependencies.end();
329 fout << "Begin Project Dependency\n";
330 fout << "Project_Dep_Name " << GetVS6TargetName(*i) << "\n";
331 fout << "End Project Dependency\n";
338 // Standard end of dsw file
339 void cmGlobalVisualStudio6Generator::WriteDSWFooter(std::ostream& fout)
341 fout << "######################################################"
342 "#########################\n\n";
343 fout << "Global:\n\n";
344 fout << "Package=<5>\n{{{\n}}}\n\n";
345 fout << "Package=<3>\n{{{\n}}}\n\n";
346 fout << "#####################################################"
347 "##########################\n\n";
351 // ouput standard header for dsw file
352 void cmGlobalVisualStudio6Generator::WriteDSWHeader(std::ostream& fout)
354 fout << "Microsoft Developer Studio Workspace File, Format Version 6.00\n";
355 fout << "# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!\n\n";
358 //----------------------------------------------------------------------------
360 cmGlobalVisualStudio6Generator::WriteUtilityDepend(cmTarget* target)
362 std::string pname = target->GetName();
364 pname = GetVS6TargetName(pname.c_str());
365 std::string fname = target->GetMakefile()->GetStartOutputDirectory();
369 cmGeneratedFileStream fout(fname.c_str());
370 fout.SetCopyIfDifferent(true);
372 "# Microsoft Developer Studio Project File - Name=\""
373 << pname << "\" - Package Owner=<4>\n"
374 "# Microsoft Developer Studio Generated Build File, Format Version 6.00\n"
375 "# ** DO NOT EDIT **\n"
377 "# TARGTYPE \"Win32 (x86) Generic Project\" 0x010a\n"
379 "CFG=" << pname << " - Win32 Debug\n"
380 "!MESSAGE \"" << pname << " - Win32 Debug\""
381 " (based on \"Win32 (x86) Generic Project\")\n"
382 "!MESSAGE \"" << pname << " - Win32 Release\" "
383 "(based on \"Win32 (x86) Generic Project\")\n"
384 "!MESSAGE \"" << pname << " - Win32 MinSizeRel\" "
385 "(based on \"Win32 (x86) Generic Project\")\n"
386 "!MESSAGE \"" << pname << " - Win32 RelWithDebInfo\" "
387 "(based on \"Win32 (x86) Generic Project\")\n"
391 "# Name \"" << pname << " - Win32 Debug\"\n"
392 "# Name \"" << pname << " - Win32 Release\"\n"
393 "# Name \"" << pname << " - Win32 MinSizeRel\"\n"
394 "# Name \"" << pname << " - Win32 RelWithDebInfo\"\n"
401 //----------------------------------------------------------------------------
402 void cmGlobalVisualStudio6Generator
403 ::GetDocumentation(cmDocumentationEntry& entry) const
405 entry.Name = this->GetName();
406 entry.Brief = "Generates Visual Studio 6 project files.";
410 //----------------------------------------------------------------------------
412 cmGlobalVisualStudio6Generator
413 ::AppendDirectoryForConfig(const char* prefix,