Makefile是什么东西?
有哪些步骤?
每步都有什么目的?
序。 Makefile 是什么?
Makefile是用于自动编译和链接的,一个工程有很多文件组成,每一个文件的改变都会导致工程的重新链接,但是不是所有的文件都需要重新编译,Makefile中纪录有文件的信息,在make时会决定在链接的时候需要重新编译哪些文件。
Makefile的宗旨就是:让编译器知道要编译一个文件需要依赖其他的哪些文件。当那些依赖文件有了改变,编译器会自动的发现最终的生成文件已经过时,而重新编译相应的模块。
Makefile的基本结构不是很复杂,但当一个程序开发人员开始写Makefile时,经常会怀疑自己写的是否符合惯例,而且自己写的Makefile经常和自己的开发环境相关联,当系统环境变量或路径发生了变化后,Makefile可能还要跟着修改。这样就造成了手工书写Makefile的诸多问题,automake恰好能很好地帮助我们解决这些问题。
使用automake,程序开发人员只需要写一些简单的含有预定义宏的文件,由autoconf根据一个宏文件生成configure,由automake根据另一个宏文件生成Makefile.in,再使用configure依据Makefile.in来生成一个符合惯例的Makefile。下面我们将详细介绍Makefile的automake生成方法。
一。Makefile 编写工具链介绍
automake,autoconf,autoscan,aclocal
autoconf(2.13)中文手册
GNU Automake(1.3, 3)中文手册
二。编写步骤
1。为各目录(包括根目录和所有子目录)编写Makefile.am文件
一些说明的地方,即Makefile.am应该怎么写。
ksou/Makefile.am模板:
EXTRA_DIST = BUGS ChangeLog.O
SUBDIRS = src
ksou/src/Makefile.am 模板:
AUTOMAKE_OPTIONS = foreign
bin_PROGRAMS = ksou
ksou_SOURCES = main.cpp ksou.h
ksou_LDADD = $(INTLLIBS) $(ALLOCA)
localedir = $(datadir)/locale
INCLUDES = -I../intl -DLOCALEDIR="$(localedir)"
2。执行autoscan以生成Configure.in 的模板 Configure.scan
假设目录结构如下所示
ksou/ 项目根目录
ksou/src 源程序目录
ksou/src/main.cpp 入口main 所在文件
ksou/src/ksou.h 某个头文件
要求:这两个源文件要能输出hello world 吧。:)
sh> autoscan
sh> ls
autoscan-2.5x.log configure.scan src
sh>mv configure.scan configure.in
用你喜欢的编辑器编辑configure.in文件
一些要说明的宏
简单的configure.in模板:
# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
AC_PREREQ(2.59)
AC_INIT(ksou, 0.1, jason@ksou.org)
AM_INIT_AUTOMAKE(1.6.1)
AC_CONFIG_SRCDIR([src/ksou.h])
AC_CONFIG_HEADER([src/config.h])
# Checks for programs.
AC_PROG_CXX
#AC_PROG_CC
# Checks for libraries.
# Checks for header files.
AC_HEADER_STDC
AC_CHECK_HEADERS([stdlib.h])
# Checks for typedefs, structures, and compiler characteristics.
# Checks for library functions.
AC_CONFIG_FILES([Makefile src/Makefile])
AC_OUTPUT
3。执行aclocal以生成aclocal.m4
sh> aclocal
sh> ls
aclocal.m4 autom4te.cache autoscan-2.5x.log configure.in src
4。执行autoconf 以生成Configure脚本
sh> autoconf
sh> ls
aclocal.m4 autom4te.cache autoscan-2.5x.log configure
configure.in src
5。在你指定的地方加上config.h.in模板,这个是在根目录的 configure.in中指定的。它将在automake的时候生成config.h,生成一个与程序相关的宏定义以供程序使用。
config.h.in模板:
/* src/config.h.in. Generated from configure.in by autoheader. */
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
/* Define to 1 if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H
/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H
/* Define to 1 if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H
/* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* Name of package */
#undef PACKAGE
/* Define to the address where bug reports for this package should be sent. */
#undef PACKAGE_BUGREPORT
/* Define to the full name of this package. */
#undef PACKAGE_NAME
/* Define to the full name and version of this package. */
#undef PACKAGE_STRING
/* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME
/* Define to the version of this package. */
#undef PACKAGE_VERSION
/* Define to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS
/* Version number of package */
#undef VERSION
6。执行automake生成Makefile
sh> automake --add-missing
有可能出现下面输出:
Makefile.am: required file `./NEWS' not found
Makefile.am: required file `./README' not found
Makefile.am: required file `./AUTHORS' not found
Makefile.am: required file `./ChangeLog' not found
手工创建这些文件即可,即使为空文件也成。再次执行automake --add-missing看是否还会有什么错误。如果没有,则有如果结果:
sh> ls
total 221
lrwxrwxrwx 1 jason None 31 Jul 23 17:28 COPYING -> /usr/share/automake-1.9/COPYING
lrwxrwxrwx 1 jason None 31 Jul 23 17:28 INSTALL -> /usr/share/automake-1.9/INSTALL
-rw-r--r-- 1 jason None 13 Jul 23 17:26 Makefile.am
-rw-r--r-- 1 jason None 0 Jul 23 17:26 Makefile.am.bak
-rw-r--r-- 1 jason None 31120 Jul 23 17:22 aclocal.m4
drwxr-xr-x 2 jason None 0 Jul 23 17:22 autom4te.cache
-rw-r--r-- 1 jason None 0 Jul 23 17:17 autoscan-2.5x.log
-rwxr-xr-x 1 jason None 163385 Jul 23 17:23 configure
-rw-r--r-- 1 jason None 573 Jul 23 17:21 configure.in
-rw-r--r-- 1 jason None 546 Jul 23 17:21 configure.in.bak
lrwxrwxrwx 1 jason None 31 Jul 23 17:28 depcomp -> /usr/share/automake-1.9/depcomp
lrwxrwxrwx 1 jason None 34 Jul 23 17:28 install-sh -> /usr/share/automake-1.9/install-sh
lrwxrwxrwx 1 jason None 31 Jul 23 17:28 missing -> /usr/share/automake-1.9/missing
drwxr-xr-x 2 jason None 0 Jul 23 16:42 src
是不是感觉到已经有经常使用的./configure ; make ; make install ; 的模样了呢?其实这就是了。下面就可以这套半自动化工具链的成果了。
7。使用
就和安装其他软件一样了、
sh> ./configure
sh> make
sh> make install
有没有生成你想要的东西呢?试试吧。下面是我的:
sh> ls src
Makefile config.h ksou.exe
main.cpp stamp-h1 akefile.am Makefile.in
config.h.in ksou.h main.o
sh> src/ksou.exe
HELLO WORLD
我用的是windows下的cygwin环境下做的测试,所以生成的执行文件为ksou.exe,如果在linux下面,生成的程序一般不需要带后缀名exe(即为ksou),不过也是能执行的呀。
三。各步骤详解
四。处理新扩展名文件
在C/C++项目中, 我们赏需要涉及其他扩展名的文件,如在proc*c/c++ 中,它使用的扩展名为.pc,还有时候需要处理java文件,这种情况automake 能处理的了吗?当然,答案是肯定的。
首先,需要使用到automake的SUFFIXES变量,它是在automake 系统中表示能处理的文件的扩展名的。
在Makefile.am文件中写入下面几行:
SUFFIXES = .pc .cpp
.pc.cpp:
$(PROCPP) XXXXparamsXXXXX
然后运行一下automake.看看结果怎么样。