VS: Add option to choose the `.sln` startup project (#15578)

Add a `VS_STARTUP_PROJECT` directory property to specify the project
that should be placed first in the `.sln` file so that it will be
selected as the default startup project.

Co-Author: Taylor Braun-Jones <taylor.braunjones@avigilon.com>
This commit is contained in:
Davy Durham 2016-03-17 16:12:02 -04:00 committed by Brad King
parent 5c1f4da83d
commit 78ec046130
13 changed files with 80 additions and 1 deletions

View File

@ -76,6 +76,7 @@ Properties on Directories
/prop_dir/VARIABLES
/prop_dir/VS_GLOBAL_SECTION_POST_section
/prop_dir/VS_GLOBAL_SECTION_PRE_section
/prop_dir/VS_STARTUP_PROJECT
.. _`Target Properties`:

View File

@ -0,0 +1,12 @@
VS_STARTUP_PROJECT
------------------
Specify the default startup project in a Visual Studio solution.
The property must be set to the name of an existing target. This
will cause that project to be listed first in the generated solution
file causing Visual Studio to make it the startup project if the
solution has never been opened before.
If this property is not specified, then the "ALL_BUILD" project
will be the default.

View File

@ -0,0 +1,6 @@
vs-startup-project
------------------
* The :ref:`Visual Studio Generators` learned to honor a new
:prop_dir:`VS_STARTUP_PROJECT` directory property that specifies
the default startup project for generated solutions (``.sln`` files).

View File

@ -94,7 +94,8 @@ void cmGlobalVisualStudio71Generator
TargetDependSet projectTargets;
TargetDependSet originalTargets;
this->GetTargetSets(projectTargets, originalTargets, root, generators);
OrderedTargetDependSet orderedProjectTargets(projectTargets, "ALL_BUILD");
OrderedTargetDependSet orderedProjectTargets(
projectTargets, this->GetStartupProjectName(root));
this->WriteTargetsToSolution(fout, root, orderedProjectTargets);

View File

@ -518,6 +518,32 @@ cmGlobalVisualStudioGenerator::GetUtilityDepend(
return i->second;
}
//----------------------------------------------------------------------------
std::string
cmGlobalVisualStudioGenerator::GetStartupProjectName(
cmLocalGenerator const* root) const
{
const char* n = root->GetMakefile()->GetProperty("VS_STARTUP_PROJECT");
if (n && *n)
{
std::string startup = n;
if (this->FindTarget(startup))
{
return startup;
}
else
{
root->GetMakefile()->IssueMessage(
cmake::AUTHOR_WARNING,
"Directory property VS_STARTUP_PROJECT specifies target "
"'" + startup + "' that does not exist. Ignoring.");
}
}
// default, if not specified
return this->GetAllTargetName();
}
//----------------------------------------------------------------------------
#include <windows.h>

View File

@ -106,6 +106,8 @@ public:
void ComputeTargetObjectDirectory(cmGeneratorTarget* gt) const;
std::string GetStartupProjectName(cmLocalGenerator const* root) const;
void AddSymbolExportCommand(
cmGeneratorTarget*, std::vector<cmCustomCommand>& commands,
std::string const& configName);

View File

@ -8,3 +8,5 @@ run_cmake(MorePost)
run_cmake(PrePost)
run_cmake(Override1)
run_cmake(Override2)
run_cmake(StartupProject)
run_cmake(StartupProjectMissing)

View File

@ -0,0 +1,4 @@
getFirstProject(first_project StartupProject)
if(NOT first_project STREQUAL "TestStartup")
error("TestStartup is not the startup project")
endif()

View File

@ -0,0 +1,2 @@
add_custom_target(TestStartup)
set_property(DIRECTORY PROPERTY VS_STARTUP_PROJECT "TestStartup")

View File

@ -0,0 +1,4 @@
getFirstProject(first_project StartupProjectMissing)
if(NOT first_project STREQUAL "ALL_BUILD")
error("ALL_BUILD is not the startup project")
endif()

View File

@ -0,0 +1,4 @@
^CMake Warning \(dev\) in CMakeLists.txt:
Directory property VS_STARTUP_PROJECT specifies target 'DoesNotExist' that
does not exist. Ignoring.
This warning is for project developers. Use -Wno-dev to suppress it.$

View File

@ -0,0 +1 @@
set_property(DIRECTORY PROPERTY VS_STARTUP_PROJECT "DoesNotExist")

View File

@ -50,6 +50,20 @@ macro(parseGlobalSections arg_out_pre arg_out_post testName)
endmacro()
macro(getFirstProject arg_out_first_project testName)
set(${arg_out_first_project} "")
set(sln "${RunCMake_TEST_BINARY_DIR}/${testName}.sln")
if(NOT EXISTS "${sln}")
error("Expected solution file ${sln} does not exist")
endif()
file(STRINGS "${sln}" project_lines REGEX "^Project\\(")
list(GET project_lines 0 first_project)
string(REGEX REPLACE ".* = \"" "" first_project "${first_project}")
string(REGEX REPLACE "\", .*" "" first_project "${first_project}")
set(${arg_out_first_project} "${first_project}")
endmacro()
macro(testGlobalSection prefix sectionName)
if(NOT DEFINED ${prefix}_${sectionName})
error("Section ${sectionName} does not exist")