main
  1# psake v0.11
  2# Copyright � 2008 James Kovacs
  3# Permission is hereby granted, free of charge, to any person obtaining a copy
  4# of this software and associated documentation files (the "Software"), to deal
  5# in the Software without restriction, including without limitation the rights
  6# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  7# copies of the Software, and to permit persons to whom the Software is
  8# furnished to do so, subject to the following conditions:
  9#
 10# The above copyright notice and this permission notice shall be included in
 11# all copies or substantial portions of the Software.
 12#
 13# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 14# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 15# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 16# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 17# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 18# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 19# THE SOFTWARE.
 20
 21param(
 22  [string]$buildFile = 'default.ps1',
 23  [string[]]$taskList = @(),
 24  [string]$framework = '3.5',
 25  [switch]$debug = $false,
 26  [switch]$help  = $false
 27)
 28
 29
 30
 31if($help) {
 32@"
 33psake [buildFile] [tasks] [-framework ver] [-debug]
 34  where buildFile is the name of the build file, (default: default.ps1)
 35        tasks is a list of tasks to execute from the build file,
 36        ver is the .NET Framework version to target - 1.0, 1.1, 2.0, 3.0, or 3.5
 37            3.5 is the default
 38        debug dumps information the tasks.
 39psake -help
 40  Displays this message.
 41"@
 42  return
 43}
 44
 45$global:tasks = @{}
 46$global:properties = @()
 47$script:executedTasks = New-Object System.Collections.Stack
 48$script:callStack = New-Object System.Collections.Stack
 49$originalEnvPath = $env:path
 50$originalDirectory = Get-Location
 51
 52function task([string]$name, [scriptblock]$action = $null, [string[]]$depends = @()) {
 53  if($name -eq 'default' -and $action -ne $null) {
 54    throw "Error: default task cannot specify an action"
 55  }
 56  $newTask = @{
 57    Name = $name
 58    DependsOn = $depends
 59    Action = $action
 60  }
 61  if($global:tasks.$name -ne $null) { throw "Error: Task, $name, has already been defined." }
 62  $global:tasks.$name = $newTask
 63}
 64
 65function properties([scriptblock]$propertyBlock) {
 66  $global:properties += $propertyBlock
 67}
 68
 69
 70function AssertNotCircular([string]$name) {
 71  if($script:callStack.Contains($name)) {
 72    throw "Circular reference found for task, $name"
 73  }
 74}
 75
 76function ExecuteTask([string]$name) {
 77  if($script:executedTasks.Contains($name)) { return }
 78  AssertNotCircular $name
 79  $script:callStack.Push($name)
 80  
 81  $task = $global:tasks.$name
 82  foreach($childTask in $task.DependsOn) {
 83    ExecuteTask $childTask
 84  }
 85  if($name -ne 'default') {
 86    Write-Host "Executing task, $name..."
 87    if($task.Action -ne $null) {
 88      & $task.Action
 89    }
 90    Write-Host "`n"
 91  }
 92  
 93  $poppedTask = $script:callStack.Pop()
 94  if($poppedTask -ne $name) {
 95    throw "CallStack was corrupt. Expected $name, but got $poppedTask."
 96  }
 97  $script:executedTasks.Push($name)
 98}
 99
100function DumpTasks {
101  Write-Host 'Dumping tasks:'
102  foreach($key in $global:tasks.Keys) {
103    $task = $global:tasks.$key;
104    $task.Name + " depends on " + $task.DependsOn.Length + " other tasks: " + $task.DependsOn;
105  }
106  Write-Host "`n"
107}
108
109function DumpProperties {
110  Write-Host 'Dumping properties:'
111  $global:properties
112}
113
114function ConfigureEnvForBuild {
115  $version = $null
116  switch ($framework) {
117    '1.0' { $version = 'v1.0.3705'  }
118    '1.1' { $version = 'v1.1.4322'  }
119    '2.0' { $version = 'v2.0.50727' }
120    '3.0' { $version = 'v2.0.50727' } # .NET 3.0 uses the .NET 2.0 compilers
121    '3.5' { $version = 'v3.5'       }
122    default { throw "Error: Unknown .NET Framework version, $framework" }
123  }
124  $frameworkDir = "$env:windir\Microsoft.NET\Framework\$version\"
125  if(!(test-path $frameworkDir)) {
126    throw "Error: No .NET Framework installation directory found at $frameworkDir"
127  }
128  $env:path = "$frameworkDir;$env:path"
129}
130
131function Cleanup {
132  $env:path = $originalEnvPath
133  $global:tasks = $null
134  Set-Location $originalDirectory
135}
136
137function RunBuild {
138  # Faking a finally block
139  trap {
140    Write-Host -foregroundcolor Red $_
141    Cleanup
142    break
143  }
144
145  # Execute the build file to set up the tasks and defaults
146  if(test-path $buildFile) {
147    $buildFile = resolve-path $buildFile
148    set-location (split-path $buildFile)
149    & $buildFile
150  } else {
151    throw "Error: Could not find the build file, $buildFile."
152  }
153
154  if($debug) {
155    DumpProperties
156    DumpTasks
157  }
158
159  ConfigureEnvForBuild
160
161
162  foreach($propertyBlock in $global:properties) {
163    . $propertyBlock
164  }
165
166
167  # Execute the list of tasks or the default task
168  if($taskList.Length -ne 0) {
169    foreach($task in $taskList) {
170      ExecuteTask $task
171    }
172  } elseif ($global:tasks.default -ne $null) {
173    EXecuteTask default
174  }
175
176  # Clear out any global variables
177  Cleanup
178}
179
180# Avoids printing of error dump with line numbers
181trap {
182 # continue
183}
184
185RunBuild
186