聲明:如果涉及侵權,請聯繫本人刪除侵權內容。
聲明:本文由本人以以往工作經驗爲依據,總結而得,如有錯誤,歡迎指正,便於後人參考,少走彎路。
Demo Makefile文件請移步github:Demo Makefile。
在開發過程中經常需要交叉編譯,這就會面臨如下問題:
- 直接用"gcc"、"g++"、"arm-gcc"、"arm-g++"編譯,每次都要敲命令行,太繁瑣;
- 針對不同的編譯工具:"gcc"、"g++"、"arm-gcc"、"arm-g++",不同的文件類型:".c"和".cpp",寫四個Makefile處理,需要在使用時區分,還是繁瑣;
- 用一個Makefile來處理,需要優化,優化如下。
目錄
1. 共用處理
共用的變量,標誌放在開始位置
TARGET := App #1
LOCAL_LDFLAGS := -lpthread #2
LOCAL_LDFLAGS += -W
MAP_FILE_NAME := $(TARGET) #3
LOCAL_LDFLAGS += -Wl,-Map=./$(MAP_FILE_NAME).map
- #1:定義終極目標爲:APP
- #2:添加鏈接選項到:LOCAL_LDFLAGS
- #3:實現".map"文件生成
2. 分支處理
分支處理可以用兩種方式實現,我採用第二種
- 方式一:
ifeq ()
# 分支一
endif
ifeq ()
# 分支二
endif
ifeq ()
# 分支三
endif
ifeq ()
# 分支四
endif
- 方式二:
ifeq ()
# 分支一
else ifeq ()
# 分支二
else ifeq ()
# 分支三
else ifeq ()
# 分支四
endif
2.1. x86_gcc分支
這個分支的應用場景:
- 編譯工具:gcc
- 編譯文件類型:.c
# x86_gcc ###################################################
ifeq ($(tool),x86_gcc) #1
SRCS := $(shell ls *.c) #2
OBJS := $(patsubst %.c,%.o,$(SRCS)) #3
CC := gcc #4
$(TARGET) : $(OBJS) #5
$(CC) -o $@ $^ $(LOCAL_LDFLAGS)
%.o:%.c
$(CC) -c -o $@ $< $(LOCAL_LDFLAGS)
- #1:
make tool=
中給tool
賦值x86_gcc
; - #2:獲取源文件
- #3:轉換目標文件
- #4:確定編譯工具
- #5:編譯
2.2. x86_g++分支
這個分支的應用場景:
- 編譯工具:g++
- 編譯文件類型:.cpp
# x86_g++ ###################################################
else ifeq ($(tool),x86_g++) #1
SRCS := $(shell ls *.cpp) #2
OBJS := $(patsubst %.cpp,%.o,$(SRCS)) #3
CC := g++ #4
$(TARGET) : $(OBJS) #5
$(CC) -o $@ $^ $(LOCAL_LDFLAGS)
%.o:%.cpp
$(CC) -c -o $@ $< $(LOCAL_LDFLAGS)
- #1:
make tool=
中給tool
賦值x86_g++
; - #2:獲取源文件
- #3:轉換目標文件
- #4:確定編譯工具
- #5:編譯
2.3. arm_gcc分支
這個分支的應用場景:
- 編譯工具:arm-gcc
- 編譯文件類型:.c
# arm_gcc ###################################################
else ifeq ($(tool),arm_gcc) #1
SRCS := $(shell ls *.c) #2
OBJS := $(patsubst %.c,%.o,$(SRCS)) #3
CC := /usr/local/gcc-3.4.6-glibc-2.3.3/bin/aarch32-linux-gnu-gcc #4
$(TARGET) : $(OBJS) #5
$(CC) -o $@ $^ $(LOCAL_LDFLAGS)
%.o:%.c
$(CC) -c -o $@ $< $(LOCAL_LDFLAGS)
- #1:
make tool=
中給tool
賦值arm_gcc
; - #2:獲取源文件
- #3:轉換目標文件
- #4:確定編譯工具
- #5:編譯
2.4. arm_g++分支
這個分支的應用場景:
- 編譯工具:arm-g++
- 編譯文件類型:.cpp
# arm_g++ ###################################################
else ifeq ($(tool),arm_g++) #1
SRCS := $(shell ls *.cpp) #2
OBJS := $(patsubst %.cpp,%.o,$(SRCS)) #3
CC := /usr/local/gcc-3.4.6-glibc-2.3.3/bin/aarch32-linux-gnu-g++ #4
$(TARGET) : $(OBJS) #5
$(CC) -o $@ $^ $(LOCAL_LDFLAGS)
%.o:%.cpp
$(CC) -c -o $@ $< $(LOCAL_LDFLAGS)
endif
- #1:
make tool=
中給tool
賦值arm_g++
; - #2:獲取源文件
- #3:轉換目標文件
- #4:確定編譯工具
- #5:編譯
3. 優化
3.1. 參數錯誤
由於這個Makefile要實現四個分支,需要通過"tool"的值來判斷,傳錯參數的情況發生的概率比較高,所以加入以下內容來判斷參數是否錯誤:
ifneq ($(tool),) #1
.PHONY : PARAERROR #2
PARAERROR :
@echo "Error : Parameters error." #3
@exit #4
endif
- #1:經過之前的分支判斷,如果"tool"不爲空,說明參數傳錯;
- #2:定義僞目標,便於添加命令;
- #3:顯示錯誤提示;
- #4:退出;
- 該代碼段必須放到"分支"之後,"參數空"判斷前;
3.2. 參數空
後續會添加".clean"處理,如果不加參數空判斷,會使得使用"make"時執行".clean"的命令,體驗不好,處理如下:
ifeq ($(1),) #1
.PHONY : PARAEMPTY #2
PARAEMPTY :
@echo "Error : Please enter parameters." #3
@exit #4
endif
- #1:判斷參數是否爲空;
- #2:定義僞目標;
- #3:顯示提示信息;
- #4:退出
- 該代碼段必須放到僞目標".clean"之前;
3.3. 僞目標.clean
添加僞目標,方便刪除編譯結果,便於重新編譯,實現如下:
PHONY : clean
clean :
-rm -f $(TARGET) $(MAP_FILE_NAME).map *.o
4. 編譯
如果直接應用當前的makefile,每次編譯需要使用如下中的一個指令,需要在命令行輸入參數,還是有點不方便:
make tool=x86_gcc # 用於編譯分支一
make tool=x86_g++ # 用於編譯分支二
make tool=arm_gcc # 用於編譯分支三
make tool=arm_g++ # 用於編譯分支四
爲了再方便一點,做如下處理:
-
- 在用戶家目錄的".bashrc"文件尾添加如下內容:
alias makexc='make tool=x86_gcc'
alias makex+='make tool=x86_g++'
alias makeac='make tool=arm_gcc'
alias makea+='make tool=arm_g++'
alias makecl='make clean'
-
- 命令行執行
source ~/.bashrc
,重新加載該文件;
- 命令行執行
-
- 接下來可以在終端直接輸入"makexc"、"makex+"、"makeac"、"makea+"、"makecl"命令來分別執行"make tool=x86_gcc" 、"make tool=x86_g++"、"make tool=arm_gcc"、"make tool=arm_g++"、"make clean"命令。
5. 備註
- 需要用到其他編譯選型(-D、-std=c++11...)可自行添;
- makefile中的"ifeq ()"中間需要一個空格;
- makefile中命令開始必須是一個"tab";
- 這裏的交叉編譯工具鏈是胡謅的,實際按照自己使用的修改;
- 命令前加"@"表示不回顯命令;
- 命令前加"-"表示出錯繼續向下處理。