How do I change the startup project of a Visual Studio solution via CMake?

Visual StudioCmakeStartupVisual Studio-Project

Visual Studio Problem Overview


I am using CMake to generate Visual Studio projects. Everything works fine except one thing.

The startup project in the solution is always ALL_BUILD. How do I change the startup project to the real project I want via CMake?

Visual Studio Solutions


Solution 1 - Visual Studio

CMake now supports this with versions 3.6 and higher through the VS_STARTUP_PROJECT directory property:

cmake_minimum_required(VERSION 3.6)
project(foo)
# ...

add_executable(bar ${BAR_SOURCES})
set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT bar)

This will set bar as the startup project for the foo.sln solution.

Solution 2 - Visual Studio

You can't. The startup-project is stored in a binary file, which is NOT generated by CMake. Without that binary file, visual studio will default to the first project in the solution file and the ALL_BUILD project is always first...

Update: this answer is "out-of-date" since it is now feasible with CMake 3.6. See the answer by ComicSansMS.

Solution 3 - Visual Studio

Since Visual 2005, the configuration is stored in a file name projectname.vc(x)proj.user, which is plain xml.

I don't know about a way to change the startup project, but you certainly can set ALL_BUILD to run the desired executable instead of displaying the stupid popup :

create_default_target_launcher(
    your_desired_target_name
    WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/desired_path/"
    # or ${CMAKE_CURRENT_BINARY_DIR}, depending on your setup
)

This module is available on rpavlik's github. You simply need to add this in your topmost CMakeLists.txt :

list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/external/rpavlik-cmake-modules-1c73e35") # or whichever path you put the module in.
include(CreateLaunchers)

Examples available here.

Solution 4 - Visual Studio

If you can't allow a perl dependency like me, I just wrote a little command line utility for windows called slnStartupProject to solve this. It sets the Startup Project automatically like this:

slnStartupProject slnFilename projectName

I personally use it to set the project after generating the solution with cmake that always sets a dummy ALL_BUILD project as the first project in the solution.

The source is on github:

https://github.com/michaKFromParis/slnStartupProject

Forks and feedbacks are welcome.

Hope this helps!

Solution 5 - Visual Studio

It is correct that the explicit choice the user makes when hitting "Set as startup project" in IDE is stored in a binary file. But I found somewhere else that Visual Studio takes the first Project in the solution as an implicit Startup Project when first opening a solution, so CMake does have an influence on this.

Our problem now: ALL_BUILD is always the first project. To change this, I am running a short perl script after CMake that cuts the desired project definition out of the file and pastes it into the front. Path to solution file in first parameter, project name in second:

use strict;
use File::Spec;

# variables
my $slnPath = File::Spec->rel2abs($ARGV[0]);
my $projectName = $ARGV[1];
my $contents;
my $header;
my $project;
my $GUID = "[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}";
my $fh;

# read file content (error if not found)
print "Setting \"$projectName\" as Startup Project in \"$slnPath\"...\n";
die "Error: path \"$slnPath\" not found!\n" if not -f $slnPath;
open($fh, "<", $slnPath) or die "Error: cannot read $slnPath: $!";
$contents = do { local $/; <$fh> };
close($fh) or warn "close failed: $!";

# extract part before Projects definition section (the first mention of "Project([GUID])")
$header = $1 if $contents =~ s{(.*?(?=Project\("\{${GUID}\}"\)))}{}si;

# extract definition of the project specified (error if not found)
$project = $1 if $contents =~ s{(Project\("\{${GUID}\}"\) = \"${projectName}\".*?EndProject\s)}{}si;
die "Error: Project not found!\n" if not defined $project or not length $project;

# write header, project definition and remaining content back into the file
`attrib -R "$slnPath"`;
open($fh, ">", $slnPath) or die "Error: cannot write to $slnPath: $!";
print $fh $header, $project, $contents;
close($fh) or warn "close failed: $!";

print "Successfully done.\n";

Once the solution has been opened, the implicit startup project is saved in the binary file and thus becomes explicit, so this even survives a CMake rerun (e.g. triggered by ZERO-CHECK, which doesn't allow post-execution). In the same way, anm explicit user choice is also preserved.

(Written and tested on Win7 machine with ActiveState Perl)

Solution 6 - Visual Studio

With cmake 3.5, the startup project (for VS 2010) can be changed with

SET(CMAKE_DEFAULT_STARTUP_PROJECT myFavoriteProject)

in the main CMakeLists.txt of the project. By default, it is set to ALL_BUILD.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestiongiggleView Question on Stackoverflow
Solution 1 - Visual StudioComicSansMSView Answer on Stackoverflow
Solution 2 - Visual StudioAndréView Answer on Stackoverflow
Solution 3 - Visual StudioCalvin1602View Answer on Stackoverflow
Solution 4 - Visual StudiomichaKView Answer on Stackoverflow
Solution 5 - Visual StudioSvenSView Answer on Stackoverflow
Solution 6 - Visual StudiomtartarView Answer on Stackoverflow