blob: 14de698d505236f9a8621284d1dfb883374719fe [file] [log] [blame]
/*============================================================================
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"
#include <cmsys/FStream.hxx>
// 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(cmake* cm)
: cmGlobalVisualStudioGenerator(cm)
{
this->MSDevCommandInitialized = false;
this->Version = VS6;
}
void cmGlobalVisualStudio6Generator
::EnableLanguage(std::vector<std::string>const& lang,
cmMakefile *mf,
bool optional)
{
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->ReadDependentFile(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.");
}
}
//----------------------------------------------------------------------------
void cmGlobalVisualStudio6Generator::FindMakeProgram(cmMakefile* mf)
{
this->cmGlobalVisualStudioGenerator::FindMakeProgram(mf);
mf->AddDefinition("CMAKE_VS_MSDEV_COMMAND",
this->GetMSDevCommand().c_str());
}
//----------------------------------------------------------------------------
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 std::string& makeProgram,
const std::string& projectName,
const std::string& /*projectDir*/,
const std::string& targetName,
const std::string& config,
bool /*fast*/, bool /*verbose*/,
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;
std::string realTarget = targetName;
if ( realTarget == "clean" )
{
clean = true;
realTarget = "ALL_BUILD";
}
if (!realTarget.empty())
{
targetArg += realTarget;
}
else
{
targetArg += "ALL_BUILD";
}
targetArg += " - ";
if(!config.empty())
{
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(cmMakefile* mf)
{
return new cmLocalVisualStudio6Generator(this, mf);
}
void cmGlobalVisualStudio6Generator::Generate()
{
// first do the superclass method
this->cmGlobalVisualStudioGenerator::Generate();
// Now write out the DSW
this->OutputDSWFile();
if (!this->CMakeInstance->GetIsInTryCompile())
{
const char* cmakeWarnVS6 =
this->CMakeInstance->GetState()->GetCacheEntryValue("CMAKE_WARN_VS6");
if (!cmakeWarnVS6 || !cmSystemTools::IsOff(cmakeWarnVS6))
{
this->CMakeInstance->IssueMessage(
cmake::WARNING,
"The \"Visual Studio 6\" generator is deprecated "
"and will be removed in a future version of CMake."
"\n"
"Add CMAKE_WARN_VS6=OFF to the cache to disable this warning."
);
}
}
}
// 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, "ALL_BUILD");
for(OrderedTargetDependSet::const_iterator
tt = orderedProjectTargets.begin();
tt != orderedProjectTargets.end(); ++tt)
{
cmTarget const* target = (*tt)->Target;
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()->GetCurrentBinaryDirectory();
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.empty())
{
return;
}
std::string fname = root->GetMakefile()->GetCurrentBinaryDirectory();
fname += "/";
fname += root->GetMakefile()->GetProjectName();
fname += ".dsw";
cmsys::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<std::string, 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 std::string& dspname,
const char* dir,
cmTarget const& 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 std::string& name,
const char* location,
const std::set<std::string>& 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<std::string>::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 const* target)
{
std::string pname = target->GetName();
pname += "_UTILITY";
pname = GetVS6TargetName(pname.c_str());
std::string fname = target->GetMakefile()->GetCurrentBinaryDirectory();
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 = "Deprecated. Generates Visual Studio 6 project files.";
}
//----------------------------------------------------------------------------
void
cmGlobalVisualStudio6Generator
::AppendDirectoryForConfig(const std::string& prefix,
const std::string& config,
const std::string& suffix,
std::string& dir)
{
if(!config.empty())
{
dir += prefix;
dir += config;
dir += suffix;
}
}