1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229
|
<#
.NOTES
Summary: Windows native build script.
It does however provided the minimum necessary to support parts of local Windows
development and Windows to Windows CI.
Usage Examples (run from repo root):
"scripts/make.ps1 -Client" to build docker.exe client 64-bit binary (remote repo)
"scripts/make.ps1 -TestUnit" to run unit tests
"scripts/make.ps1 -Daemon -TestUnit" to build the daemon and run unit tests
"scripts/make.ps1 -All" to run everything this script knows about that can run in a container
"scripts/make.ps1" to build the daemon binary (same as -Daemon)
"scripts/make.ps1 -Binary" shortcut to -Client and -Daemon
.PARAMETER Binary
Builds the client and daemon binaries. A convenient shortcut to `make.ps1 -Client -Daemon`.
.PARAMETER Race
Use -race in go build and go test.
.PARAMETER Noisy
Use -v in go build.
.PARAMETER ForceBuildAll
Use -a in go build.
.PARAMETER NoOpt
Use -gcflags -N -l in go build to disable optimisation (can aide debugging).
.PARAMETER CommitSuffix
Adds a custom string to be appended to the commit ID (spaces are stripped).
.PARAMETER TestUnit
Runs unit tests.
.PARAMETER All
Runs everything this script knows about that can run in a container.
TODO
- Unify the head commit
- Add golint and other checks (swagger maybe?)
#>
param(
[Parameter(Mandatory=$False)][switch]$Binary,
[Parameter(Mandatory=$False)][switch]$Race,
[Parameter(Mandatory=$False)][switch]$Noisy,
[Parameter(Mandatory=$False)][switch]$ForceBuildAll,
[Parameter(Mandatory=$False)][switch]$NoOpt,
[Parameter(Mandatory=$False)][string]$CommitSuffix,
[Parameter(Mandatory=$False)][switch]$TestUnit,
[Parameter(Mandatory=$False)][switch]$All
)
$ErrorActionPreference = "Stop"
$ProgressPreference = "SilentlyContinue"
$pushed=$False # To restore the directory if we have temporarily pushed to one.
# Utility function to get the commit ID of the repository
Function Get-GitCommit() {
if (-not (Test-Path ".\.git")) {
# If we don't have a .git directory, but we do have the environment
# variable DOCKER_GITCOMMIT set, that can override it.
if ($env:DOCKER_GITCOMMIT.Length -eq 0) {
Throw ".git directory missing and DOCKER_GITCOMMIT environment variable not specified."
}
Write-Host "INFO: Git commit ($env:DOCKER_GITCOMMIT) assumed from DOCKER_GITCOMMIT environment variable"
return $env:DOCKER_GITCOMMIT
}
$gitCommit=$(git rev-parse --short HEAD)
if ($(git status --porcelain --untracked-files=no).Length -ne 0) {
$gitCommit="$gitCommit-unsupported"
Write-Host ""
Write-Warning "This version is unsupported because there are uncommitted file(s)."
Write-Warning "Either commit these changes, or add them to .gitignore."
git status --porcelain --untracked-files=no | Write-Warning
Write-Host ""
}
return $gitCommit
}
# Build a binary (client or daemon)
Function Execute-Build($additionalBuildTags, $directory) {
# Generate the build flags
$buildTags = "autogen"
if ($Noisy) { $verboseParm=" -v" }
if ($Race) { Write-Warning "Using race detector"; $raceParm=" -race"}
if ($ForceBuildAll) { $allParm=" -a" }
if ($NoOpt) { $optParm=" -gcflags "+""""+"-N -l"+"""" }
if ($additionalBuildTags -ne "") { $buildTags += $(" " + $additionalBuildTags) }
# Get the git commit. This will also verify if we are in a repo or not. Then add a custom string if supplied.
$gitCommit=Get-GitCommit
if ($CommitSuffix -ne "") { $gitCommit += "-"+$CommitSuffix -Replace ' ', '' }
if (Test-Path Env:\DOCKER_GITCOMMIT) {$gitCommit=$env:DOCKER_GITCOMMIT}
# Get the version of docker (eg 17.04.0-dev)
$dockerVersion="0.0.0-dev"
if (Test-Path Env:\VERSION) {$dockerVersion=$env:VERSION}
# Do the go build in the appropriate directory
# Note -linkmode=internal is required to be able to debug on Windows.
# https://github.com/golang/go/issues/14319#issuecomment-189576638
Write-Host "INFO: Building..."
$buildTime=$(Get-Date).ToUniversalTime()
$env:GO_LDFLAGS="-linkmode=internal `
-X \""github.com/docker/cli/cli/version.Version=$dockerVersion\"" `
-X \""github.com/docker/cli/cli/version.GitCommit=$gitCommit\"" `
-X \""github.com/docker/cli/cli/version.BuildTime=$buildTime\"""
if ($env:PLATFORM) {
$env:GO_LDFLAGS="$env:GO_LDFLAGS -X \""github.com/docker/cli/cli/version.PlatformName=$env:PLATFORM\"""
}
# Generate a version in the form major,minor,patch,build
$versionQuad=$dockerVersion -replace "[^0-9.]*" -replace "\.", ","
# If you really want to understand this madness below, search the Internet for powershell variables after verbatim arguments... Needed to get double-quotes passed through to the compiler options.
# Generate the .syso files containing all the resources and manifest needed to compile the final docker binaries. Both 32 and 64-bit clients.
$env:_ag_dockerVersion=$dockerVersion
$env:_ag_gitCommit=$gitCommit
New-Item -ItemType Directory -Path .\tmp -Force | Out-Null
windres -i scripts/winresources/docker.rc -o cli/winresources/rsrc_amd64.syso -F pe-x86-64 --use-temp-file -I ./tmp -D DOCKER_VERSION_QUAD=$versionQuad --% -D DOCKER_VERSION=\"%_ag_dockerVersion%\" -D DOCKER_COMMIT=\"%_ag_gitCommit%\"
if ($LASTEXITCODE -ne 0) { Throw "Failed to compile client 64-bit resources" }
windres -i scripts/winresources/docker.rc -o cli/winresources/rsrc_386.syso -F pe-i386 --use-temp-file -I ./tmp -D DOCKER_VERSION_QUAD=$versionQuad --% -D DOCKER_VERSION=\"%_ag_dockerVersion%\" -D DOCKER_COMMIT=\"%_ag_gitCommit%\"
if ($LASTEXITCODE -ne 0) { Throw "Failed to compile client 32-bit resources" }
Remove-Item .\tmp -Recurse -Force -ErrorAction SilentlyContinue | Out-Null
Push-Location $root\cmd\$directory; $global:pushed=$True
# By using --% we can use \"key=%foo%\" and have a environment variable foo that contains spaces
go build $raceParm $verboseParm $allParm $optParm -tags "$buildTags" `
-o "$root\build\$directory.exe" `
-ldflags --% "%GO_LDFLAGS%"
if ($LASTEXITCODE -ne 0) { Throw "Failed to compile" }
Pop-Location; $global:pushed=$False
}
# Run the unit tests
Function Run-UnitTests() {
Write-Host "INFO: Running unit tests..."
$testPath="./..."
$goListCommand = "go list -e -f '{{if ne .Name """ + '\"github.com/docker/cli\"' + """}}{{.ImportPath}}{{end}}' $testPath"
$pkgList = $(Invoke-Expression $goListCommand)
if ($LASTEXITCODE -ne 0) { Throw "go list for unit tests failed" }
$pkgList = $pkgList | Select-String -Pattern "github.com/docker/cli"
$pkgList = $pkgList | Select-String -NotMatch "github.com/docker/cli/vendor"
$pkgList = $pkgList | Select-String -NotMatch "github.com/docker/cli/man"
$pkgList = $pkgList | Select-String -NotMatch "github.com/docker/cli/e2e"
$pkgList = $pkgList -replace "`r`n", " "
$goTestCommand = "go test" + $raceParm + " -cover -ldflags -w -tags """ + "autogen" + """ -a """ + "-test.timeout=10m" + """ $pkgList"
Invoke-Expression $goTestCommand
if ($LASTEXITCODE -ne 0) { Throw "Unit tests failed" }
}
# Start of main code.
Try {
Write-Host -ForegroundColor Cyan "INFO: make.ps1 starting at $(Get-Date)"
# Get to the root of the repo
$root = $(Split-Path $MyInvocation.MyCommand.Definition -Parent | Split-Path -Parent)
Push-Location $root
# Handle the "-All" shortcut to turn on all things we can handle.
# Note we expressly only include the items which can run in a container - the validations tests cannot
# as they require the .git directory which is excluded from the image by .dockerignore
if ($All) { $Client=$True; $TestUnit=$True }
# Handle the "-Binary" shortcut to build both client and daemon.
if ($Binary) { $Client = $True; }
# Verify git is installed
if ($(Get-Command git -ErrorAction SilentlyContinue) -eq $nil) { Throw "Git does not appear to be installed" }
# Verify go is installed
if ($(Get-Command go -ErrorAction SilentlyContinue) -eq $nil) { Throw "GoLang does not appear to be installed" }
# Build the binaries
if ($Client) {
# Create the build directory if it doesn't exist
if (-not (Test-Path ".\build")) { New-Item ".\build" -ItemType Directory | Out-Null }
# Perform the actual build
Execute-Build "" "docker"
}
# Run unit tests
if ($TestUnit) { Run-UnitTests }
# Gratuitous ASCII art.
if ($Client) {
Write-Host
Write-Host -ForegroundColor Green " ________ ____ __."
Write-Host -ForegroundColor Green " \_____ \ `| `|/ _`|"
Write-Host -ForegroundColor Green " / `| \`| `<"
Write-Host -ForegroundColor Green " / `| \ `| \"
Write-Host -ForegroundColor Green " \_______ /____`|__ \"
Write-Host -ForegroundColor Green " \/ \/"
Write-Host
}
}
Catch [Exception] {
Write-Host -ForegroundColor Red ("`nERROR: make.ps1 failed:`n$_")
# More gratuitous ASCII art.
Write-Host
Write-Host -ForegroundColor Red "___________ .__.__ .___"
Write-Host -ForegroundColor Red "\_ _____/____ `|__`| `| ____ __`| _/"
Write-Host -ForegroundColor Red " `| __) \__ \ `| `| `| _/ __ \ / __ `| "
Write-Host -ForegroundColor Red " `| \ / __ \`| `| `|_\ ___// /_/ `| "
Write-Host -ForegroundColor Red " \___ / (____ /__`|____/\___ `>____ `| "
Write-Host -ForegroundColor Red " \/ \/ \/ \/ "
Write-Host
Throw $_
}
Finally {
Pop-Location # As we pushed to the root of the repo as the very first thing
if ($global:pushed) { Pop-Location }
Write-Host -ForegroundColor Cyan "INFO: make.ps1 ended at $(Get-Date)"
}
|