build.ps1 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. #requires -version 5
  2. <#
  3. .SYNOPSIS
  4. Builds this repository.
  5. .DESCRIPTION
  6. This build script installs required tools and runs an MSBuild command on this repository.
  7. This script can be used to invoke various targets, such as targets to produce packages,
  8. build projects, run tests, and generate code.
  9. .PARAMETER RepoPath
  10. The folder to build. Defaults to the folder containing this script. This will be removed soon.
  11. .PARAMETER CI
  12. Sets up CI specific settings and variables.
  13. .PARAMETER Restore
  14. Run restore on projects.
  15. .PARAMETER Build
  16. Compile projects.
  17. .PARAMETER Pack
  18. Produce packages.
  19. .PARAMETER Test
  20. Run tests.
  21. .PARAMETER Sign
  22. Run code signing.
  23. .PARAMETER Projects
  24. A list of projects to build. Globbing patterns are supported, such as "$(pwd)/**/*.csproj"
  25. .PARAMETER All
  26. Build all project types.
  27. .PARAMETER Managed
  28. Build managed projects (C#, F#, VB).
  29. .PARAMETER Native
  30. Build native projects (C++).
  31. .PARAMETER NodeJS
  32. Build NodeJS projects (TypeScript, JS).
  33. .PARAMETER Installers
  34. Build Windows Installers. Required .NET 3.5 to be installed (WiX toolset requirement).
  35. .PARAMETER MSBuildArguments
  36. Additional MSBuild arguments to be passed through.
  37. .EXAMPLE
  38. Building both native and managed projects.
  39. build.ps1 -managed -native
  40. .EXAMPLE
  41. Building a subfolder of code.
  42. build.ps1 "$(pwd)/src/SomeFolder/**/*.csproj"
  43. .EXAMPLE
  44. Running tests.
  45. build.ps1 -test
  46. .LINK
  47. Online version: https://github.com/aspnet/AspNetCore/blob/master/docs/BuildFromSource.md
  48. #>
  49. [CmdletBinding(PositionalBinding = $false, DefaultParameterSetName='Groups')]
  50. param(
  51. # Bootstrapper options
  52. [Obsolete('This parameter will be removed when we finish https://github.com/aspnet/AspNetCore/issues/4246')]
  53. [string]$RepoRoot = $PSScriptRoot,
  54. [switch]$CI,
  55. # Build lifecycle options
  56. [switch]$Restore = $True, # Run tests
  57. [switch]$Build = $True, # Compile
  58. [switch]$Pack, # Produce packages
  59. [switch]$Test, # Run tests
  60. [switch]$Sign, # Code sign
  61. # Project selection
  62. [Parameter(ParameterSetName = 'All')]
  63. [switch]$All, # Build everything
  64. # A list of projects which should be built.
  65. [Parameter(ParameterSetName = 'Projects')]
  66. [string]$Projects,
  67. # Build a specified set of project groups
  68. [Parameter(ParameterSetName = 'Groups')]
  69. [switch]$Managed,
  70. [Parameter(ParameterSetName = 'Groups')]
  71. [switch]$Native,
  72. [Parameter(ParameterSetName = 'Groups')]
  73. [switch]$NodeJS,
  74. [Parameter(ParameterSetName = 'Groups')]
  75. [switch]$Installers,
  76. # By default, Windows builds will use MSBuild.exe. Passing this will force the build to run on
  77. # dotnet.exe instead, which may cause issues if you invoke build on a project unsupported by
  78. # MSBuild for .NET Core
  79. [switch]$ForceCoreMsbuild,
  80. # Other lifecycle targets
  81. [switch]$Help, # Show help
  82. # Capture the rest
  83. [Parameter(ValueFromRemainingArguments = $true)]
  84. [string[]]$MSBuildArguments
  85. )
  86. Set-StrictMode -Version 2
  87. $ErrorActionPreference = 'Stop'
  88. #
  89. # Functions
  90. #
  91. function Get-KoreBuild {
  92. if (!(Test-Path $LockFile)) {
  93. Get-RemoteFile "$ToolsSource/korebuild/channels/$Channel/latest.txt" $LockFile
  94. }
  95. $version = Get-Content $LockFile | Where-Object { $_ -like 'version:*' } | Select-Object -first 1
  96. if (!$version) {
  97. Write-Error "Failed to parse version from $LockFile. Expected a line that begins with 'version:'"
  98. }
  99. $version = $version.TrimStart('version:').Trim()
  100. $korebuildPath = Join-Paths $DotNetHome ('buildtools', 'korebuild', $version)
  101. if (!(Test-Path $korebuildPath)) {
  102. Write-Host -ForegroundColor Magenta "Downloading KoreBuild $version"
  103. New-Item -ItemType Directory -Path $korebuildPath | Out-Null
  104. $remotePath = "$ToolsSource/korebuild/artifacts/$version/korebuild.$version.zip"
  105. try {
  106. $tmpfile = Join-Path ([IO.Path]::GetTempPath()) "KoreBuild-$([guid]::NewGuid()).zip"
  107. Get-RemoteFile $remotePath $tmpfile
  108. if (Get-Command -Name 'Expand-Archive' -ErrorAction Ignore) {
  109. # Use built-in commands where possible as they are cross-plat compatible
  110. Expand-Archive -Path $tmpfile -DestinationPath $korebuildPath
  111. }
  112. else {
  113. # Fallback to old approach for old installations of PowerShell
  114. Add-Type -AssemblyName System.IO.Compression.FileSystem
  115. [System.IO.Compression.ZipFile]::ExtractToDirectory($tmpfile, $korebuildPath)
  116. }
  117. }
  118. catch {
  119. Remove-Item -Recurse -Force $korebuildPath -ErrorAction Ignore
  120. throw
  121. }
  122. finally {
  123. Remove-Item $tmpfile -ErrorAction Ignore
  124. }
  125. }
  126. return $korebuildPath
  127. }
  128. function Join-Paths([string]$path, [string[]]$childPaths) {
  129. $childPaths | ForEach-Object { $path = Join-Path $path $_ }
  130. return $path
  131. }
  132. function Get-RemoteFile([string]$RemotePath, [string]$LocalPath) {
  133. if ($RemotePath -notlike 'http*') {
  134. Copy-Item $RemotePath $LocalPath
  135. return
  136. }
  137. $retries = 10
  138. while ($retries -gt 0) {
  139. $retries -= 1
  140. try {
  141. $ProgressPreference = 'SilentlyContinue' # Workaround PowerShell/PowerShell#2138
  142. Invoke-WebRequest -UseBasicParsing -Uri $RemotePath -OutFile $LocalPath
  143. return
  144. }
  145. catch {
  146. Write-Verbose "Request failed. $retries retries remaining"
  147. }
  148. }
  149. Write-Error "Download failed: '$RemotePath'."
  150. }
  151. #
  152. # Main
  153. #
  154. # Load configuration or set defaults
  155. if ($Help) {
  156. Get-Help $PSCommandPath
  157. exit 1
  158. }
  159. $RepoRoot = Resolve-Path $RepoRoot
  160. $Channel = 'master'
  161. $ToolsSource = 'https://aspnetcore.blob.core.windows.net/buildtools'
  162. $ConfigFile = Join-Path $PSScriptRoot 'korebuild.json'
  163. $LockFile = Join-Path $PSScriptRoot 'korebuild-lock.txt'
  164. if (Test-Path $ConfigFile) {
  165. try {
  166. $config = Get-Content -Raw -Encoding UTF8 -Path $ConfigFile | ConvertFrom-Json
  167. if ($config) {
  168. if (!($Channel) -and (Get-Member -Name 'channel' -InputObject $config)) { [string] $Channel = $config.channel }
  169. if (!($ToolsSource) -and (Get-Member -Name 'toolsSource' -InputObject $config)) { [string] $ToolsSource = $config.toolsSource}
  170. }
  171. } catch {
  172. Write-Warning "$ConfigFile could not be read. Its settings will be ignored."
  173. Write-Warning $Error[0]
  174. }
  175. }
  176. $DotNetHome = if ($env:DOTNET_HOME) { $env:DOTNET_HOME } `
  177. elseif ($CI) { Join-Path $PSScriptRoot '.dotnet' } `
  178. elseif ($env:USERPROFILE) { Join-Path $env:USERPROFILE '.dotnet'} `
  179. elseif ($env:HOME) {Join-Path $env:HOME '.dotnet'}`
  180. else { Join-Path $PSScriptRoot '.dotnet'}
  181. $env:DOTNET_HOME = $DotNetHome
  182. # Execute
  183. $korebuildPath = Get-KoreBuild
  184. # Project selection
  185. if ($All) {
  186. $MSBuildArguments += '/p:BuildAllProjects=true'
  187. }
  188. elseif ($Projects) {
  189. if (![System.IO.Path]::IsPathRooted($Projects))
  190. {
  191. $Projects = Join-Path (Get-Location) $Projects
  192. }
  193. $MSBuildArguments += "/p:Projects=$Projects"
  194. }
  195. else {
  196. # When adding new sub-group build flags, add them to this check.
  197. if((-not $Native) -and (-not $Managed) -and (-not $NodeJS) -and (-not $Installers)) {
  198. Write-Warning "No default group of projects was specified, so building the 'managed' and 'native' subsets of projects. Run ``build.cmd -help`` for more details."
  199. # This goal of this is to pick a sensible default for `build.cmd` with zero arguments.
  200. # Now that we support subfolder invokations of build.cmd, we will be pushing to have build.cmd build everything (-all) by default
  201. $Managed = $true
  202. $Native = $true
  203. }
  204. $MSBuildArguments += "/p:BuildManaged=$Managed"
  205. $MSBuildArguments += "/p:BuildNative=$Native"
  206. $MSBuildArguments += "/p:BuildNodeJS=$NodeJS"
  207. $MSBuildArguments += "/p:BuildWindowsInstallers=$Installers"
  208. }
  209. # Target selection
  210. $MSBuildArguments += "/p:_RunRestore=$Restore"
  211. $MSBuildArguments += "/p:_RunBuild=$Build"
  212. $MSBuildArguments += "/p:_RunPack=$Pack"
  213. $MSBuildArguments += "/p:_RunTests=$Test"
  214. $MSBuildArguments += "/p:_RunSign=$Sign"
  215. Import-Module -Force -Scope Local (Join-Path $korebuildPath 'KoreBuild.psd1')
  216. try {
  217. Set-KoreBuildSettings -ToolsSource $ToolsSource -DotNetHome $DotNetHome -RepoPath $RepoRoot -ConfigFile $ConfigFile -CI:$CI
  218. if ($ForceCoreMsbuild) {
  219. $global:KoreBuildSettings.MSBuildType = 'core'
  220. }
  221. Invoke-KoreBuildCommand 'default-build' @MSBuildArguments
  222. }
  223. finally {
  224. Remove-Module 'KoreBuild' -ErrorAction Ignore
  225. }