Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
GNU Makeの使い方 / How to use GNU Make
Search
kaityo256
PRO
May 09, 2024
Programming
15
5.4k
GNU Makeの使い方 / How to use GNU Make
研究室ハンズオン資料
kaityo256
PRO
May 09, 2024
Tweet
Share
More Decks by kaityo256
See All by kaityo256
生成AIとの付き合い方 / Generative AI and us
kaityo256
PRO
7
1.3k
モンテカルロ法(3) 発展的アルゴリズム / Simulation 04
kaityo256
PRO
8
1.5k
UMAPをざっくりと理解 / Overview of UMAP
kaityo256
PRO
6
2.6k
SSH公開鍵認証による接続 / Connecting with SSH Public Key Authentication
kaityo256
PRO
6
580
論文紹介のやり方 / How to review
kaityo256
PRO
17
86k
デバッグの話 / Debugging for Beginners
kaityo256
PRO
15
1.7k
ビット演算の話 / Let's play with bit operations
kaityo256
PRO
8
610
制限ボルツマンマシンの話 / Introduction of RBM
kaityo256
PRO
3
1.4k
論文の読み方 / How to survey
kaityo256
PRO
229
180k
Other Decks in Programming
See All in Programming
タスクの特性や不確実性に応じた最適な作業スタイルの選択(ペアプロ・モブプロ・ソロプロ)と実践 / Optimal Work Style Selection: Pair, Mob, or Solo Programming.
honyanya
3
140
Model Pollution
hschwentner
1
180
overlayPreferenceValue で実現する ピュア SwiftUI な AdMob ネイティブ広告
uhucream
0
110
アメ車でサンノゼを走ってきたよ!
s_shimotori
0
140
iOSDC.pdf
chronos2500
2
660
プログラミングどうやる? ~テスト駆動開発から学ぶ達人の型~
a_okui
0
190
なぜあの開発者はDevRelに伴走し続けるのか / Why Does That Developer Keep Running Alongside DevRel?
nrslib
3
370
ネイティブ製ガントチャートUIを作って学ぶUICollectionViewLayoutの威力
jrsaruo
0
130
『毎日の移動』を支えるGoバックエンド内製開発
yutautsugi
2
180
(Extension DC 2025) Actor境界を越える技術
teamhimeh
1
220
10年もののAPIサーバーにおけるCI/CDの改善の奮闘
mbook
0
770
Pythonスレッドとは結局何なのか? CPython実装から見るNoGIL時代の変化
curekoshimizu
4
1.3k
Featured
See All Featured
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
234
17k
Fireside Chat
paigeccino
40
3.7k
Building Adaptive Systems
keathley
43
2.8k
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
46
7.6k
How GitHub (no longer) Works
holman
315
140k
Faster Mobile Websites
deanohume
310
31k
The Pragmatic Product Professional
lauravandoore
36
6.9k
Making Projects Easy
brettharned
119
6.4k
Build your cross-platform service in a week with App Engine
jlugia
232
18k
Making the Leap to Tech Lead
cromwellryan
135
9.5k
The Cult of Friendly URLs
andyhume
79
6.6k
It's Worth the Effort
3n
187
28k
Transcript
1 37 GNU Makeの使い方 慶應義塾大学理工学部物理情報工学科 渡辺 ハンズオン用リポジトリ https://github.com/kaityo256/make_tutorial
2 37 Makeとはなにか • プログラムのビルドを自動化してくれる • 依存関係を認識してくれる • インストールなどの作業も自動化できる ビルドツールの一つ
コード開発にはビルドツールは必須 他には、CMake、Rake (Ruby)、 SCons (Python)、Ant (Java)など多数
3 37 なぜビルドツールが必要か? 人間は間違える生き物だから
4 37 依存関係のあるタスク 装置AとBからなるシステムがあり Aの電源を入れてからBの電源を 入れないとBが壊れてしまう 装置A 装置B
5 37 ありがちな解決策 テプラによる注意喚起 ↓ 装置Bの電源確認!!! ←Bが上がるまで押さない!
6 37 ありがちな解決策 ↓ 装置Bの電源確認!!! 危機管理を人間の注意力に依存してはならない ←Bが上がるまで押さない!
7 37 正しい解決策 「これを押せば良い」というボタンを一つ作る とにかくボタンを押せば よしなに解決してくれる のひとつ
8 37 正しい解決策 「これを押せば良い」というボタンを一つ作る 装置Bをチェック OFFなら電源ON 装置Bが立ち上がったら 装置Aの電源ON 内部では依存関係を認識し、正しく処理 のひとつ
9 37 ルール Makeでは、条件とコマンドを「ルール」として記述する ルールは、ターゲット、前提条件、コマンドから構成される ターゲット: 前提条件 コマンド ターゲット 実現したいこと、作りたいもの
前提条件 実現していなければならないこと コマンド 前提条件が満たされているとき、 ターゲットを作るために必要なこと タブ
10 37 C++の分割コンパイル 以下の3つのファイルを考える #include "param.hpp" #include <cstdio> void show(void);
int main(void) { printf("main: N is %d¥n", N); show(); } const int N = 10; #include "param.hpp" #include <cstdio> void show(void){ printf("sub: N is %d¥n",N); } param.hpp main.cpp sub.cpp
11 37 C++の分割コンパイル ビルド方法 g++ -c main.cpp g++ -c sub.cpp
g++ main.o sub.o 依存関係 param.hpp main.cpp sub.cpp main.o sub.o a.out インクルード コンパイル コンパイル リンク
12 37 C++の分割コンパイル まずは手順をそのままMakefileに書く all: a.out a.out: main.o sub.o g++
main.o sub.o main.o: main.cpp g++ -c main.cpp sub.o: sub.cpp g++ -c sub.cpp Makefile
13 37 C++の分割コンパイル カレントディレクトリにMakefile/makefileがある状態で makeを実行 $ make g++ -c main.cpp
g++ -c sub.cpp g++ main.o sub.o ビルドが実行される makeは、ファイルを指定しないと Makefileもしくはmakefileを探しに行く
14 37 C++の分割コンパイル all: a.out 引数なしで実行した場合、暗黙に最初の ターゲットを指定したことになる 最終的に欲しい物をallの前提条件として書く ターゲット 前提条件
コマンド なし ※デフォルトターゲットが未指定の場合
15 37 C++の分割コンパイル a.out: main.o sub.o g++ main.o sub.o ターゲット
前提条件 コマンド a.outを作りたい そのためには main.oとsub.oが要る main.oとsub.oが用意できたら リンクしてa.outを作る
16 37 C++の分割コンパイル main.o: main.cpp g++ -c main.cpp ターゲット 前提条件
コマンド main.oを作りたい main.oが無いか、main.cppより 古ければ作り直す main.cppからmain.oを作る方法
17 37 C++の分割コンパイル ビルドをきれいにするルール「クリーン」を作る clean: rm -f a.out *.o ターゲット
ビルドをきれいにしたい(clean) コマンド 中間ファイルや最終ターゲットを削除 前提条件 なし make clean make これでクリーンビルドできる
18 37 C++の分割コンパイル all: a.out a.out: main.o sub.o g++ main.o
sub.o main.o: main.cpp g++ -c main.cpp sub.o: sub.cpp g++ -c sub.cpp clean: rm -f a.out *.o cleanも追加したMakefile 似たような記述が繰り返されている
19 37 DRY原則 Don't Repeat Yourself 同じような記述を繰り返してはならない ※ 例えば一部を修正した場合、残りの修正忘れが発生するから
20 37 パターンルール all: a.out a.out: main.o sub.o g++ main.o
sub.o main.o: main.cpp g++ -c main.cpp sub.o: sub.cpp g++ -c sub.cpp clean: rm -f a.out *.o all: a.out a.out: main.o sub.o g++ main.o sub.o %.o: %.cpp g++ -c $< clean: rm -f a.out *.o まとめる
21 37 パターンルール %.o: %.cpp a.out: main.o sub.o a.outを作るにはmain.oが必要 マッチ
マッチにより%=mainと展開 main.o: main.cpp
22 37 自動変数(マクロ) main.o: main.cpp g++ -c $< 依存関係の一番左に展開される main.cpp
他には・・・ $@ ターゲット名に展開 (main.o) $* パターンがマッチした部分 (main) 等多数 ※ 気になったら「make 自動変数」で検索してください
23 37 パターンルール %.o: %.cpp g++ -c $< ターゲットとしてmain.oがマッチ main.o:
main.cpp g++ -c main.cpp sub.oも同様
24 37 変数 コンパイルとリンクで 同じコマンドを使っている 別のコンパイラを使う時、二か所を修正しなければならない DRY原則に反する all: a.out a.out:
main.o sub.o g++ main.o sub.o %.o: %.cpp g++ -c $< clean: rm -f a.out *.o
25 37 変数 CXX=g++ all: a.out a.out: main.o sub.o $(CXX)
main.o sub.o %.o: %.cpp $(CXX) -c $< clean: rm -f a.out *.o all: a.out a.out: main.o sub.o g++ main.o sub.o %.o: %.cpp g++ -c $< clean: rm -f a.out *.o CXXという変数を定義し、g++という値を代入 コンパイラを変更する場合は、一か所だけ修正すればよくなった 使う時は$(変数名)とする
26 37 依存関係 all: a.out CXX=g++ a.out: main.o sub.o $(CXX)
main.o sub.o %.o: %.cpp $(CXX) -c $< clean: rm -f a.out *.o このMakefileには、param.hppの依存関係が正しく入っていない 依存関係をmakeにどうやって教えるか?
27 37 依存関係 がんばって人間が依存関係を書く ツールに自動的に依存関係を抽出させる 人間のミスを防ぐための仕組みを 人間が作るのはナンセンス
28 37 依存関係 g++はMake用の依存関係を出力できる $ g++ -MM *.cpp main.o: main.cpp
param.hpp sub.o: sub.cpp param.hpp $ g++ -MM *.cpp > makefile.dep ファイルにリダイレクトして Makefileにインクルードする -include makefile.dep
29 37 完成 all: a.out CXX=g++ a.out: main.o sub.o $(CXX)
main.o sub.o %.o: %.cpp $(CXX) -c $< clean: rm -f a.out *.o -include makefile.dep ※ 依存関係を自動で作ったり、ソースファイルを自動で取得したり、 まだ自動化できる部分はいろいろある
30 37 makeの応用例:データ処理 大量のデータをスクリプトで変換したい input0.dat input1.dat input2.dat input3.dat … input9.dat
output0.dat output1.dat output2.dat output3.dat … output9.dat convert.py python convert.py < input0.dat > output0.dat python convert.py < input1.dat > output1.dat python convert.py < input2.dat > output2.dat …
31 37 makeの応用例:データ処理 INPUTS=$(shell ls input*.dat) OUTPUTS=$(INPUTS:input%=output%) all: $(OUTPUTS) output%:
input% python convert.py < $< > $@ clean: rm -f $(OUTPUTS) こんなMakefileを書けばmake一発で変換できる
32 37 シェル関数 INPUTS=$(shell ls input*.dat) 実行結果を変数に代入する INPUTS=input0.dat input1.dat input2.dat
… input9.dat
33 37 変数の置換 OUTPUTS=$(INPUTS:input%=output%) 別の変数を、パターンマッチにより置換する INPUTS=input0.dat input1.dat … input9.dat OUTPUTS=output0.dat
output1.dat … output9.dat
34 37 パターンルール all: output0.dat output1.dat … output%: input% python
convert.py < $< > $@ マッチ output0.dat: input0.dat python convert.py < $< > $@ % = 0.dat input0.dat output0.dat
35 37 Makeによるデータ処理 更新されたファイルのみ変換されて効率的 make –j による並列ビルドができて便利 データの変換方法が記録として残る 三日後の自分は他人 「データフォルダでmakeすればよい」とだけ
覚えておけば良いので、判断力を消費しない ※ makeではなくシェルスクリプトでも良いから、とにかく自動化&保存
36 37 Makeによる論文ビルド PDF TeX データファイル データファイル gnuplot python 画像ファイル
画像ファイル コンパイル 最初に精度の低いデータで図を作っておいて、後から 本番の図に差し替える時等に便利 依存関係と処理をMakefileに記述しておけば、データの 更新から論文PDFまでmake一発で行く
37 37 まとめ 依存関係のあるタスクは原則として自動化する 「〇〇したら〇〇しなければならない」や 「〇〇の前には〇〇すること」は危険信号 データ処理などは原則として自動化しておく 便利のためというより、後の記録のために