C/C++ 通用 Makefile


http://www.chinaunix.net 作者:whyglinux  發表於:2008-04-26 22:46:39
發表評論】 【查看原文】 【C/C++討論區】【關閉

[size=5]C/C++ 通用 Makefile[/size] 
[color=green]Generic Makefile for C/C++ Program[/color] 

================================================== 
Keywords: Makefile, make, Generic, C/C++ 
Author:   whyglinux (whyglinux AT hotmail DOT com) 
Date:     2006-03-04 
================================================== 

本文提供了一個用於對 C/C++ 程序進行編譯和連接以產生可執行程序的通用 Makefile。 

在使用 Makefile 之前,只需對它進行一些簡單的設置即可;而且一經設置,即使以後對源程序文件有所增減一般也不再需要改動 Makefile。因此,即便是一個沒有學習過 Makefile 書寫規則的人,也可以爲自己的 C/C++ 程序快速建立一個可工作的 Makefile。 

這個 Makefile 可以在 GNU Make 和 GCC 編譯器下正常工作。但是不能保證對於其它版本的 Make 和編譯器也能正常工作。 

如果你發現了本文中的錯誤,或者對本文有什麼感想或建議,可通過 whyglinux AT hotmail DOT com 郵箱和作者聯繫。  

此 Makefile 的使用方法如下: 
[list=1][*]程序目錄的組織 
儘量將自己的源程序集中在一個目錄中,並且把 Makefile 和源程序放在一起,這樣用起來比較方便。當然,也可以將源程序分類存放在不同的目錄中。 

在程序目錄中創建一個名爲 Makefile 的文本文件,將後面列出的 Makefile 的內容複製到這個文件中。(注意:在複製的過程中,Makfile 中各命令前面的 Tab 字符有可能被轉換成若干個空格。這種情況下需要把 Makefile 命令前面的這些空格替換爲一個 Tab。) 

將當前工作目錄切換到 Makefile 所在的目錄。目前,這個 Makefile 只支持在當前目錄中的調用,不支持當前目錄和 Makefile 所在的路徑不是同一目錄的情況。 

[*]指定可執行文件 
程序編譯和連接成功後產生的可執行文件在 Makefile 中的 PROGRAM 變量中設定。這一項不能爲空。爲自己程序的可執行文件起一個有意義的名子吧。 

[*]指定源程序 
要編譯的源程序由其所在的路徑和文件的擴展名兩項來確定。由於頭文件是通過包含來使用的,所以在這裏說的源程序不應包含頭文件。 

程序所在的路徑在 SRCDIRS 中設定。如果源程序分佈在不同的目錄中,那麼需要在 SRCDIRS 中一一指定,並且路徑名之間用空格分隔。 

在 SRCEXTS 中指定程序中使用的文件類型。C/C++ 程序的擴展名一般有比較固定的幾種形式:.c、.C、.cc、.cpp、.CPP、.c++、.cp、或者.cxx(參見 man gcc)。擴展名決定了程序是 C 還是 C++ 程序:.c 是 C 程序,其它擴展名錶示 C++ 程序。一般固定使用其中的一種擴展名即可。但是也有可能需要使用多種擴展名,這可以在 SOURCE_EXT 中一一指定,各個擴展名之間用空格分隔。 

雖然並不常用,但是 C 程序也可以被作爲 C++ 程序編譯。這可以通過在 Makefile 中設置 CC = $(CXX) 和 CFLAGS = $(CXXFLAGS) 兩項即可實現。 

這個 Makefile 支持 C、C++ 以及 C/C++ 混合三種編譯方式: 
[list][*]如果只指定 .c 擴展名,那麼這是一個 C 程序,用 $(CC) 表示的編譯命令進行編譯和連接。 
[*]如果指定的是除 .c 之外的其它擴展名(如 .cc、.cpp、.cxx 等),那麼這是一個 C++ 程序,用 $(CXX) 進行編譯和連接。 
[*]如果既指定了 .c,又指定了其它 C++ 擴展名,那麼這是 C/C++ 混合程序,將用 $(CC) 編譯其中的 C 程序,用 $(CXX) 編譯其中的 C++ 程序,最後再用 $(CXX) 連接程序。 
[/list] 
這些工作都是 make 根據在 Makefile 中提供的程序文件類型(擴展名)自動判斷進行的,不需要用戶干預。 

