1. 程式人生 > >autoconf和automake實踐

autoconf和automake實踐

2010-11-11

周海漢 2010.11.11 光棍不再

linux程式原始碼編譯三部曲: ./configure make make install 非常省事。一個configure可以為多變環境生成不同的makefile,確保make可以通過。 所以我們寫程式碼時也非常希望利用上這些快捷工具,免得自己去寫configure和makefile。 autoconf和automake聯合起來,可以為編譯省很多事。

下面是gnu畫的autoconf和automake關係圖: 來源:http://www.gnu.org/software/autoconf/manual/autoconf.html 用autoconf生成configure.帶*表示可以執行。帶[]表示可選。

     your source files --> [autoscan*] --> [configure.scan] --> configure.ac

     configure.ac --.
                    |   .------> autoconf* -----> configure
     [aclocal.m4] --+---+
                    |   `-----> [autoheader*] --> [config.h.in]
     [acsite.m4] ---'

用automake生成Makefile.in,但Makefile.am是手動編輯的。

     [acinclude.m4] --.
                      |
     [local macros] --+--> aclocal* --> aclocal.m4
                      |
     configure.ac ----'

     configure.ac --.
                    +--> automake* --> Makefile.in
     Makefile.am ---'

配置軟體包用到的檔案。

                            .-------------> [config.cache]
     configure* ------------+-------------> config.log
                            |
     [config.h.in] -.       v            .-> [config.h] -.
                    +--> config.status* -+               +--> make*
     Makefile.in ---'                    `-> Makefile ---'

其中configure.ac和Makefile.am是必須手工修改的。

測試程式: [email protected]:~/hello$ ls hello.c hello.h

我希望為測試程式生成./configure和Makefile

[email protected]:~/hello$ cat hello.c
//////////////////////////////////////////
//author 	zhouhh
//date 		2010.11.8
//web       http://abloz.com
//history
/////////////////////////////////////////

#include
#include
#include
#include
#include
#include
#include
#include

#include

#include

#include "hello.h"

int         epoll_handle;
struct epoll_event    events[EPOLL_SIZE];
pthread_t accept_tid;
static void *accept_thread(void *arg);

int main(int argc, char *argv[])
{
    int perr, nfds, i;

    epoll_handle = epoll_create(EPOLL_SIZE);
    if (epoll_handle == -1) {
        perror("process exitn");
        exit(EXIT_FAILURE);
    }
    perr = pthread_create(&accept_tid, NULL, accept_thread, NULL);
    if (perr != 0) {
        perror("pthread_create");
        exit(EXIT_FAILURE);
    }
    char buf[1024]={0};
    int len = 0;
    while (1) {
        nfds = epoll_wait(epoll_handle, events, EPOLL_SIZE, -1);
        if (nfds == -1) {
            perror("epoll_wait");
            exit(EXIT_FAILURE);
        }
        for (i = 0; i < nfds; i++) {
            printf("%d recv socket fd %d is donen", i, events[i].data.fd);
            len = read(events[i].data.fd,buf,1024);
            buf[len]='\0';
            printf("rcved "%s",len= %d n",buf,len);
            write(events[i].data.fd,buf,len);
            //write(stdout,buf,1024);

        } //for (i = 0; i < nfds; i++)
    } //while(1)
    return 0;
}
static void *accept_thread(void *arg)
{
    int                 sockfd;
    int                    connfd;
    int                    t;
    socklen_t            clilen = 0;
    struct sockaddr     servaddr, cliaddr;
    struct sockaddr_in    *st_in = (struct sockaddr_in *)&servaddr;
    struct epoll_event    ev;

    t = pthread_detach(pthread_self());
    if (t != 0) {
        perror("pthread_detach");
        return NULL;
    }

    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd == -1) {
        perror("process exitn");
        exit(EXIT_FAILURE);
    }
    int opt = 1;
    setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&opt, sizeof(opt));
    bzero(&servaddr, sizeof(struct sockaddr));
    st_in->sin_family = AF_INET;
    st_in->sin_port = htons(PORT);
    st_in->sin_addr.s_addr = htonl(INADDR_ANY);
    if (bind(sockfd, &servaddr, sizeof(servaddr)) == -1) {
        perror("bind");
        exit(EXIT_FAILURE);
    }
    if (listen(sockfd, 10) == -1) {
        perror("process exitn");
        exit(EXIT_FAILURE);
    }

    clilen = sizeof(cliaddr);
    ev.events = EPOLLIN | EPOLLET;

    while (1) {
        if ( (connfd = accept(sockfd, (struct sockaddr *)&cliaddr, &clilen)) < 0) {
            perror("accept");
            break;
        }
        printf("accept return %dn", connfd);
        ev.data.fd = connfd;
        if (epoll_ctl(epoll_handle, EPOLL_CTL_ADD, connfd, &ev) < 0) {
            perror("epoll_ctl");
        }
    }

    return NULL;
}

