September 30, 2003
New versions of Fast Solution Build may be found on http://workspacewhiz.com/ in the Other Add-ins section.
The transition from Visual C++ 6 to Visual Studio .NET resulted in multi-project solutions building quite a bit slower than their Visual C++ 6 counterpart workspaces. This appears due to very slow visual "dependency checking" for every project of the solution. This add-in is a solution to that problem.
Fast Solution Build emulates the Visual C++ 6 build style, in that it only builds those projects with changes. It builds on the concepts from the original Fast Project Build VBScript macro, while providing more ease of use and error checking. In addition, the Run (Debug) command is now available.
New in Version 2.20 is support for incremental linking a multi-project solution. Visual C++ does not seem to support incremental linking when a file in a library project has changed. In fact, when examining the output after turning on the verbose linker output, it appears to be nearly identical to a full link. Fast Solution Build enables incremental linking support for all projects in the solution. It is amazing how quickly links perform when they are incremental.
See the Known Issues and Known Bugs sections for additional details around the conditions where multi-project incremental linking works.
Please note: Fast Solution Build is unable to support fast dependency checking for any other .NET language due to limitations in the Visual Studio.NET automation interface. It is highly recommended a makefile system is employed to speed up your builds.
Debug.Start
is available through the Run Active Project
command. Unlike Debug.Start
, a slow full solution dependency check is
not performed.The installer will ask whether multi-project incremental linking should be turned on by default. The answer is solely based on the needs of your project. There should be no problem turning on the incremental linking support. A project or configuration in a project can turn off incremental linking support as needed.
Please note: Fast Solution Build's multi-project incremental linking support is only available if the project has incremental linking turned on in the first place.
Under normal circumstances, it is okay to accept the keyboard binding defaults offered when Visual Studio .NET starts up for the first time after installing Fast Solution Build. These defaults correspond to the Visual C++ 6 equivalents of the commands.
In the event the defaults can't be accepted, the following instructions may be followed for setting up your own key bindings.
Tools->Options->Keyboard
.Save As
button and name your key bindings.Show commands containing:
, type FastSolutionBuild
.FastProjectBuild.Connect.BuildActiveProject
.Press shortcut key(s)
.F7
(or your desired key).Assign
.FastProjectBuild.Connect.DebugActiveProject
.Press shortcut key(s)
.F5
(or your desired key).Assign
.OK
.The bold project in the Solution Explorer is the top-level
project built by the Fast Solution Build macro. To make a different project
the "startup" project, right click on the desired project and choose
Set as StartUp Project
.
Run Fast Solution Build's BuildActiveProject
or
DebugActiveProject
commands from the Tools menu or press the keyboard key
assigned to the add-in commands.
There are two ways to enable multi-project incremental linking. The
first involves setting Fast Solution Build to always attempt a
multi-project incremental link. Choose Yes to the installation dialog
asking whether multi-project incremental linking should be on by default, or
navigate in the registry to the key HKEY_CURRENT_USER\Software\Fast
Solution Build
and change the DefaultIncrementalLink
value
to 1.
If multi-project incremental linking is not on by default, a special file
enabling the incremental link needs to exist in the
same directory as the main executable or DLL .vcproj
. This
file is named MainExecutableProject.vcprojFSB
file. If this
file is empty, support for multi-project incremental linking is turned on.
The .vcprojFSB
file can be populated with configuration
information. The first line must be:
VERSION=1
The only understood key at this point is IncrementalLink
.
This key may be followed by a true or a false, dependent on whether incremental
linking should be on.
IncrementalLink=true
If a key is to be accepted only for a given solution configuration, the configuration name followed by a colon may precede the key.
Release:IncrementalLink=false
The first time you link with Fast Solution Build's BuildActiveProject
command, a full link will be performed. Thereafter, a faster incremental
link will be used. Note that if you ever use Visual Studio .NET's Build
commands, the multi-project incremental link will not work.
When linking, a file called MainExecutableProject.vcproj.rsp
is
created. It is purposely not destroyed after the build finishes.
This file contains all the .obj files to perform the executable's link.
This list can, at your discretion, be inserted into the Command Line Linker
options in Visual Studio .NET.
Fast Solution Build is a C++/ATL enhanced version of the VBScript Fast Project Build macro. It demonstrates many add-in concepts learned while developing the Workspace Whiz add-in for Visual Studio .NET. Most importantly, it illustrates the steps I have discovered to solidly run an add-in.
Fast Solution Build is a dual add-in, working simultaneously under Visual Studio.NET 2002 and 2003. It does so through a lot of internal code duplication, and while this isn't the most desirable implementation, it is very effective. The binary distribution of Fast Solution Build consists of one .dll and a redirecting link executable.
First, Fast Solution Build is fully capable of installing and uninstalling
itself through just a regsvr32
call. Especially when
debugging, it is far more
convenient to not run an installer for add-in
installations and uninstallations. In AddIn.cpp
,
DllRegisterServer()
handles registering the server and hooking up the
add-in's registry entries. The critical registry keys are at
HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\7.0\AddIns\FastSolutionBuild.Connect
and HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\7.0\PreloadAddinState
(in Visual Studio 7.1, the 7.0
in the registry key is merely changed to
7.1
).
The PreloadAddinState
key tells Visual Studio .NET to force
creation of the add-in commands. Usually, VS .NET caches the add-in
commands and toolbar entries. Unfortunately, it doesn't do a very good job
of it and often loses the settings for them. Also, separate registry keys
are stored down per 7.0 and 7.1 build for default incremental linking support.
DllUnregisterServer()
illustrates a couple important functions.
First, the add-in registry keys are removed, including GUIDs, typelibs, etc.
Finally, Fast Solution Build actually connects with the VS .NET DTE COM object and
removes its registered commands. It does this for both the
VisualStudio.DTE.7
and VisualStudio.DTE.7.1
ProgIDs. If the add-in created a toolbar (Fast
Solution Build just adds commands to the Tools menu), this is an appropriate
place to remove the toolbar, too.
The CConnect::OnConnection()
code is quite a bit different from
the boilerplate AppWizard generated code. It performs the following steps:
m_pDTE
and m_pAddInInstance
are set to
NULL
. While developing Workspace Whiz, VS .NET called the
OnConnection()
function more than once without calling
OnDisconnection()
. Setting these values to NULL
ensures double OnConnection()
calls don't crash.CommandBars
object, for instance, results in Visual Studio
throwing an exception, instead of returning a proper error code. A
similar thing happens when trying to add a named command to the Commands
object. Even though you can successfully retrieve the Commands
object, called AddNamedCommand()
also causes Visual Studio to
throw an exception.
OnConnection()
again with a ConnectMode
of 5
(which causes recreation of the toolbar items and add-in commands). This
check force recreates the commands, making the assumption they aren't there.OnDisconnection()
not being called.
Whole VS .NET crashes would result. Fast Solution Build unregisters the
event handlers before it registers them.Fast Solution Build implements two commands, BuildActiveProject
and DebugActiveProject
. CConnect::Exec()
identifies the proper command and routes accordingly.
In a nutshell, BuildActiveProject
works by performing the
following steps. The whole process is actually a lot more complex than
this, though.
BuildActiveProject
exits.
GetOutputWindowPane()
. It is cleared and some informational build text is displayed.
EnvDTE
objects can't be retrieved, BuildActiveProject
exits with an error.CComSafeArray
. If you attach a SAFEARRAY
to a CComSafeArray
and don't intend it to be destroyed, be sure to detach it
or CComSafeArray
will destroy it!.obj
files are
generated based on the VCFileConfiguration
object. The
list of .obj
files are critical for the incremental linker to
work. By providing the list of .obj
files before the
.lib
files, the linker can successfully incrementally link..vcprojFSB
file is read..obj
files are
written to the file ProjectName.vcproj.rsp
.LINK.exe
, it runs Fast
Solution Build's copy.LINK.exe
prepends the linker
response file ProjectName.vcproj.rsp
onto the Linker command
line. It looks up the location of Visual Studio .NET's LINK.exe
and executes it.
LINK.exe
, because the IDE provides no way of prepending linker response
files onto the command-line.VCConfiguration.UpToDate
property is obtained.
This is truly where all the magic happens. It seems as if the Build Solution
command
ignores the UpToDate
property and calls Build
all
the time. In fact, without the check for UpToDate
in Fast
Solution Build, the macro behaves no different than Build Solution
!RunActiveProject
expands on BuildActiveProject
by
doing the following extra items:
Debug.Start
is fired, to simulate the
Debug
menu's Continue
behavior when stepping or at a
breakpoint.Finally, Fast Solution Build wedges itself into a couple BuildEvents
.
When OnBuildProjConfigDone
is triggered, Fast Solution Build checks
for any errors during the current project's build. If it finds any, it
aborts the rest of the build through the Build.Cancel
command.
When OnBuildDone
is triggered and no build errors occurred,
Debug.Start
is called, causing the debugger to become active.
The following "issues" aren't actually issues at all. In fact, if an executable application didn't have any library projects and all files were in the master project, these same issues would occur during the executable link. They are described here so a better understanding may be had of the causes.
.lib
based link, the linker tends to ignore
duplicate symbols residing in subsequently linked .lib
files.
When using an .obj
based link, the link is treated as if it was
one big library. Duplicate symbols may not exist in the same library.
Likewise, duplicate symbols may not exist in the current Fast Solution
Build incremental link..obj
-based
incremental link. Stub in the function bodies, and the link will work
fine..obj
file, it is considered for the
link.Please report any comments, bugs, or fixes to jjensen@workspacewhiz.com.
Thanks,
Joshua Jensen
Author, Fast Solution Build
http://workspacewhiz.com/
30 Sep 2003 - Version 2.20
20 Mar 2003 - Version 2.10
10 Feb 2003 - Version 2.03
4 Feb 2003 - Version 2.02
5 Dec 2002 - Version 2.01
4 Dec 2002 - Version 2.00