Merge pull request #3310 from crazy-max/goversioninfo

Use goversioninfo to create Windows version info
This commit is contained in:
Sebastiaan van Stijn 2021-10-11 18:53:39 +02:00 committed by GitHub
commit 053056660e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 154 additions and 88 deletions

View File

@ -4,4 +4,6 @@
.gitignore
appveyor.yml
build
/cli/winresources/versioninfo.json
/cli/winresources/*.syso
/vndr.log

3
.gitignore vendored
View File

@ -8,7 +8,8 @@
Thumbs.db
.editorconfig
/build/
cli/winresources/rsrc_*.syso
/cli/winresources/versioninfo.json
/cli/winresources/*.syso
/man/man1/
/man/man5/
/man/man8/

View File

@ -3,6 +3,7 @@
ARG BASE_VARIANT=alpine
ARG GO_VERSION=1.16.8
ARG XX_VERSION=1.0.0-rc.2
ARG GOVERSIONINFO_VERSION=v1.3.0
FROM --platform=$BUILDPLATFORM golang:${GO_VERSION}-${BASE_VARIANT} AS gostable
FROM --platform=$BUILDPLATFORM golang:1.17rc1-${BASE_VARIANT} AS golatest
@ -47,9 +48,18 @@ ARG GO_STRIP
ARG CGO_ENABLED
# VERSION sets the version for the produced binary
ARG VERSION
RUN --mount=ro --mount=type=cache,target=/root/.cache \
# COMPANY_NAME sets the company that produced the windows binary
ARG COMPANY_NAME
# GOVERSIONINFO_VERSION defines goversioninfo tool version
ARG GOVERSIONINFO_VERSION
RUN --mount=type=cache,target=/root/.cache \
# install goversioninfo tool
GO111MODULE=auto go install github.com/josephspurrier/goversioninfo/cmd/goversioninfo@${GOVERSIONINFO_VERSION}
RUN --mount=type=bind,target=.,ro \
--mount=type=cache,target=/root/.cache \
--mount=from=dockercore/golang-cross:xx-sdk-extras,target=/xx-sdk,src=/xx-sdk \
--mount=type=tmpfs,target=cli/winresources \
# override the default behavior of go with xx-go
xx-go --wrap && \
# export GOCACHE=$(go env GOCACHE)/$(xx-info)$([ -f /etc/alpine-release ] && echo "alpine") && \
TARGET=/out ./scripts/build/binary && \

View File

@ -1,6 +1,10 @@
#
# github.com/docker/cli
#
# Sets the name of the company that produced the windows binary.
COMPANY_NAME ?=
all: binary
_:=$(shell ./scripts/warn-outside-container $(MAKECMDGOALS))

View File

@ -1,16 +0,0 @@
/*Package winresources is used to embed Windows resources into docker.exe.
These resources are used to provide
* Version information
* An icon
* A Windows manifest declaring Windows version support
The resource object files are generated when building with scripts/build/binary .
The resource source files are located in scripts/winresources.
This occurs automatically when you run scripts/build/windows.
These object files are picked up automatically by go build when this package
is included.
*/
package winresources

View File

@ -0,0 +1,11 @@
// Package winresources is used to embed Windows resources into docker.exe.
//
// These resources are used to provide:
// * Version information
// * An icon
// * A Windows manifest declaring Windows version support
//
// The resource object files are generated when building with goversioninfo
// in scripts/build/binary and are located in cmd/docker/winresources.
// This occurs automatically when you build against Windows OS.
package winresources

View File

@ -1,3 +0,0 @@
package main
import _ "github.com/docker/cli/cli/winresources"

View File

@ -0,0 +1,8 @@
//go:build windows && 386
// +build windows,386
//go:generate goversioninfo -o=../../cli/winresources/resource.syso -icon=winresources/docker.ico -manifest=winresources/docker.exe.manifest ../../cli/winresources/versioninfo.json
package main
import _ "github.com/docker/cli/cli/winresources"

View File

@ -0,0 +1,8 @@
//go:build windows && amd64
// +build windows,amd64
//go:generate goversioninfo -64=true -o=../../cli/winresources/resource.syso -icon=winresources/docker.ico -manifest=winresources/docker.exe.manifest ../../cli/winresources/versioninfo.json
package main
import _ "github.com/docker/cli/cli/winresources"

View File

@ -0,0 +1,8 @@
//go:build windows && arm
// +build windows,arm
//go:generate goversioninfo -arm=true -o=../../cli/winresources/resource.syso -icon=winresources/docker.ico -manifest=winresources/docker.exe.manifest ../../cli/winresources/versioninfo.json
package main
import _ "github.com/docker/cli/cli/winresources"

View File

@ -0,0 +1,8 @@
//go:build windows && arm64
// +build windows,arm64
//go:generate goversioninfo -arm=true -64=true -o=../../cli/winresources/resource.syso -icon=winresources/docker.ico -manifest=winresources/docker.exe.manifest ../../cli/winresources/versioninfo.json
package main
import _ "github.com/docker/cli/cli/winresources"

