создать временную метку сборки в Go - PullRequest
0 голосов
/ 28 октября 2018

Я хочу, чтобы в программе Go (использующей Go 1.11.1 в Debian / Linux / x86-64) была сохранена временная метка сборки со строкой, объясняющей последний git commit.

В программе на C (FWIW мой проект bismon делает что-то очень похожее), я просто сгенерировал бы какой-нибудь файл _timestamp.c, например, с рецептом Makefile, например:

_timestamp.c: 
    date +'const char my_timestamp[]='%c';%n' > $@
    (echo -n 'const char my_lastgitcommit[]="'; \
     git log --format=oneline --abbrev=12 --abbrev-commit -q | head -1 \
       | tr -d '\n\r\f\"\\\\' ; echo '";') >> $@

, и я бы связал свойзапрограммируйте myprog что-то вроде:

myprog: $(MYOBJECTS) _timestamp.c
    $(LINK.c) $(MYOBJECTS) _timestamp.c -o $@
    $(RM) _timestamp.c

Обратите внимание, что _timestamp.c автоматически удаляется при каждой успешной ссылке.Конечно, в каком-то заголовке я бы объявил extern const char my_timestamp[]; и extern const char my_lastgitcommit[]: и использовал бы, например, my_timestamp и my_lastgitcommit в моем main.cMYOBJECTS содержит main.o)

Itпохоже, что go generate можно использовать, чтобы вести себя подобным образом.Я хотел бы иметь пакет "timestamp", определяющий две строковые глобальные переменные timestamp.My_timestamp и timestamp.My_gitcommit, но я не совсем понимаю, как это сделать.

Я попытался добавить файл timestamp/timestamp.go с помощью

package timestamp

//go:generate date +'var My_timestamp = "%c"%n'

// Code generated - DO NOT EDIT.

Но это не изменилось с go generate, тогда go install

Конечно, эти временные метки должны быть постоянными строками во время компиляции, и я ожидаю найти их при запуске *Утилита 1041 * strings (1) в исполняемом файле ELF.

Кстати, я вспоминаю одну из причин команды go :

Явная цель Go с самого начала состояла в том, чтобы иметь возможность создавать код Go, используя только информацию, найденную в самом источнике, без необходимости писать make-файл или одну из многих современных замен для make-файлов.Если бы Go понадобился файл конфигурации для объяснения того, как собрать вашу программу, то Go потерпел бы неудачу.

Так что я все еще ожидаю, что что-то войдет в исходный код один, без дополнительной настройки для сборки.

Другими словами, я хочу генерировать при каждой сборке файла Go, подобного:

// generated timestamp.go file
package timestamp
var Buildtime = "Tue 30 Oct 2018 09:39:01 AM MET";
var Buildlastgitcommit = "7fde394b60bc adding timestamp.go"

Строка Buildtime генерируется date +%c.Строка Buildlastgitcommit может быть сгенерирована командами, похожими на то, что делает мое правило _timestamp.c make.

Мне нужно, чтобы эти строки были постоянными и встроенными в исполняемый файл ELF, созданный сборкой Go (которую япредпочел бы сделать это с помощью обычных команд, либо без дополнительных аргументов для go build или любого другого инструмента автоматизации сборки, либо с каким-либо способом завершить сборку, если обязательные аргументы забыты, следовательно, atanayel'sответа не достаточно).Поэтому я хочу, чтобы утилита strings (1) быстро находила эти строки в исполняемом файле.И генерация таких файлов должна быть сконфигурирована в какие-то файлы, не требующие дополнительных аргументов для сборщиков.

Я мог бы рассмотреть возможность перехода на какую-то другую, Go-friendly , сборкусистема автоматизации (но кажется, что даже с gb я не могу легко делать то, что хочу: быстро генерировать простой файл .go при каждой сборке).Но я не понимаю, почему так сложно использовать сгенерированные Go файлы в программах Go.Генерация простого кода следует философии Unix и практикуется на протяжении многих десятилетий (например, см. goyacc , вдохновленный старой программой yacc ).

Примечание: обоснование для go generate прямо упоминает, что:

Целью этого предложения не является создание обобщенной системы сборки, такой как утилита Unix make(1).,

и более поздних версий

после того, как все решено, автор передает сгенерированные файлы в исходный репозиторий,

(и это не мой вариант использования)

PS.Я забочусь только о системах POSIX;Мне действительно все равно, если мое программное обеспечение Go не может быть построено на Windows.И я склонен думать, что (в отличие от того, что объясняет go мотивация команды ), в моем конкретном случае мне do нужен какой-то инструмент автоматизации сборки.В моем игрушечном проекте bastawigo (GPLv3 +) я использую make (управление командой go)

Ответы [ 3 ]

0 голосов
/ 29 октября 2018

Вы можете использовать флаги времени сборки, чтобы сделать это. Этот ответ объясняет его для другого варианта использования, но ваш идентичен ему.Вы должны сделать что-то вроде этого.

  • Определить константу в вашем коде что-то вроде buildTime
  • При сборке для выпуска, сделать что-то вроде go build -ldflags='-X buildTime="My build time output from a command"'
  • Теперь ваша переменная buildTime является постоянной и равна My build time output from a command.
  • Вы можете использовать свою предыдущую команду, чтобы найти правильный My build time output froma a command.

См. Ответ, который я связалдля лучшего объяснения.

0 голосов
/ 07 декабря 2018

Как уже упоминалось в других ответах, вы можете ввести необходимые значения в двоичный файл во время сборки.

Например, если у нас есть следующие переменные пакета:

// build flags
var (
    BuildTime  string
    CommitHash string
    GoVersion  string
    GitTag     string
)

Затем мы можем заполнить ихиспользуя этот скрипт:

#!/bin/sh

clear

TRG_PKG='main'
BUILD_TIME=$(date +"%Y%m%d.%H%M%S")
CommitHash=N/A
GoVersion=N/A
GitTag=N/A

if [[ $(go version) =~ [0-9]+\.[0-9]+\.[0-9]+ ]];
then
    GoVersion=${BASH_REMATCH[0]}
fi

GV=$(git tag || echo 'N/A')
if [[ $GV =~ [^[:space:]]+ ]];
then
    GitTag=${BASH_REMATCH[0]}
fi

GH=$(git log -1 --pretty=format:%h || echo 'N/A')
if [[ GH =~ 'fatal' ]];
then
    CommitHash=N/A
else
    CommitHash=$GH
fi

FLAG="-X $TRG_PKG.BuildTime=$BUILD_TIME"
FLAG="$FLAG -X $TRG_PKG.CommitHash=$CommitHash"
FLAG="$FLAG -X $TRG_PKG.GoVersion=$GoVersion"
FLAG="$FLAG -X $TRG_PKG.GitTag=$GitTag"

if [[ $1 =~ '-i' ]];
then
    echo 'go install'
    go install -v -ldflags "$FLAG"
else
    echo 'go build'
    go build -v -ldflags "$FLAG"
fi

Пример кода взят из этого репо .

0 голосов
/ 29 октября 2018
export LAST_BUILD=$(date +"%T") ; go build ...

Os.Getenv("LAST_BUILD")
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...