• 系统程序员成长计划工程管理(三)


    转载时请注明出处和作者联系方式
    文章出处:http://www.limodev.cn/blog
    作者联系方式:李先静 <xianjimli at hotmail dot com>

    系统程序员成长计划-工程管理(三)

    函数库

    现在我们用automake来管理我们前面所建立的函数库,这是一个基础的函数库,我们就把它命名为base吧。

    o 目录结构
    base 根目录
    base/src 源代码目录

    o 创建Makefile模板
    base/Makefile.am内容为:
    SUBDIRS=src

    base/src/Makefile.am内容为:

    lib_LTLIBRARIES=libbase.la

    libbase_la_SOURCES= darray.c /

    darray.h /

    dlist.c /

    dlist.h /

    darray_iterator.h /

    dlist_iterator.h /

    hash_table.c /

    hash_table.h /

    invert.c /

    iterator.h /

    linear_container_darray.c /

    linear_container_darray.h /

    linear_container_dlist.c /

    linear_container_dlist.h /

    linear_container.h /

    queue.c /

    queue.h /

    sort.c /

    sort.h /

    stack.c /

    stack.h /

    typedef.h

    libbase_la_LDFLAGS=-lpthread

    noinst_PROGRAMS=darray_test dlist_test

    darray_test_SOURCES=darray.c

    darray_test_CFLAGS=-DDARRAY_TEST

    dlist_test_SOURCES=dlist.c

    dlist_test_CFLAGS=-DDLIST_TEST

    basedir=$(includedir)/base

    base_HEADERS=darray.h dlist.h iterator.h linear_container_dlist.h typedef.h /

    darray_iterator.h dlist_iterator.h linear_container_darray.h /

    linear_container.h

    EXTRA_DIST=/

    linear_container_test.c /

    invert_ng.c /

    darray_iterator.c /

    dlist_iterator.c /

    test_helper.c

    LTLIBRARIES是关键字。LT代表libtool,libtool是用来封装共享库在不同平台上差异的脚本,其具体实现我们不用关心。

    libbase.la 是函数库的名称,扩展名用.la而不是.so或.a,同时会生成共享库和静态库。libbase_la_SOURCES是生成libbase.la所需要的源文件。
    LDFLAGS是关键字,用来指定链接时需要的参数,-lpthread表示要链接libpthread.so。

    noinst_PROGRAMS是关键字,表示不需要安装的可执行文件,通常是测试程序。为了简单明了,这里没有写出全部的测试程序。

    CFLAGS是关键字,用来指定编译和预处理时的参数。

    HEADERS是关键字,列出所要安装的头文件。xxx_HEADERS和xxxdir要配套使用,后者表示要安装的位置。这里在base_HEADERS中列出的头文件会安装到basedir目录里。

    o 创建autoconf的模板。
    运行:
    autoscan
    mv configure.scan configure.in

    然后按前面介绍的方法修改configure.in,得到下面的内容:

    AC_PREREQ(2.61)
    AC_INIT(base, 0.1, xianjimli@hotmail.com)
    AC_CONFIG_SRCDIR([src/invert.c])
    AC_CONFIG_HEADER([config.h])
    AM_INIT_AUTOMAKE(base, 0.1)
    # Checks for programs.
    AC_PROG_CC
    AC_PROG_LIBTOOL

    # Checks for libraries.
    # FIXME: Replace `main' with a function in `-lpthread':
    AC_CHECK_LIB([pthread], [main])

    # Checks for header files.
    AC_HEADER_STDC
    AC_CHECK_HEADERS([stdlib.h string.h unistd.h])

    # Checks for typedefs, structures, and compiler characteristics.
    AC_C_INLINE
    AC_TYPE_SIZE_T

    # Checks for library functions.
    AC_FUNC_MALLOC
    AC_FUNC_REALLOC

    AC_CONFIG_FILES([Makefile
    src/Makefile])
    AC_OUTPUT

    与前面不同的是:
    AC_PROG_LIBTOOL 用来检查libtool脚本。
    AC_CHECK_LIB用来检查共享库是否存在。
    AC_CHECK_HEADERS 用来检查头文件是否存在。
    AC_FUNC_MALLOC 用来检查标准的malloc函数是否存在。

    o 收集用到的m4宏。
    运行:aclocal

    o 产生配置头文件的模板。
    运行:autoheader

    o 创建README、NEWS、ChangeLog和AUTHORS几个文件。

    o 生成libtool需要的文件。
    运行:libtoolize –force –copy

    这个命令的主要功能是生成ltmain.sh,而ltmain.sh用来产生libtool脚本。

    o 生成Makefile.in和需要的脚本。
    运行:automake -a

    o 产生configure脚本。
    运行:autoconf

    o 产生最终的Makefile。
    运行:./configure –prefix=$HOME/usr

    o 编译运行:make

    o 安装
    运行:make install

    o 发布软件包
    运行:make dist

    我们编译好的文件安装到/home/lixianjing/usr/lib/目录下了:
    libbase.a libbase.la libbase.so libbase.so.0 libbase.so.0.0.0

    静态库:libbase.a
    动态库:libbase.so
    libtool的包装:libbase.la

    头文件和库都安装好了,调用者还需要知道下列信息才能使用:

    头文件和库安装在哪里?
    还依赖哪些其它模块?

    为了解决这个问题,我们需要借助另外一个名为pkg-config的工具。pkg是package的简写,pkg-config负责查询指定软件包 的配置信息,如软件包的名称、说明、版本号、头文件、库和依赖关系等等。为了让pkg-config能正常工作,软件包的实现者需要提供一个扩展名为pc 的配置文件。

    系统中的pkg-config配置文件通常放在/usr/lib/pkgconfig/和/usr/local/lib/pkgconfig/下,下面是gtk+-2.0.pc:

    prefix=/usr
    exec_prefix=/usr
    libdir=/usr/lib
    includedir=/usr/include
    target=x11

    gtk_binary_version=2.10.0
    gtk_host=i386-redhat-linux-gnu

    Name: GTK+
    Description: GIMP Tool Kit (${target} target)
    Version: 2.12.10
    Requires: gdk-${target}-2.0 atk cairo
    Libs: -L${libdir} -lgtk-${target}-2.0
    Cflags: -I${includedir}/gtk-2.0

    前面部分是定义的一些变量,后面是一些关键字:

    Name: 名称
    Description: 功能描述
    Version: 版本号
    Requires: 所依赖的软件包
    Libs: 调用者的链接参数。
    Cflags: 调用者的编译参数。

    由于 prefix之类的变量是在软件包configure时才决定的,不能直接写死在pc文件中。我们可以让configure根据模板文件来产生。

    模板文件名为base.pc.in,内容为:

    prefix=@prefix@
    exec_prefix=${prefix}
    libdir=${prefix}/lib
    includedir=${prefix}/include

    Name: @PACKAGE_NAME@
    Description: a basic library.
    Version: @VERSION@
    Requires:
    Libs: -L${libdir} -lbase
    Cflags: -I${includedir}/base

    这个模板文件和Makefile.in的替换规则一样,用两个@@括起来的变量会替换成configure检测出来的值,@prefix@等变量是标准的变量。

    修改一下base/Makefile.am,增加下列两行代码:

    pkgconfigdir=${libdir}/pkgconfig
    pkgconfig_DATA=base.pc

    这是安装数据文件的方法,pkgconfig不是关键字,取个描述性的名称就好了。dir和_DATA是关键字,它们有相同的前缀,前者表示安装的目录,后者表示要安装的文件。按照惯例,pc文件安装到${libdir}/pkgconfig下。

    修改configure.in,增加输入出文件base.pc
    AC_OUTPUT([base.pc])

    放到AC_CONFIG_FILES也可以,它告诉configure脚本要产生的文件。

    重新运行configure后会生成base.pc,内容为:

    prefix=/home/lixianjing/usr/local

    exec_prefix=${prefix}

    libdir=${prefix}/lib

    includedir=${prefix}/include

    Name: base

    Description: a basic library.

    Version: 0.1

    Requires:

    Libs: -L${libdir} -lbase

    Cflags: -I${includedir}/base

    (prefix与configure时指定的prefix参数一致。)

    在下一节中,我们再学习调用者如何使用pc文件。

  • 相关阅读:
    jstl 部分标签
    Maven pom.xml 元素配置说明(一)
    spring 参数绑定
    mysql 索引
    ArrayList和HashSet的Contains()方法(转)
    每日记载内容总结44
    剑指offer42:不用加减乘除做加法
    动态规划常见题型
    华为机试-统计每个月兔子的总数
    华为机试-字符串合并处理
  • 原文地址:https://www.cnblogs.com/zhangyunlin/p/6167542.html
Copyright © 2020-2023  润新知