一文了解MakeFile

Makefile 做爲編譯c/c++ 的腳本語言,須要瞭解一下他的規則。html

  1. 語法規則
  2. <@ $^ 等是什麼意思
  3. @ - 表明什麼意義
  4. 部分api,eg:subpath【替換字符串】 addfix【添加前綴】
  5. ?= := 等
  6. .phony 的意義
  7. 執行make的流程

如下源碼,放到個人github上面,有須要的能夠上面去查看c++

語法規則

語法:git

目標: 依賴項
<tab鍵> 執行項
複製代碼

例子:github

say_hello:
        @echo "Hello World"
generate:say_hello
        @echo "Creating empty text files..."
        touch file-{1..10}.txt
clean:
        @echo "Cleaning up..."
        rm *.txt
複製代碼

執行流程

默認執行第一個目標shell

能夠經過 .DEFAULT_GOAL := generate 來進行修改api

或者 all: say_hello generate 來修改bash

變量

# 聲明變量
a = 1
b := 1
# 使用變量
echo ${a} 
echo $(a)
複製代碼

邏輯語句

conditional-directive-one
	text-if-one-is-true
else conditional-directive-two
	text-if-two-is-true
else
	text-if-one-and-two-are-false
endif

# conditional-directive 爲下面四種方法的任意一種
ifeq 'arg1' 'arg2' # 這兩種寫法都是能夠的 帶括號和不帶括號
ifneq (arg1, arg2) 

ifdef variable-name # 判斷某個值是否有值
ifndef variable-name
複製代碼

若是要在目標中寫條件語句,則使用shell語法的條件判斷。惟一不一樣,則是每一行都須要寫分號,查看這裏微信

eg:函數

# 不在目標項中
 ifeq ("x${x}", "x")
     @echo "judge success"
 endif
 
 t2:
 	# 注意都每一個執行命令都須要 ";" 
     if [ x = x"${xx}" ] ; then \
         @echo "same"; \ 
     else \
         @echo "different"; \
     fi
複製代碼

$< $@ $^ 等是什麼意思

$@:目標的名字ui

$^:依賴項的全部名字

$<:依賴項的第一個名字

$?:構造所需文件列表中更新過的文件

%: %.o
        @echo "Checking.."
        ${CC} ${LINKERFLAG} $< -o $@
複製代碼

% 表示% can match any target name

假定有一個目標是:foo,則上例被翻譯成

foo: foo.o
        @echo "Checking.."
        gcc -lm foo.o -o foo
複製代碼

@ - 表明什麼意義

@ 表示不會打印出即將執行的命令

- 表示即便該執行語句出錯,也能夠繼續運行

t1:
    @echo hello # 不會打印該語句,只會打印結果
    -mkdir test # 若是建立不了,則會報錯
t2:
    echo hello # 不只會打印該語句,還會打印結果
    mkdir test # 若是建立不了,則會報錯,並中止運行
複製代碼

= := 區別

= 代表定義的變量使用的時候才展開

:= 代表當即展開,不用等到使用的時候再展開

eg:

FOO = $(BAR) # 延遲賦值,使用到的時候,會去判斷BAR的值在哪裏,若是找到則賦值
BAR = bar

CC = gcc
CC = ${CC} # 這個地方會致使死循環,堆棧溢出

all:
    @echo ${CC}
複製代碼

FOO := $(BAR) # 當即賦值,此時爲空
BAR = bar

CC := gcc
CC := ${CC}

all:
    @echo ${CC}
複製代碼

.phony 的意義

.PHONY, 僞目標項,不管是否有同名的文件

若是你沒有加僞目標項,那麼若是有和目標項同名的文件,則不會執行該目標項,會報: make: 'xxx' is up to date.

若是增長 .PHONY 則必定會執行Makefile 的目標項

經常使用函數,部分api

${function arguments}
# or
$(function arguments)
複製代碼

$(subst 要被替換的字符串,用來替換的字符串,被處理的字符串)

$(subst from**,to,text)**

$(patsubst pattern**,replacement,var)** 能夠經過模式匹配進行替換

$(var:pattern=replacement) 和上面是一個意思

$(wildcard 尋找的文件)

$(wildcard pattern**)** 按照模式匹配進行查找

$(abspath names**…)** 絕對路徑

$(addprefix prefix**,names…) **表示添加前綴

$(addsuffix suffix**,names…)** 表示添加後綴

$(foreach var,list,text **) ** 遍歷

dirs := a b c d
files := $(foreach dir,$(dirs),$(wildcard $(dir)/*))
複製代碼
# 表示將$(LOCAL_SRC_FILES) 中的.cpp 替換成 .o 而且增長前綴 $(OUT_OBJ_DIR)/
LOCAL_OBJ_FILES = $( addprefix $(OUT_OBJ_DIR)/,$(LOCAL_SRC_FILES) ) 
LOCAL_DEP_FILES = $( patsubst %.o,%.o.d,$(LOCAL_OBJ_FILES)複製代碼

經驗:

若是執行的語句有前後關係,則可使用 進行遞進,若是不是同一行 ,則須要使用 \ 進行鏈接

t1:
	cd t1; \
	-mkdir t2 # 表示進入到t1 文件夾再建立t2 文件夾
	
複製代碼

FAQ

**{}** 和 **() **的區別

這個問題能夠查看 這裏 ,大意是,在make中沒有區別,只在makefile傳遞給make的時候有區別,$$() 表示會在shell中先執行() 裏面的東西,而後咱們可使用返回值

你能夠新建一個Makefile ,裏面的target長的像下面這個樣子:而後你就會發現不一樣

all: 
     @echo ${pwd}
     @echo $${pwd}
     @echo $(pwd)
     @echo $$(pwd) # 只有這個會執行
     @echo $(shell pwd) # 和上面一致,是使用shell的命令
複製代碼

參考

make file

makefile 官網

嘿關注一波微信公衆號唄

相關文章
相關標籤/搜索