Skip to content

Parallel Builds

Roman Kuzmin edited this page Apr 17, 2014 · 9 revisions

The script Invoke-Builds.ps1 is used in order to invoke several builds at the same time. It should be located in the same directory as Invoke-Build.ps1. Invoked builds should be independent and should not share any resources simultaneously. Other restrictions are mentioned below.

Any number of builds is allowed, including 0 and 1, though normally there are two or more builds. Maximum number of parallel builds is limited by the number of processors by default and can be changed by the parameter.

Every script is invoked in its own runspace, as if PowerShell is just started. That is why build scripts should configure environment for their tasks on their own. A calling script cannot do this. But it can prepare and pass some data in build scripts via parameters.

Builds are specified by hashtables where Task, File, and Parameters entries correspond to the Invoke-Build parameters with the same names. The extra entry Log tells to write build output to the specified file.


Example

Five parallel builds are invoked with various combinations of build parameters. Note that it is fine to reference a build script more than once if build flows specified by different tasks do not conflict:

Invoke-Builds @(
    @{File='Project1.build.ps1'}
    @{File='Project2.build.ps1'; Task='MakeHelp'}
    @{File='Project2.build.ps1'; Task='Build', 'Test'}
    @{File='Project3.build.ps1'; Log='C:\TEMP\Project3.log'}
    @{File='Project4.build.ps1'; Parameters=@{Configuration='Release'}}
)

Build order is unknown

Build logs are shown in the same order as builds are specified in the list. But the order of start and completion times is not known or guaranteed to be always the same. That is why builds in the build list should be independent.

For instance, the above example is not composed correctly if Project4 depends on Project1, that is build of Project1 should be completed before build of Project4 starts. This order is not guaranteed. Besides, build of Project4 is always performed in the example, even if build of Project1 fails.


Avoid host cmdlets and UI members

Any user interaction and use of host cmdlets and UI members should be removed from scripts designed for parallel builds.

Alternatively, scripts may be prepared to work in standard and parallel modes differently. A good way is to use a script parameter telling what the current mode is (say, the switch -Parallel used on calls by Invoke-Builds).

But a simple trick is enough now: check the host name. If it is Default Host then host cmdlets and members should be avoided, replaced with something else, or redefined. Write-Host, for example, can be redefined for doing nothing.

# Define empty Write-Host for "Default Host"
if ($Host.Name -eq "Default Host") {
    function Write-Host {}
}

There are more things to avoid in parallel builds. Unfortunately it is not that easy to list them all. Just one example: Out-String does not work properly if strict mode is enabled with some hosts, see Connect.