1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmGlobalVisualStudio6Generator.cxx,v $
6 Date: $Date: 2009-07-14 18:16:46 $
7 Version: $Revision: 1.78 $
9 Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
10 See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
12 This software is distributed WITHOUT ANY WARRANTY; without even
13 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 PURPOSE. See the above copyright notices for more information.
16 =========================================================================*/
17 #include "cmGlobalVisualStudio6Generator.h"
18 #include "cmLocalVisualStudio6Generator.h"
19 #include "cmMakefile.h"
22 cmGlobalVisualStudio6Generator::cmGlobalVisualStudio6Generator()
24 this->FindMakeProgramFile
= "CMakeVS6FindMake.cmake";
27 void cmGlobalVisualStudio6Generator
28 ::EnableLanguage(std::vector
<std::string
>const& lang
,
32 mf
->AddDefinition("CMAKE_GENERATOR_CC", "cl");
33 mf
->AddDefinition("CMAKE_GENERATOR_CXX", "cl");
34 mf
->AddDefinition("CMAKE_GENERATOR_RC", "rc");
35 mf
->AddDefinition("CMAKE_GENERATOR_NO_COMPILER_ENV", "1");
36 mf
->AddDefinition("CMAKE_GENERATOR_Fortran", "ifort");
37 mf
->AddDefinition("MSVC60", "1");
38 this->GenerateConfigurations(mf
);
39 this->cmGlobalGenerator::EnableLanguage(lang
, mf
, optional
);
42 void cmGlobalVisualStudio6Generator::GenerateConfigurations(cmMakefile
* mf
)
44 std::string fname
= mf
->GetRequiredDefinition("CMAKE_ROOT");
45 const char* def
= mf
->GetDefinition( "MSPROJECT_TEMPLATE_DIRECTORY");
52 fname
+= "/Templates";
54 fname
+= "/CMakeVisualStudio6Configurations.cmake";
55 if(!mf
->ReadListFile(mf
->GetCurrentListFile(), fname
.c_str()))
57 cmSystemTools::Error("Cannot open ", fname
.c_str(),
58 ". Please copy this file from the main "
59 "CMake/Templates directory and edit it for "
60 "your build configurations.");
62 else if(!mf
->GetDefinition("CMAKE_CONFIGURATION_TYPES"))
64 cmSystemTools::Error("CMAKE_CONFIGURATION_TYPES not set by ",
66 ". Please copy this file from the main "
67 "CMake/Templates directory and edit it for "
68 "your build configurations.");
72 std::string cmGlobalVisualStudio6Generator
73 ::GenerateBuildCommand(const char* makeProgram
,
74 const char *projectName
,
75 const char* additionalOptions
,
76 const char *targetName
,
81 // Ingoring errors is not implemented in visual studio 6
85 std::vector
<std::string
> mp
;
86 mp
.push_back("[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio"
87 "\\6.0\\Setup;VsCommonDir]/MSDev98/Bin");
88 cmSystemTools::ExpandRegistryValues(mp
[0]);
89 std::string originalCommand
= makeProgram
;
90 std::string makeCommand
=
91 cmSystemTools::FindProgram(makeProgram
, mp
);
92 if(makeCommand
.size() == 0)
94 std::string e
= "Generator cannot find Visual Studio 6 msdev program \"";
96 e
+= "\" specified by CMAKE_MAKE_PROGRAM cache entry. ";
97 e
+= "Please fix the setting.";
98 cmSystemTools::Error(e
.c_str());
101 makeCommand
= cmSystemTools::ConvertToOutputPath(makeCommand
.c_str());
103 // if there are spaces in the makeCommand, assume a full path
104 // and convert it to a path with no spaces in it as the
105 // RunSingleCommand does not like spaces
106 #if defined(_WIN32) && !defined(__CYGWIN__)
107 if(makeCommand
.find(' ') != std::string::npos
)
109 cmSystemTools::GetShortPath(makeCommand
.c_str(), makeCommand
);
113 makeCommand
+= projectName
;
114 makeCommand
+= ".dsw /MAKE \"";
116 if ( targetName
&& strcmp(targetName
, "clean") == 0 )
119 targetName
= "ALL_BUILD";
121 if (targetName
&& strlen(targetName
))
123 makeCommand
+= targetName
;
127 makeCommand
+= "ALL_BUILD";
129 makeCommand
+= " - ";
130 if(config
&& strlen(config
))
132 makeCommand
+= config
;
136 makeCommand
+= "Debug";
140 makeCommand
+= "\" /CLEAN";
144 makeCommand
+= "\" /BUILD";
146 if ( additionalOptions
)
149 makeCommand
+= additionalOptions
;
154 ///! Create a local generator appropriate to this Global Generator
155 cmLocalGenerator
*cmGlobalVisualStudio6Generator::CreateLocalGenerator()
157 cmLocalGenerator
*lg
= new cmLocalVisualStudio6Generator
;
158 lg
->SetGlobalGenerator(this);
163 void cmGlobalVisualStudio6Generator::Generate()
165 // first do the superclass method
166 this->cmGlobalVisualStudioGenerator::Generate();
168 // Now write out the DSW
169 this->OutputDSWFile();
172 // Write a DSW file to the stream
173 void cmGlobalVisualStudio6Generator
174 ::WriteDSWFile(std::ostream
& fout
,cmLocalGenerator
* root
,
175 std::vector
<cmLocalGenerator
*>& generators
)
177 // Write out the header for a DSW file
178 this->WriteDSWHeader(fout
);
180 // Get the home directory with the trailing slash
181 std::string homedir
= root
->GetMakefile()->GetStartOutputDirectory();
185 bool doneAllBuild
= false;
186 bool doneRunTests
= false;
187 bool doneInstall
= false;
188 bool doneEditCache
= false;
189 bool doneRebuildCache
= false;
190 bool donePackage
= false;
192 for(i
= 0; i
< generators
.size(); ++i
)
194 if(this->IsExcluded(root
, generators
[i
]))
198 cmMakefile
* mf
= generators
[i
]->GetMakefile();
200 // Get the source directory from the makefile
201 std::string dir
= mf
->GetStartOutputDirectory();
202 // remove the home directory and / from the source directory
203 // this gives a relative path
204 cmSystemTools::ReplaceString(dir
, homedir
.c_str(), "");
206 // Get the list of create dsp files names from the LocalGenerator, more
207 // than one dsp could have been created per input CMakeLists.txt file
209 std::vector
<std::string
> dspnames
=
210 static_cast<cmLocalVisualStudio6Generator
*>(generators
[i
])
211 ->GetCreatedProjectNames();
212 cmTargets
&tgts
= generators
[i
]->GetMakefile()->GetTargets();
213 std::vector
<std::string
>::iterator si
= dspnames
.begin();
214 for(cmTargets::iterator l
= tgts
.begin(); l
!= tgts
.end(); ++l
)
216 // special handling for the current makefile
217 if(mf
== generators
[0]->GetMakefile())
219 dir
= "."; // no subdirectory for project generated
220 // if this is the special ALL_BUILD utility, then
221 // make it depend on every other non UTILITY project.
222 // This is done by adding the names to the GetUtilities
223 // vector on the makefile
224 if(l
->first
== "ALL_BUILD" && !doneAllBuild
)
227 for(j
= 0; j
< generators
.size(); ++j
)
229 cmTargets
&atgts
= generators
[j
]->GetMakefile()->GetTargets();
230 for(cmTargets::iterator al
= atgts
.begin();
231 al
!= atgts
.end(); ++al
)
233 if (!al
->second
.GetPropertyAsBool("EXCLUDE_FROM_ALL"))
235 if (al
->second
.GetType() == cmTarget::UTILITY
||
236 al
->second
.GetType() == cmTarget::GLOBAL_TARGET
)
238 l
->second
.AddUtility(al
->first
.c_str());
242 l
->second
.AddLinkLibrary(al
->first
, cmTarget::GENERAL
);
249 // Write the project into the DSW file
250 cmTarget
* target
= &l
->second
;
251 const char* expath
= target
->GetProperty("EXTERNAL_MSPROJECT");
254 std::string project
= target
->GetName();
255 std::string location
= expath
;
256 this->WriteExternalProject(fout
, project
.c_str(),
257 location
.c_str(), target
->GetUtilities());
262 // skip ALL_BUILD and RUN_TESTS if they have already been added
263 if(l
->first
== "ALL_BUILD" )
274 if(l
->first
== "INSTALL")
285 if(l
->first
== "RUN_TESTS")
296 if(l
->first
== "EDIT_CACHE")
304 doneEditCache
= true;
307 if(l
->first
== "REBUILD_CACHE")
315 doneRebuildCache
= true;
318 if(l
->first
== "PACKAGE")
331 this->WriteProject(fout
, si
->c_str(), dir
.c_str(),l
->second
);
338 // Write the footer for the DSW file
339 this->WriteDSWFooter(fout
);
342 void cmGlobalVisualStudio6Generator
343 ::OutputDSWFile(cmLocalGenerator
* root
,
344 std::vector
<cmLocalGenerator
*>& generators
)
346 if(generators
.size() == 0)
350 std::string fname
= root
->GetMakefile()->GetStartOutputDirectory();
352 fname
+= root
->GetMakefile()->GetProjectName();
354 std::ofstream
fout(fname
.c_str());
357 cmSystemTools::Error("Error can not open DSW file for write: ",
359 cmSystemTools::ReportLastSystemError("");
362 this->WriteDSWFile(fout
, root
, generators
);
365 // output the DSW file
366 void cmGlobalVisualStudio6Generator::OutputDSWFile()
368 std::map
<cmStdString
, std::vector
<cmLocalGenerator
*> >::iterator it
;
369 for(it
= this->ProjectMap
.begin(); it
!= this->ProjectMap
.end(); ++it
)
371 this->OutputDSWFile(it
->second
[0], it
->second
);
376 // Utility function to make a valid VS6 *.dsp filename out
377 // of a CMake target name:
379 std::string
GetVS6TargetName(const std::string
& targetName
)
381 std::string
name(targetName
);
383 // Eliminate hyphens. VS6 cannot handle hyphens in *.dsp filenames...
384 // Replace them with underscores.
386 cmSystemTools::ReplaceString(name
, "-", "_");
392 // Write a dsp file into the DSW file,
393 // Note, that dependencies from executables to
394 // the libraries it uses are also done here
395 void cmGlobalVisualStudio6Generator::WriteProject(std::ostream
& fout
,
400 fout
<< "#########################################################"
401 "######################\n\n";
402 fout
<< "Project: \"" << dspname
<< "\"="
403 << dir
<< "\\" << dspname
<< ".dsp - Package Owner=<4>\n\n";
404 fout
<< "Package=<5>\n{{{\n}}}\n\n";
405 fout
<< "Package=<4>\n";
408 // insert Begin Project Dependency Project_Dep_Name project stuff here
409 if (target
.GetType() != cmTarget::STATIC_LIBRARY
)
411 cmTarget::LinkLibraryVectorType::const_iterator j
, jend
;
412 j
= target
.GetLinkLibraries().begin();
413 jend
= target
.GetLinkLibraries().end();
416 if(j
->first
!= dspname
)
418 // is the library part of this DSW ? If so add dependency
419 if(this->FindTarget(0, j
->first
.c_str()))
421 fout
<< "Begin Project Dependency\n";
422 fout
<< "Project_Dep_Name "
423 << GetVS6TargetName(j
->first
.c_str()) << "\n";
424 fout
<< "End Project Dependency\n";
430 std::set
<cmStdString
>::const_iterator i
, end
;
431 // write utility dependencies.
432 i
= target
.GetUtilities().begin();
433 end
= target
.GetUtilities().end();
438 std::string depName
= this->GetUtilityForTarget(target
, i
->c_str());
439 fout
<< "Begin Project Dependency\n";
440 fout
<< "Project_Dep_Name " << GetVS6TargetName(depName
) << "\n";
441 fout
<< "End Project Dependency\n";
448 // Write a dsp file into the DSW file,
449 // Note, that dependencies from executables to
450 // the libraries it uses are also done here
451 void cmGlobalVisualStudio6Generator::WriteExternalProject(std::ostream
& fout
,
453 const char* location
,
454 const std::set
<cmStdString
>& dependencies
)
456 fout
<< "#########################################################"
457 "######################\n\n";
458 fout
<< "Project: \"" << name
<< "\"="
459 << location
<< " - Package Owner=<4>\n\n";
460 fout
<< "Package=<5>\n{{{\n}}}\n\n";
461 fout
<< "Package=<4>\n";
465 std::set
<cmStdString
>::const_iterator i
, end
;
466 // write dependencies.
467 i
= dependencies
.begin();
468 end
= dependencies
.end();
471 fout
<< "Begin Project Dependency\n";
472 fout
<< "Project_Dep_Name " << GetVS6TargetName(*i
) << "\n";
473 fout
<< "End Project Dependency\n";
480 // Standard end of dsw file
481 void cmGlobalVisualStudio6Generator::WriteDSWFooter(std::ostream
& fout
)
483 fout
<< "######################################################"
484 "#########################\n\n";
485 fout
<< "Global:\n\n";
486 fout
<< "Package=<5>\n{{{\n}}}\n\n";
487 fout
<< "Package=<3>\n{{{\n}}}\n\n";
488 fout
<< "#####################################################"
489 "##########################\n\n";
493 // ouput standard header for dsw file
494 void cmGlobalVisualStudio6Generator::WriteDSWHeader(std::ostream
& fout
)
496 fout
<< "Microsoft Developer Studio Workspace File, Format Version 6.00\n";
497 fout
<< "# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!\n\n";
500 //----------------------------------------------------------------------------
501 void cmGlobalVisualStudio6Generator
502 ::GetDocumentation(cmDocumentationEntry
& entry
) const
504 entry
.Name
= this->GetName();
505 entry
.Brief
= "Generates Visual Studio 6 project files.";
509 //----------------------------------------------------------------------------
511 cmGlobalVisualStudio6Generator
512 ::AppendDirectoryForConfig(const char* prefix
,