1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmGlobalVisualStudio6Generator.cxx,v $
6 Date: $Date: 2008/01/28 13:38:35 $
7 Version: $Revision: 1.75 $
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 if (strncmp(l
->first
.c_str(), "INCLUDE_EXTERNAL_MSPROJECT", 26) == 0)
252 cmCustomCommand cc
= l
->second
.GetPostBuildCommands()[0];
253 const cmCustomCommandLines
& cmds
= cc
.GetCommandLines();
254 std::string project
= cmds
[0][0];
255 std::string location
= cmds
[0][1];
256 this->WriteExternalProject(fout
, project
.c_str(),
257 location
.c_str(), cc
.GetDepends());
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
);
375 // Write a dsp file into the DSW file,
376 // Note, that dependencies from executables to
377 // the libraries it uses are also done here
378 void cmGlobalVisualStudio6Generator::WriteProject(std::ostream
& fout
,
383 fout
<< "#########################################################"
384 "######################\n\n";
385 fout
<< "Project: \"" << dspname
<< "\"="
386 << dir
<< "\\" << dspname
<< ".dsp - Package Owner=<4>\n\n";
387 fout
<< "Package=<5>\n{{{\n}}}\n\n";
388 fout
<< "Package=<4>\n";
391 // insert Begin Project Dependency Project_Dep_Name project stuff here
392 if (target
.GetType() != cmTarget::STATIC_LIBRARY
)
394 cmTarget::LinkLibraryVectorType::const_iterator j
, jend
;
395 j
= target
.GetLinkLibraries().begin();
396 jend
= target
.GetLinkLibraries().end();
399 if(j
->first
!= dspname
)
401 // is the library part of this DSW ? If so add dependency
402 if(this->FindTarget(0, j
->first
.c_str()))
404 fout
<< "Begin Project Dependency\n";
405 fout
<< "Project_Dep_Name " << j
->first
.c_str() << "\n";
406 fout
<< "End Project Dependency\n";
412 std::set
<cmStdString
>::const_iterator i
, end
;
413 // write utility dependencies.
414 i
= target
.GetUtilities().begin();
415 end
= target
.GetUtilities().end();
420 std::string depName
= this->GetUtilityForTarget(target
, i
->c_str());
421 fout
<< "Begin Project Dependency\n";
422 fout
<< "Project_Dep_Name " << depName
<< "\n";
423 fout
<< "End Project Dependency\n";
430 // Write a dsp file into the DSW file,
431 // Note, that dependencies from executables to
432 // the libraries it uses are also done here
433 void cmGlobalVisualStudio6Generator::WriteExternalProject(std::ostream
& fout
,
435 const char* location
,
436 const std::vector
<std::string
>& dependencies
)
438 fout
<< "#########################################################"
439 "######################\n\n";
440 fout
<< "Project: \"" << name
<< "\"="
441 << location
<< " - Package Owner=<4>\n\n";
442 fout
<< "Package=<5>\n{{{\n}}}\n\n";
443 fout
<< "Package=<4>\n";
447 std::vector
<std::string
>::const_iterator i
, end
;
448 // write dependencies.
449 i
= dependencies
.begin();
450 end
= dependencies
.end();
453 fout
<< "Begin Project Dependency\n";
454 fout
<< "Project_Dep_Name " << *i
<< "\n";
455 fout
<< "End Project Dependency\n";
462 // Standard end of dsw file
463 void cmGlobalVisualStudio6Generator::WriteDSWFooter(std::ostream
& fout
)
465 fout
<< "######################################################"
466 "#########################\n\n";
467 fout
<< "Global:\n\n";
468 fout
<< "Package=<5>\n{{{\n}}}\n\n";
469 fout
<< "Package=<3>\n{{{\n}}}\n\n";
470 fout
<< "#####################################################"
471 "##########################\n\n";
475 // ouput standard header for dsw file
476 void cmGlobalVisualStudio6Generator::WriteDSWHeader(std::ostream
& fout
)
478 fout
<< "Microsoft Developer Studio Workspace File, Format Version 6.00\n";
479 fout
<< "# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!\n\n";
482 //----------------------------------------------------------------------------
483 void cmGlobalVisualStudio6Generator
484 ::GetDocumentation(cmDocumentationEntry
& entry
) const
486 entry
.Name
= this->GetName();
487 entry
.Brief
= "Generates Visual Studio 6 project files.";
491 //----------------------------------------------------------------------------
493 cmGlobalVisualStudio6Generator
494 ::AppendDirectoryForConfig(const char* prefix
,