void testcurl(void)
{
    CURL *curl;
    CURLcode res;

    curl = curl_easy_init();
    if(curl) {
        curl_easy_setopt(curl, CURLOPT_URL, "http://abloz.com");
        res = curl_easy_perform(curl);

        /* always cleanup */
        curl_easy_cleanup(curl);
    }
}




[email protected]:~/hello$ cat hello.h
//////////////////////////////////////////
//author 	zhouhh
//date 		2010.11.8
//web       http://abloz.com
//history
/////////////////////////////////////////

#ifndef __HELLO_H_
#define __HELLO_H_

#define PORT 5000
#define EPOLL_SIZE 50

#endif // __HELLO_H_

生成configure.scan [email protected]:~/hello$ autoscan [email protected]:~/hello$ ls autoscan.log configure.scan hello.c hello.h

[email protected]:~/hello$ vi configure.scan

將configure.scan改名configure.ac或configure.in,但第二種檔名只是為了和老版本相容。 [email protected]:~/hello$ cp configure.scan configure.ac

生成aclocal.m4 [email protected]:~/hello$ aclocal [email protected]:~/hello$ ls autom4te.cache autoscan.log configure.ac configure.scan hello.c hello.h

修改configure.ac [email protected]:~/hello$ vi configure.ac

#                                               -*- 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.h])
AC_CONFIG_HEADERS([config.h])

# Checks for programs.
AC_PROG_CC

# Checks for libraries.

# Checks for header files.
AC_CHECK_HEADERS([arpa/inet.h stdlib.h strings.h sys/socket.h unistd.h])

# Checks for typedefs, structures, and compiler characteristics.

# Checks for library functions.
AC_CHECK_FUNCS([bzero socket])

AC_OUTPUT




[email protected]:~/hello$ cp configure.scan configure.scan.bk
[email protected]:~/hello$ autoconf
configure.ac:8: error: possibly undefined macro: AM_INIT_AUTOMAKE
      If this token and others are legitimate, please use m4_pattern_allow.
      See the Autoconf documentation.

這是因為更新configure.ac後必須重新生成aclocal.m4,巨集才有定義。 [email protected]:~/hello$ ls autom4te.cache configure configure.scan hello.c autoscan.log configure.ac configure.scan.bk hello.h [email protected]:~/hello$ aclocal [email protected]:~/hello$ ls aclocal.m4 autoscan.log configure.ac configure.scan.bk hello.h autom4te.cache configure configure.scan hello.c [email protected]:~/hello$ autoconf

呼叫autoheader生成config.h.in [email protected]:~/hello$ autoheader [email protected]:~/hello$ ls aclocal.m4 autoscan.log configure configure.scan hello.c autom4te.cache config.h.in configure.ac configure.scan.bk hello.h

生成configure [email protected]:~/hello$ autoconf [email protected]:~/hello$ ls aclocal.m4 autoscan.log configure configure.scan hello.c autom4te.cache config.h.in configure.ac configure.scan.bk hello.h [email protected]:~/hello$ ./configure configure: error: cannot find install-sh, install.sh, or shtool in “.” “./..” “./../..”

為符合gnu標準,生成NEWS README AUTHORS ChangeLog,否則會報錯。但這些也可以配置不生成。 [email protected]:~/hello$ touch NEWS README AUTHORS ChangeLog

[email protected]:~/hello$ autoreconf –force –install configure.ac:8: installing ./install-sh' configure.ac:8: installing ./missing’ automake: no `Makefile.am’ found for any configure output autoreconf: automake failed with exit status: 1

[email protected]:~/hello$ autoconf [email protected]:~/hello$ ./configure checking for a BSD-compatible install… /usr/bin/install -c … configure: creating ./config.status config.status: error: cannot find input file: `Makefile.in’

[email protected]:~/hello$ automake automake: no Makefile.am' found for any configure output [email protected]:~/hello$ touch Makefile.am [email protected]:~/hello$ automake Makefile.am: required file ./INSTALL’ not found Makefile.am: automake --add-missing' can install INSTALL’ Makefile.am: required file ./COPYING' not found Makefile.am: automake –add-missing’ can install COPYING' [email protected]:~/hello$ ls aclocal.m4 ChangeLog config.status configure.scan.bk Makefile.am AUTHORS config.h.in configure hello.c missing autom4te.cache config.h.in~ configure.ac hello.h NEWS autoscan.log config.log configure.scan install-sh README [email protected]:~/hello$ automake --add-missing INSTALL COPYING automake: no Automake input file found for INSTALL’ automake: no Automake input file found for `COPYING’ automake: no input file found among supplied arguments

