學習總結:工程管理與makefile

工程管理與makefile

1、爲何須要makefile和make

一個工程中的源文件可能不少,按照類型、功能、模塊分別放在若干個目錄中,爲了有效地管理軟件工程,更高效地編譯整個工程,須要用到makefile 和 make 命令工具。Linux 程序員須學會寫makefile,使用GNU make 來構建和管理本身的軟件工程,利用makefile 進行編譯,已成爲了一種在工程方面的常見編譯方法。makefile 帶來的好處是「自動化編譯」,一旦寫好,只須要一個make 命令,整個工程徹底自動編譯,極大提升軟件開發的效率。html

2、makefile 主要編寫規則

2.1編寫格式

Target:Dependencies
(tab)命令
(tab)命令

例如:前端

prinA.cpp 包含prinA.h程序員

printB.cpp 包含printB.h函數

main.cpp 包含printA.h printB.h工具

makefile:優化

main:main.o printA.o printB.o
    g++ -o main main.o printA.o printB.o
main.o:main.cpp
    g++ -c main.cpp
printA.o:printA.cpp
    g++ -c printA.cpp
pritnB.o:printB.cpp
    g++ -c printB.cpp
.PHONY : clean
clean:
    rm *.o main

「.PHONY」表示,clean是個僞目標文件。debug

執行:makecode

g++ -c -o main.o main.cpp
g++ -c -o printA.o printA.cpp
g++ -c -o printB.o printB.cpp
g++ -o main main.o printA.o printB.ohtm

生成 main.o pritnA.o printB.o mainblog

執行:make clean

rm *.o main

刪除 全部後綴爲.o的文件 和 main 文件

2.2 讓make 自動推導

GNU的make很強大,它能夠自動推導文件以及文件依賴關係後面的命令,因而咱們就不必去在每個 .o 文件後都寫上相似的命令,由於,咱們的make會自動識別,並本身推導命令。

利用make的自動推導,能夠把makefile 簡化

簡化版makefile:

main:main.o printA.o printB.o
    g++ -o main main.o printA.o printB.o
.PHONY : clean
clean:
    rm *.o main

只要make 看到一個.o文件,它就會自動把其依賴項.c/.cpp 加在依賴關係中,而且推導出命令:

gcc/g++ -c -o .o .c/.cpp

執行make,即可以看到推導和編譯結果:

g++ -c -o main.o main.cpp
g++ -c -o printA.o printA.cpp
g++ -c -o printB.o printB.cpp
g++ -o main main.o printA.o printB.o

2.3 使用變量

要設定一個變量,只要在一行的前端寫下這個變量的名字,後面跟一個"=" 號,後面跟要是設定的這個變量的值就可.之後要引用這個變量,只寫一個"$"符號,後面是在括號裏的變量名便可.

在makefile中使用變量:

OBJS = main.o printA.o printB.o
XX = g++
CC = gcc
CFLAGS = -Wall -g -O
TARGET = main
$(TARGET):$(OBJS)
    $(XX) -o $(TARGET) $(CFLAGS) $(OBJS)
.PHONY :clean
clean:
    rm $(TARGET) $(OBJS)

CFLAGS = -Wall -g -O: 配置編譯器設置,並把它複製給CFLAGS變量,其中每一個部分含義爲:

  • -Wall :輸出全部警告信息
  • -O: 編譯時進行優化
  • -g:即是編譯debug版本

亦可以使用經常使用的內部變量:

  • $@:擴展成當前規則的目的文件名
  • $<:擴展成依靠列表中的第一個依靠文件
  • $^:擴展成整個依靠的列表

使用內部變量makefile:

OBJS = main.o printA.o printB.o
XX = g++
CC = gcc
CFLAGS = -Wall -g -O
TARGET = main
$(TARGET):$(OBJS)
    $(XX) -o $@ $(CFLAGS) $^
.PHONY :clean
clean:
    rm $(TARGET) $(OBJS)

2.4 使用函數 wildcard patsubst

wildcard 用法:

$(wildcard PATTERN...)

在makefile 中,它被展開爲已經存在的,使用空格分開的,匹配此模式的全部文件列表.若是不存在任何符合此模式的文件,函數會忽略模式字符並返回空

例子:

SOURCES = $(wildcard *.c *.cpp)

表示產生一個全部以.c .cpp 結尾的文件列表,而後存入變量SOURCES裏

patsubst 用法:

(patsubst %.src , %.dst , $(dir))

表示用patsubst 把$(dir)中的變量符合後綴是 .src 所有替換成 .dst

例子:

$(patsubt %.c, %o,$(patsubt %.cpp, %.o $(SOURCES)))

這是一個嵌套使用,表示先把 $(SOURCES)中後綴符合爲.cpp 的所有替換成.o,而後再從中把後綴符合爲.c 的所有替換成 .o

總體實現把 $(SOURCES)中後綴符合爲.c 和.cpp 的所有替換成.o

字符 '%' 的意思是匹配零或若干個字符

使用函數的makefile:

XX = g++
CC = gcc
CFLAGS = -Wall -g -O
TARGET = main

SOURCES = $(wildcard *.cpp )
OBJS = $(patsubst %.cpp,%.o, $(SOURCES))

$(TARGET):$(OBJS)
    $(XX) -o $@ $(CFLAGS) $^

.PHONY :clean
clean:
    rm $(TARGET) $(OBJS)

:以上假定全部的文件都在同一個目錄下,且沒有子目錄

2.5 多目錄下編譯

在作項目時,通常文件都會分幾個目錄來存放:

include/ bin/ src/ obj/ lib/ tools/

筆者習慣建工程時,建立前面4個目錄

mkdir include bin src obj

include/ 存放頭文件

bin/ 存放可執行文件

obj/ 存放後綴爲.o 的文件

src/ 存放.c 和.cpp 的源文件

多文件目錄工程管理的makefile:

BIN = ./bin
SRC = ./src
OBJ = ./obj
INCLUDE =./include
SOURCES = $(wildcard $(SRC)/*.cpp )
#要加notdir,去掉選定源文件的目錄,不然替換會出錯
OBJS = $(patsubst %.cpp,$(OBJ)/%.o, $(notdir $(SOURCES)))

TARGET = $(BIN)/main

XX = g++
#-I$(INCLUDE) :$(INCLUDE)下尋找頭文件
CFLAGS = -Wall -g  -I$(INCLUDE)
#用全部的.o文件生成目的可執行文件
$(TARGET):$(OBJS)
    $(XX) -o $@  $^
#生成各個.o 文件
$(OBJ)/%.o:$(SRC)/%.cpp
    $(XX) -c $(CFLAGS) -o $@ $<

.PHONY :clean 
clean:
    rm $(TARGET) $(OBJS)

轉載請註明原文出處:

http://www.cnblogs.com/pz-Feng/p/8289410.html

如有錯誤不當之處,望你們指正,謝謝!

相關文章
相關標籤/搜索