1. 程式人生 > >學習總結:工程管理與makefile

學習總結:工程管理與makefile

管理 用法 ron 有效 第一個 可執行 多目錄 log 包含

工程管理與makefile

一、為什麽需要makefile和make

一個工程中的源文件可能很多,按照類型、功能、模塊分別放在若幹個目錄中,為了有效地管理軟件工程,更高效地編譯整個工程,需要用到makefile 和 make 命令工具。Linux 程序員須學會寫makefile,使用GNU make 來構建和管理自己的軟件工程,利用makefile 進行編譯,已成為了一種在工程方面的常見編譯方法。makefile 帶來的好處是“自動化編譯”,一旦寫好,只需要一個make 命令,整個工程完全自動編譯,極大提高軟件開發的效率。

二、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是個偽目標文件。

執行: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

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

執行: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

若有錯誤不當之處,望大家指正,謝謝!

學習總結:工程管理與makefile