[email protected]:~/hello$ touch INSTALL COPYING [email protected]:~/hello$ automake [email protected]:~/hello$ ls aclocal.m4 config.h.in configure.ac hello.h missing AUTHORS config.h.in~ configure.scan INSTALL NEWS autom4te.cache config.log configure.scan.bk install-sh README autoscan.log config.status COPYING Makefile.am ChangeLog configure hello.c Makefile.in [email protected]:~/hello$ autoreconf [email protected]:~/hello$ ./configure … configure: creating ./config.status config.status: creating Makefile config.status: creating config.h config.status: executing depfiles commands

[email protected]:~/hello$ ls aclocal.m4 config.h.in configure.scan install-sh README AUTHORS config.h.in~ configure.scan.bk Makefile stamp-h1 autom4te.cache config.log COPYING Makefile.am autoscan.log config.status hello.c Makefile.in ChangeLog configure hello.h missing config.h configure.ac INSTALL NEWS [email protected]:~/hello$ vi Makefile

因為Makefile.am是空的 [email protected]:~/hello$ make make all-am make[1]: 正在進入目錄 /home/zhouhh/hello' make[1]:正在離開目錄 /home/zhouhh/hello’

[email protected]:~/hello$ vi Makefile.am

AUTOMAKE_OPTIONS = subdir-objects
ACLOCAL_AMFLAGS = ${ACLOCAL_FLAGS}

bin_PROGRAMS = hello
hello_SOURCES = hello.h hello.c
#SUBDIRS = src
#AM_CPPFLAGS = $(MYSQL_CFLAGS)
hello_LDADD =  $(CURL_LIBS)
#dist_noinst_SCRIPTS = autogen.sh

[email protected]:~/hello$ vi configure.ac

#                                               -*- 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_INIT([hello], [1.0], [[email protected]], [hello], [http://abloz.com])
AC_CONFIG_SRCDIR([hello.h])
AM_INIT_AUTOMAKE([1.0 no-define])
AC_CONFIG_HEADERS([config.h])
AC_SUBST(CFLAGS)
AC_SUBST(LD_FLAGS)

# Checks for programs.
AC_PROG_CC
AC_CONFIG_FILES([Makefile])

# Checks for libraries.
#採用pkg-config
#PKG_CHECK_MODULES([DEPS],[curl])
AC_CHECK_LIB([pthread], [pthread_rwlock_init])
AC_PROG_RANLIB
#不採用pkg-config:
AC_ARG_WITH([curl-lib-path],
  [AS_HELP_STRING([--with-curl-lib-path], [location of the curl libraries])],
  [CURL_LIBS="-L$withval -lcurl"],
  [CURL_LIBS='-lcurl'])
AC_SUBST([CURL_LIBS])
# Checks for header files.
AC_CHECK_HEADERS([arpa/inet.h stdlib.h strings.h sys/socket.h unistd.h])

# Checks for typedefs, structures, and compiler characteristics.

# Checks for library functions.
AC_CHECK_FUNCS([bzero socket])

AC_OUTPUT

不採用pkg-config的方式,如mysql:

# Get MySQL library and include locations
AC_ARG_WITH([mysql-include-path],
  [AS_HELP_STRING([--with-mysql-include-path],
    [location of the MySQL headers, defaults to /usr/include/mysql])],
  [MYSQL_CFLAGS="-I$withval"],
  [MYSQL_CFLAGS='-I/usr/include/mysql'])
AC_SUBST([MYSQL_CFLAGS])

AC_ARG_WITH([mysql-lib-path],
  [AS_HELP_STRING([--with-mysql-lib-path], [location of the MySQL libraries])],
  [MYSQL_LIBS="-L$withval -lmysqlclient"],
  [MYSQL_LIBS='-lmysqlclient'])
AC_SUBST([MYSQL_LIBS])

[email protected]:~/hello$ autoreconf –force –install Makefile.am: installing `./depcomp’ [email protected]:~/hello$ ./configure [email protected]:~/hello$ make 通過。

參考: http://www.openismus.com/documents/linux/automake/automake.shtml http://www.openismus.com/documents/linux/using_libraries/using_libraries 例子下載 http://www.gnu.org/software/automake/manual/standards/Makefile-Basics.html http://www.gnu.org/software/autoconf/manual/autoconf.html

如非註明轉載, 均為原創. 本站遵循知識共享CC協議,轉載請註明來源