5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

この記事誰得? 私しか得しないニッチな技術で記事投稿!

Makefileで書く誰得スクリプト集 + ハマりポイント対処

Last updated at Posted at 2023-06-25

はじめに

基本的な Makefile の書き方はこの記事では紹介してません。
Makefile 初学者の方には以下の記事を先に読むことをおすすめします。
(私の記事ではないですが紹介させていただきます。)

便利スクリプト集

色付き出力で結果を変わりやすく

こういった使い回したいスクリプトは Makefile.common などに記載し、 Makefileinclude Makefile.common すると便利になります。

文字列
\033[0;31m 赤色
\033[0;32m 緑色
\033[0;33m 黄色
\033[0m 無色

Makefile.common

.PHONY: echo_green
TEXT	?=	Success
echo_green:
	@echo "\n\033[0;32m${TEXT}\033[0m\n"

#-----------------------------------------------------------------------------------------------

.PHONY: echo_red
echo_red:
	@echo "\n\033[0;31m${TEXT}\033[0m\n"

#-----------------------------------------------------------------------------------------------

.PHONY: echo_yellow
echo_yellow:
	@echo "\n\033[0;33m${TEXT}\033[0m\n"

Makefile

include Makefile.common

#-----------------------------------------------------------------------------------------------

.PHONY: test
test:
	@make echo_green
	@make echo_red TEXT="Error: something wrongs"
	@make echo_yellow TEXT="Warning: something is warning"
$ make test

依存パッケージなどのインストールチェック

configure でやることじゃね?」と思われた方もいるのでは、、、

Makefile

include Makefile.common

#-----------------------------------------------------------------------------------------------

.PHONY: check_deps
check_deps:
	# Check node
	@if ! which node > /dev/null ; then \
		make echo_red TEXT="Error: node not installed" ; false ; \
	fi
	@make echo_green
	# Check yarn
	@if ! which yarn > /dev/null ; then \
		make echo_red TEXT="Error: yarn not installed" ; false ; \
	fi
	@make echo_green

#-----------------------------------------------------------------------------------------------

.PHONY: install
installl: check_deps

実行例

$ make check_deps
# Check node

Success

# Check yarn

Success

環境変数が指定されているかチェックする

.PHONY: check_env
SAMPLE_ENV ?= NOT_SPECIFIED
check_env:
	@if [ ${SAMPLE_ENV} = "NOT_SPECIFIED" ] ; then \
		make echo_red TEXT="Error: SAMPLE_ENV not specified"; false ; \
	fi

実行例

$ make check_env SAMPLE_ENV=aaa # 正常終了
$ make check_env # エラー

Error: SAMPLE_ENV not specified

アプリケーションを systemd のユニットサービスとしてインストールする

systemd 初学者向けの記事

バイナリなどの必須ファイルのインストールやユニットファイルの配置をします。

include Makefile.common

#-----------------------------------------------------------------------------------------------

## systemd unit file
define unit_file
[Unit]
Description=Sample
Documentation=Sample
After=network-online.target

[Service]
Type=simple
EnvironmentFile=${ENV_FILE_PATH}
ExecStart=${DIR_BIN}/sample $$ARGS

[Install]
WantedBy=multi-user.target
endef
export unit_file

## application env file
define env_file
ARGS="--port ${PORT}"
endef
export env_file

DIR_BIN			?= /usr/local/bin
UNIT_FILE_PATH	?= /usr/local/lib/systemd/system/sample.service
ENV_FILE_PATH	?= /usr/local/etc/default/sample
PORT			?= 80
.PHONY: install
install:
	# Install
	#@cp -b something ${DIR_BIN}/
	@echo "-> ${DIR_BIN}/something"
	@make echo_green

	# Install as systemd unit
	@echo "$$unit_file" > ${UNIT_FILE_PATH}
	@echo "-> ${UNIT_FILE_PATH}"
	@echo "$$env_file" > ${ENV_FILE_PATH}
	@echo "-> ${ENV_FILE_PATH}"
	@make echo_green
$ make install
# Install
#@cp -b something /usr/local/bin/
-> /usr/local/bin/something

Success

# Install as systemd unit
-> /usr/local/lib/systemd/system/sample.service
-> /usr/local/etc/default/sample

Success

$ systemctl daemon-reload # 配置したユニットファイルのロード
$ systemctl start sample.service # ユニットサービスの起動

ヘルプの表示

変数についてまでヘルプに含む場合は可読性が低い記述になってしまうためおすすめはしませんが、
個人で使う分には細かく記載しておきたいことが多いので僕はよくこんな感じで書いてます。

.DEFAULT_GOAL := help
.PHONY: help
TARGET	?=	''
help: ## Display this help screen.\n    VARIABLES:\n      - TARGET\n          Specify make target
	@grep '^[a-zA-Z]' Makefile | \
    awk -F ':.*?## ' 'NF==2 {printf "\033[36m  %-25s\033[0m %s\n", $$1, $$2}' | \
		grep -E ${TARGET} | \
		sed 's/^/\n/g' | sed 's/\\n/\n/g'
	@echo ""

.PHONY: check_installed
check_installed: ## Check installed (node, yarn)
# ...

.PHONY: Install
install: check_installed ## Install as systemd unit service.\n    VARIABLES:\n      - DIR_BIN\n          Specify bin dir (default: "/usr/local/bin")\n      - UNIT_FILE_PATH\n          Path to create systemd unit file. (default: "/usr/local/bin")\n      - ENV_FILE_PATH\n          Path to create env file. (default: "/usr/local/etc/default/sample")
# ...
$ make help

help                     Display this help screen.
    VARIABLES:
      - TARGET
          Specify make target

check_installed          Check installed (node, yarn)

install                  Install as systemd unit service.
    VARIABLES:
      - DIR_BIN
          Specify bin dir (default: "/usr/local/bin")
      - UNIT_FILE_PATH
          Path to create systemd unit file. (default: "/usr/local/bin")
      - ENV_FILE_PATH
          Path to create env file. (default: "/usr/local/etc/default/sample")

Makefile ハマりポイント集

echo -n-n が出力されてしまう

問題のスクリプト

.PHONY: test
test:
	@echo -n "改行したくない!"
	@echo "改行されてるじゃん!!!"
$ make test
-n 改行したくない!
改行されてるじゃん!!!

修正後

.PHONY: test
test:
	@/bin/echo -n "改行したくない!"
	@echo "できた!"

or

.PHONY: test
test:
	@bash -c 'echo -n "改行したくない!"'
	@echo "できた!"
$ make test
改行したくない!できた!

原因

make には組み込みの echo が存在し、この echo-n を解読できないため

make 変数とシェル実行時の環境変数の扱い

make 変数ではなくシェル実行時の環境変数を参照したい

make 変数

VAR		?= make変数
.PHONY: test
test:
	@echo ${VAR}

環境変数

VAR		?= make変数
.PHONY: test
test:
	@VAR=環境変数 ; \
		echo $$VAR

for ループの中で環境変数を変えながら処理をしたい

分かり易い例が思いつかなかったので僕が使っているものを抜粋して紹介します。

パイプで渡された出力やファイルの内容の1行ずつを for ループで繰り返し処理する際に解析処理などによって変数の切り出しが複雑になる場合、一度変数保持用のファイルを作成すると記述が簡単になります。

.PHONY: build_cross
build_cross: get
	go tool dist list | grep 'aix\|darwin\|freebsd\|illumos\|linux\|netbsd\|openbsd\|windows' | while read line ; \
	do \
# .build.env ファイルに環境変数を一時的に保存する
		printf GOOS= > ./.build.env ; \
		echo $$line | cut -f 1 -d "/" >> ./.build.env ; \
		printf GOARCH= >> ./.build.env ; \
		echo $$line | cut -f 2 -d "/" >> ./.build.env ; \
# .build.env ファイルの環境変数を読み込んでコマンドを実行する
		. ./.build.env ; \
		go build GOOS=$$GOOS GOARCH=$$GOARCH -o ./${MODULE}-$$GOOS-$$GOARCH ;
	done
	rm ./.build.env
5
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?