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
May 09, 2024
Programming
15
5.1k
GNU Makeの使い方 / How to use GNU Make
研究室ハンズオン資料
kaityo256
May 09, 2024
Tweet
Share
More Decks by kaityo256
See All by kaityo256
論文紹介のやり方 / How to review
kaityo256
12
44k
デバッグの話 / Debugging for Beginners
kaityo256
9
1.2k
ビット演算の話 / Let's play with bit operations
kaityo256
5
350
制限ボルツマンマシンの話 / Introduction of RBM
kaityo256
3
1k
論文の読み方 / How to survey
kaityo256
219
160k
リンゴゲームと貧富の差 / Origin of the disparity of wealth
kaityo256
14
14k
渡辺研Slackの使い方 / Slack Local Rule
kaityo256
9
8.8k
時間の矢について / Time's arrow
kaityo256
12
17k
t-SNEをざっくりと理解 / Overview of t-SNE
kaityo256
2
1.6k
Other Decks in Programming
See All in Programming
データの整合性を保つ非同期処理アーキテクチャパターン / Async Architecture Patterns
mokuo
46
17k
Introduction to kotlinx.rpc
arawn
0
690
Conform を推す - Advocating for Conform
mizoguchicoji
3
690
GitHub Actions × RAGでコードレビューの検証の結果
sho_000
0
260
CNCF Project の作者が考えている OSS の運営
utam0k
6
710
第3回関東Kaggler会_AtCoderはKaggleの役に立つ
chettub
3
1k
一休.com のログイン体験を支える技術 〜Web Components x Vue.js 活用事例と最適化について〜
atsumim
0
410
密集、ドキュメントのコロケーション with AWS Lambda
satoshi256kbyte
0
190
第3回 Snowflake 中部ユーザ会- dbt × Snowflake ハンズオン
hoto17296
4
370
Linux && Docker 研修/Linux && Docker training
forrep
24
4.5k
データベースのオペレーターであるCloudNativePGがStatefulSetを使わない理由に迫る
nnaka2992
0
130
CI改善もDatadogとともに
taumu
0
110
Featured
See All Featured
Fireside Chat
paigeccino
34
3.2k
10 Git Anti Patterns You Should be Aware of
lemiorhan
PRO
656
59k
What’s in a name? Adding method to the madness
productmarketing
PRO
22
3.3k
Save Time (by Creating Custom Rails Generators)
garrettdimon
PRO
29
1k
Optimising Largest Contentful Paint
csswizardry
34
3.1k
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
233
17k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
248
1.3M
Bash Introduction
62gerente
611
210k
The Pragmatic Product Professional
lauravandoore
32
6.4k
Navigating Team Friction
lara
183
15k
Improving Core Web Vitals using Speculation Rules API
sergeychernyshev
9
440
No one is an island. Learnings from fostering a developers community.
thoeni
21
3.1k
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 まとめ 依存関係のあるタスクは原則として自動化する 「〇〇したら〇〇しなければならない」や 「〇〇の前には〇〇すること」は危険信号 データ処理などは原則として自動化しておく 便利のためというより、後の記録のために