Commit 8a83f096 authored by Bill Hoffman's avatar Bill Hoffman
Browse files

ENH: fix for bug 3218 dependant projects are written out automatically if they...

ENH: fix for bug 3218 dependant projects are written out automatically if they are in the project.  Also fix bug 5829, remove hard coded CMAKE_CONFIGURATION_TYPES from vs 7 generator
parent 21e67917
......@@ -1036,7 +1036,6 @@ int cmGlobalGenerator::Build(
std::string makeCommand =
this->GenerateBuildCommand(makeCommandCSTR, projectName,
0, target, config, false, fast);
if (!cmSystemTools::RunSingleCommand(makeCommand.c_str(), output,
&retVal, 0, false, timeout))
{
......@@ -1291,7 +1290,7 @@ void cmGlobalGenerator::FillLocalGeneratorToTargetMap()
// Add dependencies of the included target. An excluded
// target may still be included if it is a dependency of a
// non-excluded target.
TargetDependSet const& tgtdeps = this->GetTargetDepends(target);
TargetDependSet const& tgtdeps = this->GetTargetDirectDepends(target);
for(TargetDependSet::const_iterator ti = tgtdeps.begin();
ti != tgtdeps.end(); ++ti)
{
......@@ -1684,7 +1683,7 @@ void cmGlobalGenerator::AppendDirectoryForConfig(const char*, const char*,
//----------------------------------------------------------------------------
cmGlobalGenerator::TargetDependSet const&
cmGlobalGenerator::GetTargetDepends(cmTarget const& target)
cmGlobalGenerator::GetTargetDirectDepends(cmTarget const& target)
{
// Clarify the role of the input target.
cmTarget const* depender = ⌖
......@@ -1863,6 +1862,62 @@ cmGlobalGenerator
std::back_inserter(filenames));
}
void
cmGlobalGenerator
::GetTargetSets(cmGlobalGenerator::TargetDependSet& projectTargets,
cmGlobalGenerator::TargetDependSet& originalTargets,
cmLocalGenerator* root,
std::vector<cmLocalGenerator*> const& generators)
{
// loop over all local generators
for(std::vector<cmLocalGenerator*>::const_iterator i = generators.begin();
i != generators.end(); ++i)
{
// check to make sure generator is not excluded
if(this->IsExcluded(root, *i))
{
continue;
}
cmMakefile* mf = (*i)->GetMakefile();
// Get the targets in the makefile
cmTargets &tgts = mf->GetTargets();
// loop over all the targets
for (cmTargets::iterator l = tgts.begin(); l != tgts.end(); ++l)
{
cmTarget* target = &l->second;
// put the target in the set of original targets
originalTargets.insert(target);
// Get the set of targets that depend on target
this->AddTargetDepends(target,
projectTargets);
}
}
}
void
cmGlobalGenerator::AddTargetDepends(cmTarget* target,
cmGlobalGenerator::TargetDependSet&
projectTargets)
{
// add the target itself
projectTargets.insert(target);
// get the direct depends of target
cmGlobalGenerator::TargetDependSet const& tset
= this->GetTargetDirectDepends(*target);
if(tset.size())
{
// if there are targets that depend on target
// add them and their depends as well
for(cmGlobalGenerator::TargetDependSet::const_iterator i =
tset.begin(); i != tset.end(); ++i)
{
cmTarget* dtarget = const_cast<cmTarget*>(*i);
this->AddTargetDepends(dtarget, projectTargets);
}
}
}
//----------------------------------------------------------------------------
void cmGlobalGenerator::AddToManifest(const char* config,
std::string const& f)
......@@ -1901,3 +1956,4 @@ cmGlobalGenerator::GetDirectoryContent(std::string const& dir, bool needDisk)
}
return dc;
}
......@@ -234,8 +234,9 @@ public:
// Class to track a set of dependencies.
class TargetDependSet: public std::set<cmTarget const*> {};
// what targets does the specified target depend on
TargetDependSet const& GetTargetDepends(cmTarget const& target);
// what targets does the specified target depend on directly
// via a target_link_libraries or add_dependencies
TargetDependSet const& GetTargetDirectDepends(cmTarget const& target);
const std::map<cmStdString, std::vector<cmLocalGenerator*> >& GetProjectMap()
const {return this->ProjectMap;}
......@@ -245,6 +246,15 @@ public:
void GetFilesReplacedDuringGenerate(std::vector<std::string>& filenames);
protected:
// for a project collect all its targets by following depend
// information, and also collect all the targets
void GetTargetSets(cmGlobalGenerator::TargetDependSet& projectTargets,
cmGlobalGenerator::TargetDependSet& originalTargets,
cmLocalGenerator* root,
std::vector<cmLocalGenerator*> const& generators);
void AddTargetDepends(cmTarget* target,
cmGlobalGenerator::TargetDependSet&
projectTargets);
void SetLanguageEnabledFlag(const char* l, cmMakefile* mf);
void SetLanguageEnabledMaps(const char* l, cmMakefile* mf);
......
......@@ -861,7 +861,7 @@ int cmGlobalUnixMakefileGenerator3
(target.GetMakefile()->GetLocalGenerator());
result = static_cast<int>(lg->ProgressFiles[target.GetName()].size());
TargetDependSet const& depends = this->GetTargetDepends(target);
TargetDependSet const& depends = this->GetTargetDirectDepends(target);
TargetDependSet::const_iterator i;
for (i = depends.begin(); i != depends.end(); ++i)
......@@ -898,7 +898,7 @@ cmGlobalUnixMakefileGenerator3
::AppendGlobalTargetDepends(std::vector<std::string>& depends,
cmTarget& target)
{
TargetDependSet const& depends_set = this->GetTargetDepends(target);
TargetDependSet const& depends_set = this->GetTargetDirectDepends(target);
for(TargetDependSet::const_iterator i = depends_set.begin();
i != depends_set.end(); ++i)
{
......
......@@ -45,228 +45,34 @@ void cmGlobalVisualStudio71Generator::AddPlatformDefinitions(cmMakefile* mf)
mf->AddDefinition("MSVC71", "1");
}
// Write a SLN file to the stream
void cmGlobalVisualStudio71Generator
::WriteSLNFile(std::ostream& fout,
cmLocalGenerator* root,
std::vector<cmLocalGenerator*>& generators)
{
{
// Write out the header for a SLN file
this->WriteSLNHeader(fout);
// Get the start directory with the trailing slash
std::string rootdir = root->GetMakefile()->GetStartOutputDirectory();
rootdir += "/";
bool doneAllBuild = false;
bool doneCheckBuild = false;
bool doneRunTests = false;
bool doneInstall = false;
bool doneEditCache = false;
bool doneRebuildCache = false;
bool donePackage = false;
// For each cmMakefile, create a VCProj for it, and
// add it to this SLN file
unsigned int i;
for(i = 0; i < generators.size(); ++i)
{
if(this->IsExcluded(root, generators[i]))
{
continue;
}
cmMakefile* mf = generators[i]->GetMakefile();
// Get the source directory from the makefile
std::string dir = mf->GetStartOutputDirectory();
// remove the home directory and / from the source directory
// this gives a relative path
cmSystemTools::ReplaceString(dir, rootdir.c_str(), "");
// Get the list of create dsp files names from the cmVCProjWriter, more
// than one dsp could have been created per input CMakeLists.txt file
// for each target
cmTargets &tgts = generators[i]->GetMakefile()->GetTargets();
cmTargets::iterator l = tgts.begin();
for(; l != tgts.end(); ++l)
{
// special handling for the current makefile
if(mf == generators[0]->GetMakefile())
{
dir = "."; // no subdirectory for project generated
// if this is the special ALL_BUILD utility, then
// make it depend on every other non UTILITY project.
// This is done by adding the names to the GetUtilities
// vector on the makefile
if(l->first == "ALL_BUILD" && !doneAllBuild)
{
unsigned int j;
for(j = 0; j < generators.size(); ++j)
{
cmTargets &atgts = generators[j]->GetMakefile()->GetTargets();
for(cmTargets::iterator al = atgts.begin();
al != atgts.end(); ++al)
{
if (!al->second.GetPropertyAsBool("EXCLUDE_FROM_ALL"))
{
if (al->second.GetType() == cmTarget::UTILITY ||
al->second.GetType() == cmTarget::GLOBAL_TARGET)
{
l->second.AddUtility(al->first.c_str());
}
else
{
l->second.AddLinkLibrary(al->first,cmTarget::GENERAL);
}
}
}
}
}
}
// Write the project into the SLN file
if (strncmp(l->first.c_str(), "INCLUDE_EXTERNAL_MSPROJECT", 26) == 0)
{
cmCustomCommand cc = l->second.GetPostBuildCommands()[0];
const cmCustomCommandLines& cmds = cc.GetCommandLines();
std::string project = cmds[0][0];
std::string location = cmds[0][1];
this->WriteExternalProject(fout, project.c_str(),
location.c_str(), cc.GetDepends());
}
else
{
bool skip = false;
if(l->first == "ALL_BUILD" )
{
if(doneAllBuild)
{
skip = true;
}
else
{
doneAllBuild = true;
}
}
if(l->first == CMAKE_CHECK_BUILD_SYSTEM_TARGET)
{
if(doneCheckBuild)
{
skip = true;
}
else
{
doneCheckBuild = true;
}
}
if(l->first == "INSTALL")
{
if(doneInstall)
{
skip = true;
}
else
{
doneInstall = true;
}
}
if(l->first == "RUN_TESTS")
{
if(doneRunTests)
{
skip = true;
}
else
{
doneRunTests = true;
}
}
if(l->first == "EDIT_CACHE")
{
if(doneEditCache)
{
skip = true;
}
else
{
doneEditCache = true;
}
}
if(l->first == "REBUILD_CACHE")
{
if(doneRebuildCache)
{
skip = true;
}
else
{
doneRebuildCache = true;
}
}
if(l->first == "PACKAGE")
{
if(donePackage)
{
skip = true;
}
else
{
donePackage = true;
}
}
if(!skip)
{
const char *dspname =
l->second.GetProperty("GENERATOR_FILE_NAME");
if (dspname)
{
this->WriteProject(fout, dspname, dir.c_str(),l->second);
}
}
}
}
}
// collect the set of targets for this project by
// tracing depends of all targets.
// also collect the set of targets that are explicitly
// in this project.
cmGlobalGenerator::TargetDependSet projectTargets;
cmGlobalGenerator::TargetDependSet originalTargets;
this->GetTargetSets(projectTargets,
originalTargets,
root, generators);
this->WriteTargetsToSolution(fout, root, projectTargets, originalTargets);
// Write out the configurations information for the solution
fout << "Global\n";
// Write out the configurations for the solution
this->WriteSolutionConfigurations(fout);
fout << "\tGlobalSection(" << this->ProjectConfigurationSectionName
<< ") = postSolution\n";
// loop over again and compute the depends
for(i = 0; i < generators.size(); ++i)
{
cmMakefile* mf = generators[i]->GetMakefile();
cmLocalVisualStudio7Generator* pg =
static_cast<cmLocalVisualStudio7Generator*>(generators[i]);
// Get the list of create dsp files names from the cmVCProjWriter, more
// than one dsp could have been created per input CMakeLists.txt file
// for each target
cmTargets &tgts = pg->GetMakefile()->GetTargets();
cmTargets::iterator l = tgts.begin();
std::string dir = mf->GetStartDirectory();
for(; l != tgts.end(); ++l)
{
if (strncmp(l->first.c_str(), "INCLUDE_EXTERNAL_MSPROJECT", 26) == 0)
{
cmCustomCommand cc = l->second.GetPostBuildCommands()[0];
const cmCustomCommandLines& cmds = cc.GetCommandLines();
std::string project = cmds[0][0];
this->WriteProjectConfigurations(fout, project.c_str(),
true);
}
else
{
bool partOfDefaultBuild = this->IsPartOfDefaultBuild(
root->GetMakefile()->GetProjectName(),
&l->second);
const char *dspname =
l->second.GetProperty("GENERATOR_FILE_NAME");
if (dspname)
{
this->WriteProjectConfigurations(fout, dspname,
partOfDefaultBuild);
}
}
}
}
// Write out the configurations for all the targets in the project
this->WriteTargetConfigurations(fout, root, projectTargets);
fout << "\tEndGlobalSection\n";
// Write the footer for the SLN file
this->WriteSLNFooter(fout);
}
......@@ -338,7 +144,9 @@ cmGlobalVisualStudio71Generator
if(j->first != dspname)
{
// is the library part of this SLN ? If so add dependency
if(this->FindTarget(this->CurrentProject.c_str(), j->first.c_str()))
// find target anywhere because all depend libraries are
// brought in as well
if(this->FindTarget(0, j->first.c_str()))
{
fout << "\t\t{" << this->GetGUID(j->first.c_str()) << "} = {"
<< this->GetGUID(j->first.c_str()) << "}\n";
......@@ -379,6 +187,7 @@ void cmGlobalVisualStudio71Generator
const char* location,
const std::vector<std::string>& depends)
{
std::cout << "WriteExternalProject vs71\n";
fout << "Project(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \""
<< name << "\", \""
<< this->ConvertToSolutionPath(location) << "\", \"{"
......
......@@ -56,7 +56,8 @@ protected:
virtual void WriteProjectConfigurations(std::ostream& fout,
const char* name,
bool partOfDefaultBuild);
virtual void WriteExternalProject(std::ostream& fout, const char* name,
virtual void WriteExternalProject(std::ostream& fout,
const char* name,
const char* path,
const std::vector<std::string>& depends);
virtual void WriteSLNFooter(std::ostream& fout);
......
......@@ -150,45 +150,20 @@ void cmGlobalVisualStudio7Generator::GenerateConfigurations(cmMakefile* mf)
= this->CMakeInstance->GetCacheDefinition("CMAKE_CONFIGURATION_TYPES");
if ( ct )
{
std::string configTypes = ct;
std::string::size_type start = 0;
std::string::size_type endpos = 0;
while(endpos != std::string::npos)
std::vector<std::string> argsOut;
cmSystemTools::ExpandListArgument(ct, argsOut);
for(std::vector<std::string>::iterator i = argsOut.begin();
i != argsOut.end(); ++i)
{
endpos = configTypes.find_first_of(" ;", start);
std::string config;
std::string::size_type len;
if(endpos != std::string::npos)
if(std::find(this->Configurations.begin(),
this->Configurations.end(),
*i) == this->Configurations.end())
{
len = endpos - start;
this->Configurations.push_back(*i);
}
else
{
len = configTypes.size() - start;
}
config = configTypes.substr(start, len);
if(config == "Debug" || config == "Release" ||
config == "MinSizeRel" || config == "RelWithDebInfo")
{
// only add unique configurations
if(std::find(this->Configurations.begin(),
this->Configurations.end(),
config) == this->Configurations.end())
{
this->Configurations.push_back(config);
}
}
else
{
cmSystemTools::Error(
"Invalid configuration type in CMAKE_CONFIGURATION_TYPES: ",
config.c_str(),
" (Valid types are Debug,Release,MinSizeRel,RelWithDebInfo)");
}
start = endpos+1;
}
}
// default to at least Debug and Release
if(this->Configurations.size() == 0)
{
this->Configurations.push_back("Debug");
......@@ -265,190 +240,219 @@ void cmGlobalVisualStudio7Generator::OutputSLNFile()
}
// Write a SLN file to the stream
void cmGlobalVisualStudio7Generator
::WriteSLNFile(std::ostream& fout,
cmLocalGenerator* root,
std::vector<cmLocalGenerator*>& generators)
void cmGlobalVisualStudio7Generator::AddAllBuildDepends(
cmLocalGenerator* root,
cmTarget* target,
cmGlobalGenerator::TargetDependSet& originalTargets)
{
// Write out the header for a SLN file
this->WriteSLNHeader(fout);
// Get the start directory with the trailing slash
// if this is the special ALL_BUILD utility, then
// make it depend on every other non UTILITY project.
for(cmGlobalGenerator::TargetDependSet::iterator ot =
originalTargets.begin(); ot != originalTargets.end(); ++ot)
{
cmTarget* t = const_cast<cmTarget*>(*ot);
if(!this->IsExcluded(root, *t))
{
if (t->GetType() == cmTarget::UTILITY ||
t->GetType() == cmTarget::GLOBAL_TARGET)
{
target->AddUtility(t->GetName());
}
else
{
target->AddLinkLibrary(t->GetName(),cmTarget::GENERAL);
}
}
}
}
void cmGlobalVisualStudio7Generator::WriteTargetConfigurations(
std::ostream& fout,
cmLocalGenerator* root,
cmGlobalGenerator::TargetDependSet& projectTargets)
{
// loop over again and write out configurations for each target
// in the solution
for(cmGlobalGenerator::TargetDependSet::iterator tt =
projectTargets.begin(); tt != projectTargets.end(); ++tt)
{
cmTarget* target = const_cast<cmTarget*>(*tt);
if (strncmp(target->GetName(), "INCLUDE_EXTERNAL_MSPROJECT", 26) == 0)
{
cmCustomCommand cc = target->GetPostBuildCommands()[0];
const cmCustomCommandLines& cmds = cc.GetCommandLines();
std::string project = cmds[0][0];
this->WriteProjectConfigurations(fout, project.c_str(),
true);
}
else
{
bool partOfDefaultBuild = this->IsPartOfDefaultBuild(
root->GetMakefile()->GetProjectName(), target);
const char *vcprojName =
target->GetProperty("GENERATOR_FILE_NAME");
if (vcprojName)
{
this->WriteProjectConfigurations(fout, vcprojName,
partOfDefaultBuild);
}
}
}
}
void cmGlobalVisualStudio7Generator::WriteTargetsToSolution(
std::ostream& fout,
cmLocalGenerator* root,
cmGlobalGenerator::TargetDependSet& projectTargets,
cmGlobalGenerator::TargetDependSet& originalTargets
)
{
// Create a map of project that should only show up once
// in a project
const char* onlyOnceNames[] =
{"INCLUDE_EXTERNAL_MSPROJECT","CMAKE_CHECK_BUILD_SYSTEM_TARGET",
"INSTALL", "RUN_TESTS", "EDIT_CACHE", "REBUILD_CACHE", "PACKAGE", 0};
std::map<cmStdString, int> onlyOnceMap;
int i =0;
for(const char* name = onlyOnceNames[i];
name != 0; name = onlyOnceNames[++i])
{
onlyOnceMap[name] = 0;
}
// add the CMAKE_CHECK_BUILD_SYSTEM_TARGET
onlyOnceMap[CMAKE_CHECK_BUILD_SYSTEM_TARGET] = 0;
std::string rootdir = root->GetMakefile()->GetStartOutputDirectory();
rootdir += "/";
bool doneAllBuild = false;
bool doneRunTests = false;
bool doneInstall = false;
bool doneEditCache = false;
bool doneRebuildCache = false;
bool donePackage = false;
// 1.
// Collecte all targets in generators vector and the targets
// that they depend on
// 2. loop over all targets and put .vcproj reference
// into .sln file. .vcproj files should already exist
// from local generation step. Do not add "pulled" in .vcproj
// to ALL_BUILD.
// See: cmGlobalGenerator::GetTargetDepends
// cmGlobalGenerator::TargetDependSet myset;
// foreach t in all targets
// cmGlobalGenerator::TargetDependSet const& tset = GetTargetDepends(t);
// myset.insert(tset.begin(), tset.end());
// foreach t in myset
// t->GetMakefile()->GetLocalGenerator()->GetVCProjPath()
// if t was not in original set of targets disable all for it
// For each cmMakefile, create a VCProj for it, and
// add it to this SLN file
unsigned int i;
for(i = 0; i < generators.size(); ++i)
{