Как написать Makefile для Go

Как написать Makefile для Go #

Инструкция о том, как написать удобный Makefile для сборки небольшого API-сервиса на Go.

Задача #

Особенности проекта:

  1. Он называется my_project
  2. Исполняемый файл называется my-project
  3. Проект написан на современном Go с использованием модулей
  4. Нам нужны цели для сборки, для запуска тестов и для очистки

Решение #

.PHONY: all test tidy build run clean

all: tidy test build

test:
	go test ./...

tidy:
	go mod tidy && \
	go mod vendor

build:
    CGO_ENABLED=0 go build -ldflags="-s -w" -o bin/my-project cmd/main.go

# Цель не запустится без явного указания
run:
	go run .

# Цель не запустится без явного указания
clean:
	go clean -testcache
	rm -f bin/my-project

Объяснение #

Доступные цели:

Цель сборкиПредназначение
makeэквивалент make tidy test build
testзапускает тесты на Go
buildсобирает проект на Go в каталоге cmd/main.go
runзапускает проект на Go
cleanочищает кэш тестов и результат сборки (исполняемый файл)

Другие особенности

  1. Цель .PHONY объявляет цели, которые не создают таких выходных файлов, которые бы отслеживались инструментом GNU make. Это отключит механизм пропуска целей сборки при наличии одноимённых файлов.
  2. Цель all идёт первой в этом файле — она будет выполнена при вызове make без аргументов
  3. Цель build создаёт, а цель clean очищает исполняемый файл bin/my-project

Добавляем другие цели #

Не забывайте новую цель добавить в .PHONY

Сборка docker-образа #

Цель сборки docker-образа:

image:
	docker build -t docker.local/my-project .

Описание Dockerfile см. в статье Как написать Dockerfile для Go

Генерация кода через ogen #

ogen — генератор кода на Go из OpenAPI схемы; он отличается высоким качеством, расширяемостью и генерирует идиоматичный код.

Предположим, что мы не хотим использовать go generate и полагаемся на запуск shell-скрипта.

Цель для запуска shell-скрипта bin/generate-code.sh:

generate:
    bin/generate-code.sh

Допустим, OpenAPI-схема находится в файле api/my_project.yaml.

Скрипт bin/generate-code.sh имеет флаг исполнения +x и выглядит так:

#!/usr/bin/env bash

set -o errexit

SCRIPT_DIR=$(dirname "$(readlink -f "$0")")
BACKEND_ROOT=$(dirname "$SCRIPT_DIR")

pushd "$BACKEND_ROOT" >/dev/null
go run github.com/ogen-go/ogen/cmd/ogen@latest \
    -package "api" \
    -config "ogen.yaml" \
    -target "internal/restapi/api" \
    -clean \
    "api/my_project.yaml"
popd >/dev/null

Файл конфигурации ogen.yaml выглядит, например, так:

# sets generator options.
generator:
  # sets generator features.
  features:
    enable:
      # Enables paths server generation
      - "paths/server"
      # Enables validation of client requests
      - "client/request/validation"
      # Enables paths client generation
      - "paths/client"
      # Enables validation of server responses
      - "server/response/validation"
    disable_all: true

Сайт atdd.ru — блог разработчика.