make工具
概述
为了规范,通用与移植性,Makefile采用GNU的automake系列工具生成。除非试验性质的项目, 一般来说,不建议自己书写Makefile。
GNU的Makefile生成工具由,aclocal,autoconf,libtoolize, automake组成。
Aclocal生成m4脚本。
Autoconf根据configure.ac(在早前版本称为configure.in)生成configure。
libtoolize,生成动态库所需要的脚本。
automake,根据Makefile.am,生成Makefile.in。
configure,根据Makefile.in生成Makefile。
准备条件
安装
ubuntu 8.04
sudo apt-get install autoconf sudo apt-get install automake sudo apt-get install libtool
redhat 5.x
make tools的rpm包都位于安装光盘中,不同版本的rpm包,包名除了版本号外都一致。
rpm -ivh autoconf-xxx.rpm rpm -ivh automake-xxx.rpm rpm -ivh libtool-xxx.rpm
生成步骤
如,项目名为,myproject,目录如下:
--myproject+ +--configure.ac +--Makefile.am +--src+ +Makefile.am +libmyproject.c +myprojectbin.c
生成步骤如下:
$ aclocal $ autoconf $ libtoolize -f -c $ automake -a $ touch NEWS $ touch README $ touch AUTHORS $ touch ChangeLogs $ automake $ ./configure $ make $ sudo make install
configure.ac
configure.ac的书写原则。
- 所有需要用的第三方库,都需要通过PKG_CHECK_MODULES之类的函数来检测。这类脚本除了可以在编译前检测是否存在需要的库,最大的 优点是可以自动在Makefile中加入xxx_LDADD这类参数,保证了Makefile.am的简洁。另外,有些库的头文件与库文件比较多,很难用 简单的一句话书写。
- 代码中需要的宏,都在configure.ac中定义。
- 自定义的configure参数,应当在configure.ac中实现。 以下是样例configure.ac。
# -*- Autoconf -*- # Process this file with autoconf to produce a configure script. AC_PREREQ([2.59]) AC_INIT([FULL-PACKAGE-NAME], [VERSION], [BUG-REPORT-ADDRESS]) AC_CONFIG_SRCDIR([src/myprojectbin.c]) AM_INIT_AUTOMAKE() # Checks for programs. AC_PROG_CXX AC_PROG_CC AC_PROG_LIBTOOL # Checks for libraries. PKG_CHECK_MODULES([libmyproject_la], [glib-2.0], [], [ AC_MSG_ERROR(["Error! You need to have libglib2.0 installed."]) ]) PKG_CHECK_EXISTS([cppunit], [], [ AC_MSG_ERROR(["Error! You need to have libcppunit-dev installed. Try sudo apt-get install libcppunit-dev."]) ]) # Checks for header files. AC_CHECK_HEADERS([stdlib.h stdio.h]) # Checks for typedefs, structures, and compiler characteristics. AC_HEADER_STDBOOL AC_TYPE_SIZE_T AC_ARG_WITH(debug, [AS_HELP_STRING([--with-debug], [enable debugging output])], [ if test $withval != "no"; then AC_SUBST(AM_CFLAGS, ["-g3 -O0 -Wall"]) AC_SUBST(AM_CXXFLAGS, ["-g3 -O0 -Wall"]) AC_DEFINE([WITH_DEBUG],1) fi ]) #cppunit_cflags=`pkg-config --cflags cppunit` #cppunit_libs=`pkg-config --libs cppunit` #AM_CPPFLAGS="$cppunit_cflags" #AM_LDFLAGS="$cppunit_libs" #AC_SUBST(AM_CPPFLAGS) #AC_SUBST(AM_LDFLAGS) # Checks for library functions. AC_FUNC_MALLOC AC_CHECK_FUNCS([memset]) AC_DEFINE(_LARGEFILE64_SOURCE) AC_DEFINE(_XOPEN_SOURCE, [500]) AC_DEFINE(_FILE_OFFSET_BITS, [64]) AC_DEFINE(_GNU_SOURCE) AC_CONFIG_FILES([Makefile src/Makefile]) AC_OUTPUT
Makefile.am
Makefile.am的书写原则是:
- 包含所有需要编译的可执行文件或库。
- 包含可执行文件或库相对应的源代码。
- 包含需要安装的文件,如头文件、配置文件。
- 需要引用的头文件,尽可能采用已经安装过的系统绝对目录。
- 尽可能不要通过在xxx_CFLAGS中加入-I来指定头文件位置,除非需要引用的头文件不在/usr/include或/usr/local/include下,而是位于/opt/xxx/include之类的目录下。
- 尽可能不要通过在xxx_LDADD中加入-L或-l来指定库文件位置,正确的做法应该是在configure.ac中完成这些事。
- 调试信息的添加,应当通过设置CFLAGS或CXXFLAGS环境变量来完成,然后执行configure,会保证在编译的时候是根据环境变量来 决定是否需要调试信息。不要在Makefile中用CFLAGS,CXXFLAGS,xxx_CFLAGS,xxx_CXXFLAGS来设置调试信息。这 样每次发布前都要修改Makefile.am,不利于cvs维护。 以下是样例Makefile.am
AUTOMAKE_OPTIONS = foreign lib_LTLIBRARIES = libmyproject.la libmyproject_la_SOURCES = libmyproject.c libmyproject_la_LIBADD = libmyproject_la_CPPFLAGS = $(AM_CPPFLAGS) libmyproject_la_LDFLAGS = $(AM_LDFLAGS) bin_PROGRAMS = myprojectbin myprojectbin_SOURCES = myprojectbin.c myprojectbin_LDADD = myprojectbin_CPPFLAGS = include_HEADERS = libmyproject.h sysconfdir = /etc sysconf_DATA = libmyproject.conf