psbuild/MRPP_PSBuild.xml (31 lines of code) (raw):
<?xml version="1.0" encoding="UTF-8"?>
<meta-runner name="PSBuild">
<description>A PowerShell wrapper for msbuild with OOB suuport for versioning.</description>
<settings>
<parameters>
<param name="mr.PSBuild.WorkingDirectory" value="" spec="text description='Change working directory. Relative from checkout dir.' display='normal' label='Working Directory:'" />
<param name="mr.PSBuild.BuildFile" value="" spec="text description='The specified path should be relative to the checkout directory.' display='normal' label='Build File (path):' validationMode='not_empty'" />
<param name="mr.PSBuild.MSBuild.Version" value="4.5" spec="select data_1='2.0' data_2='3.5' data_3='4.0' data_4='4.5' description='MSBuild version. Determines, along with bitness, the path to msbuild.exe' display='normal' label='MSBuild Version:'" />
<param name="mr.PSBuild.MSBuild.Bitness" value="x86" spec="select data_1='x64' data_2='x86' description='MSBuild bitness. Determines, along with version, the path to msbuild.exe' display='normal' label='Bitness:'" />
<param name="mr.PSBuild.MSBuild.ToolsVersion" value="12" spec="select data_1='' data_2='2.0' data_3='3.5' data_4='4.0' data_5='12.0' label_1='use project file' description='MSBuild ToolsVersion.' display='normal' label='MSBuild ToolsVersion:'" />
<param name="mr.PSBuild.MSBuild.Targets" value="" spec="text description='Builds the specified targets in the project instead of the default target. Use a semicolon or comma to separate multiple targets.' display='normal' label='Targets:'" />
<param name="mr.PSBuild.MSBuild.Configuration" value="" spec="text description='Configuration to build. Debug and Release are supported OOB. Leave blank to use default.' display='normal' label='Configuration:'" />
<param name="mr.PSBuild.MSBuild.Properties" value="" spec="text description='Set or override the specified project-level properties. Use a semicolon to separate multiple properties. e.g. name=value' display='normal' label='MSBuild Properties:'" />
<param name="mr.PSBuild.MSBuild.Arguments" value="" spec="text description='Any other arguments that will be passed to msbuild.exe (e.g. /m as an example)' display='normal' label='MSBuild Arguments:'" />
<param name="mr.PSBuild.Version" value="" spec="text description='Optional common assembly version (support for both semver and major.minor.build.revision). If set it will add/update assembly attributes of choice during build.' display='normal' label='Assembly Version:'" />
<param name="mr.PSBuild.AssemblyAttributesFormat" value="" spec="text description='Controls which assembly attributes gets updated with version information.' display='normal' label='Version Attributes:'" />
<param name="mr.PSBuild.AssemblyInformationFileLocation" value="" spec="text description='By default files named AssemblyInfo.cs will be found at any level. This lets you override that.' display='normal' label='Assembly Information File(s) Location:'" />
<param name="mr.PSBuild.Debug" value="SilentlyContinue" spec="checkbox checkedValue='Continue' description='Log debug messages?' display='normal' label='Debug:' uncheckedValue='SilentlyContinue'" />
<param name="mr.PSBuild.Verbose" value="SilentlyContinue" spec="checkbox checkedValue='Continue' description='Log verbose messages?' display='normal' label='Verbose:' uncheckedValue='SilentlyContinue'" />
</parameters>
<build-runners>
<runner name="PSBuild" type="jetbrains_powershell">
<parameters>
<param name="jetbrains_powershell_execution" value="PS1" />
<param name="jetbrains_powershell_minVersion" value="3.0" />
<param name="jetbrains_powershell_noprofile" value="true" />
<param name="jetbrains_powershell_errorToError" value="error" />
<param name="jetbrains_powershell_script_mode" value="CODE" />
<param name="jetbrains_powershell_bitness" value="x86" />
<param name="teamcity.step.mode" value="default" />
<param name="jetbrains_powershell_script_code">
<![CDATA[
function Invoke-MSBuild {
[CmdletBinding()]
param()
begin {
Write-Verbose $("{0} [EXEC]" -f $MyInvocation.MyCommand)
if([String]::IsNullOrWhiteSpace($mr.WorkingDirectory) -eq $false) {
Write-Debug "Changing working directory:"
Set-Location $mr.WorkingDirectory
Write-Debug $mr.WorkingDirectory
}
}
process {
$msbuild_exe = Get-MSBuild
$build_file = Get-BuildFile
$arguments = @()
$arguments += $build_file
$tools_version = Get-ToolsVersion
if($tools_version) {
$arguments += $("/tv:{0}" -f $tools_version)
}
$targets = $mr.MSBuild.Targets
if($targets) {
$arguments += $("/t:{0}" -f $targets)
}
$configuration = $mr.MSBuild.Configuration
if($configuration) {
$arguments += $("/p:Configuration={0}" -f $configuration)
}
$properties = $mr.MSBuild.Properties
if($properties) {
$arguments += $("/p:{0}" -f $properties)
}
$msbuild_arguments += $mr.MSBuild.Arguments -split ' '
foreach($arg in $msbuild_arguments) {
$arguments += $arg
}
Invoke-Executable $msbuild_exe $arguments -Before {Before-MSBuild} -After {After-MSBuild}
}
}
function Before-MSBuild {
begin {Write-Verbose $("{0} [EXEC]" -f $MyInvocation.MyCommand)}
process {
Get-AssemblyInformationFiles | % {
Write-Debug $_.FullName
Update-AssemblyInformation $_
} -Begin {Write-Debug "Updating assembly information files:"}
}
end {
if($TeamCityMode) {
Write-Host "##teamcity[blockOpened name='MSBuild']"
}
}
}
function After-MSBuild {
begin {
if($TeamCityMode) {
Write-Host "##teamcity[blockClosed name='MSBuild']"
}
Write-Verbose $("{0} [EXEC]" -f $MyInvocation.MyCommand)
}
process {
$mr.TempFiles.Values | % {
Write-Debug $("{0} (source/original)" -f $_.Original_FilePath)
Write-Debug $("{0} (dest/temp)" -f $_.Temp_FilePath)
Move-Item -Path $_.Original_FilePath -Destination $_.Temp_FilePath -Force:$true
} -Begin {Write-Debug "Restoring assembly information files:"}
}
}
function Invoke-Executable {
param(
[Parameter(ValueFromPipeline=$true)]
[String]$Exe,
[Array]$Parameters = @(),
[ScriptBlock]$Before = {},
[ScriptBlock]$After = {}
)
begin {
Write-Verbose $("{0} [EXEC]" -f $MyInvocation.MyCommand)
Write-Debug $("Invoking '{0}'" -f $Exe)
$Parameters | % {Write-Debug $_} -Begin {Write-Debug "With arguments:"}
}
process {
& $Before
& $Exe $Parameters | Out-String
$success = $?
if($success -eq $false) {
throw $("failed to execute {0}" -f $Exe)
}
& $After
}
}
function Get-AssemblyInformationFiles {
begin {Write-Verbose $("{0} [EXEC]" -f $MyInvocation.MyCommand)}
process {
if([String]::IsNullOrWhiteSpace($mr.Version) -eq $false) {
$assemblyinfo_pattern = $mr.AssemblyInformationFileLocation
$arguments = @{}
if([String]::IsNullOrWhiteSpace($assemblyinfo_pattern)) {
$arguments.Recurse = $true
$arguments.Path = "AssemblyInfo.cs"
} else {
$arguments.Path = $assemblyinfo_pattern
}
Write-Debug "Invoking 'Get-ChildItem'"
$arguments.Keys | % { Write-Debug $("-{0}:{1}" -f $_,$arguments[$_])} -Begin {Write-Debug "With arguments:" }
return Get-ChildItem @arguments
}
Write-Debug "No global version information available. Interpreted as skip assembly version update."
return @()
}
}
function Update-AssemblyInformation {
param(
$File
)
begin {
Write-Verbose $("{0} [EXEC]" -f $MyInvocation.MyCommand)
$Version = $($mr.Version -split '\+' -split '-')
$SemVer = $Version -is [Array]
if($SemVer) {
Write-Debug $("SemVer detected ({0})" -f $mr.Version)
$Version = $Version[0]
}
if([String]::IsNullOrWhiteSpace($mr.AssemblyAttributesFormat)) {
Write-Debug "No attributes specified. Using defaults."
$mr.AssemblyAttributesFormat = "AssemblyVersion;AssemblyFileVersion"
if($SemVer) {
Write-Debug "Adding SemVer compatible attribute."
$mr.AssemblyAttributesFormat += ";AssemblyInformationalVersion"
}
}
if($mr.ContainsKey("TempFiles") -eq $false) {
$mr.TempFiles = @{}
}
}
process {
$original_file = Copy-Item $File -Destination $(Join-Path $File.DirectoryName ([System.IO.Path]::GetRandomFileName())) -PassThru
$mr.TempFiles.Add($file.FullName, @{
Original_FilePath = $original_file.FullName
Temp_FilePath = $File.FullName
})
Write-Debug $("Original File: {0}" -f $original_file.FullName)
Write-Debug $("Temporary File: {0}" -f $File.FullName)
$attributes = $mr.AssemblyAttributesFormat -split ';'
$attributes | % {
Write-Debug $_
$pattern = $('^\[assembly\: {0}\(".*\)\]' -f $_)
$content = Get-Content $File
$custom_version = $($_ -split '=')
if($custom_version -is [Array]) {
Write-Debug "custom version detected"
$_ = $custom_version[0]
$v = $custom_version[1];
}
else {
if($_ -eq "AssemblyInformationalVersion" -and $SemVer) {
Write-Debug "semver + supported semver attribute detected"
$v = $mr.Version
} else {
$v = $Version
}
}
if($content -match $pattern) {
Write-Debug $("updating attribute {0} with {1}" -f $_,$v)
$content -replace $pattern, $('[assembly: {0}("{1}")]' -f $_, $v) | Set-Content -Path:$File
} else {
Write-Debug $("adding new attribute {0} with {1}" -f $_,$v)
Add-Content $File $('[assembly: {0}("{1}")]' -f $_, $v)
}
} -Begin {Write-Debug "Updating attributes:"}
}
end {
if($TeamCityMode) {
Write-Host "##teamcity[message text='Assembly Information Updated']"
}
}
}
function Get-ToolsVersion {
begin {
Write-Verbose $("{0} [EXEC]" -f $MyInvocation.MyCommand)
Write-Debug $("MSBuild ToolsVersion={0}" -f $mr.MSBuild.ToolsVersion)
}
process {
$match = Get-ChildItem -Path $("HKLM:\Software\Microsoft\MSBuild\ToolsVersions\{0}" -f $mr.MSBuild.ToolsVersion) -ErrorAction:SilentlyContinue
if($match -eq $null) {
throw $("ToolsVersion {0} is missing. You may be able to resolve this by installing the appropriate .NET Framework version." -f $mr.MSBuild.ToolsVersion)
}
return $mr.MSBuild.ToolsVersion
}
}
function Get-MSBuild {
begin {
Write-Verbose $("{0} [EXEC]" -f $MyInvocation.MyCommand)
if([String]::IsNullOrWhiteSpace($mr.MSBuild.Version)) {
Write-Debug "MSBuild version has not been configured. The default value will be used."
$mr.MSBuild.Version = "4.5"
}
if([String]::IsNullOrWhiteSpace($mr.MSBuild.Bitness)) {
Write-Debug "MSBuild bitness has not been configured. The default value will be used."
$mr.MSBuild.Bitness = "x86"
}
Write-Debug $("MSBuild Version={0}" -f $mr.MSBuild.Version)
Write-Debug $("Bitness={0}" -f $mr.MSBuild.Bitness)
}
process {
$key = $("DotNetFramework{0}_{1}_Path" -f $mr.MSBuild.Version, $mr.MSBuild.Bitness)
$msbuild_path = Get-TeamCityParameter $key | Join-Path -ChildPath "msbuild.exe"
Write-Debug $("MSBuild Path={0}" -f $msbuild_path)
if(Test-Path $msbuild_path -PathType:Leaf) {
return $msbuild_path
}
throw $("{0} doesn't exist" -f $msbuild_path)
}
}
function Get-BuildFile {
begin {
Write-Verbose $("{0} [EXEC]" -f $MyInvocation.MyCommand)
Write-Debug $("BuildFile Path={0}" -f $mr.BuildFile)
}
process {
if(Test-Path $mr.BuildFile -PathType:Leaf) {
return $mr.BuildFile
}
throw $("can't find '{0}'" -f $mr.BuildFile)
}
}
function Get-TeamCityParameter {
param(
[String]$Key
)
begin {
Write-Verbose $("{0} [EXEC]" -f $MyInvocation.MyCommand)
Write-Debug $("Requested Parameter={0}" -f $Key)
}
process {
$v = $mr.MSBuild.Paths[$Key]
return $v
}
}
function Invoke-Exit {
param(
[Int]$ExitCode
)
[System.Environment]::Exit($ExitCode)
}
function Set-PSConsole {
try {
$max = $host.UI.RawUI.MaxPhysicalWindowSize
if($max) {
$host.UI.RawUI.BufferSize = New-Object System.Management.Automation.Host.Size(9999,9999)
$host.UI.RawUI.WindowSize = New-Object System.Management.Automation.Host.Size($max.Width,$max.Height)
}
} catch {}
}
function Resolve-TeamCityParameters {
begin {
Write-Verbose $("{0} [EXEC]" -f $MyInvocation.MyCommand)
$mr.MSBuild.Paths = @{}
}
process {
$mr.MSBuild.Paths["DotNetFramework4.5_x64_Path"] = "%DotNetFramework4.5_x64_Path%"
$mr.MSBuild.Paths["DotNetFramework4.5_x86_Path"] = "%DotNetFramework4.5_x86_Path%"
$mr.MSBuild.Paths["DotNetFramework4.0_x64_Path"] = "%DotNetFramework4.0_x64_Path%"
$mr.MSBuild.Paths["DotNetFramework4.0_x86_Path"] = "%DotNetFramework4.0_x86_Path%"
$mr.MSBuild.Paths["DotNetFramework3.5_x64_Path"] = "%DotNetFramework3.5_x64_Path%"
$mr.MSBuild.Paths["DotNetFramework3.5_x86_Path"] = "%DotNetFramework3.5_x86_Path%"
$mr.MSBuild.Paths["DotNetFramework2.0_x64_Path"] = "%DotNetFramework2.0_x64_Path%"
$mr.MSBuild.Paths["DotNetFramework2.0_x86_Path"] = "%DotNetFramework2.0_x86_Path%"
}
}
$mr = @{
MSBuild = @{
Version = "%mr.PSBuild.MSBuild.Version%"
Bitness = "%mr.PSBuild.MSBuild.Bitness%"
ToolsVersion = "%mr.PSBuild.MSBuild.ToolsVersion%"
Targets = "%mr.PSBuild.MSBuild.Targets%"
Configuration = "%mr.PSBuild.MSBuild.Configuration%"
Properties = "%mr.PSBuild.MSBuild.Properties%"
Arguments = "%mr.PSBuild.MSBuild.Arguments%"
}
BuildFile = "%mr.PSBuild.BuildFile%"
Version = "%mr.PSBuild.Version%"
AssemblyAttributesFormat = "%mr.PSBuild.AssemblyAttributesFormat%"
AssemblyInformationFileLocation = "%mr.PSBuild.AssemblyInformationFileLocation%"
WorkingDirectory = "%mr.PSBuild.WorkingDirectory%"
}
$VerbosePreference = "%mr.PSBuild.Verbose%"
$DebugPreference = "%mr.PSBuild.Debug%"
$TeamCityMode = if($env:TEAMCITY_VERSION) {$true} else {$false}
if ($TeamCityMode) {
Set-PSConsole
Resolve-TeamCityParameters
}
try {
Invoke-MSBuild -ea:Stop
} catch {
Write-Error $_
Invoke-Exit 1
}
]]>
</param>
</parameters>
</runner>
</build-runners>
<requirements />
</settings>
</meta-runner>