向大家推荐一个C/C++通用Makefile

老古董 发布于 2010/11/18 09:34
阅读 5K+
收藏 16

本文推荐了一个用于对 C/C++ 程序进行编译和连接以产生可执行程序的通用 Makefile。
3 U" N* l3 Z) O( h) |' l$ q" @3 j  F. W) z! C
在使用 Makefile 之前,只需对它进行一些简单的设置即可;而且一经设置,即使以后对源程序文件有所增减一般也不再需要改动 Makefile。因此,即便是一个没有学习过 Makefile 书写规则的人,也可以为自己的 C/C++ 程序快速建立一个可工作的 Makefile。
9 d# Y6 S: O8 d2 ~8 }& p7 }. k+ t& _* d; ]
* I( k5 V6 C* U0 o这个 Makefile 可以在 GNU Make 和 GCC 编译器下正常工作。但是不能保证对于其它版本的 Make 和编译器也能正常工作。
* }% y8 b+ z& Z$ r1 Y, K- I9 Z; Q6 ?- D6 d
此 Makefile 的使用方法如下:
6 M% ], D/ ]) x* n) `9 X: A& B& k7 _  _
程序目录的组织 8 M9 F" d+ s8 I, r' L5 ^
尽量将自己的源程序集中在一个目录中,并且把 Makefile 和源程序放在一起,这样用起来比较方便。当然,也可以将源程序分类存放在不同的目录中。 0 Q+ y, T' L& N; y
在程序目录中创建一个名为 Makefile 的文本文件,将后面列出的 Makefile 的内容复制到这个文件中。(注意:在复制的过程中,Makfile 中各命令前面的 Tab 字符有可能被转换成若干个空格。这种情况下需要把 Makefile 命令前面的这些空格替换为一个 Tab。)
8 x9 M- g8 N& m 将当前工作目录切换到 Makefile 所在的目录。目前,这个 Makefile 只支持在当前目录中的调用,不支持当前目录和 Makefile 所在的路径不是同一目录的情况。6 L. J8 u" B0 z% [* ~& N

9 E' ]' w# R. T: G% h指定可执行文件   ^. A  d8 z7 K. t, F* |
程序编译和连接成功后产生的可执行文件在 Makefile 中的 PROGRAM 变量中设定。这一项不能为空。为自己程序的可执行文件起一个有意义的名子吧。
* [1 H7 |- t* O" y1 Y' R5 Q2 W& n/ L1 c; a/ ?' A3 o
指定源程序 ! F) |- [, C; A) o& f) e2 I; G
要编译的源程序由其所在的路径和文件的扩展名两项来确定。由于头文件是通过包含来使用的,所以在这里说的源程序不应包含头文件。
  A1 z( S7 T/ B6 V 程序所在的路径在 SRCDIRS 中设定。如果源程序分布在不同的目录中,那么需要在 SRCDIRS 中一一指定,并且路径名之间用空格分隔。 4 t. y# m1 X& q+ x1 {8 X0 O0 L
在 SRCEXTS 中指定程序中使用的文件类型。C/C++ 程序的扩展名一般有比较固定的几种形式:.c、.C、.cc、.cpp、.CPP、.c++、.cp、或者.cxx(参见 man gcc)。扩展名决定了程序是 C 还是 C++ 程序:.c 是 C 程序,其它扩展名表示 C++ 程序。一般固定使用其中的一种扩展名即可。但是也有可能需要使用多种扩展名,这可以在 SOURCE_EXT 中一一指定,各个扩展名之间用空格分隔。 3 ^9 R3 ?0 |& i# P8 J9 @3 s7 k7 m
虽然并不常用,但是 C 程序也可以被作为 C++ 程序编译。这可以通过在 Makefile 中设置 CC = $(CXX) 和 CFLAGS = $(CXXFLAGS) 两项即可实现。 - u7 `0 [, A+ g& r2 |. }
这个 Makefile 支持 C、C++ 以及 C/C++ 混合三种编译方式:
! \  o9 b8 s7 z* r1 l8 Q" ?; q) E: y3 X/ P2 o) }+ S
如果只指定 .c 扩展名,那么这是一个 C 程序,用 $(CC) 表示的编译命令进行编译和连接。
$ {: [6 k: P9 E% d! P) Z, o. \' e7 [2 i3 W* ~3 X
如果指定的是除 .c 之外的其它扩展名(如 .cc、.cpp、.cxx 等),那么这是一个 C++ 程序,用 $(CXX) 进行编译和连接。
- m( r/ f) E/ a, _; F, p: z 如果既指定了 .c,又指定了其它 C++ 扩展名,那么这是 C/C++ 混合程序,将用 $(CC) 编译其中的 C 程序,用 $(CXX) 编译其中的 C++ 程序,最后再用 $(CXX) 连接程序。 - d% ^7 p- p! S, S1 y& F
这些工作都是 make 根据在 Makefile 中提供的程序文件类型(扩展名)自动判断进行的,不需要用户干预。
9 n8 M( N- P, a/ Y( F4 S3 w. Q( S1 I" E. R( e3 `
指定编译选项 . y  |1 t" n/ t
编译选项由三部分组成:预处理选项、编译选项以及连接选项,分别由 CPPFLAGS、CFLAGS与CXXFLAGS、LDFLAGS 指定。 , S: {- O* J5 B4 |# d! B, P
CPPFLAGS 选项可参考 C 预处理命令 cpp 的说明,但是注意不能包含 -M 以及和 -M 有关的选项。如果是 C/C++ 混合编程,也可以在这里设置 C/C++ 的一些共同的编译选项。
8 ?) t" Y2 `$ I8 O) Z CFLAGS 和 CXXFLAGS 两个变量通常用来指定编译选项。前者仅仅用于指定 C 程序的编译选项,后者仅仅用于指定 C++ 程序的编译选项。其实也可以在两个变量中指定一些预处理选项(即一些本来应该放在 CPPFLAGS 中的选项),和 CPPFLAGS 并没有明确的界限。 : y: s/ ~3 {2 r! \/ V& v8 Y
连接选项在 LDFLAGS 中指定。如果只使用 C/C++ 标准库,一般没有必要设置。如果使用了非标准库,应该在这里指定连接需要的选项,如库所在的路径、库名以及其它联接选项。 ' N  P+ U2 i8 X6 q& S/ e% T
现在的库一般都提供了一个相应的 .pc 文件来记录使用库所需要的预编译选项、编译选项和连接选项等信息,通过 pkg-config 可以动态提取这些选项。与由用户显式指定各个选项相比,使用 pkg-config 来访问库提供的选项更方便、更具通用性。在后面可以看到一个 GTK+ 程序的例子,其编译和连接选项的指定就是用 pkg-config 实现的。
1 e8 ~/ y; V  `" J/ ~: H
" H: d/ [) s" {- B编译和连接* g$ \0 M# M$ k: J; U
5 g' E( ]2 [' F$ |  J! w& @- N! w
上面的各项设置好之后保存 Makefile 文件。执行 make 命令,程序就开始编译了。
9 _# I' f3 s5 k1 d5 {% J0 G( G- I 命令 make 会根据 Makefile 中设置好的路径和文件类型搜索源程序文件,然后根据文件的类型调用相应的编译命令、使用相应的编译选项对程序进行编译。 & m1 t& F" h$ x' {! d' Y$ O8 Q
编译成功之后程序的连接会自动进行。如果没有错误的话最终会产生程序的可执行文件。
9 P; I6 f. v- X# W7 c 注意:在对程序编译之后,会产生和源程序文件一一对应的 .d 文件。这是表示依赖关系的文件,通过它们 make 决定在源程序文件变动之后要进行哪些更新。为每一个源程序文件建立相应的 .d 文件这也是 GNU Make 推荐的方式。  _  J& F3 l! `+ H/ r. t' x% y% I* k
/ ?$ \, X7 ~; b2 z3 d; y" {
Makefile 目标(Targets)
. I! L" @0 S. U9 O4 V. y
/ ]; n% g/ \& R# r" y0 n下面是关于这个 Makefile 提供的目标以及它所完成的功能:
" G# O3 j) L: u% ?+ P! [: J
5 e. L2 @. l' W& Emake
& v0 u" u' e6 M  _( s编译和连接程序。相当于 make all。
0 w5 @) }4 Q; \& I6 c( l6 p) ^  E
, B0 ?2 S' N* ]  k; ^3 {make objs 8 S' s5 j  f8 T$ X) R% j" x
仅仅编译程序产生 .o 目标文件,不进行连接(一般很少单独使用)。
4 G* I$ }4 ^& ]2 l2 K. [
/ `1 `, n9 z# \/ A8 {5 l* cmake clean   d$ n# f, `8 W( ^% O
删除编译产生的目标文件和依赖文件。
7 m6 n, B2 E6 d. Z6 Q  O
6 `) Z2 V+ c. f# d4 Xmake cleanall 4 n+ V' ^, @0 j' _- d
删除目标文件、依赖文件以及可执行文件。
& e" \/ D- S8 S
# j, C6 b" U* \" U! p! X& O( M. `make rebuild
) e9 D& q% a1 I; ^5 V3 K4 S! d* T# Y7 l重新编译和连接程序。相当于 make clean && make all。
! }/ l; Z# U( P0 L! l" L2 v" X3 n! ]8 ~, g/ F
关于这个 Makefile 的实现原理不准备详细解释了。如果有兴趣的话,可参考文末列出的“参考资料”。
4 I; s1 h7 [' G! J7 T! E5 R4 x8 i* T2 b7 z2 B, ?

$ W' f+ j3 H  r4 X# E5 L8 t( ]) ]7 L! E$ E' N! p
Makefile 的内容如下:
6 y5 ?8 X; j% Y# R
/ D: T. y5 T5 `& g" UC代码
: X: S1 n8 E% @, p8 M" Q. q$ c2 w1.#############################################################   
" J* y( ~! f  f  p( w2.# Generic Makefile for C/C++ Program   9 E1 G- z9 Y/ M
3.#     u5 O, b& t5 x2 v* k( P
4.# License: GPL (General Public License)   
1 }. E: R5 c9 u& R0 n+ n' B5.# Author:  whyglinux <whyglinux AT gmail DOT com>   
* z* G8 T; A5 q5 P6.# Date:    2006/03/04 (version 0.1)   * [# K+ R. Z3 Z0 P8 I' i
7.#          2007/03/24 (version 0.2)   
: p2 E% C; k* r& `6 u& E" [8.#          2007/04/09 (version 0.3)   
, h- A# H3 p0 c. h5 I9.#          2007/06/26 (version 0.4)   
5 I; h& ]% D5 L10.#          2008/04/05 (version 0.5)   
. }/ H& f; L( F4 i11.#   
$ p8 J/ R: A' I) [12.# Description:   5 J6 w) m8 A+ @, O! J2 o
13.# ------------   
2 l# D9 p; _* I3 o* H/ c  {9 R14.# This is an easily customizable makefile template. The purpose is to   / }, ?9 `0 t1 C4 N8 z
15.# provide an instant building environment for C/C++ programs.   
* D7 X: Y4 `/ J4 s3 W- h' O4 C. g16.#   % B- H5 T: {+ _2 E
17.# It searches all the C/C++ source files in the specified directories,   
! ^( U* N8 A: a) F9 L1 E7 x18.# makes dependencies, compiles and links to form an executable.   $ o% j+ D4 ~$ C
19.#   
' m- D1 T0 p0 x  B! \* u' H+ `20.# Besides its default ability to build C/C++ programs which use only   * |- D9 d4 I6 ^( |& ?* G
21.# standard C/C++ libraries, you can customize the Makefile to build   * Y* J+ u* N1 u/ x
22.# those using other libraries. Once done, without any changes you can   ) F. G* N, n& z: |8 S
23.# then build programs using the same or less libraries, even if source   ) A5 H; w! p1 e" u
24.# files are renamed, added or removed. Therefore, it is particularly   
& d" k6 _4 C/ T+ B6 D; @# b/ Z25.# convenient to use it to build codes for experimental or study use.   
0 a. W/ B6 J# P, M- N26.#   # _; E+ F! j4 _& F; G' q
27.# GNU make is expected to use the Makefile. Other versions of makes   
% J$ [7 \4 g7 |- t" I( v4 X28.# may or may not work.   
3 M* k- F) k& k$ f29.#   
+ Z% a. j' H3 D8 h7 q30.# Usage:   
1 t, J0 g" W+ `5 M31.# ------   ( q0 b1 l6 m' Q5 ~% }/ m
32.# 1. Copy the Makefile to your program directory.   2 d" s& g* e& u4 b) r" r
33.# 2. Customize in the "Customizable Section" only if necessary:   1 p" p" _  U, k7 N$ \3 x; c( {- Z
34.#    * to use non-standard C/C++ libraries, set pre-processor or compiler   
0 d. b2 |, I+ I35.#      options to <MY_CFLAGS> and linker ones to <MY_LIBS>   
/ N  ^8 C0 H0 G6 u6 l36.#      (See Makefile.gtk+-2.0 for an example)   7 J7 s; a. G# |* j
37.#    * to search sources in more directories, set to <SRCDIRS>   
) J2 G) b. w& r2 _& ?) Z38.#    * to specify your favorite program name, set to <PROGRAM>   
9 W8 v" u, Y6 ^- ?: H3 v39.# 3. Type make to start building your program.   / ]2 O1 J6 v. N& m7 m
40.#   % e8 D+ e$ B9 Y' O- P
41.# Make Target:   
4 W2 A% Q2 z. l  M! k8 G* L42.# ------------   
0 |6 z. h" A4 S, D0 H! D% {43.# The Makefile provides the following targets to make:   ! e) o+ P4 v2 q' I4 }
44.#   $ make           compile and link   
9 |+ ?/ y/ g% ~/ A& S45.#   $ make NODEP=yes compile and link without generating dependencies   
! |3 Q( E# @, k* K% u46.#   $ make objs      compile only (no linking)   . c) H) L- C- A
47.#   $ make tags      create tags for Emacs editor   ; S, f/ y8 D- \  J, Q0 T
48.#   $ make ctags     create ctags for VI editor   # Y) {% |* R- q( X/ V6 @( b
49.#   $ make clean     clean objects and the executable file   
8 ]  b- Z) p% M% I. n+ C. i50.#   $ make distclean clean objects, the executable and dependencies   
& ^5 S/ ~! y  d3 J4 a. S7 V51.#   $ make help      get the usage of the makefile   
- X( Z% a$ e+ Z5 T* g52.#   $ s% A/ [3 a3 j, m+ M
53.#===========================================================================   % {# _, x" d( J( \8 }
54.  : k9 u% m2 ^( G% j$ t8 ]: P9 L# o8 Y
55.## Customizable Section: adapt those variables to suit your program.   
& G5 E3 c6 d1 a56.##==========================================================================   7 j- j0 h/ E3 ~1 D: q
57.  3 A, C2 T! _: M( `
58.# The pre-processor and compiler options.   
0 P, i! Q7 ?" W' o) A* W0 V* ?59.MY_CFLAGS =   
. o& c. m2 |/ ^* E7 Z  h! b  C7 t60.  
: a2 C. A- W; T( _, F61.# The linker options.   
$ O6 p$ }9 r% P! f62.MY_LIBS   =   4 L# A! }2 `: T/ b6 t
63.  8 b! d1 f( D% ~9 i7 j+ ^
64.# The pre-processor options used by the cpp (man cpp for more).   # e$ ?0 a* y, V( e
65.CPPFLAGS  = -Wall   
! ^' E" ^# }: A* J66.  # d$ I( q' n7 F2 ~+ c  ]4 N
67.# The options used in linking as well as in any direct use of ld.   & e: J7 O3 W+ m$ c
68.LDFLAGS   =   7 |4 ^/ p' w' q+ z1 {$ m. k/ F
69.  / |: x  \* v9 H) s* ~# i0 Z( b" B8 H
70.# The directories in which source files reside.   
0 V* P" y+ ~- r71.# If not specified, only the current directory will be serached.   
+ `, x' X# B5 T72.SRCDIRS   =   
* C) q1 c1 G! T5 l1 U! U/ y73.  
+ D3 E7 B' L2 ^. Y( w( N74.# The executable file name.   1 m9 Z1 M/ G8 G5 `" v+ M/ D
75.# If not specified, current directory name or `a.out' will be used.   - v( l7 c! F3 _0 C# x+ _% {' c
76.PROGRAM   =   
6 l2 c, t5 X; Q& X; w77.  
7 r  ?. B$ \+ [& u! ]* X78.## Implicit Section: change the following only when necessary.   + h, x  A* c; z: I4 B2 y) w# @
79.##==========================================================================   8 c2 c; E$ r, t' T, ?1 ]- `7 [
80.  . V' u5 r, s" h& @0 Z: q% b8 j
81.# The source file types (headers excluded).   ) w) @6 U7 d3 X: n" R) {
82.# .c indicates C source files, and others C++ ones.   * U* ^1 i3 a; u( I8 V2 u/ V: i
83.SRCEXTS = .c .C .cc .cpp .CPP .c++ .cxx .cp   
: ?4 K2 N. w; ~8 `. }84.  
" \5 L1 u5 o* I: r8 B; k; f85.# The header file types.   
" e% V/ R& h5 O86.HDREXTS = .h .H .hh .hpp .HPP .h++ .hxx .hp   & d& s9 |/ t6 M
87.  
, i3 u# B0 l% |* ~% K2 y88.# The pre-processor and compiler options.   # ?( G! v; D* t) U. M- N  V
89.# Users can override those variables from the command line.   $ n) W8 C. u6 L" v1 N
90.CFLAGS  = -g -O2   7 c- v' _' u* {; k! G7 h8 [  R
91.CXXFLAGS= -g -O2   & k. o3 P, ?8 e0 c# S9 A( ]& o
92.  
5 b' l9 ?* D9 G$ K, c3 [) e93.# The C program compiler.   
& j* e8 V6 L1 r- Z94.#CC     = gcc   
0 g. M! O4 L/ v) {1 N95.  " N2 I1 C2 k7 N' Y/ N) H
96.# The C++ program compiler.   
1 q  i& k* h. a3 Q; ]: p97.#CXX    = g++   # Z' A+ k! k8 \- t& y7 P  B
98.  
) m: E$ B$ ~" R99.# Un-comment the following line to compile C programs as C++ ones.   
- p3 Y8 p$ N; a3 y2 N100.#CC     = $(CXX)   
6 b5 F7 [6 F7 B, h! U" H& P5 R/ ]101.  
8 C5 P) Z7 d& \" [- g102.# The command used to delete file.   
" u: Q9 u2 P) g4 Q2 H3 u103.#RM     = rm -f   - ?+ G. r9 G4 e7 s  b
104.  9 \8 g5 E% Z5 t: c
105.ETAGS = etags   
/ \9 \( F4 N# j* J2 a+ z# S; f3 j106.ETAGSFLAGS =   
1 U9 N" R) D8 _) U2 |107.  
  K0 r$ X0 |; B" O" y$ Z108.CTAGS = ctags   + B: w& W3 g( T; x
109.CTAGSFLAGS =   - [6 u4 M3 ]9 h! d  v& Q1 r6 m9 x% D0 @
110.  ; H0 k. ^) j) d, {  w
111.## Stable Section: usually no need to be changed. But you can add more.   " }- o- b, o! X
112.##==========================================================================   
0 s- [7 J& _8 ]113.SHELL   = /bin/sh   
0 S- @0 S* b( f/ d114.EMPTY   =   
9 A& g' E! b$ p2 _6 n. S! J6 s0 C115.SPACE   = $(EMPTY) $(EMPTY)   
; _  l  w! ~# q% Q& U116.ifeq ($(PROGRAM),)   ) y5 m; J$ U8 R4 O
117.  CUR_PATH_NAMES = $(subst /,$(SPACE),$(subst $(SPACE),_,$(CURDIR)))   
1 ~! k3 D+ ^/ N4 A118.  PROGRAM = $(word $(words $(CUR_PATH_NAMES)),$(CUR_PATH_NAMES))   2 L3 w3 ~- N! p9 Z* m
119.  ifeq ($(PROGRAM),)   
5 n+ a& J7 X+ B" t4 J120.    PROGRAM = a.out   2 y0 E9 _: z, E8 d
121.  endif   ! m4 r2 V* r4 |, N- l5 _  W
122.endif   
, _$ p3 c, c: t& S9 r) z  d123.ifeq ($(SRCDIRS),)   ) T( y3 A2 @6 v! C" v5 K+ n
124.  SRCDIRS = .   + A$ x- _! ?5 G/ P
125.endif   ' }" q/ O. W+ r3 {7 g
126.SOURCES = $(foreach d,$(SRCDIRS),$(wildcard $(addprefix $(d)/*,$(SRCEXTS))))   $ G4 h+ `  A* G8 F
127.HEADERS = $(foreach d,$(SRCDIRS),$(wildcard $(addprefix $(d)/*,$(HDREXTS))))   
$ [! L  o8 r( a# `$ Q2 Z0 r128.SRC_CXX = $(filter-out %.c,$(SOURCES))   
" m! S* v5 b3 s8 {6 q  x129.OBJS    = $(addsuffix .o, $(basename $(SOURCES)))   9 A4 ^) G% Z2 K! j
130.DEPS    = $(OBJS:.o=.d)   
9 `& c) @$ {( b& G0 t4 ~: [131.  : o' o  ?' M* O) f
132.## Define some useful variables.   / J# o. C* X/ \0 |& A
133.DEP_OPT = $(shell if `$(CC) --version | grep "GCC" >/dev/null`; then \   
5 O! g& @4 x4 Y4 U( p; E! e8 L134.                  echo "-MM -MP"; else echo "-M"; fi )   9 p- x9 P! a& O1 D
135.DEPEND      = $(CC)  $(DEP_OPT)  $(MY_CFLAGS) $(CFLAGS) $(CPPFLAGS)   . _2 I! f( I. H1 f5 w0 {0 x( W: A
136.DEPEND.d    = $(subst -g ,,$(DEPEND))   
4 _& Y! z4 j, v% _! G3 V, U9 P137.COMPILE.c   = $(CC)  $(MY_CFLAGS) $(CFLAGS)   $(CPPFLAGS) -c   
9 v! v( I/ ~* ?7 I; K. [138.COMPILE.cxx = $(CXX) $(MY_CFLAGS) $(CXXFLAGS) $(CPPFLAGS) -c   
( m. D3 V' Y, Q9 @8 D6 C9 \% A139.LINK.c      = $(CC)  $(MY_CFLAGS) $(CFLAGS)   $(CPPFLAGS) $(LDFLAGS)   % M$ ~* m& O# `& e6 c( R' u: ]! \6 `
140.LINK.cxx    = $(CXX) $(MY_CFLAGS) $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS)   
1 Q7 U/ Q# \: W( h1 E  c7 k141.  
' }, z; W, X; v/ |$ {6 \1 [142..PHONY: all objs tags ctags clean distclean help show   
; Z  `( D4 a, @% K7 K143.  
* z3 [( @, L# y# |2 {5 q5 O) z144.# Delete the default suffixes   
; |0 H' J% d) n0 R% h, Z145..SUFFIXES:   
8 u  Q) L: S- [146.  
1 c6 H5 w- O- {0 i! ?2 b* N: ~- Z147.all: $(PROGRAM)   
" }4 C+ q) N4 O8 s. E. l148.  
3 ~. C" {8 z: }149.# Rules for creating dependency files (.d).   + C) L3 U" |8 w# }$ l
150.#------------------------------------------   
# S" i! }, d: N% z9 ^151.  
$ _# ]8 N0 y8 }; n152.%.d:%.c   
8 M7 G8 q1 ^& t) f153.    @echo -n $(dir $<) > $@   9 e8 F* q; T8 S2 L0 N# X
154.    @$(DEPEND.d) $< >> $@   
0 ~% t& X6 v# U6 `( A0 ^% w& w155.  
! |* q+ I  I4 u6 m& `: |156.%.d:%.C   
* |( X6 F9 A# t4 L157.    @echo -n $(dir $<) > $@   
4 F8 S! P/ ^* G! X% y9 N158.    @$(DEPEND.d) $< >> $@   4 E* q& r1 h% m& @
159.  0 |, I4 Y, P1 r
160.%.d:%.cc   # a/ p6 R3 t$ e: A: t6 v
161.    @echo -n $(dir $<) > $@   
4 q3 T. y; ^. U# h162.    @$(DEPEND.d) $< >> $@   3 b' E$ x9 h3 ^. m
163.    i( s$ l. i( |8 Z
164.%.d:%.cpp     g, |0 t. M: t$ g( ?( c( Y
165.    @echo -n $(dir $<) > $@   : o1 ]0 D. P9 G
166.    @$(DEPEND.d) $< >> $@     u1 d3 x( S; ^
167.  $ a, ~* m* Y+ X* K6 T3 g
168.%.d:%.CPP   3 e1 \+ G& I0 v3 ^$ x
169.    @echo -n $(dir $<) > $@   5 r0 x0 x2 f% D/ [' V8 m, D
170.    @$(DEPEND.d) $< >> $@   
, {- j2 J$ j" Z3 d171.  
( f$ [1 d# i: R6 i172.%.d:%.c++   
0 ?, {/ h& @' f6 p( a; d6 `2 h173.    @echo -n $(dir $<) > $@   & f! N. M" N$ g
174.    @$(DEPEND.d) $< >> $@   
" |* u" z8 Y3 l+ e+ F% O  z175.  
9 D: H/ A  |% d6 m# I176.%.d:%.cp   ; W) a" L/ A; m
177.    @echo -n $(dir $<) > $@   
; ?2 {$ q2 ~, x# w% J1 j3 H1 w178.    @$(DEPEND.d) $< >> $@   
- c- x, C. R) P8 `( B7 T179.  
( S) ]0 k8 c9 @: o/ f/ w! {0 b2 M180.%.d:%.cxx   7 F* V1 O2 h3 g1 V) q6 ]: C
181.    @echo -n $(dir $<) > $@   0 H2 X+ R, R# Z: c2 L# h2 ~0 v* p4 S
182.    @$(DEPEND.d) $< >> $@   5 [+ S8 P' v' [
183.  $ D6 m5 a! T$ O$ O: s( i  @
184.# Rules for generating object files (.o).   
; i1 ]$ `6 A4 l9 G0 b185.#----------------------------------------   
/ p' c1 ]1 u9 H186.objs:$(OBJS)   4 j! |, f8 s2 A
187.  
& V. x6 v1 y: V* Y) H- @1 i; N188.%.o:%.c   
7 k4 ?. a- y' j3 A5 @/ l: m189.    $(COMPILE.c) $< -o $@   / n4 m* H) Q8 `% L0 Z' {* K
190.  
6 ?) ]6 \  r. b+ s; n' M3 W191.%.o:%.C   # L; _" D7 o, e1 U
192.    $(COMPILE.cxx) $< -o $@   
. A2 h8 [& d  F2 G, \9 k2 N193.  
' a, y! g8 F7 k" i194.%.o:%.cc   2 ^7 T( Z% ?: t! j, ]
195.    $(COMPILE.cxx) $< -o $@   
& A$ {. n' D: Z( \  t196.  
' E6 k$ e) o% N5 y/ {1 B6 u197.%.o:%.cpp   9 A- q- P$ }, b/ ]9 |9 t# I# V
198.    $(COMPILE.cxx) $< -o $@   
# X) }9 Q6 s8 \* g- J) o2 a199.  
) S. R( {3 m( C2 V0 P% p) p: b200.%.o:%.CPP   
% s7 w) f8 c3 C* F6 V8 ^9 b0 [201.    $(COMPILE.cxx) $< -o $@   9 `! S/ r' S$ i/ L% f8 r
202.  : S; X) t3 i" F) b
203.%.o:%.c++   
- c- q1 H4 j+ \0 r* X204.    $(COMPILE.cxx) $< -o $@   2 n3 w; Q& i  y$ m+ n7 c& Y/ |
205.  
6 o! y" n& c0 A! o- j206.%.o:%.cp   
& _  N8 J5 @) V* j0 c# M# X! R" c207.    $(COMPILE.cxx) $< -o $@   " @) Q3 n7 R& {3 D9 H, g! y7 T2 }3 n
208.  4 ^* ?2 S! `9 X! e1 U5 a! r- j4 X# u
209.%.o:%.cxx   
( I7 j5 K: F& C1 _1 L( e5 m7 Q" m210.    $(COMPILE.cxx) $< -o $@   & u: c  n3 Y$ d' o  ^: A; x
211.  6 ~- a* ]( `& m+ K  z
212.# Rules for generating the tags.   $ Q5 b: ?6 J# o  c
213.#-------------------------------------   . ]" }  I3 m) c2 ~. o7 P6 X9 S
214.tags: $(HEADERS) $(SOURCES)   1 E, v# g! T* R0 m# ~
215.    $(ETAGS) $(ETAGSFLAGS) $(HEADERS) $(SOURCES)   6 `5 C) i/ D- f
216.  
  k, F2 X$ y3 ~217.ctags: $(HEADERS) $(SOURCES)   ) J( G8 g! n5 Y8 J
218.    $(CTAGS) $(CTAGSFLAGS) $(HEADERS) $(SOURCES)   
3 |+ u! D4 \" B1 q219.  
/ Q1 q+ m/ g3 y% ~9 L0 {220.# Rules for generating the executable.   
' C' Q- i- O2 n) w9 v: t221.#-------------------------------------   & h' B# l; L" J  j* y
222.$(PROGRAM):$(OBJS)   
' y6 z9 w; C4 ^7 }6 A8 s9 D223.ifeq ($(SRC_CXX),)              # C program   
% }5 S! F  O0 O" ?6 i/ d+ a224.    $(LINK.c)   $(OBJS) $(MY_LIBS) -o $@   
# s  }5 f  ^. d# g) X( F0 v225.    @echo Type ./$@ to execute the program.   
8 ?, s3 L; M, y4 G" t* n9 x226.else                            # C++ program   
9 K7 G. l- o' E2 f7 F227.    $(LINK.cxx) $(OBJS) $(MY_LIBS) -o $@     a- g- B! D5 \
228.    @echo Type ./$@ to execute the program.   / e, U5 T7 u# T+ h* ~0 p2 t
229.endif   
$ \' N) J. Z0 e- D0 h230.  
8 q; `7 Z2 z2 m4 H* G231.ifndef NODEP   
4 T, ^' R4 c9 n232.ifneq ($(DEPS),)   6 Z' P) ?$ z$ J: v/ y
233.  sinclude $(DEPS)   
4 C3 G5 \: _7 `- M6 z- D& T) ~234.endif   
; T) |: s7 o7 s$ ~6 Q& w! d. ^8 R235.endif   8 @" N3 W2 {, u) ~, y
236.  ; B4 X! C& M9 u6 [2 [6 g$ J
237.clean:   
' @9 e1 W% \4 g. B, ~238.    $(RM) $(OBJS) $(PROGRAM) $(PROGRAM).exe   
+ |" e: F" k4 ]2 ]1 [239.  
# \: Q' N+ _) _240.distclean: clean   9 P' z5 [' k2 V3 I
241.    $(RM) $(DEPS) TAGS   - C. {+ a6 h6 w6 h. q  i
242.  0 D+ ?7 A; v) B( C/ T8 n9 m
243.# Show help.   
! K* P" h: b6 P' q! v244.help:   $ J" \4 c7 W* _0 t3 S0 d7 o
245.    @echo 'Generic Makefile for C/C++ Programs (gcmakefile) version 0.5'  
/ m3 Z* D  e& A, p% l246.    @echo 'Copyright (C) 2007, 2008 whyglinux <whyglinux@hotmail.com>'    {; [  x' p* w0 z
247.    @echo   3 g3 a7 u6 m% {8 z  D1 F8 c
248.    @echo 'Usage: make [TARGET]'  
5 `0 E& X( |0 f7 g9 Q249.    @echo 'TARGETS:'  $ X9 a0 I* p; i# ?8 z9 Q( ]5 D7 Y3 B
250.    @echo '  all       (=make) compile and link.'  
2 N, B9 }& x* n; H) o  U251.    @echo '  NODEP=yes make without generating dependencies.'  
1 Q/ B/ P& c" b% L2 i" s252.    @echo '  objs      compile only (no linking).'  
5 y7 s5 N, I: i% ]# t9 b253.    @echo '  tags      create tags for Emacs editor.'  ; j) G  i& |* H) D
254.    @echo '  ctags     create ctags for VI editor.'  
8 I% Y% T9 l7 ?2 e5 l# o255.    @echo '  clean     clean objects and the executable file.'  
, D' F7 c9 e6 X5 X) S256.    @echo '  distclean clean objects, the executable and dependencies.'  
$ a) Z4 |" U1 v2 V& d* I257.    @echo '  show      show variables (for debug use only).'  
7 @4 g6 k( I# U& K- U% \7 T, [258.    @echo '  help      print this message.'  
0 @5 v8 O. i) e$ c$ x259.    @echo   
2 t$ _1 @1 ^0 W& }# }" |260.    @echo 'Report bugs to <whyglinux AT gmail DOT com>.'  ) G9 Y0 v1 G# I8 ]
261.  
& r0 i: e. ^* O8 M3 f$ `262.# Show variables (for debug use only.)   # c0 G1 Y2 G& c8 B# p( Q# B
263.show:   
8 i8 q: I" v$ y/ _264.    @echo 'PROGRAM     :' $(PROGRAM)   + M9 y9 [; L! ]
265.    @echo 'SRCDIRS     :' $(SRCDIRS)   7 D% \2 j6 j( y% K! \% t
266.    @echo 'HEADERS     :' $(HEADERS)   
7 Y" X0 r# d  ^2 d" m  v267.    @echo 'SOURCES     :' $(SOURCES)   9 S# H% K+ j! T1 V. V
268.    @echo 'SRC_CXX     :' $(SRC_CXX)   $ [5 T/ n9 L; C
269.    @echo 'OBJS        :' $(OBJS)   & w9 D4 Y' t  M$ `, A5 t0 \
270.    @echo 'DEPS        :' $(DEPS)   1 p" z1 s: \% Z; E/ J$ V
271.    @echo 'DEPEND      :' $(DEPEND)   
. Z+ v1 C) L, v272.    @echo 'COMPILE.c   :' $(COMPILE.c)   
* z; Z  u& b+ m5 @2 o273.    @echo 'COMPILE.cxx :' $(COMPILE.cxx)   
, V" r2 e& J9 s+ q7 [+ k. g274.    @echo 'link.c      :' $(LINK.c)   
( u, ~0 T/ N0 d. \! y275.    @echo 'link.cxx    :' $(LINK.cxx)   
' }6 V6 D( S9 e2 m( X276.  
# K1 C% D4 N% W% x277.## End of the Makefile ##  Suggestions are welcome  ## All rights reserved ##   8 G5 ~8 L3 k9 A, [+ P
278.##############################################################  
3 b( z; k+ L# }7 P8 O1 v* ?#############################################################
/ k5 O4 j0 ?3 e* ]# Generic Makefile for C/C++ Program/ o% }' h* U1 }; Y. b% a* c* Q* z
#
" P! q; A( m/ B) }- y( @  ]$ B) e* r# License: GPL (General Public License)
( \! I& e3 ?: v# Author:  whyglinux <whyglinux AT gmail DOT com>
4 o9 O, Y  Z2 }: y7 @  D# Date:    2006/03/04 (version 0.1)
, n7 l0 H% |" F6 J5 p8 a#          2007/03/24 (version 0.2); `* w( K" ?$ }4 W" n' K4 C1 B
#          2007/04/09 (version 0.3)
# z+ w3 J/ r; ^#          2007/06/26 (version 0.4)
8 P* g" I! q( f. G$ R* {4 Q#          2008/04/05 (version 0.5)2 O1 s- ]- B* w) M
#
3 x9 k# d" x5 ?  J) t. z& F# v4 E0 G. V# Description:
) S7 S1 d) M4 H& I, R6 W# ------------! K# H& |& j, H5 e
# This is an easily customizable makefile template. The purpose is to+ \& W2 U  C; L
# provide an instant building environment for C/C++ programs.
- {' e: ~, f' t9 u/ b3 w* Y" M6 C#
( o6 s  u, Y) ?# L1 a6 v8 D# It searches all the C/C++ source files in the specified directories,+ c+ J' c+ ^# Z
# makes dependencies, compiles and links to form an executable.7 j# Y) _, P4 f' Y1 {0 W
#  z$ j$ |% ?  {$ n2 M2 E
# Besides its default ability to build C/C++ programs which use only
0 i* P! C) ~8 T# standard C/C++ libraries, you can customize the Makefile to build
9 ^: m9 _) n  g; V& Q& T5 d5 a# those using other libraries. Once done, without any changes you can# \6 v  [& k8 {' e
# then build programs using the same or less libraries, even if source- q$ E6 c) E: I
# files are renamed, added or removed. Therefore, it is particularly" s' w' p) c/ q' l
# convenient to use it to build codes for experimental or study use.: ]  y0 O5 P: U5 G) A1 W7 p
#( h. T8 ~. i+ G8 Q$ O* o
# GNU make is expected to use the Makefile. Other versions of makes2 l6 h  G& ^- x+ C( ?
# may or may not work.
8 e5 ~5 W* l4 J9 t#
5 E  P" V$ m& c/ ~( I- V" k. C# Usage:
  A. d# K! [6 ^" t  F* e& N# ------( B0 B% @9 ~/ z8 V7 \
# 1. Copy the Makefile to your program directory.
5 K* W. t9 m& L) N, s0 Q# 2. Customize in the "Customizable Section" only if necessary:4 c6 U# K% F" n6 G# f( d. w: k( o+ I
#    * to use non-standard C/C++ libraries, set pre-processor or compiler
1 ~" [2 a$ x( x/ H#      options to <MY_CFLAGS> and linker ones to <MY_LIBS>
, {$ ]6 N9 O/ [' V+ G6 X3 O2 x#      (See Makefile.gtk+-2.0 for an example)6 z' k, `! ?0 p* ^1 V
#    * to search sources in more directories, set to <SRCDIRS>
7 r3 K4 g' G8 s& f) Z4 C/ q7 y) }7 l0 P#    * to specify your favorite program name, set to <PROGRAM>
% S' _1 [/ n& X, Z, v/ X# 3. Type make to start building your program.; z8 w4 m6 Q+ c% l2 U- s) X% [. e
#- c. |# b" C. H3 {& h3 R9 k8 K
# Make Target:
; A0 s5 W; L/ a3 L8 p  \# ------------% P# ~, T5 h* [9 |5 F
# The Makefile provides the following targets to make:- ]( K% R( u4 K7 x/ S& r8 H
#   $ make           compile and link7 d, p, i$ b+ [( ^
#   $ make NODEP=yes compile and link without generating dependencies
; f  ^# W. |! \2 z+ X! I#   $ make objs      compile only (no linking)4 ^" A7 T, c" Z/ l- Y
#   $ make tags      create tags for Emacs editor8 w8 c" F; i( N- q% W2 R
#   $ make ctags     create ctags for VI editor# h4 v1 Z- V/ |5 A0 N. T
#   $ make clean     clean objects and the executable file5 u. F: ^7 e3 B, E0 C! g0 H. ?
#   $ make distclean clean objects, the executable and dependencies
2 {* T0 r( s# V! P" T#   $ make help      get the usage of the makefile) K% }  q* j9 p0 c6 U, p
#
/ x, l9 ?; E4 b$ T1 a" X#===========================================================================" e( f; A9 c2 S9 r" U
5 ]4 }0 H1 }+ P1 K7 l2 Y9 B
## Customizable Section: adapt those variables to suit your program.: {" ]; c/ U1 N4 z, C8 ^; ^6 C
##==========================================================================
6 L3 Q" N  S2 G, ^8 C/ z. t7 r
, W# k; e3 _" \* ?) Y# D* S# The pre-processor and compiler options.
2 W  \+ u* k7 C# f. F: y  ?MY_CFLAGS =( n6 d: C" R. [5 p- n9 \( T

$ p" E/ E, Z/ h# The linker options.
8 {8 w0 U4 V7 x1 tMY_LIBS   =
6 h$ `% ]0 y, X; B9 G& j2 P0 e! [1 M
# The pre-processor options used by the cpp (man cpp for more).
# A4 S( T2 C8 c0 K' k' Q2 [CPPFLAGS  = -Wall
! O  w. {  n- I2 E9 ~$ I- }6 f5 G! c
# The options used in linking as well as in any direct use of ld.- b) J. |1 ?" @$ \3 B- r8 N: p
LDFLAGS   =
# ?! g6 x# M, l/ x2 {* t7 y9 j! r8 m
# The directories in which source files reside./ d3 z" h: p( S9 v* r* {3 P
# If not specified, only the current directory will be serached.3 x( g) y+ l  x4 |+ `3 W2 X" z  s
SRCDIRS   =* _0 Y* K! p2 i) b2 I% x

: F% L, |* Y) J4 K! \; C+ X- s# The executable file name.+ a. p3 Z3 @% a
# If not specified, current directory name or `a.out' will be used.
2 O5 G: {+ }! e& d* yPROGRAM   =
5 E9 H4 ~2 R% F: e( y  j/ Q+ M- s* E# s3 C/ Y; S
## Implicit Section: change the following only when necessary.- a7 T0 O2 [& E% T3 L! z
##==========================================================================- D/ y' [: H- G1 K, c7 g8 A7 B

: A, B( ^9 c  i" c! P# The source file types (headers excluded).
( z4 J6 k' p5 g) k2 Q) {# .c indicates C source files, and others C++ ones.
/ `! g! \! o! xSRCEXTS = .c .C .cc .cpp .CPP .c++ .cxx .cp# u4 t4 d7 D4 D; s1 q9 g) O
( h; Q# D4 Q) k5 ]% L
# The header file types.8 V: [" k3 }/ ?
HDREXTS = .h .H .hh .hpp .HPP .h++ .hxx .hp
4 R' j5 d# D  c9 u, ]0 s) b
" |# L8 o7 M- v. [# The pre-processor and compiler options." ?$ W  R) p% H3 E: C0 y
# Users can override those variables from the command line.
, F0 y( \& i: J& Q( W' TCFLAGS  = -g -O2
" d3 c: f( l+ }: WCXXFLAGS= -g -O2& ~( @1 [/ x/ i% Y8 t

8 m: n* d/ O4 [" ~# U# The C program compiler.4 f: t+ ]  ~* o4 L- G
#CC     = gcc
; c, V$ }& Y3 d
8 ?) T4 \7 U# _, ~- x3 ^9 q# The C++ program compiler.
! R- y9 U  v9 f% Z0 k#CXX    = g++
( N# b2 t3 {% ]
6 M/ g# `/ `4 X5 \' n" I4 ?# Un-comment the following line to compile C programs as C++ ones.
3 Z, _' Q+ P# |/ q2 J#CC     = $(CXX)
! Y0 x# }, L$ W! Q  n8 [3 i" a! F. h! Q# X( d( i$ v. a; o. \
# The command used to delete file.4 s' K( z1 p6 }9 h
#RM     = rm -f4 z) B3 b9 r2 Y1 F5 K2 B# D4 X7 r

* }0 ~( P5 }0 w! S  c- W  C6 qETAGS = etags
, ^3 ^; O; T% g" v) I% g! @& sETAGSFLAGS =
9 Z0 H. x# Y! A+ l- {, E- O5 D+ B- B* z  a7 s& P% [
CTAGS = ctags( ]# {6 x+ ]5 R+ s' G' a5 o
CTAGSFLAGS =4 q; f' L4 d& n' `  t7 V
; r/ J" k( X7 z+ r5 U' ~: X
## Stable Section: usually no need to be changed. But you can add more.
! V3 Y/ X$ h4 w0 N( X7 l! w  W##==========================================================================
' ^/ v% ~6 _' S2 DSHELL   = /bin/sh
8 Q' f) u( H& D/ \EMPTY   =. v/ ]* K8 N) {% v* T
SPACE   = $(EMPTY) $(EMPTY)# r! t  v: Q0 b8 n( m$ N
ifeq ($(PROGRAM),)
% [2 C" k0 ]# w1 Y  |  CUR_PATH_NAMES = $(subst /,$(SPACE),$(subst $(SPACE),_,$(CURDIR)))# M5 z9 I4 u; P  H4 a# W
  PROGRAM = $(word $(words $(CUR_PATH_NAMES)),$(CUR_PATH_NAMES))
) I, W# x" F: ~9 d  m  ifeq ($(PROGRAM),)4 H5 h3 o/ l# {8 V" @0 G* p* y, Y
    PROGRAM = a.out8 n7 Q! Y- w/ G) @$ l( `
  endif
/ `2 o5 w$ o" O! Q' k$ }endif/ |& t+ o2 s. F/ N7 H) C1 F4 D9 _
ifeq ($(SRCDIRS),)
0 Q, x6 N# R& M  z  SRCDIRS = .; }/ S/ T6 H4 G
endif
' N  @/ |7 W& |5 Z# {5 p/ H/ oSOURCES = $(foreach d,$(SRCDIRS),$(wildcard $(addprefix $(d)/*,$(SRCEXTS))))+ S" _4 R1 ~  p' E$ p' t5 }0 N
HEADERS = $(foreach d,$(SRCDIRS),$(wildcard $(addprefix $(d)/*,$(HDREXTS))))
. B: N, r% o. RSRC_CXX = $(filter-out %.c,$(SOURCES))
" q2 ^' U2 o, }" nOBJS    = $(addsuffix .o, $(basename $(SOURCES)))( }% c2 f4 r7 J
DEPS    = $(OBJS:.o=.d)! f1 m6 t& f' a; v2 K" n3 h0 _

# S) s) K  }* d( j! g## Define some useful variables.4 y9 ^- R6 v: x# W" s
DEP_OPT = $(shell if `$(CC) --version | grep "GCC" >/dev/null`; then \
: g4 L$ S9 n% ?$ N4 a) Q: e' k                  echo "-MM -MP"; else echo "-M"; fi )
* T4 a5 |: O4 M. t0 \DEPEND      = $(CC)  $(DEP_OPT)  $(MY_CFLAGS) $(CFLAGS) $(CPPFLAGS)
, g. O9 y  q) _6 Y% A9 _: zDEPEND.d    = $(subst -g ,,$(DEPEND))! a1 f7 F0 E. B' x) d
COMPILE.c   = $(CC)  $(MY_CFLAGS) $(CFLAGS)   $(CPPFLAGS) -c8 o8 E5 U; Q" O7 ]) S# Z% \
COMPILE.cxx = $(CXX) $(MY_CFLAGS) $(CXXFLAGS) $(CPPFLAGS) -c
4 `! U" B/ n! S0 Z1 VLINK.c      = $(CC)  $(MY_CFLAGS) $(CFLAGS)   $(CPPFLAGS) $(LDFLAGS)" Z. c, V# [0 H) k$ Q8 R
LINK.cxx    = $(CXX) $(MY_CFLAGS) $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS)$ P* k; i, v; O$ ~1 }
% S, t7 B6 F7 k$ f& S2 {0 k- x
.PHONY: all objs tags ctags clean distclean help show
! a4 z& V" D- U# V; X# [
! c4 }3 Y( e, G4 s- d  a" ?( D# Delete the default suffixes7 S* B* A, w8 N" y/ j
.SUFFIXES:
( {& c/ H' W. W. u
  q; L) z7 J3 wall: $(PROGRAM)
5 a' e7 l; z& p
$ O: [; ~7 X# d9 E6 O. a; V# Rules for creating dependency files (.d).
* I+ Z0 q3 i, g" C#------------------------------------------$ ]7 U% n1 d" l# x! u  ~% M& C  q

6 @6 A/ j8 G# {0 [: h, ?%.d:%.c
+ p+ b9 X7 d. E* B        @echo -n $(dir $<) > $@( K4 P- [$ ?0 R: T! X: b- X
        @$(DEPEND.d) $< >> $@6 W/ w# ?! n+ \$ z/ b
- P, R5 W  ~6 z; a' C
%.d:%.C
$ n; h: B2 q+ p4 W        @echo -n $(dir $<) > $@( S9 z7 X) j9 L! a
        @$(DEPEND.d) $< >> $@! f5 V8 F$ w0 a( X, ?* f6 C3 G. R
! t$ B: o0 {/ {. A& P! X
%.d:%.cc
8 |) I& i. h) B) A1 S$ l6 g0 W" c        @echo -n $(dir $<) > $@
# i. Z( |) v% A) u" R3 D# ~; z        @$(DEPEND.d) $< >> $@6 k9 s* \1 y2 f" d0 U& q2 o

0 G6 Z( C  F% L& W; ~2 k%.d:%.cpp: B  b8 L4 U; X+ w
        @echo -n $(dir $<) > $@# F+ h, I, T( Z# T, E( p
        @$(DEPEND.d) $< >> $@
# K7 O% t5 g/ s. @4 W) c9 `0 Z9 v; @8 Q' T9 h7 X; F, k* [# l
%.d:%.CPP
3 R7 Y; s; S* ^* j        @echo -n $(dir $<) > $@3 E0 S6 {0 d, ~) b+ I, B
        @$(DEPEND.d) $< >> $@, Y! h9 Q" |' b3 U7 K  N. j

8 |7 E" M2 `0 W+ {3 S%.d:%.c++
* G; J; ?# J' `" E$ _5 ?! L        @echo -n $(dir $<) > $@' W* b; Y. H3 C( W+ J4 m0 |1 g6 m
        @$(DEPEND.d) $< >> $@2 _# m0 J- M9 P+ d" m9 o

: O; A- Q. M: R3 u# r; P% Q%.d:%.cp1 Z+ U  g9 |1 R. H+ L. i
        @echo -n $(dir $<) > $@
$ F/ E. X3 X3 |8 z) s        @$(DEPEND.d) $< >> $@
: h: m3 \' l$ x1 E
+ p: _* C+ H- V4 Y2 i%.d:%.cxx
0 ^& z8 V  t) ~) j        @echo -n $(dir $<) > $@
' _; x. a; C, X        @$(DEPEND.d) $< >> $@  J$ B" H' p! s; D% f# {3 c
. E" t% E( w1 m8 H
# Rules for generating object files (.o).8 e+ E- b) P5 x1 D- j
#----------------------------------------- P# X8 \# U; j7 M% [) D
objs:$(OBJS)5 d2 C5 ]1 |7 L6 L  g7 j: j  i& P5 R
8 D5 S$ D) x' m0 f
%.o:%.c
9 z$ B8 ~: @' F) Z" u$ \        $(COMPILE.c) $< -o $@
+ ]  |& }- h+ k3 H$ T  ^- T' h2 |- `8 i! G1 u9 w
%.o:%.C
, J& b8 q6 [5 ]8 ^; v, I& }  x3 n. d1 A        $(COMPILE.cxx) $< -o $@
1 \  E, M. O# Y/ Q% M
9 d# o/ s' M) G- {6 e7 ~/ R3 R%.o:%.cc0 S  ~, j% Q5 C. }' P- f
        $(COMPILE.cxx) $< -o $@
: Q' L5 W: P+ ^9 {: H7 h) }1 ~1 g/ ], I) Z) Y5 ?
%.o:%.cpp
# L# Y. M- |# y- B/ ~, I) V& \* p5 q        $(COMPILE.cxx) $< -o $@
# D: W# F: y) c4 ^, {% z
0 \7 f, ]' Z+ P5 f3 W5 l%.o:%.CPP2 o4 `; f. B7 N8 r  l
        $(COMPILE.cxx) $< -o $@
/ t  x5 Q2 i  O* P
" v; `: x8 Z3 n6 t4 }%.o:%.c++" Q" x/ F: M7 I! p$ k2 f
        $(COMPILE.cxx) $< -o $@
4 M) z! F$ b# h' }9 w2 [0 G
- p3 j2 g3 l2 i/ K" d%.o:%.cp
: ]) G! H& k  l# F. h9 [        $(COMPILE.cxx) $< -o $@
3 [1 S3 r+ o6 C, c# Y' }) j! t6 A* [( V+ \9 l; R  M
%.o:%.cxx
1 [# H9 t/ a/ Z0 A  P9 r        $(COMPILE.cxx) $< -o $@5 ?& k. i8 B) R1 X# K

1 b9 H9 L& X6 \' x# Rules for generating the tags.: n: o, l- i' ^( J, a( I% o
#-------------------------------------5 G2 N4 R; p. K4 q% N
tags: $(HEADERS) $(SOURCES)
  M9 C: Y/ m, @) A, P- K( A3 z        $(ETAGS) $(ETAGSFLAGS) $(HEADERS) $(SOURCES)7 h$ h1 N: ~' h2 |  l
" D0 l! v1 {9 Y! j' k+ \/ b
ctags: $(HEADERS) $(SOURCES)6 V% r, H; x" p! j( ^! K3 n9 j
        $(CTAGS) $(CTAGSFLAGS) $(HEADERS) $(SOURCES)2 K% y& T% B' q' N& K; M2 \
3 X: N4 B2 V1 @- X+ q
# Rules for generating the executable.
$ y+ H+ V, C7 H, H. ?#-------------------------------------
, C1 z1 S9 ]; d* T7 {0 j0 ]. j4 K$(PROGRAM):$(OBJS)- }* `& i6 D9 }& J7 O9 _8 ?
ifeq ($(SRC_CXX),)              # C program
  n, c: v1 `- J9 N; ^        $(LINK.c)   $(OBJS) $(MY_LIBS) -o $@
) z+ t9 e- i* c& H; `% Q1 Z        @echo Type ./$@ to execute the program.
" V4 e( M9 F+ _6 z2 melse                            # C++ program" ^9 J& Q! T% G# R
        $(LINK.cxx) $(OBJS) $(MY_LIBS) -o $@7 F- I( S% W/ D" B% s
        @echo Type ./$@ to execute the program.: c+ s, S4 h2 R$ `8 _8 z& g
endif
$ m- ~* `: n7 Z2 \1 @9 K; V. e8 j+ y9 t! f6 |% E
ifndef NODEP
8 l  {! H; M% g4 E3 k5 P. u$ Pifneq ($(DEPS),)- |! m/ q0 a, z6 q( r2 A
  sinclude $(DEPS)7 r+ c. R  f1 h7 i8 U+ p! A
endif
: ~% X9 C. l1 {endif& E; a; v( q7 ^- M8 _7 ]

: q" A+ \( Q, t2 Z, C4 X  ~clean:
4 Z1 x1 h3 E7 H$ [: A        $(RM) $(OBJS) $(PROGRAM) $(PROGRAM).exe
4 g1 @* z. P. w" b, N1 \: Z( H' ]+ `' s0 H) \3 H! o) z
distclean: clean5 V1 a! q7 }1 B$ V
        $(RM) $(DEPS) TAGS
5 e( ?* f+ [  ?8 {
9 G4 |9 A& t! ]  I8 Q6 j# ]# Show help.3 L/ D( ^8 F0 N4 ^9 I- \) w: g: q
help:
) c  K- N) }; ]' }  o( s2 L8 E' N, }        @echo 'Generic Makefile for C/C++ Programs (gcmakefile) version 0.5'
$ Z' t$ b7 F2 f5 ^  \$ S: n/ k" i" ?        @echo 'Copyright (C) 2007, 2008 whyglinux <whyglinux@hotmail.com>'
+ Z3 g7 w& b; X' Q9 |9 ^$ j        @echo! }! `* q( f6 ^: A7 |* O
        @echo 'Usage: make [TARGET]'+ H5 }4 s. R2 C8 m/ K8 h" J* c
        @echo 'TARGETS:'
5 t& D# ]3 K& j& K& P6 n/ }- V        @echo '  all       (=make) compile and link.'; Y3 Y% b; c' ^, E9 Q, E, C, j( D
        @echo '  NODEP=yes make without generating dependencies.'; E2 i9 F2 D( d$ U3 z3 o! L8 P
        @echo '  objs      compile only (no linking).'
; |" b  `0 A3 `3 y. S0 ?2 r. i0 X        @echo '  tags      create tags for Emacs editor.'
& y: C" J" y/ f& ]! r( I8 j! J% |        @echo '  ctags     create ctags for VI editor.'- A* c. a( @) R, N7 f& y
        @echo '  clean     clean objects and the executable file.'
( u  ?( r% q; }* R; x        @echo '  distclean clean objects, the executable and dependencies.'; }; {$ Y/ }+ @  s  A0 r
        @echo '  show      show variables (for debug use only).'
+ F1 j2 l9 E  w7 ~4 @        @echo '  help      print this message.'
& t% _& r5 L$ d" Q3 r5 @        @echo  ?# M9 P* s+ l& d
        @echo 'Report bugs to <whyglinux AT gmail DOT com>.'& C1 q# h7 c$ K+ }

) c3 X+ G4 I( h* G5 A# Show variables (for debug use only.)
, l# c# x7 d6 \6 c5 ~$ {show:
, H/ \2 e) h. Z- U9 g' z        @echo 'PROGRAM     :' $(PROGRAM)4 o; j0 h% G: V% y% ?' ?- ^( o
        @echo 'SRCDIRS     :' $(SRCDIRS)+ D. M: d9 V2 L& l9 z" j, X
        @echo 'HEADERS     :' $(HEADERS)7 R( e5 U* l+ A. ^
        @echo 'SOURCES     :' $(SOURCES)
: A- i: a6 V# o) P+ K+ p. B        @echo 'SRC_CXX     :' $(SRC_CXX)7 J2 k# I% m7 C4 o: I% p  i. }
        @echo 'OBJS        :' $(OBJS)5 Q" ^4 @" P0 H. b1 ^' [# _
        @echo 'DEPS        :' $(DEPS). u7 n3 w. L% N. u1 e4 l  l
        @echo 'DEPEND      :' $(DEPEND)
! v3 q  ^  g/ K% Y  ?4 s2 |        @echo 'COMPILE.c   :' $(COMPILE.c). Y. b/ F  U6 t: r
        @echo 'COMPILE.cxx :' $(COMPILE.cxx)  E6 X0 _: o  b$ d; ?: P" g
        @echo 'link.c      :' $(LINK.c). }/ v7 P( @0 \! w' d) m" L. N  D
        @echo 'link.cxx    :' $(LINK.cxx)
9 K6 P' L/ P) u7 V3 g7 t3 x$ p: @9 {% u% f5 s+ A5 P
## End of the Makefile ##  Suggestions are welcome  ## All rights reserved ##
. [; S5 k% z: p; ?! ~* D4 E##############################################################
, ~4 \: s) Y) P% b5 c- X, Q  0 u$ L8 E$ Q+ g( S8 W
  `* R% [+ h( L5 j: J

: b0 W# N+ J  b' x. e2 O5 m/ P$ ` & Y: c: f1 u) F& ~7 |* v2 r; F1 O

8 }% P) A, |6 @# B下面提供两个例子来具体说明上面 Makefile 的用法。 ! c5 s1 |; c, a' m7 H
7 ?% i/ }, c8 [6 k5 N  m
例一 Hello World 程序
7 _) o. G; D6 V0 z1 k, i$ }! V1 ~5 o& [
这个程序的功能是输出 Hello, world! 这样一行文字。由 hello.h、hello.c、main.cxx 三个文件组成。前两个文件是 C 程序,后一个是 C++ 程序,因此这是一个 C 和 C++ 混编程序。- ~9 j; q; O; g  Z+ }# ?. t

% O" b  G) h; u6 s+ {C代码
4 U& ?% O; t* _6 F, H1./* File name: hello.h  % a; k0 y5 ?3 b; _9 [
2. * C header file  , ]% ?: @& Z* Z5 ?) ~
3. */  ) k" J5 z, H- Y" O; ?4 v
4.  ) w9 N& ?! {: }* w# w
5.#ifndef HELLO_H   8 X- F% c9 w' @; E, g6 ~, y9 x
6.#define HELLO_H   
2 d( f" o. |7 z. b$ J' M5 X7.  
! I4 S, I  y7 v$ i: D* B; |8.#ifdef __cplusplus   
( j4 i  ?  m, f$ H2 f: ~0 ~9.extern "C" {   
# S& A7 N' `3 ^' n10.#endif   
7 l5 Q  K4 Z- s4 S, N; J  c11.  
7 F2 u% t, T+ ~/ k12.  void print_hello();   1 S3 a3 B6 @6 \6 a
13.#ifdef __cplusplus   
4 i7 U0 f& X% W* E5 z) Z14.}   ) g: k; P0 w; P- E; o- i
15.  
( o* H% t0 x$ t) y8 y! N$ I4 m0 M16.#endif   
, n* J. c) F5 G# c# w( `17.#endif   5 W3 u" i9 R, v$ a8 b, i. b$ \
18.  ( r8 a0 i4 l, X9 R$ H5 V- G
19.  
! j4 |! t% o6 {2 Q' Q20./* File name: hello.c  
- M+ K. T. g+ b% p6 e- P21. * C source file.  
2 c. x1 W5 N& S22. */  ; O% o* e  @5 m" O" ^# w
23.  
. l% b9 Y7 D, Y* _% g# s$ Z5 D  [24.#include "hello.h"   
/ Y3 T& _2 j# r6 `25.#include <stdio.h>   
' p/ T/ @, v; _/ U# t26.  
; j9 t, k, m2 O( `  u27.void print_hello()   5 E$ |4 Y  i* M5 e, R3 Y7 }* z# @8 u
28.{   , B  z9 w  q* O3 R! Z( ]! A
29.  puts( "Hello, world!" );   / y6 ~+ V4 r" V; g" p% }
30.}   ( O/ q& _6 `, O6 o) G' W' ?3 R: P
31.  
* d  a0 P3 l9 ]" a, j/ K32.  
+ ?. P1 g5 B) X9 N" M1 ?33./* File name: main.cxx  6 \0 a2 `- h$ l: j; H6 ^
34. * C++ source file.  
$ _* n- _2 J' T9 p5 E35. */  
& v( S$ v7 v- y/ Y" l" T36.  
, C$ |$ ?- H* i1 d' B9 ~0 d37.#include "hello.h"   8 j% M* K4 I. a7 P3 }9 {$ q
38.  
; t8 k4 X" j  K0 d! ?39.int main()   + R0 ~( `( K; I% ]/ h% Z
40.{   : G/ a. `. _! \  b0 E
41.  print_hello();   
. B9 x6 n+ O! u- ^- s& }4 f( X6 O" x42.  return 0;   
2 ?6 _8 p; I- i. Y! f' A; ?& w43.}  
. V+ j. p6 q4 x' A/* File name: hello.h3 h, P+ m" a9 P8 q) N
* C header file
# p' C8 C+ P6 y0 w */' |2 m2 h& I( G1 N) c
& z: [. H, E6 r) T! v0 w; y2 g
#ifndef HELLO_H
5 @6 _6 T0 K4 i( Z# J#define HELLO_H
) P5 j6 y! [/ `& ~; K% n! j  l
0 J8 I2 j; L9 n# F; P% J+ \#ifdef __cplusplus7 @0 v& _& L% y: b# z9 T
extern "C" {
, o/ h- a- u9 c7 R" ?#endif
4 z4 A* d* [+ d8 N3 ^: E1 u: Z: ]2 _5 A
  void print_hello();
5 g% z8 M% S) r; r#ifdef __cplusplus# E# S& x8 `& m7 r
}0 H+ j" B; p# |, Q4 r( y  F; x
' |2 B# K! e8 U6 n; V
#endif+ a% q' E5 J( H" t0 Z) S, {3 l7 Z
#endif5 x3 R6 ], l: i7 g0 t) @

6 E) y8 n2 j6 h  @
% \+ E4 b* O" I( V6 o" s: {/* File name: hello.c8 F+ w) o9 W1 L# Z! M7 f- ?7 ?
* C source file.  L) m1 a' `$ y
*/" B7 c( T, y7 j; K: ]

, O) k2 N9 A" T/ g$ P#include "hello.h"8 K" _1 A( f3 _
#include <stdio.h>
6 g) ?/ J. F1 p/ h4 Z- [* N! f& m0 S/ g0 v+ F& `
void print_hello()
) b4 M* W' i5 i+ n{$ _6 @! [, J) o8 T  d
  puts( "Hello, world!" );
, P4 O" `' r+ H$ K}
: E: f0 i) ~: E% s
7 a3 T* x" T2 s+ [* A; I4 M0 p
! Q: o- ^3 J2 [+ p$ w6 }/* File name: main.cxx
0 }9 E6 O, f( x: k * C++ source file.& i, c9 S& T) X
*/
! i& C' x. D# D4 e7 [- \1 C7 ^
& b, z3 u" i, y8 a#include "hello.h"
/ H4 i$ G  Q, t
/ z& N$ c1 U5 ]6 f% Wint main()! A; ]6 M7 i4 X$ S1 T
{
3 B$ [: I/ b+ @/ F7 u  print_hello();
% o1 o" O3 u. o  return 0;
( L. S7 h( }/ A$ z1 x}  
% a6 u6 P2 _+ E" m- ^
5 u+ Z7 Z* h/ b: ~4 h4 |8 C( y! x6 f  A/ ?
建立一个新的目录,然后把这三个文件拷贝到目录中,也把 Makefile 文件拷贝到目录中。之后,对 Makefile 的相关项目进行如下设置: # O9 ]0 [: N8 U. X; J8 t7 e) _

2 {  `$ v* M% R  F% K/ U  b% JPROGRAM   := hello      # 设置运行程序名! p! \1 s1 B* r7 E  K/ P6 m8 L6 H
3 ]- \4 q' ~0 j0 h+ w
SRCDIRS   := .          # 源程序位于当前目录下' N7 P& p1 N% a. J! L6 u
: W. W; ?: m6 H( O. z! {
4 C' L0 h; g0 b6 @' q
SRCEXTS   := .c .cxx    # 源程序文件有 .c 和 .cxx 两种类型
/ T; M6 h6 Y( |8 K- o6 G5 F: E. z4 b, m5 ^3 _
CFLAGS    := -g         # 为 C 目标程序包含 GDB 可用的调试信息) n* [# H! N+ I  ~  v

' i  b- t6 z% K( ~/ gCXXFLAGS  := -g         # 为 C++ 目标程序包含 GDB 可用的调试信息 : y7 t$ r" I1 h0 m6 B9 e7 I  l

2 n* p4 U, f; ^6 V. B7 W+ K  x 由于这个简单的程序只使用了 C 标准库的函数(puts),所以对于 CFLAGS 和 CXXFLAGS 没有过多的要求,LDFLAGS 和 CPPFLAGS 选项也无需设置。
3 ]6 x% {. }( T1 ?" g7 q* I- }7 t4 r# \" e% W5 K6 N
经过上面的设置之后,执行 make 命令就可以编译程序了。如果没有错误出现的话,./hello  就可以运行程序了。3 S% \* @5 C8 H+ L4 h
1 S) C: `* X1 y4 M4 T9 b1 k
如果修改了源程序的话,可以看到只有和修改有关的源文件被编译。也可以再为程序添加新的源文件,只要它们的扩展名是已经在 Makefile 中设置过的,那么就没有必要修改 Makefile。 : N* c% a0 b1 \* L& L
- @! o1 ^3 [, K/ `/ [

( w# {9 C3 Z1 Q% O, R5 M( ^9 w' N
例二 GTK+ 版 Hello World 程序
: n- V4 N* y6 o. ^; `8 ?6 d# d" S$ S: q1 v1 j( u
这个 GTK+ 2.0 版的 Hello World 程序可以从下面的网址上得到:http://www.gtk.org/tutorial/c58.html#SEC-HELLOWORLD。当然,要编译 GTK+ 程序,还需要你的系统上已经安装好了 GTK+。 % J1 ^. Q' `( ], v5 v
跟第一个例子一样,单独创建一个新的目录,把上面网页中提供的程序保存为 main.c 文件。对 Makefile 做如下设置:
( K4 e) v0 x. w# z: C* lPROGRAM   := hello      # 设置运行程序名# `4 p6 P. K9 }
SRCDIRS   := .          # 源程序位于当前目录下  x4 O1 X3 F3 h+ ~! E
SRCEXTS   := .c         # 源程序文件只有 .c 一种类
$ l' w0 ?" p3 E0 f, _# `
( A2 g" L8 T( f; x- yCFLAGS    := `pkg-config --cflags gtk+-2.0`  # CFLAGS
, o- z% S- u  w! }/ D& pLDFLAGS   := `pkg-config --libs gtk+-2.0`    # LDFLAGS! f# y4 p$ J7 ~+ c7 s2 W& j

& K+ F5 d0 `5 m9 g$ ?% a; q) }) F这是一个 C 程序,所以 CXXFLAGS 没有必要设置——即使被设置了也不会被使用。
1 U% p5 @8 G, _8 ^3 Y: @, m编译和连接 GTK+ 库所需要的 CFLAGS 和 LDFLAGS 由 pkg-config 程序自动产生。
  W, I. W1 ^0 U现在就可以运行 make 命令编译、./hello 执行这个 GTK+ 程序了。

加载中
0
Jackarain
Jackarain

手写makefile太累了吧? 这种方式应该早早淘汰掉.

0
DEC_LIU
DEC_LIU

太复杂啦。看的头疼

0
echor
echor

automake

0
Injection
Injection

没有MSVC系列的通用makefile吗

?

0
divl
divl

正打算学习下;makefile到底是怎么回事

0
张林
张林

红薯云云:给我弄到代码区!!!!!

0
Yongqiang
Yongqiang

cmake or scons

0
y
ywq111

谁能出个bakefile教程吗?

悲剧呀,不知道bakefile怎么编写,简单的例子是会了,bakefile也有不少例子我都看了。到最后因为写不出makefile.bkl,还是只有改wxsqlite3的makefile.gcc,花了好几天的时间才搞定一个小程序的编译。但是用wxsqlite3居然用result取不出中文字段,头痛中。。。

 

wxSQLite3ResultSet set = db->ExecuteQuery(wxT("SELECT * FROM test"));
 
 int count = 0;
 while (set.NextRow())
 {
  wxString s = set.GetAsString(1);

/*假定第二个字段含中文

那么这个里面的s居然是空的。。。不知道啥情况。。。

*/
  count++;
 }

返回顶部
顶部