View File

Before

Width:  |  Height:  |  Size: 100 KiB

After

Width:  |  Height:  |  Size: 100 KiB

View File

@ -10,6 +10,11 @@ variable "STRIP_TARGET" {
default = ""
}
# Sets the name of the company that produced the windows binary.
variable "COMPANY_NAME" {
default = ""
}
group "default" {
targets = ["binary"]
}
@ -21,6 +26,7 @@ target "binary" {
args = {
BASE_VARIANT = USE_GLIBC != "" ? "buster" : "alpine"
VERSION = VERSION
COMPANY_NAME = COMPANY_NAME
GO_STRIP = STRIP_TARGET
}
}

View File

@ -9,6 +9,9 @@ DOCKER_CLI_MOUNTS ?= -v "$(CURDIR)":/go/src/github.com/docker/cli
DOCKER_CLI_CONTAINER_NAME ?=
DOCKER_CLI_GO_BUILD_CACHE ?= y
# Sets the name of the company that produced the windows binary.
COMPANY_NAME ?=
DEV_DOCKER_IMAGE_NAME = docker-cli-dev$(IMAGE_TAG)
BINARY_NATIVE_IMAGE_NAME = docker-cli-native$(IMAGE_TAG)
CROSS_IMAGE_NAME = docker-cli-cross$(IMAGE_TAG)
@ -44,7 +47,7 @@ DOCKER_RUN := docker run --rm $(ENVVARS) $(DOCKER_CLI_MOUNTS) $(DOCKER_RUN_NAME_
.PHONY: binary
binary:
docker buildx bake binary
COMPANY_NAME=$(COMPANY_NAME) docker buildx bake binary
build: binary ## alias for binary
@ -65,7 +68,7 @@ test: test-unit test-e2e
.PHONY: cross
cross:
docker buildx bake cross
COMPANY_NAME=$(COMPANY_NAME) docker buildx bake cross
.PHONY: plugins-windows
plugins-windows: build_cross_image ## build the example CLI plugins for Windows
@ -77,7 +80,7 @@ plugins-osx: build_cross_image ## build the example CLI plugins for macOS
.PHONY: dynbinary
dynbinary: ## build dynamically linked binary
USE_GLIBC=1 docker buildx bake dynbinary
USE_GLIBC=1 COMPANY_NAME=$(COMPANY_NAME) docker buildx bake dynbinary
.PHONY: dev
dev: build_docker_image ## start a build container in interactive mode for in-container development

View File

@ -19,6 +19,13 @@ RUN --mount=type=cache,target=/root/.cache/go-build \
--mount=type=tmpfs,target=/go/src/ \
GO111MODULE=on go install github.com/LK4D4/vndr@${VNDR_VERSION}
FROM golang AS goversioninfo
ARG GOVERSIONINFO_VERSION=v1.3.0
RUN --mount=type=cache,target=/root/.cache/go-build \
--mount=type=cache,target=/go/pkg/mod \
--mount=type=tmpfs,target=/go/src/ \
GO111MODULE=on go install github.com/josephspurrier/goversioninfo/cmd/goversioninfo@${GOVERSIONINFO_VERSION}
FROM golang AS dev
RUN apk add --no-cache \
bash \
@ -32,8 +39,9 @@ CMD bash
ENV DISABLE_WARN_OUTSIDE_CONTAINER=1
ENV PATH=$PATH:/go/src/github.com/docker/cli/build
COPY --from=vndr /go/bin/* /go/bin/
COPY --from=gotestsum /go/bin/* /go/bin/
COPY --from=vndr /go/bin/* /go/bin/
COPY --from=gotestsum /go/bin/* /go/bin/
COPY --from=goversioninfo /go/bin/* /go/bin/
WORKDIR /go/src/github.com/docker/cli
ENV GO111MODULE=auto

View File

@ -54,30 +54,19 @@ if [ -n "$GO_STRIP" ]; then
LDFLAGS="$LDFLAGS -s -w"
fi
if [ "$(go env GOOS)" = "windows" ]; then
: "${WINDRES=$($(go env CC) --print-prog-name=windres)}"
if [ -z "$WINDRES" ]; then
>&2 echo "Empty WINDRES detected, skipping manifesting binary"
else
# Generate a Windows file version of the form major,minor,patch,build
VERSION_QUAD=$(printf "%s" "$VERSION" | sed -re 's/^([0-9.]*).*$/\1/' | tr . , | sed -re 's/,$//' | sed -re 's/^[0-9]+$/\0,0/' | sed -re 's/^[0-9]+,[0-9]+$/\0,0/' | sed -re 's/^[0-9]+,[0-9]+,[0-9]+$/\0,0/')
set --
[ -n "$VERSION" ] && set -- "$@" -D "DOCKER_VERSION=\"$VERSION\""
[ -n "$VERSION_QUAD" ] && set -- "$@" -D "DOCKER_VERSION_QUAD=$VERSION_QUAD"
[ -n "$GITCOMMIT" ] && set -- "$@" -D "DOCKER_COMMIT=\"$GITCOMMIT\""
target="$(dirname "$0")/../../cli/winresources/rsrc_$(go env GOARCH).syso"
mkdir -p "$(dirname "${target}")"
"$WINDRES" -i "$(dirname "$0")/../winresources/docker.rc" -o "$target" --use-temp-file "$@"
echo "package winresources" > "$(dirname "${target}")/stub_windows.go"
fi
fi
echo "Building $GO_LINKMODE $(basename "${TARGET}")"
export GO111MODULE=auto
go build -o "${TARGET}" -tags "${GO_BUILDTAGS}" --ldflags "${LDFLAGS}" ${GO_BUILDMODE} "${SOURCE}"
if [ "$(go env GOOS)" = "windows" ]; then
if [ ! -x "$(command -v goversioninfo)" ]; then
>&2 echo "goversioninfo not found, skipping manifesting binary"
else
./scripts/build/mkversioninfo
(set -x ; go generate -v "${SOURCE}")
fi
fi
(set -x ; go build -o "${TARGET}" -tags "${GO_BUILDTAGS}" --ldflags "${LDFLAGS}" ${GO_BUILDMODE} "${SOURCE}")
ln -sf "$(basename "${TARGET}")" "$(dirname "${TARGET}")/docker"

60
scripts/build/mkversioninfo Executable file
View File

@ -0,0 +1,60 @@
#!/usr/bin/env sh
set -eu
: "${COMPANY_NAME=}"
. ./scripts/build/.variables
# Create version quad for Windows of the form major.minor.patch.build
VERSION_QUAD=$(printf "%s" "$VERSION" | sed -re 's/^([0-9.]*).*$/\1/' | sed -re 's/\.$//' | sed -re 's/^[0-9]+$/\0\.0/' | sed -re 's/^[0-9]+\.[0-9]+$/\0\.0/' | sed -re 's/^[0-9]+\.[0-9]+\.[0-9]+$/\0\.0/')
# Generate versioninfo.json to be able to create a syso file which contains
# Microsoft Windows Version Information and an icon using goversioninfo.
# https://docs.microsoft.com/en-us/windows/win32/menurc/stringfileinfo-block
# https://github.com/josephspurrier/goversioninfo/blob/master/testdata/resource/versioninfo.json
cat > ./cli/winresources/versioninfo.json <<EOL
{
"FixedFileInfo":
{
"FileVersion": {
"Major": $(echo "$VERSION_QUAD" | cut -d. -f1),
"Minor": $(echo "$VERSION_QUAD" | cut -d. -f2),
"Patch": $(echo "$VERSION_QUAD" | cut -d. -f3),
"Build": $(echo "$VERSION_QUAD" | cut -d. -f4)
},
"FileFlagsMask": "3f",
"FileFlags ": "00",
"FileOS": "040004",
"FileType": "01",
"FileSubType": "00"
},
"StringFileInfo":
{
"Comments": "",
"CompanyName": "${COMPANY_NAME}",
"FileDescription": "Docker Client",
"FileVersion": "${VERSION_QUAD}",
"InternalName": "",
"LegalCopyright": "Copyright © 2015-$(date +'%Y') Docker Inc.",
"LegalTrademarks": "",
"OriginalFilename": "$(basename "${TARGET}")",
"PrivateBuild": "",
"ProductName": "Docker Client",
"ProductVersion": "${VERSION}",
"SpecialBuild": "${GITCOMMIT}"
},
"VarFileInfo":
{
"Translation": {
"LangID": "0409",
"CharsetID": "04B0"
}
}
}
EOL
(set -x ; cat ./cli/winresources/versioninfo.json)
# Create winresources package stub if removed while using tmpfs in Dockerfile
if [ ! -f "./cli/winresources/winresources.go" ]; then
echo "package winresources" > "./cli/winresources/winresources.go"
fi

View File

@ -1,38 +0,0 @@
// Application icon
1 ICON "docker.ico"
// Windows executable manifest
1 24 /* RT_MANIFEST */ "docker.exe.manifest"
// Version information
1 VERSIONINFO
#ifdef DOCKER_VERSION_QUAD
FILEVERSION DOCKER_VERSION_QUAD
PRODUCTVERSION DOCKER_VERSION_QUAD
#endif
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "000004B0"
BEGIN
VALUE "ProductName", DOCKER_NAME
#ifdef DOCKER_VERSION
VALUE "FileVersion", DOCKER_VERSION
VALUE "ProductVersion", DOCKER_VERSION
#endif
#ifdef DOCKER_COMMIT
VALUE "OriginalFileName", DOCKER_COMMIT
#endif
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x0000, 0x04B0
END
END

View File

@ -1,3 +0,0 @@
#define DOCKER_NAME "Docker Client"
#include "common.rc"