CMake/Source/cmGlobalVisualStudio6Generator.cxx
Brad King c8ddb6813b Cleanup cmGlobalGenerator::GetTargetSets method
This commit cleans up the declaration, definition, and invocations of
the GetTargetSets method and related code.  There is no change in
function except to make the method virtual.
2009-10-01 10:26:54 -04:00

409 lines
12 KiB
C++

/*============================================================================
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"
// 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()
{
this->FindMakeProgramFile = "CMakeVS6FindMake.cmake";
}
void cmGlobalVisualStudio6Generator
::EnableLanguage(std::vector<std::string>const& lang,
cmMakefile *mf,
bool optional)
{
mf->AddDefinition("CMAKE_GENERATOR_CC", "cl");
mf->AddDefinition("CMAKE_GENERATOR_CXX", "cl");
mf->AddDefinition("CMAKE_GENERATOR_RC", "rc");
mf->AddDefinition("CMAKE_GENERATOR_NO_COMPILER_ENV", "1");
mf->AddDefinition("CMAKE_GENERATOR_Fortran", "ifort");
mf->AddDefinition("MSVC60", "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->ReadListFile(mf->GetCurrentListFile(), 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.");
}
}
std::string cmGlobalVisualStudio6Generator
::GenerateBuildCommand(const char* makeProgram,
const char *projectName,
const char* additionalOptions,
const char *targetName,
const char* config,
bool ignoreErrors,
bool)
{
// Ingoring errors is not implemented in visual studio 6
(void) ignoreErrors;
// now build the test
std::vector<std::string> mp;
mp.push_back("[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio"
"\\6.0\\Setup;VsCommonDir]/MSDev98/Bin");
cmSystemTools::ExpandRegistryValues(mp[0]);
std::string originalCommand = makeProgram;
std::string makeCommand =
cmSystemTools::FindProgram(makeProgram, mp);
if(makeCommand.size() == 0)
{
std::string e = "Generator cannot find Visual Studio 6 msdev program \"";
e += originalCommand;
e += "\" specified by CMAKE_MAKE_PROGRAM cache entry. ";
e += "Please fix the setting.";
cmSystemTools::Error(e.c_str());
return "";
}
makeCommand = cmSystemTools::ConvertToOutputPath(makeCommand.c_str());
// if there are spaces in the makeCommand, assume a full path
// and convert it to a path with no spaces in it as the
// RunSingleCommand does not like spaces
#if defined(_WIN32) && !defined(__CYGWIN__)
if(makeCommand.find(' ') != std::string::npos)
{
cmSystemTools::GetShortPath(makeCommand.c_str(), makeCommand);
}
#endif
makeCommand += " ";
makeCommand += projectName;
makeCommand += ".dsw /MAKE \"";
bool clean = false;
if ( targetName && strcmp(targetName, "clean") == 0 )
{
clean = true;
targetName = "ALL_BUILD";
}
if (targetName && strlen(targetName))
{
makeCommand += targetName;
}
else
{
makeCommand += "ALL_BUILD";
}
makeCommand += " - ";
if(config && strlen(config))
{
makeCommand += config;
}
else
{
makeCommand += "Debug";
}
if(clean)
{
makeCommand += "\" /CLEAN";
}
else
{
makeCommand += "\" /BUILD";
}
if ( additionalOptions )
{
makeCommand += " ";
makeCommand += additionalOptions;
}
return makeCommand;
}
///! Create a local generator appropriate to this Global Generator
cmLocalGenerator *cmGlobalVisualStudio6Generator::CreateLocalGenerator()
{
cmLocalGenerator *lg = new cmLocalVisualStudio6Generator;
lg->SetGlobalGenerator(this);
return lg;
}
void cmGlobalVisualStudio6Generator::Generate()
{
// first do the superclass method
this->cmGlobalVisualStudioGenerator::Generate();
// Now write out the DSW
this->OutputDSWFile();
}
// 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);
std::string rootdir = root->GetMakefile()->GetStartOutputDirectory();
rootdir += "/";
for(OrderedTargetDependSet::const_iterator
tt = orderedProjectTargets.begin();
tt != orderedProjectTargets.end(); ++tt)
{
cmTarget* target = *tt;
cmMakefile* mf = target->GetMakefile();
// 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
{
bool skip = false;
// if it is a global target or the check build system target
// or the all_build target
// then only use the one that is for the root
if(target->GetType() == cmTarget::GLOBAL_TARGET
|| !strcmp(target->GetName(), this->GetAllTargetName()))
{
if(target->GetMakefile() != root->GetMakefile())
{
skip = true;
}
}
// if not skipping the project then write it into the
// solution
if(!skip)
{
std::string dspname = GetVS6TargetName(target->GetName());
std::string dir = target->GetMakefile()->GetStartOutputDirectory();
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()->GetStartOutputDirectory();
fname += "/";
fname += root->GetMakefile()->GetProjectName();
fname += ".dsw";
std::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<cmStdString, 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 char* dspname,
const char* dir,
cmTarget& 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";
// insert Begin Project Dependency Project_Dep_Name project stuff here
if (target.GetType() != cmTarget::STATIC_LIBRARY)
{
cmTarget::LinkLibraryVectorType::const_iterator j, jend;
j = target.GetLinkLibraries().begin();
jend = target.GetLinkLibraries().end();
for(;j!= jend; ++j)
{
if(j->first != dspname)
{
// is the library part of this DSW ? If so add dependency
if(this->FindTarget(0, j->first.c_str()))
{
fout << "Begin Project Dependency\n";
fout << "Project_Dep_Name "
<< GetVS6TargetName(j->first.c_str()) << "\n";
fout << "End Project Dependency\n";
}
}
}
}
std::set<cmStdString>::const_iterator i, end;
// write utility dependencies.
i = target.GetUtilities().begin();
end = target.GetUtilities().end();
for(;i!= end; ++i)
{
if(*i != dspname)
{
std::string depName = this->GetUtilityForTarget(target, i->c_str());
fout << "Begin Project Dependency\n";
fout << "Project_Dep_Name " << GetVS6TargetName(depName) << "\n";
fout << "End Project Dependency\n";
}
}
fout << "}}}\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 char* name,
const char* location,
const std::set<cmStdString>& 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<cmStdString>::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";
}
//----------------------------------------------------------------------------
void cmGlobalVisualStudio6Generator
::GetDocumentation(cmDocumentationEntry& entry) const
{
entry.Name = this->GetName();
entry.Brief = "Generates Visual Studio 6 project files.";
entry.Full = "";
}
//----------------------------------------------------------------------------
void
cmGlobalVisualStudio6Generator
::AppendDirectoryForConfig(const char* prefix,
const char* config,
const char* suffix,
std::string& dir)
{
if(config)
{
dir += prefix;
dir += config;
dir += suffix;
}
}