Как быстро собрать / установить кросс-скомпилированные вложенные пакеты? - PullRequest
0 голосов
/ 05 апреля 2019

У меня есть хранилище с группой вложенных пакетов go, организованных следующим образом:

$GOPATH/src/
  - mypackage/common/utils.go
  - mypackage/app1/main.go
  - mypackage/app2/main.go
  ...

Он компилируется в несколько двоичных файлов.Для выпуска я кросс-компилирую для множества платформ / арок (я развертываю неоднократно с разными GOOS и GOARCH).Я пытаюсь записать результаты компиляции в каталог по своему выбору, но я борюсь с набором инструментов.

Я могу:

  1. Объединить GOBINи go install при компиляции для моей собственной архитектуры (т.е. не кросс-компиляция):

    # build + output all binaries in /somedir/bin
    # this works great when compiling for my local architecture.
    GOBIN=/somedir/bin go install mypackage/app1 mypackage/app2 mypackage/app3
    

    Но, к сожалению, GOBIN конфликтует с кросс-компиляцией, например:

    # Throws: "cannot install cross-compiled binaries when GOBIN is set"
    GOBIN=/somedir/bin GOARCH=amdm64 GOOS=darwin go install mypackage/app1 mypackage/app2
    
  2. Используйте go build с GOOS=X и GOARCH=Y для каждого подпакета

    # cross compile one of the binaries
    cd /output/darwin-386-bin/ && \
    GOOS=darwin GOARCH=386 go build mypackage/app1
    
    # but if given multiple binaries, there is no output. (as documented)
    GOOS=darwin GOARCH=386 go build mypackage/app1 mypackage/app2
    

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

    Другая возможная проблема с использованиемgo build, как это, заключается в том, что он потенциально смешивает двоичные и промежуточные результаты для нескольких архитектур в одном рабочем пространстве.Но, возможно, это просто вопрос вкуса.Надеемся, что набор инструментов хранит кэшированные результаты отдельно для разных архитектур.

Как это обрабатывается на практике?Должен ли я относиться к каждому подпакету как к отдельному пакету, несмотря на их общий общий код (будет ли безопасно строить их все параллельно)?

Статьи по теме:

  • go build vs go install: https://groups.google.com/forum/#!topic/golang-nuts/s8Csz3-7EXA (мало информации о кросс-компиляции или настройках нескольких пакетов)

  • кросс-компиляция с go 1.5 .: https://dave.cheney.net/2015/08/22/cross-compilation-with-go-1-5 (конкретно не касается компиляции multipackage / common code. Также, насколько я могу судить, утверждение о необходимости перекомпилировать стандартную библиотеку в / usr / local / go / pkg, похоже, больше не выполняется в 1.9.1)

  • Перейти к созданию нескольких вложенных пакетов: Перейти к созданию нескольких / вложенных пакетов? .(Принятый ответ go build ./... ведет себя так же, как и передача нескольких пакетов в одной команде сборки, и, следовательно, не выводит двоичные файлы. Поток также не охватывает кросс-компиляцию)

1 Ответ

0 голосов
/ 05 апреля 2019

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

Вы можете отброситьGOBIN из команды установки:

# I'm not on this platform, so this is a cross compile
GOOS=darwin GOARCH=amd64 go install mypackage/app1 mypackage/app2

Предполагается, что ваш пакет находится в $GOPATH/src/mypackage, указанная выше команда установит два двоичных файла в:

$GOPATH/bin/darwin_amd64/{app1, app2}

и файлы зависимостей компиляции .a в:

$GOPATH/pkg/darwin_amd64/mypackage/{app1,app2,common}

Если вы запускаете это в цикле for для всех платформ, которые вы планируете поддерживать, одна неприятность этого процесса заключается в том, что когда вы передаете GOOS=x GOARCH=y в соответствии с вашей локальной архитектурой (т.е. не пересекаютсякомпиляции), тогда исполняемые файлы будут помещены непосредственно в $GOPATH/bin/, а не $GOPATH/bin/x_y/.

(пакеты с другой стороны всегда заканчиваются на $GOPATH/pkg/x_y/, кросс-компиляция или нет).

Чтобы определить локальную архитектуру, вы можете выполнить следующие шаги в этом ответе: https://stackoverflow.com/a/35669816/5556676.

Имитация GOBIN=/foo/bin GOOS=x GOARCH=y go install mypackage/app{1,2,3}

Изменение$GOPATH мало влияет на то, куда go install пишет вывод.С некоторыми командами go, такими как go get, вы настраиваете, где установлены пакеты, добавляя новый компонент перед $GOPATH.Но в версии 1.9 go install всегда будет копировать двоичные файлы в папку bin/, которая является родственным элементом src/, в котором содержатся пакеты для установки.

Вместо использования GOBIN=/foo/bin вы можете притворитьсяисходные файлы находятся в /foo/src/mypackage (вы можете использовать символическую ссылку), а затем выполните GOPATH=/foo GOOS=x GOARCH=y go install mypackage/app{1,2,3}.Это поместит двоичные файлы в /foo/bin из-за поведения, которое я описал в предыдущем абзаце.

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

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