[CMake] Making ALL_BUILD be Visual Studio's "startup project"

David.Karr at L-3COM.COM David.Karr at L-3COM.COM
Mon Nov 24 14:22:22 EST 2008



In a certain project where we started using CMake about five years ago,
it used to be that when we opened the Visual Studio 6.0 workspace
created by CMake, the ALL_BUILD project was conveniently defined as the
"startup project" already, meaning that all one had to do was to click
the "Build" button (or press F7) to build the entire workspace.  (OK,
the project probably should have used at least Visual Studio .NET by
that time, but that's another story entirely.)

I've noticed that in Visual Studio 7.0 (.NET) and later, ALL_BUILD is no
longer defined as the default startup project.

It is not vital to my project that ALL_BUILD be the startup project by
default, but it was convenient (at least saving a few mouse clicks to
change that setting).  I think I know why this "broke" and at least one
way to "fix" it.  Is this something other people would find useful?  If
so, keep reading.


As it turns out, the behavior that I thought was so convenient in the
workspace generated for VS 6.0 appears to be an accident.  In
cmGlobalVisualStudio6Generator.cxx, ALL_BUILD and the other projects are
stored in an std::map (typedef'd cmTargets) whose key is the name of the
project.  The iterator over this map visits the targets in lexical
order, in which it just happened that ALL_BUILD was first among all the
target names in my project (not hard to do when the name starts "AL").
Hence it gets listed first in the workspace.  And apparently Visual
Studio sets the first project in the workspace as the "startup project"
by default.

In cmGlobalVisualStudio7Generator.cxx, on the other hand, the projects
are stored in a cmGlobalGenerator::TargetDependSet, which it turns out
is really an std::set of pointers to the targets.  Again, the first
project listed in the workspace (or rather the "solution") is the
startup project, and again the iterator visits the targets in sequence,
only this time I believe the first target visited is whichever one is
closest to the start of virtual memory.  Generally, this is not
ALL_BUILD.

It turns out to be fairly simple to force the ALL_BUILD project to be
first in the workspace/solution.  (Unfortunately there are two
independent code changes needed if this is to be done for both the VS6
and VS7 generators, due to the completely different data structures
used, and the new code would be more efficient for the VS7 generator if
it used an std::map rather than std::set).

The fix is to modify the function that actually writes the
workspace/solution file so that instead of just iterating over targets,
it looks for the ALL_BUILD target first, does what it needs to do for
that target, then iterates through all the targets EXCEPT the ALL_BUILD
target.  I have versions of cmGlobalVisualStudio7Generator.cxx and
cmGlobalVisualStudio7Generator.h that do this; the change to each file
is highly localized.  I suppose with a little more effort (and almost as
simple a change in the code) one could make this happen only if
requested, for example by SET(CMAKE_DEFAULT_STARTUP_PROJECT ALL_BUILD),
which would let you choose a different default startup project if you
like.

So, the question: Does anyone want this?

David Karr



More information about the CMake mailing list