精华帖 (6) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (2)
|
|
---|---|
作者 | 正文 |
发表时间:2010-09-29
最后修改:2010-09-29
本文推荐了一个用于对 C/C++ 程序进行编译和连接以产生可执行程序的通用 Makefile。 此 Makefile 的使用方法如下: 程序目录的组织 指定可执行文件 指定源程序 如果只指定 .c 扩展名,那么这是一个 C 程序,用 $(CC) 表示的编译命令进行编译和连接。 如果指定的是除 .c 之外的其它扩展名(如 .cc、.cpp、.cxx 等),那么这是一个 C++ 程序,用 $(CXX) 进行编译和连接。 指定编译选项 编译和连接 上面的各项设置好之后保存 Makefile 文件。执行 make 命令,程序就开始编译了。 Makefile 目标(Targets) 下面是关于这个 Makefile 提供的目标以及它所完成的功能: make make objs make clean make cleanall make rebuild 关于这个 Makefile 的实现原理不准备详细解释了。如果有兴趣的话,可参考文末列出的“参考资料”。
Makefile 的内容如下: ############################################################# # Generic Makefile for C/C++ Program # # License: GPL (General Public License) # Author: whyglinux <whyglinux AT gmail DOT com> # Date: 2006/03/04 (version 0.1) # 2007/03/24 (version 0.2) # 2007/04/09 (version 0.3) # 2007/06/26 (version 0.4) # 2008/04/05 (version 0.5) # # Description: # ------------ # This is an easily customizable makefile template. The purpose is to # provide an instant building environment for C/C++ programs. # # It searches all the C/C++ source files in the specified directories, # makes dependencies, compiles and links to form an executable. # # Besides its default ability to build C/C++ programs which use only # standard C/C++ libraries, you can customize the Makefile to build # those using other libraries. Once done, without any changes you can # then build programs using the same or less libraries, even if source # files are renamed, added or removed. Therefore, it is particularly # convenient to use it to build codes for experimental or study use. # # GNU make is expected to use the Makefile. Other versions of makes # may or may not work. # # Usage: # ------ # 1. Copy the Makefile to your program directory. # 2. Customize in the "Customizable Section" only if necessary: # * to use non-standard C/C++ libraries, set pre-processor or compiler # options to <MY_CFLAGS> and linker ones to <MY_LIBS> # (See Makefile.gtk+-2.0 for an example) # * to search sources in more directories, set to <SRCDIRS> # * to specify your favorite program name, set to <PROGRAM> # 3. Type make to start building your program. # # Make Target: # ------------ # The Makefile provides the following targets to make: # $ make compile and link # $ make NODEP=yes compile and link without generating dependencies # $ make objs compile only (no linking) # $ make tags create tags for Emacs editor # $ make ctags create ctags for VI editor # $ make clean clean objects and the executable file # $ make distclean clean objects, the executable and dependencies # $ make help get the usage of the makefile # #=========================================================================== ## Customizable Section: adapt those variables to suit your program. ##========================================================================== # The pre-processor and compiler options. MY_CFLAGS = # The linker options. MY_LIBS = # The pre-processor options used by the cpp (man cpp for more). CPPFLAGS = -Wall # The options used in linking as well as in any direct use of ld. LDFLAGS = # The directories in which source files reside. # If not specified, only the current directory will be serached. SRCDIRS = # The executable file name. # If not specified, current directory name or `a.out' will be used. PROGRAM = ## Implicit Section: change the following only when necessary. ##========================================================================== # The source file types (headers excluded). # .c indicates C source files, and others C++ ones. SRCEXTS = .c .C .cc .cpp .CPP .c++ .cxx .cp # The header file types. HDREXTS = .h .H .hh .hpp .HPP .h++ .hxx .hp # The pre-processor and compiler options. # Users can override those variables from the command line. CFLAGS = -g -O2 CXXFLAGS= -g -O2 # The C program compiler. #CC = gcc # The C++ program compiler. #CXX = g++ # Un-comment the following line to compile C programs as C++ ones. #CC = $(CXX) # The command used to delete file. #RM = rm -f ETAGS = etags ETAGSFLAGS = CTAGS = ctags CTAGSFLAGS = ## Stable Section: usually no need to be changed. But you can add more. ##========================================================================== SHELL = /bin/sh EMPTY = SPACE = $(EMPTY) $(EMPTY) ifeq ($(PROGRAM),) CUR_PATH_NAMES = $(subst /,$(SPACE),$(subst $(SPACE),_,$(CURDIR))) PROGRAM = $(word $(words $(CUR_PATH_NAMES)),$(CUR_PATH_NAMES)) ifeq ($(PROGRAM),) PROGRAM = a.out endif endif ifeq ($(SRCDIRS),) SRCDIRS = . endif SOURCES = $(foreach d,$(SRCDIRS),$(wildcard $(addprefix $(d)/*,$(SRCEXTS)))) HEADERS = $(foreach d,$(SRCDIRS),$(wildcard $(addprefix $(d)/*,$(HDREXTS)))) SRC_CXX = $(filter-out %.c,$(SOURCES)) OBJS = $(addsuffix .o, $(basename $(SOURCES))) DEPS = $(OBJS:.o=.d) ## Define some useful variables. DEP_OPT = $(shell if `$(CC) --version | grep "GCC" >/dev/null`; then \ echo "-MM -MP"; else echo "-M"; fi ) DEPEND = $(CC) $(DEP_OPT) $(MY_CFLAGS) $(CFLAGS) $(CPPFLAGS) DEPEND.d = $(subst -g ,,$(DEPEND)) COMPILE.c = $(CC) $(MY_CFLAGS) $(CFLAGS) $(CPPFLAGS) -c COMPILE.cxx = $(CXX) $(MY_CFLAGS) $(CXXFLAGS) $(CPPFLAGS) -c LINK.c = $(CC) $(MY_CFLAGS) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) LINK.cxx = $(CXX) $(MY_CFLAGS) $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS) .PHONY: all objs tags ctags clean distclean help show # Delete the default suffixes .SUFFIXES: all: $(PROGRAM) # Rules for creating dependency files (.d). #------------------------------------------ %.d:%.c @echo -n $(dir $<) > $@ @$(DEPEND.d) $< >> $@ %.d:%.C @echo -n $(dir $<) > $@ @$(DEPEND.d) $< >> $@ %.d:%.cc @echo -n $(dir $<) > $@ @$(DEPEND.d) $< >> $@ %.d:%.cpp @echo -n $(dir $<) > $@ @$(DEPEND.d) $< >> $@ %.d:%.CPP @echo -n $(dir $<) > $@ @$(DEPEND.d) $< >> $@ %.d:%.c++ @echo -n $(dir $<) > $@ @$(DEPEND.d) $< >> $@ %.d:%.cp @echo -n $(dir $<) > $@ @$(DEPEND.d) $< >> $@ %.d:%.cxx @echo -n $(dir $<) > $@ @$(DEPEND.d) $< >> $@ # Rules for generating object files (.o). #---------------------------------------- objs:$(OBJS) %.o:%.c $(COMPILE.c) $< -o $@ %.o:%.C $(COMPILE.cxx) $< -o $@ %.o:%.cc $(COMPILE.cxx) $< -o $@ %.o:%.cpp $(COMPILE.cxx) $< -o $@ %.o:%.CPP $(COMPILE.cxx) $< -o $@ %.o:%.c++ $(COMPILE.cxx) $< -o $@ %.o:%.cp $(COMPILE.cxx) $< -o $@ %.o:%.cxx $(COMPILE.cxx) $< -o $@ # Rules for generating the tags. #------------------------------------- tags: $(HEADERS) $(SOURCES) $(ETAGS) $(ETAGSFLAGS) $(HEADERS) $(SOURCES) ctags: $(HEADERS) $(SOURCES) $(CTAGS) $(CTAGSFLAGS) $(HEADERS) $(SOURCES) # Rules for generating the executable. #------------------------------------- $(PROGRAM):$(OBJS) ifeq ($(SRC_CXX),) # C program $(LINK.c) $(OBJS) $(MY_LIBS) -o $@ @echo Type ./$@ to execute the program. else # C++ program $(LINK.cxx) $(OBJS) $(MY_LIBS) -o $@ @echo Type ./$@ to execute the program. endif ifndef NODEP ifneq ($(DEPS),) sinclude $(DEPS) endif endif clean: $(RM) $(OBJS) $(PROGRAM) $(PROGRAM).exe distclean: clean $(RM) $(DEPS) TAGS # Show help. help: @echo 'Generic Makefile for C/C++ Programs (gcmakefile) version 0.5' @echo 'Copyright (C) 2007, 2008 whyglinux <whyglinux@hotmail.com>' @echo @echo 'Usage: make [TARGET]' @echo 'TARGETS:' @echo ' all (=make) compile and link.' @echo ' NODEP=yes make without generating dependencies.' @echo ' objs compile only (no linking).' @echo ' tags create tags for Emacs editor.' @echo ' ctags create ctags for VI editor.' @echo ' clean clean objects and the executable file.' @echo ' distclean clean objects, the executable and dependencies.' @echo ' show show variables (for debug use only).' @echo ' help print this message.' @echo @echo 'Report bugs to <whyglinux AT gmail DOT com>.' # Show variables (for debug use only.) show: @echo 'PROGRAM :' $(PROGRAM) @echo 'SRCDIRS :' $(SRCDIRS) @echo 'HEADERS :' $(HEADERS) @echo 'SOURCES :' $(SOURCES) @echo 'SRC_CXX :' $(SRC_CXX) @echo 'OBJS :' $(OBJS) @echo 'DEPS :' $(DEPS) @echo 'DEPEND :' $(DEPEND) @echo 'COMPILE.c :' $(COMPILE.c) @echo 'COMPILE.cxx :' $(COMPILE.cxx) @echo 'link.c :' $(LINK.c) @echo 'link.cxx :' $(LINK.cxx) ## End of the Makefile ## Suggestions are welcome ## All rights reserved ## ##############################################################
下面提供两个例子来具体说明上面 Makefile 的用法。 /* 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。
例二 GTK+ 版 Hello World 程序 这个 GTK+ 2.0 版的 Hello World 程序可以从下面的网址上得到:http://www.gtk.org/tutorial/c58.html#SEC-HELLOWORLD。当然,要编译 GTK+ 程序,还需要你的系统上已经安装好了 GTK+。 CFLAGS := `pkg-config --cflags gtk+-2.0` # CFLAGS 这是一个 C 程序,所以 CXXFLAGS 没有必要设置——即使被设置了也不会被使用。
声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2010-10-01
JavaEye的C/C++论坛这么冷清吗
|
|
返回顶楼 | |
发表时间:2010-10-04
虽然我都是用premake和automake的,但还是顶个!
|
|
返回顶楼 | |
发表时间:2010-10-04
lpn520 写道 JavaEye的C/C++论坛这么冷清吗
Javaeye 为什么以 java开头呢..呵呵 ... 都探讨Java 技术的 关于 C C++ 方面 现在做这块的人 并不是很多 |
|
返回顶楼 | |
发表时间:2010-10-05
为什么不用Eclipse
|
|
返回顶楼 | |
发表时间:2010-10-06
收藏
可以当做模板 |
|
返回顶楼 | |
发表时间:2010-10-09
原来一直觉得makefile象天书,看多了。。竟然也明白了。。
|
|
返回顶楼 | |
发表时间:2010-10-09
还是rake好。用ruby搞makefile吧。。。
|
|
返回顶楼 | |
发表时间:2010-10-11
jinleileiking 写道 还是rake好。用ruby搞makefile吧。。。
不同场景用不同的工具...你写个相当的rakefile来看看?估计不会有什么优势。另外,rake对并行任务支持并不是很好,而用Makefile只要编译的时候加-j[n]参数就可以充分利用多核。 竟然有人投隐藏?!看不惯啊... |
|
返回顶楼 | |
发表时间:2010-10-11
scons绝对是构建c/c++程序的利器。
基本上写一个就可以不加改动的到处使用了。 scons主要是声明式的,比起make那种使用要简单的多。 |
|
返回顶楼 | |