[*]指定編譯選項 
編譯選項由三部分組成:預處理選項、編譯選項以及連接選項,分別由 CPPFLAGS、CFLAGS與CXXFLAGS、LDFLAGS 指定。 

CPPFLAGS 選項可參考 C 預處理命令 cpp 的說明,但是注意不能包含 -M 以及和 -M 有關的選項。如果是 C/C++ 混合編程,也可以在這裏設置 C/C++ 的一些共同的編譯選項。 

CFLAGS 和 CXXFLAGS 兩個變量通常用來指定編譯選項。前者僅僅用於指定 C 程序的編譯選項,後者僅僅用於指定 C++ 程序的編譯選項。其實也可以在兩個變量中指定一些預處理選項(即一些本來應該放在 CPPFLAGS 中的選項),和 CPPFLAGS 並沒有明確的界限。 

連接選項在 LDFLAGS 中指定。如果只使用 C/C++ 標準庫,一般沒有必要設置。如果使用了非標準庫,應該在這裏指定連接需要的選項,如庫所在的路徑、庫名以及其它聯接選項。 

現在的庫一般都提供了一個相應的 .pc 文件來記錄使用庫所需要的預編譯選項、編譯選項和連接選項等信息,通過 pkg-config 可以動態提取這些選項。與由用戶顯式指定各個選項相比,使用 pkg-config 來訪問庫提供的選項更方便、更具通用性。在後面可以看到一個 GTK+ 程序的例子,其編譯和連接選項的指定就是用 pkg-config 實現的。 

[*]編譯和連接 
上面的各項設置好之後保存 Makefile 文件。執行 make 命令,程序就開始編譯了。 

命令 make 會根據 Makefile 中設置好的路徑和文件類型搜索源程序文件,然後根據文件的類型調用相應的編譯命令、使用相應的編譯選項對程序進行編譯。 

編譯成功之後程序的連接會自動進行。如果沒有錯誤的話最終會產生程序的可執行文件。 

注意:在對程序編譯之後,會產生和源程序文件一一對應的 .d 文件。這是表示依賴關係的文件,通過它們 make 決定在源程序文件變動之後要進行哪些更新。爲每一個源程序文件建立相應的 .d 文件這也是 GNU Make 推薦的方式。 

[*]Makefile 目標(Targets) 
下面是關於這個 Makefile 提供的目標以及它所完成的功能: 
[list][*]make 
編譯和連接程序。相當於 make all。 
[*]make objs 
僅僅編譯程序產生 .o 目標文件,不進行連接(一般很少單獨使用)。 
[*]make clean 
刪除編譯產生的目標文件和依賴文件。 
[*]make cleanall 
刪除目標文件、依賴文件以及可執行文件。 
[*]make rebuild 
重新編譯和連接程序。相當於 make clean && make all。 
[/list][/list] 
關於這個 Makefile 的實現原理不準備詳細解釋了。如果有興趣的話,可參考文末列出的“參考資料”。 

Makefile 的內容如下: 
###############################################################################

#

# Generic Makefile for C/C++ Program

#

# Author: whyglinux (whyglinux AT hotmail DOT com)

# Date:   2006/03/04



# Description:

# The makefile searches in <SRCDIRS> directories for the source files

# with extensions specified in <SOURCE_EXT>, then compiles the sources

# and finally produces the <PROGRAM>, the executable file, by linking

# the objectives.



# Usage:

#   $ make           compile and link the program.

#   $ make objs      compile only (no linking. Rarely used).

#   $ make clean     clean the objectives and dependencies.

#   $ make cleanall  clean the objectives, dependencies and executable.

#   $ make rebuild   rebuild the program. The same as make clean && make all.

#==============================================================================



## Customizing Section: adjust the following if necessary.

##=============================================================================



# The executable file name.

# It must be specified.

# PROGRAM   := a.out    # the executable name

PROGRAM   :=



# The directories in which source files reside.

# At least one path should be specified.

# SRCDIRS   := .        # current directory

SRCDIRS   :=



# The source file types (headers excluded).

# At least one type should be specified.

# The valid suffixes are among of .c, .C, .cc, .cpp, .CPP, .c++, .cp, or .cxx.

# SRCEXTS   := .c      # C program

# SRCEXTS   := .cpp    # C++ program

# SRCEXTS   := .c .cpp # C/C++ program

SRCEXTS   :=



# The flags used by the cpp (man cpp for more).

