linux autotools案例升级(多目录编程实例)

本文开发环境配置

需要的工具 优麒麟等deb系 fedora等rpm系
autotools工具 apt install autoconf automake libtool yum install autoconf automake libtool
glib库 apt install libglib2.0-dev yum install glib2-devel
notify库 apt install libnotify-dev yum install libnotify-devel
  • 项目资源: linux autotools案例升级(多目录编程实例)_第1张图片
  • csdn链接:linux autotools多目录编程实例
  • github链接: 暂无

1、目标:解决子目录之间源码包含与编译依赖的关系

本篇重在理解多目录项目工程中,Makefile.am文件怎么编写,以及如何解决不同目录之间的源码依赖关系
即重点应该查看源码#include与Makefile.am中_LIBADD _LDADD字段

2、项目的README文件:

1、命令行手动编译  gcc time-notify/time-notify.c time-notify/time-notify.h src/show-notify.c src/show-notify.h test/main.c `pkg-config --cflags --libs glib-2.0 gdk-pixbuf-2.0` -I./src -I./time-notify -I. -lnotify

2、重点关注:
	- configure.ac内subdir-objects关键字的作用:多目录工程中,automake要使用该参数
	- Makefile.am中.la文件的使用:用于解决gcc链接阶段的依赖问题

3、新增知识难度:
    - 源码目录结构的改变:所有源码在同一目录 --->  项目中存在多个目录,每个目录下均有源代码
    - 链接形式的改变:单一目录时链接寻找 .o 文件  --->  多目录时链接寻找 .la 文件

4、一些改变:(针对于案例入门项目的改变)
    根据步骤3中新增的难度,主要涉及2方面的改变:
    - configure.ac
        1) 需要增加 subdir-objects 关键字:--->  AM_INIT_AUTOMAKE(subdir-objects)
        2) 需要增加编译器检测:--->  AC_PROG_LIBTOOL
        3) 列出某一个需要生成 Makfile 文件的目录: --->  AC_CONFIG_FILES([....]),具体参见configure.ac文件
    - Makefile.am
        Makefile 的本质应该在于自动寻找依赖,那么这一块的改变主要是在Makefile.am中指定多目录时如何寻找依赖。
        参见 time-notify/Makefile.am 中 libtime_notify_la_LIBADD 条目

5、autotools系列命令运行顺序:(主要是新增libtoolize命令)
    - autoscan、mv configure.sacn configure.ac
    - autoheader
    - 编写Makefile.am文件
    - aclocal
    - libtoolize
    - automake --copy --add-missing
    - autoconf
    - ./configure
6、一个Makefile.am书写说明
	问题描述:我编写这个项目案例时在 time-notify/Makefile.am 的 libtime_notify_la_SOURCES 条目中使用 $(top_srcdir) 变量时,项目编译不过去。(具体写法可见该文件的最后一行)
	资料查找:出现问题后我发现开源Makefile.am在 _SOURCES 条目中列举源文件时,如果是与Makefile.am同目录的源文件,则不使用 $(top_srcdir) 变量。
	问题解决:删去该变量后,项目可以编译通过;不确定与环境是否有关,读者可以自行尝试。

3、项目的configure.ac文件

#                                               -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
#autoscan命令的版本
AC_PREREQ([2.69])
#项目名称,版本号,作者联系方式
AC_INIT([notify-plus], [1.0], [[email protected]])
#项目需要使用automake工具,所以增加下面这一行
#subdir-objects:多目录编程时,必须要有该关键字
AM_INIT_AUTOMAKE(subdir-objects)
#指定$(top_srcdir)的值为config.h.in所在的目录
AC_CONFIG_SRCDIR([config.h.in])
#AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_HEADERS([config.h])

# Checks for programs.编译器检测
#自动检测要使用的C编译器
AC_PROG_CC
AC_PROG_CPP
#使用pkg-config根据.pc文件自动为我们生成 _CFLAGS 和 _LIBS
AC_PATH_PROG(PKG_CONFIG, pkg-config, no)
#生成.la文件需要
AC_PROG_LIBTOOL

#下面这个写法是参考开源项目的写法
LIBNOTIFY_REQUIRED_VERSION=0.7.0
GLIB_REQUIRED_VERSION=2.17.3

