GNU Autotools (autoconf, automake, libtool, etc.) 自动化编译 (1) 简单示例

0. 操作平台: Linux


1. 软件包安装(Debian)

yes | sudo apt-get install gcc make autoconf automake libtool

2. 从一个例子谈起。

    2.0 完整拷贝如下代码直接在终端执行或者保存为auto-example.sh,添加执行权限执行。或者参考2.1~2.5逐步执行。

echo "create directory ..."
echo_exit()
{
	echo "ERROR: $@"
	exit 1
}

# 1.
mkdir hello && cd hello || echo_exit "mkdir hello or cd hello failed"
cat > hello.c <
int main()
{
    printf("hello auto-tools!\n");
    return 0;
}
EOF

# 2.
cat > Makefile.am << EOF || echo_exit "generates Makefile.am failed"
bin_PROGRAMS = hello
hello_SOURCES = hello.c
EOF

# 3.
cat > configure.ac << EOF || echo_exit "generates configure.ac failed"
#                                               -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.

AC_PREREQ([2.67])
AC_INIT([hello], [1.0], [[email protected]])
AM_INIT_AUTOMAKE([-Wall -Werror foreign])
AC_CONFIG_SRCDIR([hello.c])
AC_CONFIG_HEADERS([config.h])

# Checks for programs.
AC_PROG_CC

# Checks for libraries.

# Checks for header files.

# Checks for typedefs, structures, and compiler characteristics.

# Checks for library functions.

AC_CONFIG_FILES([Makefile])
AC_OUTPUT
EOF

# 4.
autoreconf --install || echo_exit "autoreconf --install failed"

# 5.
./configure && make || echo_exit "configure or make failed"

# 6.
make dist && make distcheck || echo_exit "make dist && make distcheck failed"

echo "All Do Over Success"


    2.1 创建hello目录和源代码hello.c:         

~$ mkdir hello && cd hello
~$ cat > hello.c <
int main()
{
    printf("hello auto-tools!\n");
    return 0;
}
EOF
    2.2 创建 Makefile.am
~$ cat > Makefile.am << EOF
bin_PROGRAMS = hello
hello_SOURCES = hello.c
EOF
    2.3 用 autoscan 生成configure.ac的模板configure.scan

~$ autoscan
~$ cat configure.scan
#                                               -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.

AC_PREREQ([2.67])
AC_INIT([FULL-PACKAGE-NAME], [VERSION], [BUG-REPORT-ADDRESS])
AC_CONFIG_SRCDIR([hello.c])
AC_CONFIG_HEADERS([config.h])

# Checks for programs.
AC_PROG_CC

# Checks for libraries.

# Checks for header files.

# Checks for typedefs, structures, and compiler characteristics.

# Checks for library functions.

AC_CONFIG_FILES([Makefile])
AC_OUTPUT
      需要修改configure.scan的不问内容并保存为configure.ac。为了方便,直接用如下指令生成configure.ac:

~$ cat > configure.ac << EOF
#                                               -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.

AC_PREREQ([2.67])
AC_INIT([hello], [1.0], [[email protected]])
AM_INIT_AUTOMAKE([-Wall -Werror foreign])
AC_CONFIG_SRCDIR([hello.c])
AC_CONFIG_HEADERS([config.h])

# Checks for programs.
AC_PROG_CC

# Checks for libraries.

# Checks for header files.

# Checks for typedefs, structures, and compiler characteristics.

# Checks for library functions.

AC_CONFIG_FILES([Makefile])
AC_OUTPUT
EOF
      可以看出,只是修改了AC_INIT行,并添加了AM_INIT_AUTOMAKE行。

    2.4 使用autoreconf直接生成可执行configure并执行编译:

~$ autoreconf --install
configure.ac:6: installing `./install-sh'
configure.ac:6: installing `./missing'
Makefile.am: installing `./depcomp'
~$ ./configure 
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for a thread-safe mkdir -p... /bin/mkdir -p
checking for gawk... gawk
checking whether make sets $(MAKE)... yes
checking for gcc... gcc
checking whether the C compiler works... yes
checking for C compiler default output file name... a.out
checking for suffix of executables... 
checking whether we are cross compiling... no
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether gcc accepts -g... yes
checking for gcc option to accept ISO C89... none needed
checking for style of include used by make... GNU
checking dependency style of gcc... gcc3
configure: creating ./config.status
config.status: creating Makefile
config.status: creating config.h
config.status: executing depfiles commands
~$ make
make  all-am
make[1]: Entering directory `/tmp/hello'
gcc -DHAVE_CONFIG_H -I.     -g -O2 -MT hello.o -MD -MP -MF .deps/hello.Tpo -c -o hello.o hello.c
mv -f .deps/hello.Tpo .deps/hello.Po
gcc  -g -O2   -o hello hello.o  
make[1]: Leaving directory `/tmp/hello'
~$ ./hello
hello auto-tools!
    2.5生成发行包并检测完整性:

~$ make dist && make distcheck
/bin/sh ./config.status --recheck
running CONFIG_SHELL=/bin/sh /bin/sh ./configure --no-create --no-recursion
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for a thread-safe mkdir -p... /bin/mkdir -p
checking for gawk... gawk
checking whether make sets $(MAKE)... yes
checking for gcc... gcc
checking whether the C compiler works... yes
checking for C compiler default output file name... a.out
checking for suffix of executables... 
checking whether we are cross compiling... no
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether gcc accepts -g... yes
checking for gcc option to accept ISO C89... none needed
checking for style of include used by make... GNU
checking dependency style of gcc... gcc3
configure: creating ./config.status
 /bin/sh ./config.status
config.status: creating Makefile
config.status: creating config.h
config.status: config.h is unchanged
config.status: executing depfiles commands
{ test ! -d "hello-1.0" || { find "hello-1.0" -type d ! -perm -200 -exec chmod u+w {} ';' && rm -fr "hello-1.0"; }; }
test -d "hello-1.0" || mkdir "hello-1.0"
test -n "" \
	|| find "hello-1.0" -type d ! -perm -755 \
		-exec chmod u+rwx,go+rx {} \; -o \
	  ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \
	  ! -type d ! -perm -400 -exec chmod a+r {} \; -o \
	  ! -type d ! -perm -444 -exec /bin/sh /tmp/hello/install-sh -c -m a+r {} {} \; \
	|| chmod -R a+r "hello-1.0"
tardir=hello-1.0 && /bin/sh /tmp/hello/missing --run tar chof - "$tardir" | GZIP=--best gzip -c >hello-1.0.tar.gz
{ test ! -d "hello-1.0" || { find "hello-1.0" -type d ! -perm -200 -exec chmod u+w {} ';' && rm -fr "hello-1.0"; }; }
{ test ! -d "hello-1.0" || { find "hello-1.0" -type d ! -perm -200 -exec chmod u+w {} ';' && rm -fr "hello-1.0"; }; }
test -d "hello-1.0" || mkdir "hello-1.0"
test -n "" \
	|| find "hello-1.0" -type d ! -perm -755 \
		-exec chmod u+rwx,go+rx {} \; -o \
	  ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \
	  ! -type d ! -perm -400 -exec chmod a+r {} \; -o \
	  ! -type d ! -perm -444 -exec /bin/sh /tmp/hello/install-sh -c -m a+r {} {} \; \
	|| chmod -R a+r "hello-1.0"
tardir=hello-1.0 && /bin/sh /tmp/hello/missing --run tar chof - "$tardir" | GZIP=--best gzip -c >hello-1.0.tar.gz
{ test ! -d "hello-1.0" || { find "hello-1.0" -type d ! -perm -200 -exec chmod u+w {} ';' && rm -fr "hello-1.0"; }; }
case 'hello-1.0.tar.gz' in \
	*.tar.gz*) \
	  GZIP=--best gzip -dc hello-1.0.tar.gz | /bin/sh /tmp/hello/missing --run tar xf - ;;\
	*.tar.bz2*) \
	  bzip2 -dc hello-1.0.tar.bz2 | /bin/sh /tmp/hello/missing --run tar xf - ;;\
	*.tar.lzma*) \
	  lzma -dc hello-1.0.tar.lzma | /bin/sh /tmp/hello/missing --run tar xf - ;;\
	*.tar.xz*) \
	  xz -dc hello-1.0.tar.xz | /bin/sh /tmp/hello/missing --run tar xf - ;;\
	*.tar.Z*) \
	  uncompress -c hello-1.0.tar.Z | /bin/sh /tmp/hello/missing --run tar xf - ;;\
	*.shar.gz*) \
	  GZIP=--best gzip -dc hello-1.0.shar.gz | unshar ;;\
	*.zip*) \
	  unzip hello-1.0.zip ;;\
	esac
chmod -R a-w hello-1.0; chmod a+w hello-1.0
mkdir hello-1.0/_build
mkdir hello-1.0/_inst
chmod a-w hello-1.0
test -d hello-1.0/_build || exit 0; \
	dc_install_base=`CDPATH="${ZSH_VERSION+.}:" && cd hello-1.0/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \
	  && dc_destdir="${TMPDIR-/tmp}/am-dc-$/" \
	  && am__cwd=`pwd` \
	  && CDPATH="${ZSH_VERSION+.}:" && cd hello-1.0/_build \
	  && ../configure --srcdir=.. --prefix="$dc_install_base" \
	     \
	  && make  \
	  && make  dvi \
	  && make  check \
	  && make  install \
	  && make  installcheck \
	  && make  uninstall \
	  && make  distuninstallcheck_dir="$dc_install_base" \
	        distuninstallcheck \
	  && chmod -R a-w "$dc_install_base" \
	  && ({ \
	       (cd ../.. && umask 077 && mkdir "$dc_destdir") \
	       && make  DESTDIR="$dc_destdir" install \
	       && make  DESTDIR="$dc_destdir" uninstall \
	       && make  DESTDIR="$dc_destdir" \
	            distuninstallcheck_dir="$dc_destdir" distuninstallcheck; \
	      } || { rm -rf "$dc_destdir"; exit 1; }) \
	  && rm -rf "$dc_destdir" \
	  && make  dist \
	  && rm -rf hello-1.0.tar.gz \
	  && make  distcleancheck \
	  && cd "$am__cwd" \
	  || exit 1
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for a thread-safe mkdir -p... /bin/mkdir -p
checking for gawk... gawk
checking whether make sets $(MAKE)... yes
checking for gcc... gcc
checking whether the C compiler works... yes
checking for C compiler default output file name... a.out
checking for suffix of executables... 
checking whether we are cross compiling... no
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether gcc accepts -g... yes
checking for gcc option to accept ISO C89... none needed
checking for style of include used by make... GNU
checking dependency style of gcc... gcc3
configure: creating ./config.status
config.status: creating Makefile
config.status: creating config.h
config.status: executing depfiles commands
make[1]: Entering directory `/tmp/hello/hello-1.0/_build'
make  all-am
make[2]: Entering directory `/tmp/hello/hello-1.0/_build'
gcc -DHAVE_CONFIG_H -I. -I..     -g -O2 -MT hello.o -MD -MP -MF .deps/hello.Tpo -c -o hello.o ../hello.c
mv -f .deps/hello.Tpo .deps/hello.Po
gcc  -g -O2   -o hello hello.o  
make[2]: Leaving directory `/tmp/hello/hello-1.0/_build'
make[1]: Leaving directory `/tmp/hello/hello-1.0/_build'
make[1]: Entering directory `/tmp/hello/hello-1.0/_build'
make[1]: Nothing to be done for `dvi'.
make[1]: Leaving directory `/tmp/hello/hello-1.0/_build'
make[1]: Entering directory `/tmp/hello/hello-1.0/_build'
make[1]: Nothing to be done for `check'.
make[1]: Leaving directory `/tmp/hello/hello-1.0/_build'
make[1]: Entering directory `/tmp/hello/hello-1.0/_build'
make[2]: Entering directory `/tmp/hello/hello-1.0/_build'
test -z "/tmp/hello/hello-1.0/_inst/bin" || /bin/mkdir -p "/tmp/hello/hello-1.0/_inst/bin"
  /usr/bin/install -c hello '/tmp/hello/hello-1.0/_inst/bin'