# CPPFLAGS  := -Wall -Werror # show all warnings and take them as errors

CPPFLAGS  :=



# The compiling flags used only for C.

# If it is a C++ program, no need to set these flags.

# If it is a C and C++ merging program, set these flags for the C parts.

CFLAGS    :=

CFLAGS    +=



# The compiling flags used only for C++.

# If it is a C program, no need to set these flags.

# If it is a C and C++ merging program, set these flags for the C++ parts.

CXXFLAGS  :=

CXXFLAGS  +=



# The library and the link options ( C and C++ common).

LDFLAGS   :=

LDFLAGS   +=



## Implict Section: change the following only when necessary.

##=============================================================================

# The C program compiler. Uncomment it to specify yours explicitly.

#CC      = gcc



# The C++ program compiler. Uncomment it to specify yours explicitly.

#CXX     = g++



# Uncomment the 2 lines to compile C programs as C++ ones.

#CC      = $(CXX)

#CFLAGS  = $(CXXFLAGS)



# The command used to delete file.

#RM        = rm -f



## Stable Section: usually no need to be changed. But you can add more.

##=============================================================================

SHELL   = /bin/sh

SOURCES = $(foreach d,$(SRCDIRS),$(wildcard $(addprefix $(d)/*,$(SRCEXTS))))

OBJS    = $(foreach x,$(SRCEXTS), \

      $(patsubst %$(x),%.o,$(filter %$(x),$(SOURCES))))

DEPS    = $(patsubst %.o,%.d,$(OBJS))



.PHONY : all objs clean cleanall rebuild



all : $(PROGRAM)



# Rules for creating the dependency files (.d).

#---------------------------------------------------

%.d : %.c

	@$(CC) -MM -MD $(CFLAGS) $<



%.d : %.C

	@$(CC) -MM -MD $(CXXFLAGS) $<



%.d : %.cc

	@$(CC) -MM -MD $(CXXFLAGS) $<



%.d : %.cpp

	@$(CC) -MM -MD $(CXXFLAGS) $<



%.d : %.CPP

	@$(CC) -MM -MD $(CXXFLAGS) $<



%.d : %.c++

	@$(CC) -MM -MD $(CXXFLAGS) $<



%.d : %.cp

	@$(CC) -MM -MD $(CXXFLAGS) $<



%.d : %.cxx

	@$(CC) -MM -MD $(CXXFLAGS) $<



# Rules for producing the objects.

#---------------------------------------------------

objs : $(OBJS)



%.o : %.c

	$(CC) -c $(CPPFLAGS) $(CFLAGS) $<



%.o : %.C

	$(CXX) -c $(CPPFLAGS) $(CXXFLAGS) $<



%.o : %.cc

	$(CXX) -c $(CPPFLAGS) $(CXXFLAGS) $<



%.o : %.cpp

	$(CXX) -c $(CPPFLAGS) $(CXXFLAGS) $<



%.o : %.CPP

	$(CXX) -c $(CPPFLAGS) $(CXXFLAGS) $<



%.o : %.c++

	$(CXX -c $(CPPFLAGS) $(CXXFLAGS) $<



%.o : %.cp

	$(CXX) -c $(CPPFLAGS) $(CXXFLAGS) $<



%.o : %.cxx

	$(CXX) -c $(CPPFLAGS) $(CXXFLAGS) $<



# Rules for producing the executable.

#----------------------------------------------

$(PROGRAM) : $(OBJS)

ifeq ($(strip $(SRCEXTS)), .c)  # C file

	$(CC) -o $(PROGRAM) $(OBJS) $(LDFLAGS)

else                            # C++ file

	$(CXX) -o $(PROGRAM) $(OBJS) $(LDFLAGS)

endif



-include $(DEPS)



rebuild: clean all



clean :

	@$(RM) *.o *.d



cleanall: clean

	@$(RM) $(PROGRAM) $(PROGRAM).exe



### End of the Makefile ##  Suggestions are welcome  ## All rights reserved ###

###############################################################################


下面提供兩個例子來具體說明上面 Makefile 的用法。 

[color=darkred]例一 Hello World 程序[/color] 

這個程序的功能是輸出 Hello, world! 這樣一行文字。由 hello.h、hello.c、main.cxx 三個文件組成。前兩個文件是 C 程序,後一個是 C++ 程序,因此這是一個 C 和 C++ 混編程序。 
/* File name: hello.h

 * C header file

 */



#ifndef HELLO_H

#define HELLO_H



#ifdef __cplusplus

extern "C" {

#endif



  void print_hello();



#ifdef __cplusplus

}

#endif



#endif


/* File name: hello.c

 * C source file.

 */

#include "hello.h"

#include <stdio.h>



void print_hello()

{

  puts( "Hello, world!" );

}


/* File name: main.cxx

 * C++ source file.

 */

#include "hello.h"



int main()

{

  print_hello();



  return 0;

}


建立一個新的目錄,然後把這三個文件拷貝到目錄中,也把 Makefile 文件拷貝到目錄中。之後,對 Makefile 的相關項目進行如下設置: 
PROGRAM   := hello      # 設置運行程序名

SRCDIRS   := .          # 源程序位於當前目錄下

SRCEXTS   := .c .cxx    # 源程序文件有 .c 和 .cxx 兩種類型

CFLAGS    := -g         # 爲 C 目標程序包含 GDB 可用的調試信息

CXXFLAGS  := -g         # 爲 C++ 目標程序包含 GDB 可用的調試信息


由於這個簡單的程序只使用了 C 標準庫的函數(puts),所以對於 CFLAGS 和 CXXFLAGS 沒有過多的要求,LDFLAGS 和 CPPFLAGS 選項也無需設置。 

經過上面的設置之後,執行 make 命令就可以編譯程序了。如果沒有錯誤出現的話,./hello  就可以運行程序了。 

如果修改了源程序的話,可以看到只有和修改有關的源文件被編譯。也可以再爲程序添加新的源文件,只要它們的擴展名是已經在 Makefile 中設置過的,那麼就沒有必要修改 Makefile。 

[color=darkred]例二 GTK+ 版 Hello World 程序[/color] 

這個 GTK+ 2.0 版的 Hello World 程序可以從下面的網址上得到:http://www.gtk.org/tutorial/c58.html#SEC-HELLOWORLD。當然,要編譯 GTK+ 程序,還需要你的系統上已經安裝好了 GTK+。 

跟第一個例子一樣,單獨創建一個新的目錄,把上面網頁中提供的程序保存爲 main.c 文件。對 Makefile 做如下設置: 
PROGRAM   := hello      # 設置運行程序名

SRCDIRS   := .          # 源程序位於當前目錄下

SRCEXTS   := .c         # 源程序文件只有 .c 一種類型

CFLAGS    := `pkg-config --cflags gtk+-2.0`  # CFLAGS

LDFLAGS   := `pkg-config --libs gtk+-2.0`    # LDFLAGS


這是一個 C 程序,所以 CXXFLAGS 沒有必要設置——即使被設置了也不會被使用。 

編譯和連接 GTK+ 庫所需要的 CFLAGS 和 LDFLAGS 由 pkg-config 程序自動產生。 

現在就可以運行 make 命令編譯、./hello 執行這個 GTK+ 程序了。 

參考資料: 
[list=1][*]Multi-file projects and the GNU Make utility 
Author: George Foot 
http://www.elitecoders.de/mags/cscene/CS2/CS2-10.html 

[*]GNU Make Manual 
http://www.gnu.org/software/make/manual/ 
[/list]



 FH 回覆於:2006-03-04 21:58:06

不錯 
但建議LZ改一下題目,這個文件不是在所有Unix下適用的,比如:=的寫法


 whyglinux 回覆於:2006-03-04 23:07:57

引用:原帖由 FH 於 2006-3-4 21:58 發表 
不錯 
但建議LZ改一下題目,這個文件不是在所有Unix下適用的,比如:=的寫法 



關於這一點文中已有說明:“這個 Makefile 可以在 GNU Make 和 GCC 編譯器下正常工作。但是不能保證對於其它版本的 Make 和編譯器也能正常工作。” 

它應該可以適用於各個系統,包括 Linux、Unix、Windows、Mac,只要在系統上存在 GNU Make 和 GCC 編譯器,或者和 GNU Make 和 GCC 兼容。因此,在上述前提下是可以跨平臺的。 

除了平臺移植性之外,“通用”也可以指這個 Makefile 能快速適用於各種不同的應用程序。


 FH 回覆於:2006-03-05 11:40:46

引用:原帖由 whyglinux 於 2006-3-4 23:07 發表 


關於這一點文中已有說明:“這個 Makefile 可以在 GNU Make 和 GCC 編譯器下正常工作。但是不能保證對於其它版本的 Make 和編譯器也能正常工作。” 

它應該可以適用於各個系統,包括 Linux、Unix、Windows、 ... 



哦,那就改叫GNU通用好了:lol: 
如果沒有GNU,要做出一個通用的來根本就是不可能的,各編譯器的參數選項都千差萬別。


 xfly_t 回覆於:2006-03-07 17:36:23

如果有幾層目錄呢?


 Kendiv 回覆於:2006-03-07 22:03:44

恩,學習。


 dlms 回覆於:2006-03-08 17:12:40

不錯!謝謝!


 liuty2006 回覆於:2006-03-10 01:35:34

我就不明白了,那麼多L(U)nix高人,怎麼就沒人願意將生成MAKE文件的過程自動化啊? 
很難嗎?還是不屑於做? 

當linux程序員還在工具怎麼使用的時候,而WINDOWS程序員已經開始解決實際問題了。 

海,不明白啊,不明白!!!!


 havey 回覆於:2006-03-10 08:37:18

這個東西好!


 kingsz1 回覆於:2006-03-11 06:41:49

謝一樓好文。 

引用:原帖由 liuty2006 於 2006-3-10 01:35 發表 
當linux程序員還在工具怎麼使用的時候,而WINDOWS程序員已經開始解決實際問題了。


這就是Linux的問題,Linux目前還要靠開源免費來吸引眼球,而M$已經賺了多少? 
Linux/Unix的高手高不可攀,對初級入門不肖一助,而初哥不得其門而入。


 gnap 回覆於:2006-03-11 08:38:20

引用:原帖由 liuty2006 於 2006-3-10 01:35 發表 
我就不明白了,那麼多L(U)nix高人,怎麼就沒人願意將生成MAKE文件的過程自動化啊? 
很難嗎?還是不屑於做? 

當linux程序員還在工具怎麼使用的時候,而WINDOWS程序員已經開始解決實際問題了。 

海,不明白啊 ... 



GNU工具不但早就將生成Makefile的過程自動化了,還把檢測環境,連接庫等等的工作自動化了。Windows呢? 
GNU工具能夠自己動化的不加改動在N多個平臺下編譯。Windows下的Projects能嗎? 
記得某牛人都提倡Windows程序員學會nmake和lc的吧? 

`Windows程序員已經開始解決的實際問題',是UI的問題吧?:mrgreen::mrgreen:


 zfoas 回覆於:2006-03-12 12:21:31

初學者可以接觸一下automake 可以自動生產makefile


 sarahbrightman 回覆於:2006-03-12 19:59:24

好東西呀,學習一下


 tchhyc 回覆於:2006-03-12 20:25:10

頂,學習


 VirusCamp 回覆於:2006-03-15 11:02:11

引用:原帖由 liuty2006 於 2006-3-10 01:35 發表 
我就不明白了,那麼多L(U)nix高人,怎麼就沒人願意將生成MAKE文件的過程自動化啊? 
很難嗎?還是不屑於做? 

當linux程序員還在工具怎麼使用的時候,而WINDOWS程序員已經開始解決實際問題了。 

海,不明白啊 ... 



你沒有用過  
./configure 
make 
make install 
嗎? 
這就是自動生成. 

如果更自動一點,還有 

aclocal 
automake 
autoconf 

自己用man 看看, 到底是什麼用的.


 SeaKing911 回覆於:2006-03-18 22:40:54

不錯,收藏了!


 connet 回覆於:2006-03-19 14:12:49

還是 aclocal 
automake 
autoconf還用, 跨平臺,自動增加變異參數,連接庫。便於發佈。


 jervis0211 回覆於:2006-03-19 15:16:33

做個記號,好東西


 xfly_t 回覆於:2006-03-19 19:04:17

如果有很多目錄,怎麼辦?


 chen_gxing 回覆於:2006-04-17 10:37:57

學習中


 since19831023 回覆於:2006-04-23 20:29:39

Mark  我想我很快就能用上這些東西了,要學的東西太多了!


 yukunzcn 回覆於:2006-04-26 14:04:47

Makefile在Linux下,是可以自動生成的,你只需要修改或添加一些針對性的參數就可以了。


 G65535 回覆於:2006-04-26 16:04:53

多謝LZ 
收下先


 brucelee520 回覆於:2006-05-10 16:49:13

引用:原帖由 kingsz1 於 2006-3-11 06:41 發表 
謝一樓好文。 


這就是Linux的問題,Linux目前還要靠開源免費來吸引眼球,而M$已經賺了多少? 
Linux/Unix的高手高不可攀,對初級入門不肖一助,而初哥不得其門而入。 


深有感觸


 rrrrrrrr8 回覆於:2007-03-08 11:58:02

好貼,多謝.


 converse 回覆於:2007-03-08 18:08:38

請教一下要在這裏加入include目錄如何加入? 

我定義了一個變量: 
INCCDIRS   := -I/include/ 

然後再: 
%.o : %.cpp 
$(CXX) -c &(INCDIRS) $(CPPFLAGS) $(CXXFLAGS) $< 
(假設我需要編譯的是*.cpp的文件) 

可是不行...


 lenovo 回覆於:2007-03-08 19:39:26

引用:原帖由 converse 於 2007-3-8 18:08 發表 
請教一下要在這裏加入include目錄如何加入? 

我定義了一個變量: 
INCCDIRS   := -I/include/ 

然後再: 
%.o : %.cpp 
$(CXX) -c &(INCDIRS) $(CPPFLAGS) $(CXXFLAGS) $< 
(假設我需要編譯的是*.cpp的 ... 


應該是:$(INCDIRS)吧?


 whyglinux 回覆於:2007-03-08 19:48:29

頭文件的包含路徑設置(如 -I/include/)也可集中放到 CFLAGS(C程序)或者 CXXFLAGS(C++程序)變量的後面,這樣就可省略引入自己定義的變量了。


 emacsnw 回覆於:2007-03-10 01:32:32

引用:原帖由 rrrrrrrr8 於 2007-3-7 19:58 發表 
好貼,多謝. 



一年前的貼被你找出來了,贊。


 lcstudio 回覆於:2007-03-10 07:43:38

引用:原帖由 liuty2006 於 2006-3-10 01:35 發表 
我就不明白了,那麼多L(U)nix高人,怎麼就沒人願意將生成MAKE文件的過程自動化啊? 
很難嗎?還是不屑於做? 

當linux程序員還在工具怎麼使用的時候,而WINDOWS程序員已經開始解決實際問題了。 

海,不明白啊 ... 



早就有了autotool系列。別抱怨了!


 converse 回覆於:2007-03-15 15:08:21

請教whyglinux一個問題,生成的目標文件默認和源代碼文件在一個目錄裏,我想自己設置目標文件的目錄,在你的模版中加入了以下代碼,但是不行: 

OBJDIRS   := obj 
#以下修改了OBJS的寫法 
OBJS1    = $(foreach x,$(SRCEXTS), \ 
        $(patsubst %$(x),%.o,$(filter %$(x),$(SOURCES)))) 
OBJS    = $(foreach x,$(SRCDIRS), \ 
        $(patsubst %$(x), $(OBJDIRS),$(filter %$(x),$(OBJS1)))) 

第一個OBJS1是把*.$(SRCEXTS)替換成*.o文件,可以成功,這個是你的模版中原有的了,第二個想把SRCDIRS替換成OBJDIRS但是不行,不知道爲什麼? 

另外,你的這個文件要求生成的PRAGRAMM和目標文件在一個目錄下,不知道怎麼改變這個設置?

[ 本帖最後由 converse 於 2007-3-15 15:10 編輯 ]


 net_robber 回覆於:2007-03-15 16:15:21

我得Makefile裏面有解決這個問題


 net_robber 回覆於:2007-03-15 16:16:01

請注意一下下面這兩行 

$(OBJ_DIR)%.o:$(SRC_DIR)%.c $(OBJ_DIR)%.d

	$(CC) $(FLAG_COMPLE) $< -o $@






 net_robber 回覆於:2007-03-15 16:16:56

這裏是帶路經的,所以能夠正確匹配 

否則不能成功 

(我測試的時候發現必須這樣)


 whyglinux 回覆於:2007-03-20 22:00:52

引用:原帖由 converse 於 2007-3-15 15:08 發表 
請教whyglinux一個問題,生成的目標文件默認和源代碼文件在一個目錄裏,我想自己設置目標文件的目錄,在你的模版中加入了以下代碼,但是不行: 

OBJDIRS   := obj 
#以下修改了OBJS的寫法 
OBJS1    = $(foreach x,$ ... 



假設上面的變量 x 表示 abc 目錄,則 %$(x) 就是 %abc,表示的特徵是以 abc 結尾的字符串。有這樣特徵的目標文件存在嗎? 

其實有更簡單的實現方法:OBJS = $(addprefix $(SRCDIRS), $(notdir $(OBJS1))) 

要給生成的可執行文件加路徑,在 PROGRAM 中直接設定即可;或者在連接目標文件的時候將 $(PROGRAM) 改爲 $(XX_PATH)$(PROGRAM)。


 converse 回覆於:2007-03-20 23:36:05

引用:原帖由 whyglinux 於 2007-3-20 22:00 發表 


假設上面的變量 x 表示 abc 目錄,則 %$(x) 就是 %abc,表示的特徵是以 abc 結尾的字符串。有這樣特徵的目標文件存在嗎? 

其實有更簡單的實現方法:OBJS = $(addprefix $(SRCDIRS), $(notdir $(OBJS1))) 
 ... 



謝謝,我明天回去試試看,準備大規模的把這套模板用在工作中:em18::em18:


 whyglinux 回覆於:2007-03-21 01:10:22

引用:原帖由 converse 於 2007-3-20 23:36 發表 


謝謝,我明天回去試試看,準備大規模的把這套模板用在工作中:em18::em18: 



如果你的軟件需要發佈,有可能工作在不同的 Unix/Linux 平臺下,那麼這個 Makefile 不適合,因爲它缺乏基本的探測系統環境的能力,而且許多功能也需要添加,此 Makefile 的跨平臺性也沒有經過測試。所以,這時,Autotools(或者叫 GNU Build System)是更加合適的選擇。 

我寫這個 Makefile 的目的是爲了得到一個一勞永逸的軟件構建環境。也就是說,在爲某一類程序(比如使用 GTK+ 庫的程序)配置好 Makefile 之後,即使程序的源文件被改名、或者增加減少之後也不需要改動這個 Makefile,仍然可以用它來構建程序;而且,也可以用這個 Makefile 構建其它類似的程序(比如使用 GTK+ 庫的程序。)。如果沒有什麼特殊的要求,通常你需要做的只是把它拷貝到程序的目錄下、或者僅僅需要做一個符號連接。 

無論在工作還是在學習中,我們都要經常自己編寫或者實驗他人的代碼。這時,這個 Makefile 的優越性就可以體現出來了。Autotools 工具雖然功能強大,但是:一是你要學習它的使用,這對初學者有點困難;二是源程序文件變了,還需要相應地改動 Autotools 的配置文件,很難具備我上面提到的利便性。因此,除了正規的項目之外,一些實驗性的代碼我總是用我的這個 Makefile 來構建。 

(藉此機會回答了“已經有了 Autotools 工具了,還需要一個手工創建的 Makefile 嗎?”類似的疑問,同時說明了這個通用 Makefile 的一般應用場景。希望有用。)


 net_robber 回覆於:2007-03-21 15:14:56

別讓這個沉了,不好找, 

仍然學習中


 jerryfleming 回覆於:2007-03-21 15:23:06

這個比automake怎麼樣?


 centerplain 回覆於:2007-03-23 02:06:26

哈哈,太好了!正是我要找的!!!謝謝樓主,我要認真研究研究!


 whyglinux 回覆於:2007-03-25 12:19:01

C/C++ 通用 Makefile 新版本 0.2 發佈了。 

這個版本修正了上一版本中多目錄連接的錯誤,在易用性上做了進一步的改進。 

我已經在 SourceForge 上爲此 Makefile 申請建立了一個項目:[url=http://sourceforge.net/projects/gcmakefile/]gcmakefile。新版本將在近期不斷髮布,歡迎下載測試並提出改進意見。

gcmakefile-0.2.tar.gz


 emacsnw 回覆於:2007-03-25 16:14:55

引用:原帖由 whyglinux 於 2007-3-24 20:19 發表 
C/C++ 通用 Makefile 新版本 0.2 發佈了。 

這個版本修正了上一版本中多目錄連接的錯誤,在易用性上做了進一步的改進。 

我已經在 SourceForge 上爲此 Makefile 申請建立了一個項目:[url=http://sourceforge ... 



不錯,謝謝樓主。


 LIUXIAOLEI123 回覆於:2007-03-25 16:28:07

很好


 centerplain 回覆於:2007-03-26 21:40:01

已經下載,lz太強了,向你學習!!呵呵


 samuel1004 回覆於:2007-03-31 23:12:07

正在學習makefile,看了樓主的,一下子明白了很多。頂!!


 andyxie407 回覆於:2007-04-24 15:07:23

佔個位


 PCOS 回覆於:2007-04-25 14:10:15

引用:原帖由 whyglinux 於 2007-3-25 12:19 發表 
C/C++ 通用 Makefile 新版本 0.2 發佈了。 

這個版本修正了上一版本中多目錄連接的錯誤,在易用性上做了進一步的改進。 

我已經在 SourceForge 上爲此 Makefile 申請建立了一個項目:[url=http://sourceforge ... 


要積分才能下嗎?!


 wxycyel 回覆於:2007-06-25 19:39:59

我建了一個測試目錄test把你的Makefile(gcmakefile-0.3)放在test下。 
在test目錄下建了兩個子目錄main和tool,main目錄下有mytest.cpp mytest.h 
tool目錄下有tool.cpp tool.h 。 
Makefile的添加設置是 
CPPFLAGS  = -Wall -I main -I tool 
SRCDIRS   = tool main 
PROGRAM   = mytest 
CFLAGS  = -g  
CXXFLAGS= -g  
CXX    = g++ 
執行gmake可以生成執行文件。 
但只修改mytest.h的話,執行gmake不會重新編譯程序。 
如果把mytest.cpp mytest.h too.cpp tool.h 都放在test目錄下, 
不設置SRCDIRS ,只修改mytest.h,會重新編譯程序。 
我是在freebsd5.4 上測試的。gmake 爲 GNU Make 3.80


 whyglinux 回覆於:2007-06-26 19:58:28

引用:原帖由 wxycyel 於 2007-6-25 19:39 發表 
我建了一個測試目錄test把你的Makefile(gcmakefile-0.3)放在test下。 
在test目錄下建了兩個子目錄main和tool,main目錄下有mytest.cpp mytest.h 
tool目錄下有tool.cpp tool.h 。 
Makefile的添加設置是 
CPPF ... 



謝謝 wxycyel 的測試和指正。問題在於源程序文件位於多目錄時產生的依賴文件中路徑的缺失。已經作了相應的修改,並添加了在線幫助功能,更新到 [url=http://sourceforge.net/projects/gcmakefile/]gcmakefile 0.4 版,歡迎下載測試與使用。


 lujx 回覆於:2007-06-27 06:09:32

鼓勵一下。


 cjaizss 回覆於:2008-04-02 12:54:22

引用:原帖由 liuty2006 於 2006-3-10 01:35 發表 [url=http://bbs.chinaunix.net/redirect.php?goto=findpost&pid=4842635&ptid=711092] 
我就不明白了,那麼多L(U)nix高人,怎麼就沒人願意將生成MAKE文件的過程自動化啊? 
很難嗎?還是不屑於做? 

當linux程序員還在工具怎麼使用的時候,而WINDOWS程序員已經開始解決實際問題了。 

海,不明白 ... 


首先不要用win的觀點看待UNIX。在很多UNIX愛好者心中,windows是垃圾,往往總在做無用而非真正有用的事情,如同windows下程序員剛看待UNIX一個樣子,他們可能會認爲這個操作系統居然可以用? 
觀點不同,立場不同。 
但是就你的問題,其實是有解決的,只是你不知道。


 agaric 回覆於:2008-04-02 13:33:07

看到老貼,支持一個。


 xiaoninger 回覆於:2008-04-02 16:24:47

:outu:


 mymtom 回覆於:2008-04-10 19:32:26

爲什麼不用AUTOTOOL


 whyglinux 回覆於:2008-04-10 19:51:28

引用:原帖由 mymtom 於 2008-4-10 19:32 發表 [url=http://bbs.chinaunix.net/redirect.php?goto=findpost&pid=8196068&ptid=711092] 
爲什麼不用AUTOTOOL 



在 [url=http://bbs.chinaunix.net/viewthread.php?tid=711092&page=4#pid6572881]37樓 回答了這個問題。


 很平凡的Man 回覆於:2008-04-21 11:30:54

makefile是什麼東西啊?


 zhoukun 回覆於:2008-04-26 20:57:00

好東西,謝謝


 perl_study 回覆於:2008-04-26 22:46:39

好貼,收藏了!



原文鏈接:http://bbs.chinaunix.net/viewthread.php?tid=711092
轉載請註明作者名及原文出處
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章