第七章 工程管理

7.1 Hello World

1) 目录结构

hellowrold/
         |--- Makefile.am
         |
         |--- src/
               |
               |--- Makefile.am
               |--- main.c

2) helloworld/main.c

#include <stdio.h>

int main(int argc, char* argv[])
{
	printf("Hello World!\n");

	return 0;
}

3) 创建Makefile模板

Makefile.am

SUBDIRS=src  #子目录,如果有多个子目录,用空格分开.
dist_doc_DATA = README

src/Makefile.am

bin_PROGRAMS=hello      # 表示要产生的可执行文件,有多个可执行文件用空格分开; 前缀缀 bin 表示可执行文件的安装路径为bin。
hello_SOURCES=main.c    # 表示生成可执行文件需要的源文件,有多个源文件用空格分开。

4) 创建autoconf的模板

$ autoscan

在helloworld下运行 auttoscan 生成文件 configure.scan,

#                                               -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.

AC_PREREQ([2.69])
AC_INIT([FULL-PACKAGE-NAME], [VERSION], [BUG-REPORT-ADDRESS])
AC_CONFIG_SRCDIR([src/main.c])
AC_CONFIG_HEADERS([config.h])

# Checks for programs.
AC_PROG_CC
AC_PROG_INSTALL

# Checks for libraries.

# Checks for header files.

# Checks for typedefs, structures, and compiler characteristics.

# Checks for library functions.

AC_CONFIG_FILES([Makefile
                 src/Makefile])
AC_OUTPUT

改名为 configure.ac

$ mv configure.scan  configure.scan

修改 configure.ac

#                                               -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.

AC_PREREQ([2.69])
AC_INIT([helloworld], [1.0], [jxm_zn@163.com])
AC_CONFIG_SRCDIR([src/main.c])
AC_CONFIG_HEADERS([config.h])
AM_INIT_AUTOMAKE([-Wall -Werror foreign])


#  ./configure  --enable-debug 时,  CFLAGS="${CFLAGS} -g -O0"
#  ./configure                 时,  CFLAGS="-m32 -g -O2"
AC_ARG_ENABLE([debug],
	      [AS_HELP_STRING([--enable-debug],[debug program(default is no)])],
	      [CFLAGS="${CFLAGS} -g -O0"],
	      [CFLAGS="-m32 -g -O2"]
	    )

# 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
                 src/Makefile])
AC_OUTPUT

configure.ac 是由一系列的宏组成,这些宏最终有命令m4展开,得到一个脚本文件 configure , configure 的主要功能都是探测系统配置,然后根据这些配置来生成相应的Makefile文件. 比如 AC_PROG_CC 是用来检测编译器的. AC_CONFIG_FILESAC_OUTPUT 是用来产生Makefile和其他数据文件的.

5) 生成configure脚本

$ touch README
$ autoreconf --install

6) 生成最终的Makefile

$ ./configure

configure 有以下两个常用的参数。

--prefix : 用来制定安装目录,linux默认安装目录是 /usr/local

--host   : 用于交叉编译,比如x86的PC机上编译在ARM板上运行的程序.

eg:
    ./configure --prefix=/home/jxm/work/arm-root/usr/ --host=arm-linux

7) 编译与安装

$ make -j4 && make install

7.2 函数库

└── base
    ├── AUTHORS
    ├── ChangeLog
    ├── Makefile.am
    ├── NEWS
    ├── README
    ├── autogen.sh
    ├── base.pc.in
    ├── configure.ac
    └── src
        ├── Makefile.am
        ├── darray.c
        ├── darray.h
        ├── darray_iterator.c
        ├── darray_iterator.h
        ├── dlist.c
        ├── dlist.h
        ├── dlist_iterator.c
        ├── dlist_iterator.h
        ├── hash_table.c
        ├── hash_table.h
        ├── invert.c
        ├── invert_ng.c
        ├── iterator.h
        ├── linear_container.h
        ├── linear_container_darray.c
        ├── linear_container_darray.h
        ├── linear_container_dlist.c
        ├── linear_container_dlist.h
        ├── linear_container_test.c
        ├── queue.c
        ├── queue.h
        ├── sort.c
        ├── sort.h
        ├── stack.c
        ├── stack.h
        ├── test_helper.c
        └── typedef.h

