Makefileの書き方

# Makefileの書き方

沢山のライブラリーを使うCやC++をビルドするときに便利なmake。
makeするには対象のMakefileが必要なのだが、今回はその書き方を紹介する。

## Makefileとは
　複数のソースファイルから構成されるプログラムをビルドする際、ビルドに用いるコマンドを記憶したり修正するのは難しい。Makefileにはコンパイラー、ソースファイル、生成物、ビルド順序、それら依存性などを記述し、makeするだけでビルドできる。その中身を見ることでプログラムのビルドの仕方がわかる。またmakeは更新が必要なファイルを自動的に決定し、コンパイル回数を最小限にしてくれ、開発時間の短縮につながる。

有名なGNUが提供する**GNU Make**のHome Pageによると、Makeとは以下のようなToolらしい。
GNU Make is a tool which controls the generation of executables and other non-source files of a program from the program's source files.
これによると以下のようなメリットがあるようだ。

- **エンドユーザーは、その方法の詳細を知らなくてもパッケージをビルドおよびインストールできる。**
- **変更されたソースファイルに基づいて、更新が必要なファイルを自動的に把握し、また適切な順序を自動的に決定する。**
- **MakeはC言語だけでなく、その他のコンパイル言語にも対応している。**

https://www.gnu.org/software/make/

## 書き方の基本的なルール
ビルドする際に用いるコマンドを以下のルールに基づいて記述する。

```
Target：SourceFile
[ Tab ]Command
```
```makefile
hello: hello.c
	gcc -o hello hello.c
```
また、生成ファイルの削除やコピーも記述することができる。

```makefile
clean: rm -f *~ hello 
install: hello 
	install -s hello.exe Path
```
makeする際に何も引数をつけない場合、一番上のTargetを実行する。
上記のcleanやinstallを実行したい場合は、以下のように引数を指定する。

```
make clean
make install
```
Makefile以外のファイルをMakefileとして対象にする場合は、-fオプションで以下のように実行できる。

```
 make -f sample.mk
```

また、要素を変数として扱える。簡単な例を以下に示す。

```makefile
CXX            = g++
OPTIMIZE       = -O3
CFLAGS         = -IC:/Users/include \
	-IC:/Python/include 
DEST           = C:/Users/Local
LDFLAGS        = -LC:/Users/Local/libs
LIBS           = -lpython
OBJS           = hello

all: clean $(PROGRAM) install
$(PROGRAM): $(OBJS)
	$(CXX) -o $(OBJS) $(OBJS).cpp $(CFLAGS) $(LDFLAGS) $(LIBS)
clean: rm -f *~ $(OBJS)
install: $(PROGRAM)
	install -s $(OBJS).exe $(DEST)
```

## Makefileの関数
MakeにはMakefile内の文字列処理や条件分岐をするための関数がある。主なものを以下の紹介する。

https://www.gnu.org/software/make/manual/html_node/Functions.html
### notdir(ファイル名取得)
```
"$(notdir ./dir/hoge.txt)"//hoge.txt
```
### realpath(存在するフルパス取得)
```
"$(realpath ./dir/hoge.txt)"//C:users/hoge/bin/hoge.txt
```
### suffix(拡張子取得)
```
"$(suffix ./dir/hoge.txt)"//.txt
```
### wildcard(ワイルドカードを使い存在するファイル名を取得)
```
"$(suffix ./dir/*.txt)"//hoge.txt hogehoge.txt
```
### if(条件分岐)
```
"$(if $(VAR1),$(exist),$(none))"
```
### ifeq(条件分岐の別の書き方)
```
ifeq ($(CC),gcc)
  libs=$(libs_for_gcc)
else
  libs=$(normal_libs)
endif
```

## g++とmakeとcmakeのinstall方法
Windows OSでは、**g++/gcc**は**MinGW**を、**make**は**GnuWin**を、**cmake**は**cmake.zip**installすることで使うことが出来る。

 - GUIで g++ をinstall
[MinGW install](https://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win32/Personal%20Builds/mingw-builds/installer/mingw-w64-install.exe/download)
もしくは
[MinGW install](https://ja.osdn.net/projects/mingw/downloads/68260/mingw-get-setup.exe/)
からinstallerをDownloadしてinstallする。

 - GUIで make をinstall
[Make install](http://gnuwin32.sourceforge.net/packages/make.htm)からinstallerをDownloadしてinstallする。
```C:Program Files (x86)¥GnuWin32¥bin```へパスを通す

 - GUIで cmake をinstall
[CMake install](https://cmake.org/download/)からinstallerをDownloadしてinstallする。

 - CUIで g++ & make をinstall  

```
choco install mingw
choco install make
```

Linuxでは以下のコマンド。

```terminal:terminal
//まとめてinstall
sudo apt install build-essential
//個別にinstall
sudo apt install g++
sudo apt install make
```

 - 環境変数の設定  
以下のpathなどにinstallされるので、pathを通す。  
C:\Program Files (x86)\MinGW\bin  
C:\Program Files (x86)\GnuWin32\bin

## まとめ
Makefileの書き方についてまとめてみた。備忘録として更新していく。