Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

go get -ldflags update the binary, but -ldflags not working #42482

Closed
hitzhangjie opened this issue Nov 10, 2020 · 5 comments
Closed

go get -ldflags update the binary, but -ldflags not working #42482

hitzhangjie opened this issue Nov 10, 2020 · 5 comments
Labels
FrozenDueToAge WaitingForInfo Issue is not actionable because of missing required information, which needs to be provided.

Comments

@hitzhangjie
Copy link
Contributor

What version of Go are you using (go version)?

$ go version
go version go1.14 darwin/amd64

Does this issue reproduce with the latest release?

No, I didn't test it.
I just want to know is there a way to work around this problem.

What operating system and processor architecture are you using (go env)?

go env Output
$ go env
GO111MODULE="on"
GOARCH="amd64"
GOBIN=""
GOCACHE="/Users/zhangjie/Library/Caches/go-build"
GOENV="/Users/zhangjie/Library/Application Support/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOINSECURE=""
GONOPROXY="git.code.oa.com/*"
GONOSUMDB="git.code.oa.com/*"
GOOS="darwin"
GOPATH="/Users/zhangjie/go"
GOPRIVATE="git.code.oa.com/*"
GOPROXY="http://mirrors.tencent.com,direct"
GOROOT="/usr/local/go"
GOSUMDB="off"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/darwin_amd64"
GCCGO="gccgo"
AR="ar"
CC="clang"
CXX="clang++"
CGO_ENABLED="1"
GOMOD="/Users/zhangjie/Projects/Tencent/utilities/gitcode/go.mod"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/pm/m_8nt_dd0_3bm8g6zz7_l3jc0000gn/T/go-build326907781=/tmp/go-build -gno-record-gcc-switches -fno-common"
GOROOT/bin/go version: go version go1.14 darwin/amd64
GOROOT/bin/go tool compile -V: compile version go1.14
uname -v: Darwin Kernel Version 19.6.0: Thu Oct 29 22:56:45 PDT 2020; root:xnu-6153.141.2.2~1/RELEASE_X86_64
ProductName:	Mac OS X
ProductVersion:	10.15.7
BuildVersion:	19H15
lldb --version: lldb-1200.0.32.1
Apple Swift version 5.3 (swiftlang-1200.0.29.2 clang-1200.0.30.1)

What did you do?

  1. I wrote a program, its module is github.com/xxx/cmd, and tagged v1.0.0
  2. when I run cmd update, it will create an exec.Command to run go get -ldflags="-X github.com/xxx/cmd.VERSION=${tagno}" github.com/xxx/cmd@${tagno}. The ${tagno} is got by query taglist, which seems OK.
  3. when I run cmd update, indeed, it download the new tag and build, but the -ldflags seems not working, but when I run the go get -ldflags... command manually, it works.

In this occasion, cmd update cmd itself, maybe it's a special case. I want to know is this a known problem?

What did you expect to see?

I want to see -ldflags works, that means cmd.VERSION is set to ${tagno}.

What did you see instead?

I see cmd.VERSION is not set.

@seankhliao
Copy link
Member

Show the actual code you are running

@mvdan mvdan added the WaitingForInfo Issue is not actionable because of missing required information, which needs to be provided. label Nov 10, 2020
@hitzhangjie
Copy link
Contributor Author

hitzhangjie commented Nov 10, 2020

This program is a tool built upon cobra.

The most relevant code is as following:

private repository: ${private-git-host}/gitcode, when I run go get ${private-git-host}/gitcode, a binary gitcode will be installed into ~/go/bin, then I can run gitcode <subcmd> to do some actions, similar to github command line gh.

gitcode has a subcmd gitcode update, the code is in file: cmd/update.go as following. Firstly, it uses git SDK to query the tags list, then find the newest tag and run go get -ldflags="-X module-of-gitcode/config.VERSION=${tag}" module-of-gitcode@${tag} to download, build and install the binary.

package cmd

import (
	"context"
	"errors"
	"fmt"
	"os"
	"os/exec"
	"strings"

	"${private-git-host|/git-sdk-go"

	"github.com/Masterminds/semver"
	"github.com/spf13/cobra"
)

// updateCmd represents the update command
var updateCmd = &cobra.Command{
	Use:   "update",
	Short: "update this tool",
	Long:  `update this tool.`,
	RunE: func(cmd *cobra.Command, args []string) error {

		// load 1st-page tag list
		rsp, err := tgitClient.TagService().ListTag(context.Background(), &tgit.ListTagReq{
			ProjectID: tgit.ProjectID{Path: "content_platform_center/gitcode"},
			Page:      1,
			PerPage:   10,
		})
		if err != nil {
			return err
		}

		// get the newest tag version and commit
		var (
			tagVersion = "v0.0.0"
			tagCommit  = "xxxxxxxx"
		)

		for _, tag := range *rsp {
			old, err := semver.NewVersion(tagVersion)
			if err != nil {
				return err
			}

			v, err := semver.NewVersion(tag.Name)
			if err != nil {
				return err
			}
			if v.GreaterThan(old) {
				tagVersion = tag.Name
				tagCommit = tag.Commit.ShortID
			}
		}

		// build artifact version: ${tag number}-${commit hash}
		buildver := fmt.Sprintf(
			`-ldflags="-X {private-git-host}/gitcode/config.VERSION=%s-%s"`,
			tagVersion, tagCommit)

		// install with linker options, updating the config.VERSION
		updateArgs := []string{"go", "get", buildver, "${private-git-host}/gitcode@" + tagVersion}

		// run `go get` to update this tool
		command := exec.Command(updateArgs[0], updateArgs[1:]...)
		fmt.Println(strings.Join(updateCmd.Args, " "))

		command.Stdout = os.Stdout
		command.Stderr = os.Stderr
		command.Stdin = os.Stdin

		err = command.Run()
		if err != nil {
			return err
		}
		return nil
	},
}

func init() {
	rootCmd.AddCommand(updateCmd)
}

@seankhliao
Copy link
Member

seankhliao commented Nov 10, 2020

2 issues:

  1. quoting only applies to shell
  2. you should be targeting the main package
                buildver := fmt.Sprintf(
			`-ldflags=-X main.VERSION=%s-%s`,
			tagVersion, tagCommit)

@hitzhangjie
Copy link
Contributor Author

@seankhliao Thanks.

  1. quoting only applies to shell

After change -ldflags="-X 'importPath.VERSION=%s-%s'" to -ldflags=-X importPath.VERSION=%s-%s, it works.

I am still a little confused, here. I'll appreciate If you explain in details.

  1. you should be targeting the main package

Actually, we could update any package not just main package, -ldflags -X importPath.variable, importPath can point to any valid module package.

@seankhliao
Copy link
Member

"..." is for your shell (bash/zsh/...) so it knows to pass the entire thing including spaces as a single argument. Quotes are consumed by the shell before being passed to the program. As part of shell syntax, strings can concatenated by placing them next to each other, in this case -ldflags= and "-X '...'"; quoting the entire argument would also work "-ldflags=-X '...'" and probably makes things clearer.

@golang golang locked and limited conversation to collaborators Nov 11, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
FrozenDueToAge WaitingForInfo Issue is not actionable because of missing required information, which needs to be provided.
Projects
None yet
Development

No branches or pull requests

4 participants