1)创建工程

Makefile.am

SUBDIRS=src

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

src/Makefile.am

# 函数库名称
lib_LTLIBRARIES=libbase.la

# 生成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连接所需要的关键字
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

# 需要安装的头文件
# xxx_HEADERS 与  xxxdir 配套使用
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 

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

configure.ac

$ autoscan
$ mv configure.scan configure.ac
#                                               -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.

AC_PREREQ([2.69])
AC_INIT([base], [0.1], [cjiangxumin@gmail.com])
AC_CONFIG_SRCDIR([src/sort.c])
AC_CONFIG_HEADERS([config.h])
AM_INIT_AUTOMAKE([-Wall -Werror foreign])

#  ./configure  --enable-debug 时,  CFLAGS="${CFLAGS} -g -O0"
#  ./configure                 时,  CFLAGS="-m32 -g -O2"
AC_ARG_ENABLE([debug],
	      [AS_HELP_STRING([--enable-debug],[debug program(default is no)])],
	      [CFLAGS="${CFLAGS} -m3 -g -O0"],
	      [CFLAGS="-m32 -g -O2"]
	    )

# Checks for programs.
AM_PROG_AR
AC_PROG_CC
AC_PROG_LIBTOOL  # 检查 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  #检查标准malloc函数是否存在
AC_FUNC_REALLOC

AC_CONFIG_FILES([Makefile
                 src/Makefile])
AC_OUTPUT(base.pc)

2)编译与安装

# autogen
autoreconf --install

# build
./configure --prefix=/tmp/usr
make && make install

3)pkg-config 简单使用

# show info
# apt-get install -y pkg-config
export PKG_CONFIG_PATH=/tmp/usr/lib/pkgconfig
pkg-config --list-all
pkg-config --cflags --libs base

7.3 应用程序

└── appdemo
    ├── AUTHORS
    ├── ChangeLog
    ├── Makefile.am
    ├── NEWS
    ├── README
    ├── autogen.sh
    ├── configure.ac
    └── src
        ├── Makefile.am
        └── main.c

1) 创建工程

Makefile.am

SUBDIRS=src

src/Makefile.am

bin_PROGRAMS=appdemo
appdemo_SOURCES=main.c
appdemo_CFLAGS=@BASE_CFLAGS@
appdemo_LDFLAGS=@BASE_LIBS@
#                                               -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.

AC_PREREQ([2.69])
AC_INIT([appdemo], [0.1], [cjiangxumin@gmail.com])
AC_CONFIG_SRCDIR([src/main.c])
AC_CONFIG_HEADERS([config.h])
AM_INIT_AUTOMAKE([-Wall -Werror foreign])

#  ./configure  --enable-debug 时,  CFLAGS="${CFLAGS} -g -O0"
#  ./configure                 时,  CFLAGS="-m32 -g -O2"
AC_ARG_ENABLE([debug],
	      [AS_HELP_STRING([--enable-debug],[debug program(default is no)])],
	      [CFLAGS="${CFLAGS} -m3 -g -O0"],
	      [CFLAGS="-m32 -g -O2"]
	    )


AM_PROG_AR
# Checks for programs.
AC_PROG_CC
AC_PROG_INSTALL
AC_PROG_LIBTOOL   # 添加, 解决:appdemo/src/main.c:5: undefined reference to `dlist_create'

# Checks for libraries.
PKG_CHECK_MODULES(BASE, ["base"]) # 检查软件包base, 通过调用pkg-config,生成BASE_CFLAGS,BASE_LIBS
AC_SUBST(BASE_CFLAGS)   # 把所有对BASE_CFLAGS的引用替换成实际的参数,即把Makefile.am中的@BASE_CFLAGS@替换成实际值
AC_SUBST(BASE_LIBS)

# Checks for header files.

# Checks for typedefs, structures, and compiler characteristics.

# Checks for library functions.

AC_CONFIG_FILES([Makefile
                 src/Makefile])
AC_OUTPUT

2) 编译与安装

# autogen
$ autoreconf --install

# build
$ export PKG_CONFIG_PATH=/tmp/usr/lib/pkgconfig
$ ./configure --prefix=/tmp/usr
$ make && make install

3) 发布软件

# 发布软件包
$ make dist  # 或者 make distcheck