GNU Autotools (autoconf, automake, libtool) 编译简单示例
目录
Fist publish in https://blog.csdn.net/cppgp/article/details/7258875
1 操作平台: Linux
2 软件包安装(Debian)
~$ yes | sudo apt-get install gcc make autoconf automake libtool
3 从一个例子谈起。
3.1 example
完整拷贝如下代码直接在终端执行或者保存为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([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"
3.2 创建hello目录和源代码hello.c:
~$ mkdir hello && cd hello ~$ cat > hello.c <<EOF #include <stdio.h> int main() { printf("hello auto-tools!\n"); return 0; } EOF
3.3 创建 Makefile.am
~$ cat > Makefile.am << EOF bin_PROGRAMS = hello hello_SOURCES = hello.c EOF
3.4 用 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行。
3.5 使用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!
3.6 生成发行包并检测完整性:
~$ 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 ===========================================
一般项目并不是简单的一个.c文件。通常包括多个(嵌套的)目录。并且需要执行差异化的编译和安装,下一篇文章示范如何在一个实际项目中应用autoconf。