make[2]: Nothing to be done for `install-data-am'.
make[2]: Leaving directory `/tmp/hello/hello-1.0/_build'
make[1]: Leaving directory `/tmp/hello/hello-1.0/_build'
make[1]: Entering directory `/tmp/hello/hello-1.0/_build'
make[1]: Nothing to be done for `installcheck'.
make[1]: Leaving directory `/tmp/hello/hello-1.0/_build'
make[1]: Entering directory `/tmp/hello/hello-1.0/_build'
 ( cd '/tmp/hello/hello-1.0/_inst/bin' && rm -f hello )
make[1]: Leaving directory `/tmp/hello/hello-1.0/_build'
make[1]: Entering directory `/tmp/hello/hello-1.0/_build'
make[1]: Leaving directory `/tmp/hello/hello-1.0/_build'
make[1]: Entering directory `/tmp/hello/hello-1.0/_build'
make[2]: Entering directory `/tmp/hello/hello-1.0/_build'
test -z "/tmp/hello/hello-1.0/_inst/bin" || /bin/mkdir -p "/tmp/am-dc-8010//tmp/hello/hello-1.0/_inst/bin"
  /usr/bin/install -c hello '/tmp/am-dc-8010//tmp/hello/hello-1.0/_inst/bin'
make[2]: Nothing to be done for `install-data-am'.
make[2]: Leaving directory `/tmp/hello/hello-1.0/_build'
make[1]: Leaving directory `/tmp/hello/hello-1.0/_build'
make[1]: Entering directory `/tmp/hello/hello-1.0/_build'
 ( cd '/tmp/am-dc-8010//tmp/hello/hello-1.0/_inst/bin' && rm -f hello )
