# multi os binary build

## setup gox

gox라는 명령어를 이용할 것이다.

Gox - Simple Go Cross Compilation

다음 웹사이트를 참고하자.

<https://github.com/mitchellh/gox>

project 폴더에서 다음을 실행한다.

```sh
go get github.com/mitchellh/gox@v1.0.1
```

go.mod에 내용이 추가된걸 확인할수 있다.

이제 ci/cd시에 이 프로젝트를 설치하게 해주면된다.

## tools.go 추가

`vi tools.go`

```go
//go:build tools
// +build tools

package main

// These imports are to force `go mod tidy` not to remove that tools we depend
// on development. This is explained in great detail in
// https://marcofranssen.nl/manage-go-tools-via-go-modules/
import (
  _ "github.com/mitchellh/gox"
)
```

## build

make 파일을 사용해서 빌드를 해보자.

프로젝트에 Makefile을 만들자.

`vi Makefile`

```makefile
PROJECT_NAME := jiractl

.PHONY: setup clean build-binaries
setup: clean
 $Q mkdir -p bin/
 $Q go mod tidy
# From https://marcofranssen.nl/manage-go-tools-via-go-modules/
 @cat tools.go | \
  grep _ | \
  awk -F'"' '{print $$2}' | \
  GOBIN=$(CURDIR)/bin xargs -tI % go install %

clean:
 $Q rm -rf bin/*

BUILD_PLATFORMS ?= -os '!netbsd' -os '!openbsd'

build-binaries: setup
 # Building $(PROJECT_NAME) for $(BUILD_PLATFORMS)
 ${CURDIR}/bin/gox $(BUILD_PLATFORMS) \
  -output="bin/binaries/$(PROJECT_NAME)-{{.OS}}-{{.Arch}}" .
```

clean -> setup -> build-binaries 로 동작한다.

make build-binaries를 하면 패키지를 빌드한다.

## ci/cd setup

`.gitlab-ci.yml`

```yaml
variables:
  GO_VERSION: '1.18.5'
  # See https://docs.gitlab.com/ee/user/packages/generic_packages/#publish-a-package-file
  PACKAGE_REGISTRY_URL: '$CI_API_V4_URL/projects/$CI_PROJECT_ID/packages/generic/jiractl'

image: golang:${GO_VERSION}

.binaries: &binaries
  image: golang:1.18
  rules:
    - if: '$CI_COMMIT_TAG'
  stage: build
  script:
    - export platforms=$(echo $CI_JOB_NAME | sed 's|binaries ||')
    - make build-binaries BUILD_PLATFORMS="-osarch='$platforms'"
  artifacts:
    paths:
      - app/bin/binaries
    expire_in: 7d

binaries darwin/amd64: *binaries
binaries darwin/arm64: *binaries
binaries freebsd/386 freebsd/amd64 freebsd/arm: *binaries
binaries linux/386 linux/amd64 linux/arm linux/arm64 linux/ppc64le: *binaries
binaries windows/386 windows/amd64:
  extends: .binaries
```

yaml yank를 이용해서 yaml을 줄엿다. 기본적으로는 \*binaries에 위에 binary를 다 넣어주면 된다.

`binaries darwin/amd64` 이게 작업 이름인데 이것중요 darwin/amd64를 가져와서 그걸 make에 보내주면 make가 빌드를 하는 구조이다.

artifact를 이용하여 저장을 해두는것이다. 이렇게 해두면 ui에서 다운로드를 받을수 있다.

