1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Makefile の冗長さを減らす define, call, eval, foreach (マクロ)

Last updated at Posted at 2023-02-23

前記事

前記事の続きという位置付けですが, 単独で読めると思います.

はじめに

複数ファイルで使うアルゴリズムやデータ構造は, 共通のソースファイルとヘッダファイルに切り出すと良い.

例えば union-find.(cpp|hpp)code_11_%.cppsolution_11_%.cpp から使われるときの Makefile は以下のように書ける.
しかし, code_11_%solution_11_% で同じようなルールを定義している部分が冗長である.

CXX := g++
CXX_BASE_FLAGS := -Wall -Wextra -std=c++20
CXXFLAGS := $(CXX_BASE_FLAGS) -lgtest_main -lgtest -lpthread

UNION_FIND_SRC := union-find.cpp
UNION_FIND_OBJ := $(UNION_FIND_SRC:.cpp=.o)
UNION_FIND_HDR := $(UNION_FIND_SRC:.cpp=.hpp)

TARGETS := $(basename $(wildcard *_[1-9]*_[1-9]*.cpp)) # ワイルドカードは適宜変更

.PHONY: clean

all: $(TARGETS)

# ↓ union-findを使うためのルールここから ↓
code_11_%: code_11_%.o $(UNION_FIND_OBJ)
	$(CXX) $(CXXFLAGS) $^ -o $@
solution_11_%: solution_11_%.o $(UNION_FIND_OBJ)
	$(CXX) $(CXXFLAGS) $^ -o $@

code_11_%.o: code_11_%.cpp $(UNION_FIND_HDR)
solution_11_%.o: solution_11_%.cpp $(UNION_FIND_HDR)
# ↑ union-findを使うためのルールここまで ↑

$(UNION_FIND_OBJ): $(UNION_FIND_SRC) $(UNION_FIND_HDR)

.cpp.o:
	$(CXX) $(CXX_BASE_FLAGS) -c $<

clean:
	$(RM) $(TARGETS) $(UNION_FIND_OBJ)

冗長さを減らす

そこで, 以下のようにdefine, call, eval, foreach を使いマクロで冗長さを減らせる. 1 2

CXX := g++
CXX_BASE_FLAGS := -Wall -Wextra -std=c++20
CXXFLAGS := $(CXX_BASE_FLAGS) -lgtest_main -lgtest -lpthread

UNION_FIND_SRC := union-find.cpp
UNION_FIND_OBJ := $(UNION_FIND_SRC:.cpp=.o)
UNION_FIND_HDR := $(UNION_FIND_SRC:.cpp=.hpp)

TARGETS := $(basename $(wildcard *_[1-9]*_[1-9]*.cpp)) # ワイルドカードは適宜変更
TARGETS_WITH_UNION_FIND := code_11_% solution_11_%  # ← ★追加

.PHONY: clean

all: $(TARGETS)

# ↓★書き換えココから↓
define CXX_WITH_UNION_FIND
$(1): $(1).o $(UNION_FIND_OBJ)
	$$(CXX) $$(CXXFLAGS) $$^ -o $$@

$(1).o: $(1).cpp $(UNION_FIND_HDR)
endef

$(foreach T, $(TARGETS_WITH_UNION_FIND), $(eval $(call CXX_WITH_UNION_FIND, $(T))))
# ↑★書き換えココまで↑

$(UNION_FIND_OBJ): $(UNION_FIND_SRC) $(UNION_FIND_HDR)

.cpp.o:
	$(CXX) $(CXX_BASE_FLAGS) -c $<

clean:
	$(RM) $(TARGETS) $(UNION_FIND_OBJ)

確認

make -np すると, 以下のように期待どおりにルールが展開されている.

抜粋
$ make -np
.
.
.
code_11_%: code_11_%.o union-find.o
#  commands to execute (from `Makefile', line 22):
    $(CXX) $(CXXFLAGS) $^ -o $@
    

code_11_%.o: code_11_%.cpp union-find.hpp

solution_11_%: solution_11_%.o union-find.o
#  commands to execute (from `Makefile', line 22):
    $(CXX) $(CXXFLAGS) $^ -o $@
    

solution_11_%.o: solution_11_%.cpp union-find.hpp
.
.
.

make すると, 以下のように期待どおりにコンパイルされる.

出力例
$ make
g++ -Wall -Wextra -std=c++20 -c union-find.cpp
g++ -Wall -Wextra -std=c++20 -c code_11_03.cpp
g++ -Wall -Wextra -std=c++20 -lgtest_main -lgtest -lpthread code_11_03.o union-find.o -o code_11_03
g++ -Wall -Wextra -std=c++20 -c solution_11_01.cpp
g++ -Wall -Wextra -std=c++20 -lgtest_main -lgtest -lpthread solution_11_01.o union-find.o -o solution_11_01
rm code_11_03.o solution_11_01.o
  1. けど読みづらい…ので他に良い書き方があれば募集してます.

  2. $$$ をエスケープできる

1
0
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
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?