1. 程式人生 > >多目錄時Makefile 的編寫方法

多目錄時Makefile 的編寫方法

1 make分中預定義變量表

  • $* 不包含副檔名的目標檔名稱。
  • $+ 所有的依賴檔案,以空格分開,並以出現的先後為序,可能包含重複的依賴檔案。
  • $< 第一個依賴檔案的名稱。
  • $? 所有的依賴檔案,以空格分開,這些依賴檔案的修改日期比目標的建立日期晚。
  • [email protected] 目標的完整名稱。
  • $^ 所有的依賴檔案,以空格分開,不包含重複的依賴檔案。
  • $% 如果目標是歸檔成員,則該變量表示目標的歸檔成員名稱。例如,如果目標名稱
  • 為 mytarget.so(image.o),則 @mytarget.so@為mytarget.so,而% 為 image.o。
  • AR 歸檔維護程式的名稱,預設值為 ar。
  • ARFLAGS 歸檔維護程式的選項。
  • AS 彙編程式的名稱,預設值為 as。
  • ASFLAGS 彙編程式的選項。
  • CC C 編譯器的名稱,預設值為 cc。
  • CCFLAGS C 編譯器的選項。
  • CPP C 預編譯器的名稱,預設值為 $(CC) -E。
  • CPPFLAGS C 預編譯的選項。
  • CXX C++ 編譯器的名稱,預設值為 g++。
  • CXXFLAGS C++ 編譯器的選項。
  • FC FORTRAN 編譯器的名稱,預設值為 f77。
  • FFLAGS FORTRAN 編譯器的選項。

2 典型例子

CC := g++  
CFLAGS := -g  
TARGET := test  
SRCS := $(wildcard *.cpp)  
OBJS := $(patsubst %cpp,%o,$(SRCS))  

all:$(TARGET)  
%.o:%.cpp  
    $(CC) $(CFLAGS) -c $< -o 
[email protected]
$(TARGET):$(OBJS) $(CC) $(CFLAGS) -o [email protected] clean: rm -rf $(TARGET) *.o

2.1 常見賦值操作的含義

  • = 是最基本的賦值
  • := 是覆蓋之前的值
  • ?= 是如果沒有被賦值過就賦予等號後面的值
  • += 是新增等號後面的值

2.2 := 和 = 的區別

“=”

make會將整個makefile展開後,再決定變數的值。也就是說,變數的值將會是整個makefile中最後被指定的值。看例子:

x = foo
y = $(x) bar
x = xyz

在上例中,y的值將會是 xyz bar ,而不是 foo bar 。

“:=”

“:=”表示變數的值決定於它在makefile中的位置,而不是整個makefile展開後的最終值。

x := foo
y := $(x) bar
x := xyz

在上例中,y的值將會是 foo bar ,而不是 xyz bar 了。

3 多個檔案時,如何編寫Makefile

例子1:將 bin src obj include 單獨存放時,Makefile檔案的通用編寫方法

檔案存放說明:

  • bin: 存放編譯生成的二進位制檔案
  • src: 存放原始檔 (add.c multis.c sub.c main.c)
  • obj: 存放編譯生成的目標檔案
  • include: 存放標頭檔案 (add.h multis.h sub.h)
  • Makefile 檔案和 bin、src、include處於同一級目錄。

Makefile檔案的寫法:

INC_DIR=./include
BIN_DIR=./bin
SRC_DIR=./src
OBJ_DIR=./obj