dnl ------------------------------
dnl check for libnotify
dnl ------------------------------
#利用pkg-config生成 _CFLAGS _LIBS
PKG_CHECK_MODULES(LIBNOTIFY,libnotify >= $LIBNOTIFY_REQUIRED_VERSION)
#AC_SUBST输出能够被Makefile.am使用的变量,这里体现出automake从autoconf继承的关系
AC_SUBST(LIBNOTIFY_CFLAGS)
AC_SUBST(LIBNOTIFY_LIBS)

dnl ------------------------------
dnl check for glib-2.0
dnl ------------------------------
PKG_CHECK_MODULES(GLIB2,glib-2.0 >= $GLIB_REQUIRED_VERSION)
AC_SUBST(GLIB2_CFLAGS)
AC_SUBST(GLIB2_LIBS)

# Checks for libraries.检测系统库是否存在
AC_CHECK_LIB([glib-2.0],[notify])

# Checks for header files.检测头文件是否存在
AC_CHECK_HEADERS([glib.h],[libnotify/notify.h])

# Checks for typedefs, structures, and compiler characteristics.

# Checks for library functions.指定要生成Makefile文件的地方
# 多目录项目编程时自然要列出多个目录
AC_CONFIG_FILES([Makefile
                src/Makefile
                time-notify/Makefile
                test/Makefile])

AC_OUTPUT

4、项目所有的Makefile.am文件

1) 项目根目录的总Makefile.am

#定义NULL时,= 后面直接换行,不要增加空格
NULL =
#下面这行是我在调试项目时,系统提示考虑增加的,具体用处读者自查
ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}

# 在这里列举子目录时,如果目录之间存在依赖关系时,那么一定要在这里使用先后关系体现出来(被依赖的写在前面)
# 读者可以尝试打乱这里写好的顺序,自己跑一遍编译流程,查看编译报错
SUBDIRS = \
    src \
    time-notify \
    test \
    $(NULL)

2)src目录的Makefile.am

NULL =

#表示最终要生成一个libtool文件,用于其他目录下源码的编译链接
noinst_LTLIBRARIES = libshow-notify.la

# $(includdir)的值由autoconf为我们自动生成,
# 默认是'/urs/include' 或 '/usr/local/include'
# _CPPFLAGS指定预处理阶段头文件的查找目录(gcc -I)
libshow_notify_la_CPPFLAGS = \
    -I$(includedir) \
    $(GLIB2_CFLAGS) \
    $(LIBNOTIFY_CFLAGS) \
    $(NULL)

# automake可以从autoconf继承变量
# 即Makefile文件用到下列变量时可以在configure脚本文件中寻找这些变量的定义
# 当然,这些变量最初是由开发者在configure.ac文件中增加的
# _LIBADD指定链接阶段so库的查找路径(gcc -l)
libshow_notify_la_LIBADD = \
    $(GLIB2_LIBS) \
    $(LIBNOTIFY_LIBS) \
    $(NULL)

#_SOURCES指定要生成文件所依赖的源代码文件
libshow_notify_la_SOURCES = \
    $(top_srcdir)/src/show-notify.h \
    show-notify.c \
    $(NULL)

3)time-notify目录的Makefile.am

NULL =
#要生成一个libtool文件
noinst_LTLIBRARIES = libtime-notify.la

libtime_notify_la_CFLAGS = \
    -I$(top_srcdir)/src/ \
    $(GLIB2_CFLAGS) \
    $(NULL)

# 后续会总结出 _LIBADD 与 LDADD 的区别
libtime_notify_la_LIBADD = \
    $(top_srcdir)/src/libshow-notify.la \
    $(GLIB2_LIBS) \
    $(NULL)

libtime_notify_la_SOURCES = \
    time-notify.c \
    time-notify.h \
    $(NULL)
# 这个对应于README文件里描述的 $(top_srcdir) 变量的问题
#$(top_srcdir)/time-notify/time-notify.c

4)test目录的Makefile.am

NULL =
#表示要生成一个名为 test-show-notify 的二进制文件
bin_PROGRAMS = \
    test-show-notify \
    $(NULL)
#表示main.c内包含的头文件time-notify.h要从time-notify目录下查找
test_show_notify_CPPFLAGS = \
    -I$(top_srcdir)/time-notify \
    $(NULL)

# _LDADD指定生成二进制文件所有要链接的so库(gcc -l)
test_show_notify_LDADD = \
    $(top_srcdir)/time-notify/libtime-notify.la \
    $(NULL)
# _SOURCES指定要生成的二进制文件所依赖的源码文件
test_show_notify_SOURCES = \
    main.c \
    $(NULL)

你可能感兴趣的:(linux)