Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Speaker Deck
PRO
Sign in
Sign up for free
GNU Makeの使い方 / How to use GNU Make
kaityo256
PRO
May 13, 2021
Programming
11
3.7k
GNU Makeの使い方 / How to use GNU Make
研究室ハンズオン資料
kaityo256
PRO
May 13, 2021
Tweet
Share
More Decks by kaityo256
See All by kaityo256
数値計算屋のためのGit入門 / Starting Git
kaityo256
PRO
20
8.4k
マルコフ連鎖モンテカルロ法の気持ち / Markov Chain Monte Carlo
kaityo256
PRO
4
1.2k
気液界面と自由エネルギー / Gas Liquid Surface
kaityo256
PRO
1
580
Dockerで体験する富岳のアーキテクチャ「AArch64」ハンズオン / Xbyak_aarch64 handson
kaityo256
PRO
3
590
演習:GitHubの操作(応用編) / GitHub Practice Github Advanced
kaityo256
PRO
2
400
演習:GitHubの操作(基本編) / GitHub Practice Github Basic
kaityo256
PRO
1
890
演習:Gitの操作(応用編) / GitHub Practice Advanced
kaityo256
PRO
0
280
演習:Gitの操作(基本編) / GitHub Practice Basic
kaityo256
PRO
0
660
条件分岐と繰り返し処理 / Python Basic
kaityo256
PRO
1
1.6k
Other Decks in Programming
See All in Programming
Named Document って何?
harunakano
0
430
Better Reliability through Observability (and Experimentation)
ksatirli
PRO
1
280
全国の中高生がプログラミングを学んでいるCloud9環境の仕組み@JAWS-UG_SRE支部_#3
asache3
0
120
書籍『良いコード/悪いコードで学ぶ設計入門』でエンジニアリングの当たり前を変える
minodriven
3
1.1k
【Qiita Night】新卒エンジニアによるSwift6与太予想
eiji127
0
180
tfcon2022_Web3Dひとめぐり.pdf
emadurandal
0
1k
확장 가능한 테라폼 코드 관리 (Scalable Terraform Code Management)
posquit0
1
320
The future of trust stores in Python
sethmlarson
0
180
よりUXに近いSLI・SLOの運用による可用性の再設計
kazumanagano
3
670
byte列のbit表現を得るencodingライブラリ作った
convto
1
170
デュアルトラックアジャイル× Agile Testingから 見えてきたQAのミライ
atamaplus
0
370
既存画面の Jetpack Composeでの書き換え: FAANSでの事例紹介 / Case study of rewriting existing screens with Jetpack Compose
horie1024
0
160
Featured
See All Featured
Support Driven Design
roundedbygravity
86
8.5k
Music & Morning Musume
bryan
35
4.1k
KATA
mclloyd
7
8.6k
Navigating Team Friction
lara
175
11k
In The Pink: A Labor of Love
frogandcode
130
21k
BBQ
matthewcrist
74
7.9k
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
212
20k
Creatively Recalculating Your Daily Design Routine
revolveconf
205
10k
Streamline your AJAX requests with AmplifyJS and jQuery
dougneiner
125
8.5k
Designing for humans not robots
tammielis
241
23k
Designing on Purpose - Digital PM Summit 2013
jponch
106
5.6k
The MySQL Ecosystem @ GitHub 2015
samlambert
238
11k
Transcript
1 GNU Makeの使い方 慶應義塾大学理工学部物理情報工学科 渡辺 2021/5/13 ハンズオン用リポジトリ https://github.com/kaityo256/make_tutorial
2 • プログラムのビルドを自動化してくれる • 依存関係を認識してくれる • インストールなどの作業も自動化できる ビルドツールの一つ コード開発にはビルドツールは必須 他には、CMake、Rake
(Ruby)、 SCons (Python)、Ant (Java)など多数
3 人間は間違える生き物だから
4 装置AとBからなるシステムがあり Aの電源を入れてからBの電源を 入れないとBが壊れてしまう 装置A 装置B
5 テプラによる注意喚起 ↓ 装置Bの電源確認!!! ←Bが上がるまで押さない!
6 ↓ 装置Bの電源確認!!! 危機管理を人間の注意力に依存してはならない ←Bが上がるまで押さない!
7 「これを押せば良い」というボタンを一つ作る とにかくボタンを押せば よしなに解決してくれる のひとつ
8 「これを押せば良い」というボタンを一つ作る 装置Bをチェック OFFなら電源ON 装置Bが立ち上がったら 装置Aの電源ON 内部では依存関係を認識し、正しく処理 のひとつ
9 Makeでは、条件とコマンドを「ルール」として記述する ルールは、ターゲット、前提条件、コマンドから構成される ターゲット: 前提条件 コマンド ターゲット 実現したいこと、作りたいもの 前提条件 実現していなければならないこと
コマンド 前提条件が満たされているとき、 ターゲットを作るために必要なこと タブ
10 以下の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 ビルド方法 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 まずは手順をそのまま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 カレントディレクトリにMakefile/makefileがある状態で makeを実行 $ make g++ -c main.cpp g++ -c
sub.cpp g++ main.o sub.o ビルドが実行される makeは、ファイルを指定しないと Makefileもしくはmakefileを探しに行く
14 all: a.out 引数なしで実行した場合、暗黙に「all」と いうターゲットを指定したことになる 最終的に欲しい物をallの前提条件として書く ターゲット 前提条件 コマンド なし
15 a.out: main.o sub.o g++ main.o sub.o ターゲット 前提条件 コマンド
a.outを作りたい そのためには main.oとsub.oが要る main.oとsub.oが用意できたら リンクしてa.outを作る
16 main.o: main.cpp g++ -c main.cpp ターゲット 前提条件 コマンド main.oを作りたい
main.oが無いか、main.cppより 古ければ作り直す main.cppからmain.oを作る方法
17 ビルドをきれいにするルール「クリーン」を作る clean: rm -f a.out *.o ターゲット ビルドをきれいにしたい(clean) コマンド
中間ファイルや最終ターゲットを削除 前提条件 なし make clean make これでクリーンビルドできる
18 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 Don't Repeat Yourself 同じような記述を繰り返してはならない ※ 例えば一部を修正した場合、残りの修正忘れが発生するから
20 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 %.o: %.cpp a.out: main.o sub.o a.outを作るにはmain.oが必要 マッチ マッチにより%=mainと展開 main.o:
main.cpp
22 main.o: main.cpp g++ -c $< 依存関係の一番左に展開される main.cpp 他には・・・ $@
ターゲット名に展開 (main.o) $* パターンがマッチした部分 (main) 等多数 ※ 気になったら「make 自動変数」で検索してください
23 %.o: %.cpp g++ -c $< ターゲットとしてmain.oがマッチ main.o: main.cpp g++
-c main.cpp sub.oも同様
24 コンパイルとリンクで 同じコマンドを使っている 別のコンパイラを使う時、二か所を修正しなければならない 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 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 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 がんばって人間が依存関係を書く ツールに自動的に依存関係を抽出させる 人間のミスを防ぐための仕組みを 人間が作るのはナンセンス
28 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 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 大量のデータをスクリプトで変換したい 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 INPUTS=$(shell ls input*.dat) OUTPUTS=$(INPUTS:input%=output%) all: $(OUTPUTS) output%: input% python
convert.py < $< > $@ clean: rm -f $(OUTPUTS) こんなMakefileを書けばmake一発で変換できる
32 INPUTS=$(shell ls input*.dat) 実行結果を変数に代入する INPUTS=input0.dat input1.dat input2.dat … input9.dat
33 OUTPUTS=$(INPUTS:input%=output%) 別の変数を、パターンマッチにより置換する INPUTS=input0.dat input1.dat … input9.dat OUTPUTS=output0.dat output1.dat …
output9.dat
34 all: output0.dat output1.dat … output%: input% python convert.py <
$< > $@ マッチ output0.dat: input0.dat python convert.py < $< > $@ % = 0.dat input0.dat output0.dat
35 更新されたファイルのみ変換されて効率的 make –j による並列ビルドができて便利 データの変換方法が記録として残る 三日後の自分は他人 「データフォルダでmakeすればよい」とだけ 覚えておけば良いので、判断力を消費しない ※
makeではなくシェルスクリプトでも良いから、とにかく自動化&保存
36 PDF TeX データファイル データファイル gnuplot python 画像ファイル 画像ファイル コンパイル
最初に精度の低いデータで図を作っておいて、後から 本番の図に差し替える時等に便利 依存関係と処理をMakefileに記述しておけば、データの 更新から論文PDFまでmake一発で行く
37 依存関係のあるタスクは原則として自動化する 「〇〇したら〇〇しなければならない」や 「〇〇の前には〇〇すること」は危険信号 データ処理などは原則として自動化しておく 便利のためというより、後の記録のために