[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
好貼,收藏了!
|