Use goversioninfo to create Windows Version Info

Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
This commit is contained in:
CrazyMax 2021-10-11 16:54:09 +02:00
parent f14d8e7051
commit 75284bd1d1
No known key found for this signature in database
GPG Key ID: 3248E46B6BB8C7F7
20 changed files with 154 additions and 88 deletions

View File

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

3
.gitignore vendored
View File

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

View File

@ -3,6 +3,7 @@
ARG BASE_VARIANT=alpine ARG BASE_VARIANT=alpine
ARG GO_VERSION=1.16.8 ARG GO_VERSION=1.16.8
ARG XX_VERSION=1.0.0-rc.2 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:${GO_VERSION}-${BASE_VARIANT} AS gostable
FROM --platform=$BUILDPLATFORM golang:1.17rc1-${BASE_VARIANT} AS golatest FROM --platform=$BUILDPLATFORM golang:1.17rc1-${BASE_VARIANT} AS golatest
@ -47,9 +48,18 @@ ARG GO_STRIP
ARG CGO_ENABLED ARG CGO_ENABLED
# VERSION sets the version for the produced binary # VERSION sets the version for the produced binary
ARG VERSION 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=from=dockercore/golang-cross:xx-sdk-extras,target=/xx-sdk,src=/xx-sdk \
--mount=type=tmpfs,target=cli/winresources \ --mount=type=tmpfs,target=cli/winresources \
# override the default behavior of go with xx-go
xx-go --wrap && \ xx-go --wrap && \
# export GOCACHE=$(go env GOCACHE)/$(xx-info)$([ -f /etc/alpine-release ] && echo "alpine") && \ # export GOCACHE=$(go env GOCACHE)/$(xx-info)$([ -f /etc/alpine-release ] && echo "alpine") && \
TARGET=/out ./scripts/build/binary && \ TARGET=/out ./scripts/build/binary && \

View File

@ -1,6 +1,10 @@
# #
# github.com/docker/cli # github.com/docker/cli
# #
# Sets the name of the company that produced the windows binary.
COMPANY_NAME ?=
all: binary all: binary
_:=$(shell ./scripts/warn-outside-container $(MAKECMDGOALS)) _:=$(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 = "" default = ""
} }
# Sets the name of the company that produced the windows binary.
variable "COMPANY_NAME" {
default = ""
}
group "default" { group "default" {
targets = ["binary"] targets = ["binary"]
} }
@ -21,6 +26,7 @@ target "binary" {
args = { args = {
BASE_VARIANT = USE_GLIBC != "" ? "buster" : "alpine" BASE_VARIANT = USE_GLIBC != "" ? "buster" : "alpine"
VERSION = VERSION VERSION = VERSION
COMPANY_NAME = COMPANY_NAME
GO_STRIP = STRIP_TARGET 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_CONTAINER_NAME ?=
DOCKER_CLI_GO_BUILD_CACHE ?= y 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) DEV_DOCKER_IMAGE_NAME = docker-cli-dev$(IMAGE_TAG)
BINARY_NATIVE_IMAGE_NAME = docker-cli-native$(IMAGE_TAG) BINARY_NATIVE_IMAGE_NAME = docker-cli-native$(IMAGE_TAG)
CROSS_IMAGE_NAME = docker-cli-cross$(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 .PHONY: binary
binary: binary:
docker buildx bake binary COMPANY_NAME=$(COMPANY_NAME) docker buildx bake binary
build: binary ## alias for binary build: binary ## alias for binary
@ -65,7 +68,7 @@ test: test-unit test-e2e
.PHONY: cross .PHONY: cross
cross: cross:
docker buildx bake cross COMPANY_NAME=$(COMPANY_NAME) docker buildx bake cross
.PHONY: plugins-windows .PHONY: plugins-windows
plugins-windows: build_cross_image ## build the example CLI plugins for 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 .PHONY: dynbinary
dynbinary: ## build dynamically linked binary 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 .PHONY: dev
dev: build_docker_image ## start a build container in interactive mode for in-container development 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/ \ --mount=type=tmpfs,target=/go/src/ \
GO111MODULE=on go install github.com/LK4D4/vndr@${VNDR_VERSION} 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 FROM golang AS dev
RUN apk add --no-cache \ RUN apk add --no-cache \
bash \ bash \
@ -32,8 +39,9 @@ CMD bash
ENV DISABLE_WARN_OUTSIDE_CONTAINER=1 ENV DISABLE_WARN_OUTSIDE_CONTAINER=1
ENV PATH=$PATH:/go/src/github.com/docker/cli/build ENV PATH=$PATH:/go/src/github.com/docker/cli/build
COPY --from=vndr /go/bin/* /go/bin/ COPY --from=vndr /go/bin/* /go/bin/
COPY --from=gotestsum /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 WORKDIR /go/src/github.com/docker/cli
ENV GO111MODULE=auto ENV GO111MODULE=auto

View File

@ -54,30 +54,19 @@ if [ -n "$GO_STRIP" ]; then
LDFLAGS="$LDFLAGS -s -w" LDFLAGS="$LDFLAGS -s -w"
fi 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}")" echo "Building $GO_LINKMODE $(basename "${TARGET}")"
export GO111MODULE=auto 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" 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"