winston 发表于 2012-2-14 23:09:22

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


个人还是推荐使用cmake,更胜一筹!

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 <<EOF || echo_exit "generates hello.c failed"
#include <stdio.h>
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()
AC_INIT(, , )
AM_INIT_AUTOMAKE([-Wall -Werror foreign])
AC_CONFIG_SRCDIR()
AC_CONFIG_HEADERS()

# 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()
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 <<EOF
#include <stdio.h>
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()
AC_INIT(, , )
AC_CONFIG_SRCDIR()
AC_CONFIG_HEADERS()

# 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()
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()
AC_INIT(, , )
AM_INIT_AUTOMAKE([-Wall -Werror foreign])
AC_CONFIG_SRCDIR()
AC_CONFIG_HEADERS()

# 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()
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
makeall-am
make: 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: 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\
          && makedvi \
          && makecheck \
          && makeinstall \
          && makeinstallcheck \
          && makeuninstall \
          && makedistuninstallcheck_dir="$dc_install_base" \
                distuninstallcheck \
          && chmod -R a-w "$dc_install_base" \
          && ({ \
             (cd ../.. && umask 077 && mkdir "$dc_destdir") \
             && makeDESTDIR="$dc_destdir" install \
             && makeDESTDIR="$dc_destdir" uninstall \
             && makeDESTDIR="$dc_destdir" \
                    distuninstallcheck_dir="$dc_destdir" distuninstallcheck; \
              } || { rm -rf "$dc_destdir"; exit 1; }) \
          && rm -rf "$dc_destdir" \
          && makedist \
          && rm -rf hello-1.0.tar.gz \
          && makedistcleancheck \
          && 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: Entering directory `/tmp/hello/hello-1.0/_build'
makeall-am
make: 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: Leaving directory `/tmp/hello/hello-1.0/_build'
make: Leaving directory `/tmp/hello/hello-1.0/_build'
make: Entering directory `/tmp/hello/hello-1.0/_build'
make: Nothing to be done for `dvi'.
make: Leaving directory `/tmp/hello/hello-1.0/_build'
make: Entering directory `/tmp/hello/hello-1.0/_build'
make: Nothing to be done for `check'.
make: Leaving directory `/tmp/hello/hello-1.0/_build'
make: Entering directory `/tmp/hello/hello-1.0/_build'
make: 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: Nothing to be done for `install-data-am'.
make: Leaving directory `/tmp/hello/hello-1.0/_build'
make: Leaving directory `/tmp/hello/hello-1.0/_build'
make: Entering directory `/tmp/hello/hello-1.0/_build'
make: Nothing to be done for `installcheck'.
make: Leaving directory `/tmp/hello/hello-1.0/_build'
make: Entering directory `/tmp/hello/hello-1.0/_build'
( cd '/tmp/hello/hello-1.0/_inst/bin' && rm -f hello )
make: Leaving directory `/tmp/hello/hello-1.0/_build'
make: Entering directory `/tmp/hello/hello-1.0/_build'
make: Leaving directory `/tmp/hello/hello-1.0/_build'
make: Entering directory `/tmp/hello/hello-1.0/_build'
make: 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: Nothing to be done for `install-data-am'.
make: Leaving directory `/tmp/hello/hello-1.0/_build'
make: Leaving directory `/tmp/hello/hello-1.0/_build'
make: Entering directory `/tmp/hello/hello-1.0/_build'
( cd '/tmp/am-dc-8010//tmp/hello/hello-1.0/_inst/bin' && rm -f hello )
make: Leaving directory `/tmp/hello/hello-1.0/_build'
make: Entering directory `/tmp/hello/hello-1.0/_build'
make: Leaving directory `/tmp/hello/hello-1.0/_build'
make: 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: Leaving directory `/tmp/hello/hello-1.0/_build'
make: 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: 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。

作者:cppgp 发表于2012-2-14 17:40:22 原文链接


ztenv 发表于 2012-2-16 09:46:41

autotools入门,写个简单的程序,用起来很简单,但想深入还是有些难度的,主要是资料太少,大部分都是讲解单个工程的。
页: [1]
查看完整版本: GNU Autotools (autoconf, automake, libtool, etc.) 自动化编译 (1)