![](https://3379277180-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MaoWGMVdC3ztoOAzHPq%2Fuploads%2Fgit-blob-5f505c500b86ab8600a39392ec550c20ae120ca7%2F2022-08-14-12-47-34.png?alt=media)

## upload artifact to package & registries

`vi .gitlab-ci.yml`

```yaml
upload binaries to generic package for tag:
  stage: publish
  image: curlimages/curl:latest
  needs:
    - 'binaries darwin/amd64'
    - 'binaries darwin/arm64'
    - 'binaries freebsd/386 freebsd/amd64 freebsd/arm'
    - 'binaries linux/386 linux/amd64 linux/arm linux/arm64 linux/ppc64le'
    - 'binaries windows/386 windows/amd64'
  rules:
    - if: '$CI_COMMIT_TAG'
  script:
    - cd app/bin/binaries/
    - |
      for FILE in *; do
        curl --header "JOB-TOKEN: ${CI_JOB_TOKEN}" --upload-file ${FILE} ${PACKAGE_REGISTRY_URL}/${CI_COMMIT_TAG}/${FILE} ;
      done
```

아까 설정해둔 variable 을 사용한다.

```yaml
PACKAGE_REGISTRY_URL: '$CI_API_V4_URL/projects/$CI_PROJECT_ID/packages/generic/jiractl'
```

for문을 돌면서 파일을 업로드한다.

실행하면 다음과 같이 패키지에 업로드 됨을 알수있다.

![](https://3379277180-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MaoWGMVdC3ztoOAzHPq%2Fuploads%2Fgit-blob-b4c5250b602b628a8e93bd947deef547cc4d24ba%2F2022-08-14-12-50-58.png?alt=media)

![](https://3379277180-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MaoWGMVdC3ztoOAzHPq%2Fuploads%2Fgit-blob-bc87629886d8992804d38c3f97aad02999d1426d%2F2022-08-14-12-51-13.png?alt=media)

## release

`vi .gitlab-ci.yml`

일단 git에 로그를 읽어와서 description이라는 환경변수 사용해야하므로 파일에 적어둔후 artifact에 추가해준다. 나중에 $DESCRIPTION 이러면 다른 작업에서 사용할수 있다.

```yaml
generate_description:
  # generate_description needs to run in a previous stage before release
  stage: publish
  rules:
    - if: '$CI_COMMIT_TAG'
  script:
    # generate description from annotated tag's subject
    - echo "DESCRIPTION=$(git log $(git describe --tags --abbrev=0 HEAD^)..HEAD --pretty=format:'At %ci, %cN committed %h - %s' --decorate --graph)" > description.env
    - cat description.env
  artifacts:
    reports:
      dotenv: description.env
```

이제 release를 생성하자 file은 링크로 잡아서 올려주면 된다.

```yaml
release-from-tag:
  image: registry.gitlab.com/gitlab-org/release-cli
  stage: release
  needs:
    - 'upload binaries to generic package for tag'
    - 'generate_description'
  rules:
    - if: '$CI_COMMIT_TAG' # Run this job when a tag is created manually
  script:
    - echo "Creating a release for $CI_COMMIT_TAG"
    - echo "$DESCRIPTION"
  release:
    name: 'Release $CI_COMMIT_TAG'
    description: '$DESCRIPTION'
    tag_name: '$CI_COMMIT_TAG'
    ref: '$CI_COMMIT_TAG'
    assets:
      links:
        - name: 'darwin/amd64'
          url: '$PACKAGE_REGISTRY_URL/$CI_COMMIT_TAG/jiractl-darwin-amd64'
          filepath: '/app/bin/binaries/jiractl-darwin-amd64'
        - name: 'darwin/arm64'
          url: '$PACKAGE_REGISTRY_URL/$CI_COMMIT_TAG/jiractl-darwin-arm64'
          filepath: '/app/bin/binaries/jiractl-darwin-arm64'
        - name: 'freebsd/386'
          url: '$PACKAGE_REGISTRY_URL/$CI_COMMIT_TAG/jiractl-freebsd-386'
          filepath: '/app/bin/binaries/jiractl-freebsd-386'
        - name: 'freebsd/amd64'
          url: '$PACKAGE_REGISTRY_URL/$CI_COMMIT_TAG/jiractl-freebsd-amd64'
          filepath: '/app/bin/binaries/jiractl-freebsd-amd64'
        - name: 'freebsd/arm'
          url: '$PACKAGE_REGISTRY_URL/$CI_COMMIT_TAG/jiractl-freebsd-arm'
          filepath: '/app/bin/binaries/jiractl-freebsd-arm'
        - name: 'linux/386'
          url: '$PACKAGE_REGISTRY_URL/$CI_COMMIT_TAG/jiractl-linux-386'
          filepath: '/app/bin/binaries/jiractl-linux-386'
        - name: 'linux/amd64'
          url: '$PACKAGE_REGISTRY_URL/$CI_COMMIT_TAG/jiractl-linux-amd64'
          filepath: '/app/bin/binaries/jiractl-linux-amd64'
        - name: 'linux/arm'
          url: '$PACKAGE_REGISTRY_URL/$CI_COMMIT_TAG/jiractl-linux-arm'
          filepath: '/app/bin/binaries/jiractl-linux-arm'
        - name: 'linux/arm64'
          url: '$PACKAGE_REGISTRY_URL/$CI_COMMIT_TAG/jiractl-linux-arm64'
          filepath: '/app/bin/binaries/jiractl-linux-arm64'
        - name: 'linux/ppc64le'
          url: '$PACKAGE_REGISTRY_URL/$CI_COMMIT_TAG/jiractl-linux-ppc64le'
          filepath: '/app/bin/binaries/jiractl-linux-ppc64le'
        - name: 'windows/386'
          url: '$PACKAGE_REGISTRY_URL/$CI_COMMIT_TAG/jiractl-windows-386.exe'
          filepath: '/app/bin/binaries/jiractl-windows-386.exe'
        - name: 'windows/amd64'
          url: '$PACKAGE_REGISTRY_URL/$CI_COMMIT_TAG/jiractl-windows-amd64.exe'
          filepath: '/app/bin/binaries/jiractl-windows-amd64.exe'
```

다음처럼 release가 생긴것을 알수 있다.

![](https://3379277180-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MaoWGMVdC3ztoOAzHPq%2Fuploads%2Fgit-blob-2c5cc1f869e137d467c282b90b7e4f66757638c5%2F2022-08-14-12-55-13.png?alt=media)

완성


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://teamsmiley.gitbook.io/devops/go-lang/multi-os-build.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
