VS: Fix subproject .sln dependencies on custom targets

Each project listed in a .sln must be marked (or not) as part of the
"default build" for each configuration.  For targets created by the
add_custom_target() command we add them to the default build if they
are not excluded in some way or if another target depends on them.
In the top-level .sln, a custom target is excluded if it is not
created with the ALL option to add_custom_target.  In subdirectory
.sln files, a target may also be excluded if it is not within the
directory and is brought into the solution only due to a dependency
from another target in the solution.

Fix the "IsPartOfDefaultBuild" and "IsDependedOn" methods to check
every target to be included in the .sln for a dependency on the
custom target.  Otherwise transitive dependencies through targets
not in the current subdirectory will not be considered.

Extend the SubProject test with a custom target to cover this case.

Reported-by: William Deurwaarder <William.Deurwaarder@tomtom.com>
Reported-by: Dirk Steenpass <dirk.steenpass@gmail.com>
This commit is contained in:
Brad King 2014-06-12 10:36:10 -04:00
parent 5fba44cf41
commit 790e167718
5 changed files with 32 additions and 35 deletions

View File

@ -392,8 +392,7 @@ void cmGlobalVisualStudio7Generator::WriteTargetConfigurations(
else else
{ {
const std::set<std::string>& configsPartOfDefaultBuild = const std::set<std::string>& configsPartOfDefaultBuild =
this->IsPartOfDefaultBuild(root->GetMakefile()->GetProjectName(), this->IsPartOfDefaultBuild(projectTargets, target);
target);
const char *vcprojName = const char *vcprojName =
target->GetProperty("GENERATOR_FILE_NAME"); target->GetProperty("GENERATOR_FILE_NAME");
if (vcprojName) if (vcprojName)
@ -981,8 +980,7 @@ cmGlobalVisualStudio7Generator
std::set<std::string> std::set<std::string>
cmGlobalVisualStudio7Generator::IsPartOfDefaultBuild( cmGlobalVisualStudio7Generator::IsPartOfDefaultBuild(
const std::string& project, OrderedTargetDependSet const& projectTargets, cmTarget const* target)
cmTarget const* target)
{ {
std::set<std::string> activeConfigs; std::set<std::string> activeConfigs;
// if it is a utilitiy target then only make it part of the // if it is a utilitiy target then only make it part of the
@ -992,7 +990,7 @@ cmGlobalVisualStudio7Generator::IsPartOfDefaultBuild(
{ {
return activeConfigs; return activeConfigs;
} }
if(type == cmTarget::UTILITY && !this->IsDependedOn(project, target)) if(type == cmTarget::UTILITY && !this->IsDependedOn(projectTargets, target))
{ {
return activeConfigs; return activeConfigs;
} }
@ -1011,33 +1009,20 @@ cmGlobalVisualStudio7Generator::IsPartOfDefaultBuild(
} }
bool bool
cmGlobalVisualStudio7Generator::IsDependedOn(const std::string& project, cmGlobalVisualStudio7Generator
::IsDependedOn(OrderedTargetDependSet const& projectTargets,
cmTarget const* targetIn) cmTarget const* targetIn)
{ {
// Get all local gens for this project for (OrderedTargetDependSet::const_iterator l = projectTargets.begin();
std::map<std::string, std::vector<cmLocalGenerator*> >::const_iterator it = l != projectTargets.end(); ++l)
this->ProjectMap.find(project);
if (it == this->ProjectMap.end())
{ {
return false; cmTarget const& target = **l;
}
// loop over local gens and get the targets for each one
for(std::vector<cmLocalGenerator*>::const_iterator geIt = it->second.begin();
geIt != it->second.end(); ++geIt)
{
cmTargets const& targets = (*geIt)->GetMakefile()->GetTargets();
for (cmTargets::const_iterator l = targets.begin();
l != targets.end(); l++)
{
cmTarget const& target = l->second;
TargetDependSet const& tgtdeps = this->GetTargetDirectDepends(target); TargetDependSet const& tgtdeps = this->GetTargetDirectDepends(target);
if(tgtdeps.count(targetIn)) if(tgtdeps.count(targetIn))
{ {
return true; return true;
} }
} }
}
return false; return false;
} }

View File

@ -164,9 +164,11 @@ protected:
std::string ConvertToSolutionPath(const char* path); std::string ConvertToSolutionPath(const char* path);
std::set<std::string> IsPartOfDefaultBuild(const std::string& project, std::set<std::string>
IsPartOfDefaultBuild(OrderedTargetDependSet const& projectTargets,
cmTarget const* target);
bool IsDependedOn(OrderedTargetDependSet const& projectTargets,
cmTarget const* target); cmTarget const* target);
bool IsDependedOn(const std::string& project, cmTarget const* target);
std::vector<std::string> Configurations; std::vector<std::string> Configurations;
std::map<std::string, std::string> GUIDMap; std::map<std::string, std::string> GUIDMap;

View File

@ -1,6 +1,15 @@
cmake_minimum_required (VERSION 2.6) cmake_minimum_required (VERSION 2.6)
project(SubProject) project(SubProject)
message("${CMAKE_IMPORT_LIBRARY_SUFFIX}") file(REMOVE ${CMAKE_CURRENT_BINARY_DIR}/gen.cxx) # require generation
add_custom_command(
OUTPUT gen.cxx
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/gen.cxx.in
COMMAND ${CMAKE_COMMAND} -E copy
${CMAKE_CURRENT_SOURCE_DIR}/gen.cxx.in gen.cxx
)
add_custom_target(gen DEPENDS gen.cxx)
add_library(bar bar.cxx) add_library(bar bar.cxx)
target_include_directories(bar PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
add_dependencies(bar gen)
add_executable(car car.cxx) add_executable(car car.cxx)
add_subdirectory(foo) add_subdirectory(foo)

View File

@ -1,4 +1 @@
int bar() #include "gen.cxx"
{
return 10;
}

View File

@ -0,0 +1,4 @@
int bar()
{
return 10;
}