423 lines
13 KiB
C++
423 lines
13 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"
|
|
#include "cmGeneratedFileStream.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->MSDevCommandInitialized = false;
|
|
}
|
|
|
|
void cmGlobalVisualStudio6Generator
|
|
::EnableLanguage(std::vector<std::string>const& lang,
|
|
cmMakefile *mf,
|
|
bool optional)
|
|
{
|
|
cmGlobalVisualStudioGenerator::AddPlatformDefinitions(mf);
|
|
mf->AddDefinition("CMAKE_GENERATOR_RC", "rc");
|
|
mf->AddDefinition("CMAKE_GENERATOR_NO_COMPILER_ENV", "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 const& cmGlobalVisualStudio6Generator::GetMSDevCommand()
|
|
{
|
|
if(!this->MSDevCommandInitialized)
|
|
{
|
|
this->MSDevCommandInitialized = true;
|
|
this->MSDevCommand = this->FindMSDevCommand();
|
|
}
|
|
return this->MSDevCommand;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
std::string cmGlobalVisualStudio6Generator::FindMSDevCommand()
|
|
{
|
|
std::string vscmd;
|
|
std::string vskey = this->GetRegistryBase() + "\\Setup;VsCommonDir";
|
|
if(cmSystemTools::ReadRegistryValue(vskey.c_str(), vscmd,
|
|
cmSystemTools::KeyWOW64_32))
|
|
{
|
|
cmSystemTools::ConvertToUnixSlashes(vscmd);
|
|
vscmd += "/MSDev98/Bin/";
|
|
}
|
|
vscmd += "msdev.exe";
|
|
return vscmd;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void
|
|
cmGlobalVisualStudio6Generator::GenerateBuildCommand(
|
|
std::vector<std::string>& makeCommand,
|
|
const char* makeProgram,
|
|
const char* projectName,
|
|
const char* /*projectDir*/,
|
|
const char* targetName,
|
|
const char* config,
|
|
bool /*fast*/,
|
|
std::vector<std::string> const& makeOptions
|
|
)
|
|
{
|
|
// now build the test
|
|
makeCommand.push_back(
|
|
this->SelectMakeProgram(makeProgram, this->GetMSDevCommand())
|
|
);
|
|
|
|
makeCommand.push_back(std::string(projectName)+".dsw");
|
|
makeCommand.push_back("/MAKE");
|
|
std::string targetArg;
|
|
bool clean = false;
|
|
if ( targetName && strcmp(targetName, "clean") == 0 )
|
|
{
|
|
clean = true;
|
|
targetName = "ALL_BUILD";
|
|
}
|
|
if (targetName && strlen(targetName))
|
|
{
|
|
targetArg += targetName;
|
|
}
|
|
else
|
|
{
|
|
targetArg += "ALL_BUILD";
|
|
}
|
|
targetArg += " - ";
|
|
if(config && strlen(config))
|
|
{
|
|
targetArg += config;
|
|
}
|
|
else
|
|
{
|
|
targetArg += "Debug";
|
|
}
|
|
makeCommand.push_back(targetArg);
|
|
if(clean)
|
|
{
|
|
makeCommand.push_back("/CLEAN");
|
|
}
|
|
else
|
|
{
|
|
makeCommand.push_back("/BUILD");
|
|
}
|
|
makeCommand.insert(makeCommand.end(),
|
|
makeOptions.begin(), makeOptions.end());
|
|
}
|
|
|
|
///! 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);
|
|
|
|
for(OrderedTargetDependSet::const_iterator
|
|
tt = orderedProjectTargets.begin();
|
|
tt != orderedProjectTargets.end(); ++tt)
|
|
{
|
|
cmTarget* target = *tt;
|
|
if(target->GetType() == cmTarget::INTERFACE_LIBRARY)
|
|
{
|
|
continue;
|
|
}
|
|
// 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
|
|
{
|
|
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";
|
|
VSDependSet const& depends = this->VSTargetDepends[&target];
|
|
for(VSDependSet::const_iterator di = depends.begin();
|
|
di != depends.end(); ++di)
|
|
{
|
|
const char* name = di->c_str();
|
|
fout << "Begin Project Dependency\n";
|
|
fout << "Project_Dep_Name " << GetVS6TargetName(name) << "\n";
|
|
fout << "End Project Dependency\n";
|
|
}
|
|
fout << "}}}\n\n";
|
|
|
|
UtilityDependsMap::iterator ui = this->UtilityDepends.find(&target);
|
|
if(ui != this->UtilityDepends.end())
|
|
{
|
|
const char* uname = ui->second.c_str();
|
|
fout << "Project: \"" << uname << "\"="
|
|
<< dir << "\\" << uname << ".dsp - Package Owner=<4>\n\n";
|
|
fout <<
|
|
"Package=<5>\n{{{\n}}}\n\n"
|
|
"Package=<4>\n"
|
|
"{{{\n"
|
|
"Begin Project Dependency\n"
|
|
"Project_Dep_Name " << dspname << "\n"
|
|
"End Project Dependency\n"
|
|
"}}}\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";
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
std::string
|
|
cmGlobalVisualStudio6Generator::WriteUtilityDepend(cmTarget* target)
|
|
{
|
|
std::string pname = target->GetName();
|
|
pname += "_UTILITY";
|
|
pname = GetVS6TargetName(pname.c_str());
|
|
std::string fname = target->GetMakefile()->GetStartOutputDirectory();
|
|
fname += "/";
|
|
fname += pname;
|
|
fname += ".dsp";
|
|
cmGeneratedFileStream fout(fname.c_str());
|
|
fout.SetCopyIfDifferent(true);
|
|
fout <<
|
|
"# Microsoft Developer Studio Project File - Name=\""
|
|
<< pname << "\" - Package Owner=<4>\n"
|
|
"# Microsoft Developer Studio Generated Build File, Format Version 6.00\n"
|
|
"# ** DO NOT EDIT **\n"
|
|
"\n"
|
|
"# TARGTYPE \"Win32 (x86) Generic Project\" 0x010a\n"
|
|
"\n"
|
|
"CFG=" << pname << " - Win32 Debug\n"
|
|
"!MESSAGE \"" << pname << " - Win32 Debug\""
|
|
" (based on \"Win32 (x86) Generic Project\")\n"
|
|
"!MESSAGE \"" << pname << " - Win32 Release\" "
|
|
"(based on \"Win32 (x86) Generic Project\")\n"
|
|
"!MESSAGE \"" << pname << " - Win32 MinSizeRel\" "
|
|
"(based on \"Win32 (x86) Generic Project\")\n"
|
|
"!MESSAGE \"" << pname << " - Win32 RelWithDebInfo\" "
|
|
"(based on \"Win32 (x86) Generic Project\")\n"
|
|
"\n"
|
|
"# Begin Project\n"
|
|
"# Begin Target\n"
|
|
"# Name \"" << pname << " - Win32 Debug\"\n"
|
|
"# Name \"" << pname << " - Win32 Release\"\n"
|
|
"# Name \"" << pname << " - Win32 MinSizeRel\"\n"
|
|
"# Name \"" << pname << " - Win32 RelWithDebInfo\"\n"
|
|
"# End Target\n"
|
|
"# End Project\n"
|
|
;
|
|
return pname;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void cmGlobalVisualStudio6Generator
|
|
::GetDocumentation(cmDocumentationEntry& entry)
|
|
{
|
|
entry.Name = cmGlobalVisualStudio6Generator::GetActualName();
|
|
entry.Brief = "Generates Visual Studio 6 project files.";
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void
|
|
cmGlobalVisualStudio6Generator
|
|
::AppendDirectoryForConfig(const char* prefix,
|
|
const char* config,
|
|
const char* suffix,
|
|
std::string& dir)
|
|
{
|
|
if(config)
|
|
{
|
|
dir += prefix;
|
|
dir += config;
|
|
dir += suffix;
|
|
}
|
|
}
|