Как передать -ldflags в exec.Command с несколькими аргументами - PullRequest
0 голосов
/ 28 августа 2018

У меня довольно простой файл go, который собирает несколько внутренних инструментов, написанных на go. Это работало хорошо, пока я не решил добавить -ldflags в мою команду сборки. Ниже приведен фрагмент, который форматирует команду go build.

var cmd *exec.Cmd
file := fmt.Sprintf("%s.%s.%s", p.Bin, e.OS, e.Arch)
if len(p.Flags) > 0 {
    ldflags := ""
    for _, f := range p.Flags {
        if len(ldflags) > 0 {
            ldflags = ldflags + " "
        }
        ldflags = ldflags + f.Flag
    }
    ldflags = "\"" + ldflags + "\""
    fmt.Println("go", "build", "-v", "-a", "-ldflags", ldflags, "-o", fmt.Sprintf("/tmp/bin/%s", file), ".")
    cmd = exec.Command("go", "build", "-a", "-ldflags", ldflags, "-o", fmt.Sprintf("/tmp/bin/%s", file), ".")
} else {
    fmt.Println("go", "build", "-v", "-a", "-o", fmt.Sprintf("/tmp/bin/%s", file), ".")
    cmd = exec.Command("go", "build", "-a", "-o", fmt.Sprintf("/tmp/bin/%s", file), ".")
        }
cmd.Dir = p.Pkg
cmd.Stdout = ioutil.Discard
cmd.Stderr = os.Stdout
cmd.Env = append(cleanEnv(),
    fmt.Sprintf("GOOS=%s", e.OS),
    fmt.Sprintf("GOARCH=%s", e.Arch),
)

if err := cmd.Run(); err != nil {
    return err
}

Мои флаги определены как простые строки, например

[]flagarg{
    {Flag:"-X main.buildstamp=`date -u '+%Y-%m-%d_%I:%M:%S%p'`"},
    {Flag:"-X main.githash=`git rev-parse --short HEAD`"},
}

Ниже выводится, когда я печатаю

go build -v -a -ldflags "-X main.buildstamp=`date -u
'+%Y-%m-%d_%I:%M:%S%p'` -X main.githash=`git rev-parse --short HEAD`"
-o /tmp/bin/bro.linux.amd64 .

Приведенная выше команда работает, когда я вставляю ее в свой CLI, но не работает, когда я запускаю этот go build через мой скрипт go. Когда я говорю сбой, я имею в виду, что он не устанавливает мои переменные githash и buildstamp. Копирование и вставка команды действительно устанавливает эти переменные как ожидалось.

Я подумал, что это должно быть что-то с кавычками, и я попытался изменить их, но я не могу заставить вещи работать. Я начинаю думать, что иду по неверному пути, и это должен быть лучший способ заставить это работать.

1 Ответ

0 голосов
/ 28 августа 2018

Скорее всего, проблема связана с подстановкой команды (обратные метки) ; он не делает то, что вы ожидаете, потому что это особенность оболочки, а не команда "go build".

[]flagarg{
    {Flag:"-X main.buildstamp=`date -u '+%Y-%m-%d_%I:%M:%S%p'`"},
    // Bash command subst ----^------------------------------^

Попробуйте выполнить напечатанную командную строку в качестве единственного строкового аргумента для "bash -c", например ::

cmd = exec.Command("bash", "-c", "go build -v -a ...")

Вы также можете рассмотреть возможность использования формы подстановки команд bash $(...) (я думаю, что это легче читать), вот простой пример для демонстрации:

cmdline := "echo \"The time is now '$(date)'!\""
out, err := exec.Command("bash", "-c", cmdline).Output()
if err != nil {
    panic(err)
}
fmt.Println(string(out))
// The time is now 'Tue Aug 28 09:33:34 MDT 2018'!
...