SRC=${wildcard ${SRC_DIR}/*.c}
OBJ=${patsubst %.c, $(OBJ_DIR)/%.o, ${notdir ${SRC}}}

#用於檢視變數的值
#test:
#   echo $(SRC)
#   echo $(OBJ)

TARGET=main
BIN_TARGET=${BIN_DIR}/${TARGET}

CC=gcc
CFLAGS= -g -Wall -I${INC_DIR}

${BIN_TARGET}:${OBJ}
    ${CC} ${OBJ} -o [email protected]

${OBJ_DIR}/%.o:${SRC_DIR}/%.c
    ${CC} ${CFLAGS} -c $< -o [email protected]

clean:
    find ${OBJ_DIR} -name *.o -exec rm -rf {} \;
  • 說明:
  • notdir ${SRC}: 去除.c 檔案中的目錄,如:./src/mytest.c, 通過notdir之後得到 mytest.c。
  • $(wildcard .cpp /xxx/xxx/.cpp) 為獲取當前目錄下和/xxx/xxx/目錄下所有.cpp檔名
  • (patsubst(patsubst(SRC))為替換所有的.cpp為.o
  • find ${OBJ_DIR} -name *.o -exec rm -rf {} \;輸入man find,檢視find命令中 -exec的具體用法。

Execute command; true if 0 status is returned. All following arguments to find are taken to be argu‐ 
ments to the command until an argument consisting of ;' is encountered. The string{}’ is replaced 
by the current file name being processed everywhere it occurs in the arguments to the command, not just 
in arguments where it is alone, as in some versions of find. Both of these constructions might need to 
be escaped (with a `\’) or quoted to protect them from expansion by the shell. See the EXAMPLES sec‐ 
tion for examples of the use of the -exec option. The specified command is run once for each matched 
file. The command is executed in the starting directory. There are unavoidable security problems 
surrounding use of the -exec action; you should use the -execdir option instead.

例子2:多個檔案存放在不同的目錄時,Makefile的寫法。

檔案存放說明:

  • add 目錄 (add.c add.h)
  • sub 目錄 (sub.c sub.h)
  • mutis 目錄 (mutis.c mutis.h)
  • main 目錄(main.c Makefile)

Makefile檔案的寫法:

CUR_DIR=add/sub/mutis/main檔案所處的目錄

ADD_DIR=${CUR_DIR}/add
SUB_DIR=${CUR_DIR}/sub
MUL_DIR=${CUR_DIR}/multis
MAIN_DIR=${CUR_DIR}/main

INC_DIR= -I${ADD_DIR} \
         -I${SUB_DIR} \
         -I${MUL_DIR} \
         -I${MAIN_DIR}

SRC = ${wildcard  ${ADD_DIR}/*.c} \
      ${wildcard  ${SUB_DIR}/*.c} \
      ${wildcard  ${MUL_DIR}/*.c} \
      ${wildcard  ${MAIN_DIR}/*.c}

OBJ = ${patsubst %.c, %.o, ${SRC}}

TARGET=main
CC=gcc
CCFLAGS=-g -Wall ${INC_DIR}

${TARGET}: ${OBJ}
    ${CC} ${notdir ${OBJ} } -o [email protected]
    echo "Compile done."
${OBJ}:${SRC}
    $(CC) ${CCFLAGS} -c $? 

clean:
    rm -f ${OBJ}
    rm -f *.o
    rm -f *~
    rm -f ${TARGET}
    echo "Clean done."

改進版本:

CUR_DIR=/home/plv/Desktop/demo_multi_makefile/test3

ADD_DIR=${CUR_DIR}/add
SUB_DIR=${CUR_DIR}/sub
MUL_DIR=${CUR_DIR}/multis
MAIN_DIR=${CUR_DIR}/main

INC_DIR= -I${ADD_DIR} \
         -I${SUB_DIR} \
         -I${MUL_DIR} \
         -I${MAIN_DIR}

SRC = ${wildcard  ${ADD_DIR}/*.c} \
      ${wildcard  ${SUB_DIR}/*.c} \
      ${wildcard  ${MUL_DIR}/*.c} \
      ${wildcard  ${MAIN_DIR}/*.c}
OBJ = ${patsubst %.c, %.o, ${SRC}}

TARGET=main
CC=gcc
CCFLAGS=-g -Wall ${INC_DIR}


${TARGET}: ${OBJ}
    ${CC} ${OBJ} -o [email protected]
    @echo "Compile done."

#${OBJ}:${SRC}
#   $(CC) ${CCFLAGS} -c $? 

$(OBJ):%.o:%.c
    @echo "Compiling $< ==> [email protected]"
    ${CC} ${CCFLAGS} -c $< -o [email protected]

clean:
    @rm -f ${OBJ}
    @echo "Clean object files done."

    @rm -f *~
    @echo "Clean tempreator files done."

    @rm -f ${TARGET}
    @echo "Clean target files done."

    @echo "Clean done."

說明:

1.@ echo "" 表示執行該條命令,但不輸出該命令的內容。

2.改進版本中將

${OBJ}:${SRC}
    $(CC) ${CCFLAGS} -c $? 

替換成了,

$(OBJ):%.o:%.c
    @echo "Compiling $< [email protected]"
    ${CC} ${CCFLAGS} -c $< -o [email protected]

相關推薦

目錄Makefile編寫方法

1 make分中預定義變量表$* 不包含副檔名的目標檔名稱。$+ 所有的依賴檔案,以空格分開,並以出現的先後為序,可能包含重複的依賴檔案。$< 第一個依賴檔案的名稱。$? 所有的依賴檔案,以空格分開,這些依賴檔案的修改日期比目標的建立日期晚。[email pr

Pyqt5 中執行緒的編寫方法

對於執行緒的概念就不在此處進行詳細的說明了,下面就說明如何使用: 對於你想要多執行緒的執行的邏輯業務,你都需要例項化一個執行緒物件: class WorkThread(QThread): trigger = pyqtSignal() def __int_

檔案編譯的makefile編寫(附當前目錄下所有.c/.cpp檔案編譯makefile)

C程式碼是如何變成可以執行程式的過程:     1、由前處理器把程式設計師所編寫的C程式碼翻譯成標準C程式碼,可以得到以.i結尾的預處理檔案。         gcc -E code.c         gcc -E code.c -o code.i      2、由彙編器

[Makefile]目錄Makefile寫法

16px 間隔 ews pro images include 先來 文章 status 最近需要寫一個測試程序,這個測試程序需要集成一些功能,寫在同一個文件看上去很不好,多個文件的Makefile又不是很熟,於是分享下面這篇文章 轉自:http://blog.csdn.ne

個文件目錄Makefile的寫法

png 當前 echo 多個 class tro 符號 str 一行 1、前言   目前從事於linux下程序開發,涉及到多個文件,多個目錄,這時候編譯文件的任務量比較大,需要寫Makefile。關於Makefile的詳細內容可以參考網上流傳非常廣泛的《跟我一起寫Make

MySQL啟動必需到usr/local/mysql目錄的問題解決方法

set pid director med mat 需要 develop example create 之前我安裝MySql數據庫的時候,由於我的MySQL不是安裝在標準的/usr/local/mysql目錄,而是安裝在/usr/local/development/mysql

從入門到製作編譯目錄檔案的makefile

makefile作用:用於管理編譯檔案。通常編譯linux專案時,有長達幾千個檔案,在某次更改其中一個檔案的話,若要將整個工程全部編譯,太繁瑣耗時。引入makefile,它依據檔案更新的時間,從而只編譯改動過的檔案。 1 makefile名詞解釋: 目標:指編譯後生成檔案

如何將個C檔案連結在一起----Makefile編寫及make指令

需使用GCC編譯器,關於MinGW的安裝指南:https://people.eng.unimelb.edu.au/ammoffat/teaching/20005/Install-MinGW.pdf   單個.c檔案且沒有使用自定義標頭檔案的編譯,在命令列:   &nbs

SVN 一次性提交目錄中檔案的方法

情況一:將專案中未加入版本控制的檔案提交到版本庫。  在使用WINDOW下的SVN客戶端工具時,在提交一個專案的檔案時,如果有未加入版本庫的檔案,這時可以先將未加入的檔案選中,然後一起提交。  但在LINUX命令列中,如果一個專案中新建立了一個檔案new.php,那麼我們可以使用如下命令來進行版本的提交。 

個檔案目錄Makefile的寫法

1、前言   目前從事於linux下程式開發,涉及到多個檔案,多個目錄,這時候編譯檔案的任務量比較大,需要寫Makefile。關於Makefile的詳細內容可以參考網上流傳非常廣泛的《跟我一起寫Makefile》http://blog.csdn.net/haoel/article/details/2886/

利用Promise實現數據個請求加載完成執行某個方法

art data 關於 es6 下一個 方法 csdn tails blog 在實際開發中常常有些業務的數據是來自多個接口的,因為ajax是異步,這樣就導致我們需要判斷是否請求到了數據然後在做其他的邏輯,在Promise沒有出現之前,通常我們的解決方法是,第一粗暴的改異步為

Makefile目錄原始檔

在很多C/C++工程中原始檔放到一個目錄下面,標頭檔案放在另一個目錄下面,這樣生成的目標檔案(.o檔案)直接放在原始檔相同的資料夾下。但是對於多個目錄中都存在原始檔的情況下,無論將目標檔案放在一個目錄下還是放在和對應原始檔相同的目錄下都不像所有原始檔在一個目錄下那樣簡單。下面

linux目錄空間不足的擴容方法

一、目的 在使用CentOS6.3版本linux系統的時候,發現根目錄(/)的空間不是很充足,而其他目錄空間有很大的空閒,所以本文主要是針對現在已有的空間進行調整。首先,先來檢視一下系統的空間分配情況: 01.[[email protected] /]# df -h  02.Filesystem 

Ubuntu下個版本OpenCV管理(cmake makefile設定方法)

-L $ {exec_prefix} / lib目錄-lopencv_calib3d -lopencv_contrib -lopencv_core -lopencv_features2d -lopencv_flann -lopencv_gpu -lopencv_highgui -lopencv_imgpro

利用Promise實現資料個請求載入完成執行某個方法

在實際開發中常常有些業務的資料是來自多個介面的,因為ajax是非同步,這樣就導致我們需要判斷是否請求到了資料然後在做其他的邏輯,在Promise沒有出現之前,通常我們的解決方法是,第一粗暴的改非同步為同步,但這樣會造成阻塞,非同步好像又失去了意義,第二也就是大家常用的解決辦法

tensorflow 一個矩陣與個矩陣相乘的計算方法(二維和三維張量相乘為例)

當tensor1 的 shape 為[k, m, n], tensor2 的 shape 為 [n, p]時, 要將tensor1的後兩維構成的k個矩陣與tensor2中的矩陣做矩陣乘法得到 shape 為[k, m, p]的向量 解決辦法: 1,我們知道Tenso

RadioGroup呼叫check(id)方法,onCheckedChanged方法被執行次解決辦法

RadioGroup bottomMenuBar = (RadioGroup) findViewById(R.id.bottomMenuBar); bottomMenuBar.setOnCheckedChangeListener(this); bottomMenuBar.c

子類繼承父類,重寫父類方法,運用呼叫重寫的方法呼叫子類的還是呼叫父類的?

package 第五天; public class Person { public void say() { System.out.println("我是Person的say方法"); } } 子類Student如下: package 第五天; publ

目錄Makefile(庫及分層目錄)

本文程式碼雖簡單,但涉及比較複雜的各種呼叫關係,欲研究者需有耐心及清醒頭腦。 切切! 背景交待: 1、正在移植U-Boot,並對其原始碼進行了一些分析,感覺它的Makefile十分強勁; 2、以前寫的Makefile模板不合適多層目錄; 3、研究一下多個庫之間相互

CMakeLists目錄通用模板及Win&Linux相容動態庫編寫

CMakeLists多目錄通用模板 CMake不僅具有跨平臺(一次編寫,多次編譯)的特點,還有便於工程管理的特點,支援CMake的IDE也有很多(VS[MS],QT,CodeBlock等)。 以一個通用組織的工程(包含PCL,VTK,libLAS第三方庫)為