zoukankan      html  css  js  c++  java
  • GNU Automake By Example

    Table of Contents

    1. Abstract
    2. A Minimal Project
    3. Editing Automake-based Projects with KDevelop
    4. Adding Doxygen Support
    5. A More Complex Example
    6. Topics Not Covered
    7. Links

    Abstract

    This article presents several simple Automake/Autoconf-based projects. I assume that you know what Automake, Autoconf, and configure are, and that you know how to install a software package from sources (i.e., you know how to invoke "configure & make & make install"). (If you don’t, you can still follow the instructions to create a very small project to play around with.) This article does not contain lengthy explanations or detailed background information. Rather, I present a few examples that (hopefully) get the ideas across.

    Some of the topics for which examples are presented:

    • Doxygen support
    • Multiple subdirectories
    • Flex/Bison support
    • Libtool Convenience libraries
    • KDevelop Automake Manager

    I have tested all examples on GNU/Linux using Automake 1.9.5 and Autoconf 2.59.

    I am not an Automake guru myself (not yet ;-) ). When I ported mfGraph to Automake, I was looking for short and simple examples like those presented in this article that would illustrate what the Automake and Autoconf manuals were talking about. I didn’t find exactly what I was looking for. The Automake Book [1], while being a good introduction, didn’t answer all my questions either. If you’re like me, maybe you’ll find this article helpful.

    I appreciate all your feedback, especially if you find any errors or abuses of Automake/Autoconf concepts.

    In the meantime, another very interesting book about Automake/Autoconf is available online: Autotools: a practitioner’s guide to Autoconf, Automake and Libtool [7] at the Free Software Magazine web site.

    A Minimal Project

    Create a directry structure with the following files in it:

    
        foobar/
            m4/
            src/
                Makefile.am
                <your source code files>
            AUTHORS
            COPYING
            ChangeLog
            Makefile.am
            NEWS
            README
            autogen.sh
            configure.ac
    
    

    This is the source tree of the project. Apart from the .cpp and .h files, these text files are the only files that you need to create for a minimal GNU Automake/Autoconf-based project. All other files will be generated by the tools.

    Root Makefile.am

    Let’s take a look at the contents of the files. The files named Makefile.am are the input to the Automake tool. First, the root Makefile.am:

    
    foobar/Makefile.am:
        ACLOCAL_AMFLAGS = -I m4
        SUBDIRS = src
        EXTRA_DIST = autogen.sh
    
    
    • For a minimal project, we only need to name the subdirectories containing additional Makefile.am files.
    • The option -I m4 tells Autoconf to look for additional Autoconf macros in the m4 subdirectory. We’ll make use of this when we introduce Doxygen.
    • The EXTRA_DIST directive tells Automake to place the file autogen.sh in the distribution archive, so that that file is shipped to our users.

    autogen.sh

    The file autogen.sh is a shell script that invokes autoreconf for us. The tool autoreconf is responsible for calling Autoconf, Automake and related tools in the right order.

    Don’t forget to set the Execute bit for the file autogen.sh!

    
    foobar/autogen.sh:
        #!/bin/sh
        autoreconf --force --install -I config -I m4
    
    
    • The --force option rebuilds the configure script regardless of its timestamp in relation to that of the file configure.ac.
    • The option --install copies some missing files to the directory, including the text files COPYING and INSTALL.
    • We add -I config and -I m4 so that the tools find the files that we’re going to place in those subdirectories instead of in the project root.

    Note: Don’t run autogen.sh yet. We have to write configure.ac and Makefile.am first.

    For more information on autoreconf, run info autoreconf. If you’re using KDE, you can also enter info:autoreconf in the Konqueror address box.

    configure.ac

    The file configure.ac is the input to Autoconf. Autoconf produces the configure shell script, which, in turn, produces the final Makefiles, so that users can type make install to install your software.

    
    foobar/configure.ac:
        dnl Process this file with autoconf to produce a configure script.
        AC_INIT(foobar, 1.0, me@mail.com)
        AC_CONFIG_AUX_DIR(config)
        AC_CONFIG_SRCDIR(src/foobar.cpp)
    
        AM_INIT_AUTOMAKE
    
        AC_PROG_CXX
    
        AC_OUTPUT(Makefile src/Makefile)
    
    
    • The lines up to and including AM_INIT_AUTOMAKE are more or less boilerplate code. AC_CONFIG_AUX_DIR is the place where some helper files will be placed. This keeps the root directory cleaner.
    • AC_PROG_CXX enables C++ compiler support. Autoconf will generate code for the configure script that determines the location of the compiler, tests various compiler switches, etc.
      • Larger projects will require additional checks and switches here.
    • AC_OUTPUT lists the Makefiles that the configure script should generate on the user’s machine. For every Makefile.am that we write, Automake will generate a Makefile.in. The configure scripts turns these into Makefiles.

    For more information on Autoconf, please see the Autoconf manual (info autoconf).

    src/Makefile.am

    Each subdirectory has its own Makefile.am. Our file src/Makefile.am builds an executable program from a single C++ source file.

    
    foobar/src/Makefile.am:
        bin_PROGRAMS = foobar
        foobar_SOURCES = foobar.cpp
    
    
    • "PROGRAMS" is called a primary. Other primaries include:
      • LIBRARIES for static libraries (.a)
      • LTLIBRARIES for Libtool-based shared libraries (.la)
      • HEADERS
    • The prefix "bin_" tells Automake where to copy the resulting program when the user runs make install. Known directory prefixes include:
      • bin_ – for programs, e.g., /usr/local/bin
      • lib_ – where libraries are placed, e.g., /usr/local/lib
      • include_ – where header files are placed, e.g., /usr/local/include
      • pkginclude_ – e.g., /usr/local/include/foobar
      • noinst_ – files that will not be copied anywhere by make install

      Note: The user can specify the locations of these directories when running the configure script. For more info, run configure --help.

    • "SOURCES" is a variable that lists the source files of the program. For programs and libraries, possible variables include:
      • CFLAGS, CPPFLAGS, CXXFLAGS – extra arguments passed to the compiler/preprocessor
      • LIBADD – extra objects for a library
      • LDADD – extra objects for a program
      • LDFLAGS – extra arguments passed to the linker

    For more information on Automake, please see the Automake manual (info automake).

    Running the Tools

    Now it’s time to run the tools and attempt a build.

    1. Run ./autogen.sh and see which files are produced by this step.
    2. Create a separate build tree and run configure:
          > mkdir build
          > cd build
          > ../configure
      

      Note: You can pass various arguments to configure. Take a look at these by running configure --help.

      Again, see which files are produced by this step.

    3. Run make, then make install.
    4. To produce a distribution package, run make dist or, better yet, make distcheck.

    Editing Automake-based Projects with KDevelop

    You can work with Automake-based projects from within the KDevelop IDE.

    1. Click Project > Import Existing Project…
    2. Specify the directory that contains your Automake-based project
      (Screenshot taken in KDevelop 3.2.0)
    3. Using the Automake Manager, you can add/remove sub-projects, add/remove files, set options, etc.
    4. If your main program is not named after the project, you need to set the Run Options in Project > Options to be able to debug:

    Note: Not everything can be done directly in the IDE. Sometimes you will have to edit the files configure.ac and Makefile.am manually.

    Adding Doxygen Support

    Doxygen is a tool that generates HTML documentation from special comments in C++ source code. (However, I assume you already know the tool. If you don’t, you can safely skip this section.)

    Adding Doxygen support means that we want to have a Make target that generates the HTML documentation, and that the generated HTML documentation should be included in the distribution archive. For this to work, you need to download a few files from Oren Ben-Kiki’s web site and place them in your directory structure (new files are in boldface):

    
        foobar/
            m4/
                ac_doxygen.m4
            src/
                Makefile.am
                <your source code files>
            AUTHORS
            COPYING
            ChangeLog
            Makefile.am
            NEWS
            README
            aminclude.am
            autogen.sh
            configure.ac
            doxygen.cfg
    
    

    Note: Older versions of these files seem to be available at the Autoconf Macro Archive, but these don’t work as good.

    • ac_doxygen.m4 contains Autoconf macros that we can use in configure.ac.
    • aminclude.am contains the Doxygen-related make targets.
    • doxygen.cfg is a Doxyfile template that contains a few macros that will be expanded when the configure script is run. Modify the file so that it suits your needs (and the version of Doxygen that you’re using!).

    Next, we need to make a change to the file Makefile.am in the root directory so that the generated documentation will be included in the distribution archive (added lines are in boldface):

    
    foobar/Makefile.am:
        ACLOCAL_AMFLAGS = -I m4
        SUBDIRS = src
    
        include aminclude.am
    
        EXTRA_DIST = autogen.sh $(DX_CONFIG) doc/html
    
    

    Finally, we add Doxygen-related macro calls to the file configure.ac (added lines are in boldface):

    
    foobar/configure.ac:
        dnl Process this file with autoconf to produce a configure script.
        AC_INIT(foobar, 1.0, me@mail.com)
        AC_CONFIG_AUX_DIR(config)
        AC_CONFIG_SRCDIR(src/foobar.cpp)
    
        AM_INIT_AUTOMAKE
    
        AC_PROG_CXX
    
        DX_HTML_FEATURE(ON)
        DX_CHM_FEATURE(OFF)
        DX_CHI_FEATURE(OFF)
        DX_MAN_FEATURE(OFF)
        DX_RTF_FEATURE(OFF)
        DX_XML_FEATURE(OFF)
        DX_PDF_FEATURE(OFF)
        DX_PS_FEATURE(OFF)
        DX_INIT_DOXYGEN(foobar, doxygen.cfg, doc)
    
        AC_OUTPUT(Makefile src/Makefile)
    
    

    Documentation will be generated when you run make doxygen-doc or when you produce a distribution archive with make distcheck.

    Note: When you look at the generated Makefile, you’ll see that the documentation only depends on the files in pkginclude_HEADERS, regardless of what you set "INPUT" to in the file doxygen.cfg. If you want to force the documentation to be re-generated (maybe before the final build), it might be a good idea to delete the entire Doxygen output folder (doc/html by default) before doing the build.

    A More Complex Example

    Finally, I’d like to present a more complex example with the following features:

    • Several subdirectories, each with their own Makefile.am
    • Libtool shared and convenience libraries
    • Generated source files (the typical Flex/Bison example)

    The new directory structure looks like this (added entries in boldface):

    
        foobar/
            m4/
                ac_doxygen.m4
            some_shared_lib/
                Makefile.am
                <your some_shared_lib-specific source code files>
            src/
                Makefile.am
                <your source code files>
            AUTHORS
            COPYING
            ChangeLog
            Makefile.am
            NEWS
            README
            aminclude.am
            autogen.sh
            configure.ac
            doxygen.cfg
    
    

    For Libtool libraries as well as for Flex/Bison, we need additional checks in configure.ac. Also, we must specify the new subdirectory (added text in boldface):

    
    foobar/configure.ac:
        dnl Process this file with autoconf to produce a configure script.
        AC_INIT(foobar, 1.0, me@mail.com)
        AC_CONFIG_AUX_DIR(config)
        AC_CONFIG_SRCDIR(src/foobar.cpp)
    
        AM_INIT_AUTOMAKE
    
        AC_PROG_CXX
        AM_PROG_LEX
        AC_PROG_YACC
        AC_PROG_LIBTOOL
    
        DX_HTML_FEATURE(ON)
        DX_CHM_FEATURE(OFF)
        DX_CHI_FEATURE(OFF)
        DX_MAN_FEATURE(OFF)
        DX_RTF_FEATURE(OFF)
        DX_XML_FEATURE(OFF)
        DX_PDF_FEATURE(OFF)
        DX_PS_FEATURE(OFF)
        DX_INIT_DOXYGEN(foobar, doxygen.cfg, doc)
    
        AC_OUTPUT(Makefile src/Makefile some_shared_lib/Makefile)
    
    

    Note: When building with Libtool, all sources will be compiled twice–once for static libraries and once for dynamic libraries. If you only ever build dynamic libraries, you can save compilation time by inserting AC_DISABLE_STATIC before AC_PROG_LIBTOOL.

    The additional subdirectory must also be added to Makefile.am (added text in boldface):

    
    foobar/Makefile.am:
        ACLOCAL_AMFLAGS = -I m4
        SUBDIRS = src some_shared_lib
    
        include aminclude.am
    
        EXTRA_DIST = autogen.sh $(DX_CONFIG) doc/html
    
    

    In the file src/Makefile.am, we build a Libtool convenience library from the sources in the src directory. A convenience library is a library that is not installed (as specified by the "noinst_" prefix). Such a library is useful whenever you want to link the same set of sources into several executables or shared libraries, without having to list these sources in every Makefile.am.

    Another complication in src/Makefile.am is that it includes a Flex/Bison-generated parser. With Automake, you only have to list the Bison grammar file (.yy) and the Flex lexer file (.ll) file; Automake knows how to invoke Flex/Bison to generate the source code.

    The only thing you have to remember is to specify mfg_bison.h in BUILT_SOURCES. This way, Automake will run the commands that generate mfg_bison.h before compiling any other files that might depend on it. (Typically, the generated mfg_flex.cpp is one such file that depends on mfg_bison.h. If you don’t specify BUILT_SOURCES, it might happen that the Make tool tries to compile mfg_flex.cpp before mfg_bison.h exists.)

    We also specify public_api.h in the list pkginclude_HEADERS. When the user runs make install, the listed files will be copied to /usr/local/include/foobar (or a different directory passed to configure).

    
    foobar/src/Makefile.am:
        BUILT_SOURCES = mfg_bison.h
        AM_YFLAGS = -d -p mfg
        AM_LFLAGS = -o$(LEX_OUTPUT_ROOT).c
    
        noinst_LTLIBRARIES = libsrc.la
        libsrc_la_SOURCES = public_api.cpp mfg_bison.yy mfg_flex.ll
    
        pkginclude_HEADERS = public_api.h
    
    

    If we didn’t want to install any headers, we’d list the headers in libsrc_la_SOURCES. Headers that are not listed anywhere are not included in the distribution archive.

    In the subdirectory some_shared_lib, we link the convenience library, libsrc.la, and an additional source file into a shared library, libfoobar.la, that will be installed to /usr/local/lib (or a different directory passed to configure).

    The Makefile.am looks like this:

    
    foobar/some_shared_lib/Makefile.am:
        lib_LTLIBRARIES = libfoobar.la
        libfoobar_la_SOURCES = shared_library.cpp
        libfoobar_la_CPPFLAGS = -I$(top_srcdir)/src
        libfoobar_la_LIBADD = ../src/libsrc.la
    
    

    I’ve specified $(top_srcdir)/src as an additional include directory, because it’s common to have #include directives for sources found in src in source files such as some_shared_lib/shared_library.cpp. Note that for linking to the convenience library, I specifiy ../src instead. This is because the library will be found in the build tree, not in the source tree.

    Topics Not Covered

    One topic that I didn’t cover but that I’m very much interested in is

    • building and running a unit test suite automatically during a build.

    Maybe someone of you has a simple working example?

    Links

    1. Gary V. Vaughan, Ben Elliston, Tom Tromey and Ian Lance Taylor. GNU Automake, Autoconf, and Libtool. http://sources.redhat.com/autobook/.
    2. Automake Manual. http://sources.redhat.com/automake/automake.html.
    3. Autoconf Manual. http://www.gnu.org/software/autoconf/manual/index.html.
    4. The GNU Autoconf Macro Archive. http://www.gnu.org/software/ac-archive/.
    5. Oren Ben-Kiki. Doxample. http://ben-kiki.org/oren/doxample/.
    6. This article presents another Automake example: Building SWIG Python Extensions on GNU/Linux
    7. John Calcote. Autotools: a practitioner’s guide to Autoconf, Automake and Libtool. http://www.freesoftwaremagazine.com/books/autotools_a_guide_to_autoconf_automake_libtool.  
  • 相关阅读:
    【周年庆】china-pub 14周年庆感恩回馈四波狂热来袭
    《Python自然语言处理》
    《大教堂与集市》
    《Redis设计与实现》
    《处理器虚拟化技术》
    《Erlang程序设计(第2版)》
    《数据化管理:洞悉零售及电子商务运营》
    《MySQL Workbench数据建模与开发》
    angular中的MVVM模式
    JavaScript函数柯里化
  • 原文地址:https://www.cnblogs.com/nickchan/p/3104406.html
Copyright © 2011-2022 走看看