---
# System prepended metadata

title: Makefile編寫要點
tags: [tutorials, C語言, Computer Science, 程式設計（一）]

---

# Makefile編寫要點
###### tags: `C語言` `Computer Science` `程式設計（一）`  `tutorials`
---
## Header File
+ 要編寫程式先將main.c(主程式)編成binary檔案
 ``` makefile
 gcc -c main.c -o main.o        
 ```
 再將函式檔編成binary檔
 ``` makefile 
 gcc -c mymax.c -o mymax.o       
 ```
 最後在compiler裏頭匯入
 ``` makefile  
gcc main.o mymax.o -o main     
 ```
 
+ gcc是整合型工具，所以也可以直接將.c檔案gcc執行，它會幫你自動做組譯到編譯，故可以直接利用
 ``` makefile 
gcc main.c mymax.o -o main.c  
 ```
當然也可以這樣
 ``` makefile 
gcc main.c mymax.c -o main.c  
 ```
>**但在大型程式中就無法判別哪裏出錯**

+ function的程式碼在mymax.c --> compile成mymax.o，再將mymax.o與main.o匯集成主程式檔，mymax.h只是用到的自訂義函數protorype(標頭檔)。
+  header file 需要去避免後面重複定義，因此要加上
 ``` makefile 
 #ifndef X included
 #define X 
 #endif
 ```
新版C語言可以直接使用pragma once避免重複定義，如下
 ``` makefile 
 #pragma once
 ```
 
## 靜態連結與動態連結
### 靜態連結寫法
+ all後方檢查檔案中是否有mymax.o及main.c
``` Makefile
all: mymax.o main.c 
    gcc main.c mymax.o -o main
		 
mymax.o: mymax.c
    gcc -c mymax.c -o mymax.o
```
### 動態連結寫法
+ L代表要搜尋的目錄位置，.代表當前目錄
 ``` Makefile
all: mymax.o main.c 
    gcc main.c -o main_dyn -L. lmymax
	 
mymax.o: mymax.c
    gcc -c mymax.c -o mymax.o
    gcc -shared mymax.o -o libmymax.so
		   (編成共享函式庫，so的s代表共享)
```

+ 若共享function在當前目錄，在執行時需加上
 LD_LIBRARY_PATH = ./ 
## 多函式、程式連結
### 基本、簡易方法
``` Makefile
 # use variable to store target objects
 obj = dep01.o dep02.o dep03.o dep04.o dep05.o entry.o
 # pass in variable
 all: $(obj)
     gcc -o hw$(obj)
 clean:
 	 rm *.o
```
### 進階寫法
+ wildcard 只會搜尋**當下資料夾**符合該pattern的檔案
   Ex: $(wildcard*.c) 
   會list all .c file under current directory
   
+ 如何把.c檔案取代成.o檔案
  Ex: $(SRC: .c = .o)
  會replace .c suffix with .o
  
+ automated variable把全部.o檔案link再一起使用$^
   代表all prerequisites, seperated by space
+ 利用Wildcard與$(SRC)與\$^寫法
``` Makefile
 # use variable to store target objects
 SRC = $(wildcard *.c)
 # pass in variable
 all: $(SRC:.c = .o)
    gcc -o res $^
 clean:
    rm  *.o res
```
### 多層目錄寫法
+ 多層資料夾需make時需要注意如下

 ```makefile
all: 
    cd 目標資料夾a && make # 不可分開寫要不然會造成無限迴圈
    cd 目標資料夾b && make # 不可分開寫要不然會造成無限迴圈
    cp 複製目標資料夾a路徑 複製目標檔案
    gcc -g -o 執行檔名稱 main.c -動態共享庫 -lm -L. -Wl, -rpath, `pwd`
clean:
    -rm main 動態共享庫.so 
    cd 目標資料夾a && make clean # 不可分開寫要不然會造成無限迴圈
    cd 目標資料夾b && make clean # 不可分開寫要不然會造成無限迴圈
```
