build: get binary build info from debug/buildinfo

Since `go1.18` the runtime has a package that provides information about module
versions, version control information, and build flags embedded in executable
files built by the go command.

The new packages allows us to get information needed by the `version` command
without having to rely on `ldflags` set at build time.

This can be really helpful while debugging errors from people using custom
binaries. For example a build from master.
This commit is contained in:
positiveblue
2022-10-01 15:09:34 -07:00
parent 27fdd0a5b0
commit 5924964a9b
2 changed files with 32 additions and 27 deletions

View File

@@ -25,13 +25,11 @@ ANDROID_BUILD_DIR := $(MOBILE_BUILD_DIR)/android
ANDROID_BUILD := $(ANDROID_BUILD_DIR)/Lndmobile.aar ANDROID_BUILD := $(ANDROID_BUILD_DIR)/Lndmobile.aar
COMMIT := $(shell git describe --tags --dirty) COMMIT := $(shell git describe --tags --dirty)
COMMIT_HASH := $(shell git rev-parse HEAD)
GOBUILD := go build -v GOBUILD := go build -v
GOINSTALL := go install -v GOINSTALL := go install -v
GOTEST := go test GOTEST := go test
GOVERSION := $(shell go version | awk '{print $$3}')
GOFILES_NOVENDOR = $(shell find . -type f -name '*.go' -not -path "./vendor/*" -not -name "*pb.go" -not -name "*pb.gw.go" -not -name "*.pb.json.go") GOFILES_NOVENDOR = $(shell find . -type f -name '*.go' -not -path "./vendor/*" -not -name "*pb.go" -not -name "*pb.gw.go" -not -name "*.pb.json.go")
RM := rm -f RM := rm -f
@@ -48,19 +46,13 @@ DEV_TAGS := $(if ${tags},$(DEV_TAGS) ${tags},$(DEV_TAGS))
# We only return the part inside the double quote here to avoid escape issues # We only return the part inside the double quote here to avoid escape issues
# when calling the external release script. The second parameter can be used to # when calling the external release script. The second parameter can be used to
# add additional ldflags if needed (currently only used for the release). # add additional ldflags if needed (currently only used for the release).
make_ldflags = $(2) -X $(PKG)/build.Commit=$(COMMIT) \ make_ldflags = $(1) -X $(PKG)/build.Commit=$(COMMIT)
-X $(PKG)/build.CommitHash=$(COMMIT_HASH) \
-X $(PKG)/build.GoVersion=$(GOVERSION) \
-X $(PKG)/build.RawTags=$(shell echo $(1) | sed -e 's/ /,/g')
DEV_GCFLAGS := -gcflags "all=-N -l" DEV_GCFLAGS := -gcflags "all=-N -l"
LDFLAGS := -ldflags "$(call make_ldflags, ${tags}, -s -w)" DEV_LDFLAGS := -ldflags "$(call make_ldflags)"
DEV_LDFLAGS := -ldflags "$(call make_ldflags, $(DEV_TAGS))"
ITEST_LDFLAGS := -ldflags "$(call make_ldflags, $(ITEST_TAGS))"
# For the release, we want to remove the symbol table and debug information (-s) # For the release, we want to remove the symbol table and debug information (-s)
# and omit the DWARF symbol table (-w). Also we clear the build ID. # and omit the DWARF symbol table (-w). Also we clear the build ID.
RELEASE_LDFLAGS := $(call make_ldflags, $(RELEASE_TAGS), -s -w -buildid=) RELEASE_LDFLAGS := $(call make_ldflags, -s -w -buildid=)
# Linting uses a lot of memory, so keep it under control by limiting the number # Linting uses a lot of memory, so keep it under control by limiting the number
# of workers if requested. # of workers if requested.
@@ -118,24 +110,24 @@ build:
build-itest: build-itest:
@$(call print, "Building itest btcd and lnd.") @$(call print, "Building itest btcd and lnd.")
CGO_ENABLED=0 $(GOBUILD) -tags="rpctest" -o lntest/itest/btcd-itest$(EXEC_SUFFIX) $(ITEST_LDFLAGS) $(BTCD_PKG) CGO_ENABLED=0 $(GOBUILD) -tags="rpctest" -o lntest/itest/btcd-itest$(EXEC_SUFFIX) $(DEV_LDFLAGS) $(BTCD_PKG)
CGO_ENABLED=0 $(GOBUILD) -tags="$(ITEST_TAGS)" -o lntest/itest/lnd-itest$(EXEC_SUFFIX) $(ITEST_LDFLAGS) $(PKG)/cmd/lnd CGO_ENABLED=0 $(GOBUILD) -tags="$(ITEST_TAGS)" -o lntest/itest/lnd-itest$(EXEC_SUFFIX) $(DEV_LDFLAGS) $(PKG)/cmd/lnd
@$(call print, "Building itest binary for ${backend} backend.") @$(call print, "Building itest binary for ${backend} backend.")
CGO_ENABLED=0 $(GOTEST) -v ./lntest/itest -tags="$(DEV_TAGS) $(RPC_TAGS) rpctest $(backend)" -c -o lntest/itest/itest.test$(EXEC_SUFFIX) CGO_ENABLED=0 $(GOTEST) -v ./lntest/itest -tags="$(DEV_TAGS) $(RPC_TAGS) rpctest $(backend)" -c -o lntest/itest/itest.test$(EXEC_SUFFIX)
build-itest-race: build-itest-race:
@$(call print, "Building itest btcd and lnd with race detector.") @$(call print, "Building itest btcd and lnd with race detector.")
CGO_ENABLED=0 $(GOBUILD) -tags="rpctest" -o lntest/itest/btcd-itest$(EXEC_SUFFIX) $(ITEST_LDFLAGS) $(BTCD_PKG) CGO_ENABLED=0 $(GOBUILD) -tags="rpctest" -o lntest/itest/btcd-itest$(EXEC_SUFFIX) $(DEV_LDFLAGS) $(BTCD_PKG)
CGO_ENABLED=1 $(GOBUILD) -race -tags="$(ITEST_TAGS)" -o lntest/itest/lnd-itest$(EXEC_SUFFIX) $(ITEST_LDFLAGS) $(PKG)/cmd/lnd CGO_ENABLED=1 $(GOBUILD) -race -tags="$(ITEST_TAGS)" -o lntest/itest/lnd-itest$(EXEC_SUFFIX) $(DEV_LDFLAGS) $(PKG)/cmd/lnd
@$(call print, "Building itest binary for ${backend} backend.") @$(call print, "Building itest binary for ${backend} backend.")
CGO_ENABLED=0 $(GOTEST) -v ./lntest/itest -tags="$(DEV_TAGS) $(RPC_TAGS) rpctest $(backend)" -c -o lntest/itest/itest.test$(EXEC_SUFFIX) CGO_ENABLED=0 $(GOTEST) -v ./lntest/itest -tags="$(DEV_TAGS) $(RPC_TAGS) rpctest $(backend)" -c -o lntest/itest/itest.test$(EXEC_SUFFIX)
install: install:
@$(call print, "Installing lnd and lncli.") @$(call print, "Installing lnd and lncli.")
$(GOINSTALL) -tags="${tags}" $(LDFLAGS) $(PKG)/cmd/lnd $(GOINSTALL) -tags="${tags}" $(RELEASE_LDFLAGS) $(PKG)/cmd/lnd
$(GOINSTALL) -tags="${tags}" $(LDFLAGS) $(PKG)/cmd/lncli $(GOINSTALL) -tags="${tags}" $(RELEASE_LDFLAGS) $(PKG)/cmd/lncli
release-install: release-install:
@$(call print, "Installing release lnd and lncli.") @$(call print, "Installing release lnd and lncli.")
@@ -157,7 +149,7 @@ docker-release:
# Run the actual compilation inside the docker image. We pass in all flags # Run the actual compilation inside the docker image. We pass in all flags
# that we might want to overwrite in manual tests. # that we might want to overwrite in manual tests.
$(DOCKER_RELEASE_HELPER) make release tag="$(tag)" sys="$(sys)" COMMIT="$(COMMIT)" COMMIT_HASH="$(COMMIT_HASH)" $(DOCKER_RELEASE_HELPER) make release tag="$(tag)" sys="$(sys)" COMMIT="$(COMMIT)"
docker-tools: docker-tools:
@$(call print, "Building tools docker image.") @$(call print, "Building tools docker image.")
@@ -305,22 +297,22 @@ vendor:
apple: vendor mobile-rpc apple: vendor mobile-rpc
@$(call print, "Building iOS and macOS cxframework ($(IOS_BUILD)).") @$(call print, "Building iOS and macOS cxframework ($(IOS_BUILD)).")
mkdir -p $(IOS_BUILD_DIR) mkdir -p $(IOS_BUILD_DIR)
$(GOMOBILE_BIN) bind -target=ios,iossimulator,macos -tags="mobile $(DEV_TAGS) $(RPC_TAGS)" $(LDFLAGS) -v -o $(IOS_BUILD) $(MOBILE_PKG) $(GOMOBILE_BIN) bind -target=ios,iossimulator,macos -tags="mobile $(DEV_TAGS) $(RPC_TAGS)" $(RELEASE_LDFLAGS) -v -o $(IOS_BUILD) $(MOBILE_PKG)
ios: vendor mobile-rpc ios: vendor mobile-rpc
@$(call print, "Building iOS cxframework ($(IOS_BUILD)).") @$(call print, "Building iOS cxframework ($(IOS_BUILD)).")
mkdir -p $(IOS_BUILD_DIR) mkdir -p $(IOS_BUILD_DIR)
$(GOMOBILE_BIN) bind -target=ios,iossimulator -tags="mobile $(DEV_TAGS) $(RPC_TAGS)" $(LDFLAGS) -v -o $(IOS_BUILD) $(MOBILE_PKG) $(GOMOBILE_BIN) bind -target=ios,iossimulator -tags="mobile $(DEV_TAGS) $(RPC_TAGS)" $(RELEASE_LDFLAGS) -v -o $(IOS_BUILD) $(MOBILE_PKG)
macos: vendor mobile-rpc macos: vendor mobile-rpc
@$(call print, "Building macOS cxframework ($(IOS_BUILD)).") @$(call print, "Building macOS cxframework ($(IOS_BUILD)).")
mkdir -p $(IOS_BUILD_DIR) mkdir -p $(IOS_BUILD_DIR)
$(GOMOBILE_BIN) bind -target=macos -tags="mobile $(DEV_TAGS) $(RPC_TAGS)" $(LDFLAGS) -v -o $(IOS_BUILD) $(MOBILE_PKG) $(GOMOBILE_BIN) bind -target=macos -tags="mobile $(DEV_TAGS) $(RPC_TAGS)" $(RELEASE_LDFLAGS) -v -o $(IOS_BUILD) $(MOBILE_PKG)
android: vendor mobile-rpc android: vendor mobile-rpc
@$(call print, "Building Android library ($(ANDROID_BUILD)).") @$(call print, "Building Android library ($(ANDROID_BUILD)).")
mkdir -p $(ANDROID_BUILD_DIR) mkdir -p $(ANDROID_BUILD_DIR)
$(GOMOBILE_BIN) bind -target=android -tags="mobile $(DEV_TAGS) $(RPC_TAGS)" $(LDFLAGS) -v -o $(ANDROID_BUILD) $(MOBILE_PKG) $(GOMOBILE_BIN) bind -target=android -tags="mobile $(DEV_TAGS) $(RPC_TAGS)" $(RELEASE_LDFLAGS) -v -o $(ANDROID_BUILD) $(MOBILE_PKG)
mobile: ios android mobile: ios android

