From 75284bd1d1ac3bb3f9c4e4467990f253e7f3f3dc Mon Sep 17 00:00:00 2001 From: CrazyMax Date: Mon, 11 Oct 2021 16:54:09 +0200 Subject: [PATCH] Use goversioninfo to create Windows Version Info Signed-off-by: CrazyMax --- .dockerignore | 2 + .gitignore | 3 +- Dockerfile | 12 +++- Makefile | 4 ++ cli/winresources/res_windows.go | 16 ----- cli/winresources/winresources.go | 11 ++++ cmd/docker/docker_windows.go | 3 - cmd/docker/docker_windows_386.go | 8 +++ cmd/docker/docker_windows_amd64.go | 8 +++ cmd/docker/docker_windows_arm.go | 8 +++ cmd/docker/docker_windows_arm64.go | 8 +++ .../docker}/winresources/docker.exe.manifest | 0 .../docker}/winresources/docker.ico | Bin docker-bake.hcl | 6 ++ docker.Makefile | 9 ++- dockerfiles/Dockerfile.dev | 12 +++- scripts/build/binary | 31 +++------ scripts/build/mkversioninfo | 60 ++++++++++++++++++ scripts/winresources/common.rc | 38 ----------- scripts/winresources/docker.rc | 3 - 20 files changed, 154 insertions(+), 88 deletions(-) delete mode 100644 cli/winresources/res_windows.go create mode 100644 cli/winresources/winresources.go delete mode 100644 cmd/docker/docker_windows.go create mode 100644 cmd/docker/docker_windows_386.go create mode 100644 cmd/docker/docker_windows_amd64.go create mode 100644 cmd/docker/docker_windows_arm.go create mode 100644 cmd/docker/docker_windows_arm64.go rename {scripts => cmd/docker}/winresources/docker.exe.manifest (100%) rename {scripts => cmd/docker}/winresources/docker.ico (100%) create mode 100755 scripts/build/mkversioninfo delete mode 100644 scripts/winresources/common.rc delete mode 100644 scripts/winresources/docker.rc diff --git a/.dockerignore b/.dockerignore index 1718dd67c2..9a78d381c3 100644 --- a/.dockerignore +++ b/.dockerignore @@ -4,4 +4,6 @@ .gitignore appveyor.yml build +/cli/winresources/versioninfo.json +/cli/winresources/*.syso /vndr.log diff --git a/.gitignore b/.gitignore index c479555c88..8a2dcbf68e 100644 --- a/.gitignore +++ b/.gitignore @@ -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/ diff --git a/Dockerfile b/Dockerfile index 63e6ba8faf..76c93aca08 100644 --- a/Dockerfile +++ b/Dockerfile @@ -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 && \ diff --git a/Makefile b/Makefile index e476f21af9..b478b14ef6 100644 --- a/Makefile +++ b/Makefile @@ -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)) diff --git a/cli/winresources/res_windows.go b/cli/winresources/res_windows.go deleted file mode 100644 index 033995d0bc..0000000000 --- a/cli/winresources/res_windows.go +++ /dev/null @@ -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 diff --git a/cli/winresources/winresources.go b/cli/winresources/winresources.go new file mode 100644 index 0000000000..f6a63b7773 --- /dev/null +++ b/cli/winresources/winresources.go @@ -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 diff --git a/cmd/docker/docker_windows.go b/cmd/docker/docker_windows.go deleted file mode 100644 index 88ac499486..0000000000 --- a/cmd/docker/docker_windows.go +++ /dev/null @@ -1,3 +0,0 @@ -package main - -import _ "github.com/docker/cli/cli/winresources" diff --git a/cmd/docker/docker_windows_386.go b/cmd/docker/docker_windows_386.go new file mode 100644 index 0000000000..76a948aa2e --- /dev/null +++ b/cmd/docker/docker_windows_386.go @@ -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" diff --git a/cmd/docker/docker_windows_amd64.go b/cmd/docker/docker_windows_amd64.go new file mode 100644 index 0000000000..514abc56f9 --- /dev/null +++ b/cmd/docker/docker_windows_amd64.go @@ -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" diff --git a/cmd/docker/docker_windows_arm.go b/cmd/docker/docker_windows_arm.go new file mode 100644 index 0000000000..378fe83616 --- /dev/null +++ b/cmd/docker/docker_windows_arm.go @@ -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" diff --git a/cmd/docker/docker_windows_arm64.go b/cmd/docker/docker_windows_arm64.go new file mode 100644 index 0000000000..a4dba5a8f9 --- /dev/null +++ b/cmd/docker/docker_windows_arm64.go @@ -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" diff --git a/scripts/winresources/docker.exe.manifest b/cmd/docker/winresources/docker.exe.manifest similarity index 100% rename from scripts/winresources/docker.exe.manifest rename to cmd/docker/winresources/docker.exe.manifest diff --git a/scripts/winresources/docker.ico b/cmd/docker/winresources/docker.ico similarity index 100% rename from scripts/winresources/docker.ico rename to cmd/docker/winresources/docker.ico diff --git a/docker-bake.hcl b/docker-bake.hcl index 59598dfe69..90978c7fb3 100644 --- a/docker-bake.hcl +++ b/docker-bake.hcl @@ -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 } } diff --git a/docker.Makefile b/docker.Makefile index 11b675a603..9310d33c3f 100644 --- a/docker.Makefile +++ b/docker.Makefile @@ -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 diff --git a/dockerfiles/Dockerfile.dev b/dockerfiles/Dockerfile.dev index a6c611c6b4..fd7af19285 100644 --- a/dockerfiles/Dockerfile.dev +++ b/dockerfiles/Dockerfile.dev @@ -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 diff --git a/scripts/build/binary b/scripts/build/binary index 7d134fc6f5..e807878b67 100755 --- a/scripts/build/binary +++ b/scripts/build/binary @@ -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" diff --git a/scripts/build/mkversioninfo b/scripts/build/mkversioninfo new file mode 100755 index 0000000000..e1d89fc766 --- /dev/null +++ b/scripts/build/mkversioninfo @@ -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 < "./cli/winresources/winresources.go" +fi diff --git a/scripts/winresources/common.rc b/scripts/winresources/common.rc deleted file mode 100644 index 000fb35367..0000000000 --- a/scripts/winresources/common.rc +++ /dev/null @@ -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 diff --git a/scripts/winresources/docker.rc b/scripts/winresources/docker.rc deleted file mode 100644 index 40c645ad1d..0000000000 --- a/scripts/winresources/docker.rc +++ /dev/null @@ -1,3 +0,0 @@ -#define DOCKER_NAME "Docker Client" - -#include "common.rc"