Python function for building .NET 2003 Solutions

David Blume dblume at pinnaclesys.com
Thu Jun 10 16:18:41 EDT 2004


I'm very grateful to Roger Burnham for his Visual Studio 6.0 build
script listed here: 
http://mail.python.org/pipermail/python-list/2001-December/076881.html

Now that I'm building projects in .NET 2003, I thought I'd post an
update to his DoBuild() function that does the same thing with
Solutions.  Note the differences:

1. Instead of having a RebuildAll() function, we have to Clean() then
Build().  This function does the cleaning of all the targets in one
pass, then the building of all the targets, in case some targets share
dependencies.
2. On a compile-time error, instead of raising SystemExit, which is
much cleaner, this script returns the BuildLog.htm of the component
that failed.  (Which may not have been the target that was built, but
a sub-project.)  I didn't really know how to determine exactly which
subproject failed, so I parse the contents of the output window to
find it.  (VC6 is much easier, the .plg file showed the build status
of the target and all its dependencies.)

Anyway, here's BuildSolution() with similar parameters as Roger's
DoBuild().  Please fix any line-wrapping errors that have occurred
between my sending of the post and your reception of it.  Sorry about
those.

import win32com.client.dynamic
import string
import pywintypes
import win32clipboard
import win32con

def BuildSolution(VC, solution, projectList, configSuffix, force):
  """Build Visual C++ 7.1 Solutions

  returns None if successful, or the build log if 
  there were compile time errors."""
  if VC is None:
    VC = win32com.client.Dispatch('VisualStudio.DTE')
    VC.MainWindow.Visible = True
  VCDocs = VC.Documents
  VCDocs.CloseAll(3)

  sln = VC.Solution
  sln.Open(solution)
  slnBuild = sln.SolutionBuild
  tailLen = len(configSuffix)
  # First, clean everything if doing a forced rebuild
  if force:
    for projectName in projectList:
      for project in sln.Projects:
        if str(project.Name) == projectName:
          for config in slnBuild.SolutionConfigurations:
            name = str(config.Name)
            if name[-tailLen:] == configSuffix:
              for context in config.SolutionContexts:
                if projectName + "." in context.ProjectName:
                  context.ShouldBuild = True
              break
        break
    slnBuild.Clean(True)
  # Then, build the specified projects
  for projectName in projectList:
    projFound = 0
    for project in sln.Projects:
      if str(project.Name) == projectName:
        projFound = 1
        for config in slnBuild.SolutionConfigurations:
          confFound = 0
          name = str(config.Name)
          if name[-tailLen:] == configSuffix:
            confFound = 1
            slnBuild.BuildProject(config.Name, project.UniqueName,
True)
            if slnBuild.BuildState == 3:
              if slnBuild.LastBuildInfo != 0:
                print 'There were', slnBuild.LastBuildInfo, 'errors
building', projectName + '.\n'
                # We have to jump through some hoops to determine
which
                # subproject actually failed, because the BuildLog.htm
                # associated with this target does not reflect the
                # compiled state of the subprojects.Here's what we do:
                # 1. Obtain the OutputWindow from MSDev.
                # 2. Copy the text to the clipboard, and extract that
                #    into a "lines" array.
                # 3. Search for lines containing the word "error" and
                #    assume that's the first failed project.
                # 4. Extract and return the filename of the
                #    BuildLog.htm for the assumed failed project.
                outputPane =
VC.Windows.Item('{34E76E81-EE4A-11D0-AE2E-00A0C90FFFC3}').Object.ActivePane
# vsWindowKindOutput
                outputPane.TextDocument.Selection.SelectAll()
                outputPane.TextDocument.Selection.Copy()
                outputPane = None
                win32clipboard.OpenClipboard(0)
                lines =
win32clipboard.GetClipboardData(win32con.CF_TEXT)
                win32clipboard.CloseClipboard()
                bFoundErrorMessages = False
                LogfileString = "Build log was saved at \"file://"
                for line in string.split(lines, "\n"):
                  if not bFoundErrorMessages and line.find(" : error
") != -1:
                    print "This is the first error:"
                    print line + "\n"
                    bFoundErrorMessages = True
                  if bFoundErrorMessages and
line.startswith(LogfileString):
                    return line[len(LogfileString):line.rfind('"')]
                raise "Could not locate the failing project's
logfile."
            else:
              raise "BuildProject is returning asynchronously!"
            break
        if not confFound:
          print 'Build failed: Could not find the', configSuffix,
'for', projectName + '.'
        break
    if not projFound:
      print 'Build failed: Could not find the project', projectName +
'.'
  return None



More information about the Python-list mailing list