View File

@@ -7,6 +7,7 @@ package build
import ( import (
"fmt" "fmt"
"runtime/debug"
"strings" "strings"
) )
@@ -17,16 +18,14 @@ var (
// -ldflags during compilation. // -ldflags during compilation.
Commit string Commit string
// CommitHash stores the current commit hash of this build, this should // CommitHash stores the current commit hash of this build.
// be set using the -ldflags during compilation.
CommitHash string CommitHash string
// RawTags contains the raw set of build tags, separated by commas. This // RawTags contains the raw set of build tags, separated by commas.
// should be set using -ldflags during compilation.
RawTags string RawTags string
// GoVersion stores the go version that the executable was compiled // GoVersion stores the go version that the executable was compiled
// with. This should be set using -ldflags during compilation. // with.
GoVersion string GoVersion string
) )
@@ -62,6 +61,20 @@ func init() {
"alphabet", r)) "alphabet", r))
} }
} }
// Get build information from the runtime.
if info, ok := debug.ReadBuildInfo(); ok {
GoVersion = info.GoVersion
for _, setting := range info.Settings {
switch setting.Key {
case "vcs.revision":
CommitHash = setting.Value
case "-tags":
RawTags = setting.Value
}
}
}
} }
// Version returns the application version as a properly formed string per the // Version returns the application version as a properly formed string per the