make[1]: Leaving directory `/tmp/hello/hello-1.0/_build'
make[1]: Entering directory `/tmp/hello/hello-1.0/_build'
make[1]: Leaving directory `/tmp/hello/hello-1.0/_build'
make[1]: Entering directory `/tmp/hello/hello-1.0/_build'
{ test ! -d "hello-1.0" || { find "hello-1.0" -type d ! -perm -200 -exec chmod u+w {} ';' && rm -fr "hello-1.0"; }; }
test -d "hello-1.0" || mkdir "hello-1.0"
test -n "" \
	|| find "hello-1.0" -type d ! -perm -755 \
		-exec chmod u+rwx,go+rx {} \; -o \
	  ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \
	  ! -type d ! -perm -400 -exec chmod a+r {} \; -o \
	  ! -type d ! -perm -444 -exec /bin/sh /tmp/hello/hello-1.0/install-sh -c -m a+r {} {} \; \
	|| chmod -R a+r "hello-1.0"
tardir=hello-1.0 && /bin/sh /tmp/hello/hello-1.0/missing --run tar chof - "$tardir" | GZIP=--best gzip -c >hello-1.0.tar.gz
{ test ! -d "hello-1.0" || { find "hello-1.0" -type d ! -perm -200 -exec chmod u+w {} ';' && rm -fr "hello-1.0"; }; }
make[1]: Leaving directory `/tmp/hello/hello-1.0/_build'
make[1]: Entering directory `/tmp/hello/hello-1.0/_build'
test -z "hello" || rm -f hello
rm -f *.o
rm -f *.tab.c
test -z "" || rm -f 
test . = ".." || test -z "" || rm -f 
rm -f config.h stamp-h1
rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
rm -f config.status config.cache config.log configure.lineno config.status.lineno
rm -rf ./.deps
rm -f Makefile
make[1]: Leaving directory `/tmp/hello/hello-1.0/_build'
{ test ! -d "hello-1.0" || { find "hello-1.0" -type d ! -perm -200 -exec chmod u+w {} ';' && rm -fr "hello-1.0"; }; }
===========================================
hello-1.0 archives ready for distribution: 
hello-1.0.tar.gz
===========================================

3. 一般项目并不是简单的一个.c文件。通常包括多个(嵌套的)目录。并且需要执行差异化的编译和安装,下一篇文章示范如何在一个实际项目中应用autotools。

你可能感兴趣的:(GNU Autotools (autoconf, automake, libtool, etc.) 自动化编译 (1) 简单示例)