linux autotools案列強化(使用autotools生成庫文件)

項目資料:

1、目標:項目能夠生成 .a .so庫文件,並能夠順利執行make install操作

1)生成庫文件主要關注src/Makefile.am中的lib_LTLIBRARIES關鍵字即可
2)make install的安裝目錄取決於Makefile.am目錄中DESTDIR變量,讀者可自行翻閱生成的Makefile文件

2、項目的README文件

1、命令行手動編譯 gcc test/main.c src/show-notify.h src/show-notify.c -I./src `pkg-config --cflags --libs glib-2.0 gdk-2.0` -lnotify

2、本篇重點關注對象:
	- src目錄下Makefile.am文件中
		-- 之前項目中的noinst_LTLIBRARIES 變成了lib_LTLIBRARIES;後者表示最終要生成庫文件,前者只生成中間文件即可。
		-- _includedir 條目指定了make install操作時頭文件被安裝的目錄
		-- _include_HEADERS 條目指定了make install操作時要被安裝的頭文件有哪些
			--- _includedir 和 _include_HEADERS 應該成對出現,否則編譯會報錯
	- src 和 test子目錄中Makefile.am文件最後出現的 DESTDIR 變量
		-- DESTDIR變量在生成的Makefile文件中默認值爲空
		   即make install操作默認會將庫文件與頭文件安裝到系統目錄 /usr/local/
		-- 如果給DESTDIR賦值了,如 DESTDIR = $(abs_top_srcdir)
		   則make install會將庫文件和頭文件安裝到項目根目錄下的 usr/local/ 目錄下。

3、項目的configure.ac文件

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

AC_PREREQ([2.69])
#項目名,版本號,聯繫方式
AC_INIT([notify-lib], [1.0], [[email protected]])
#使用automake工具,subdir-objects表示多目錄編程
AM_INIT_AUTOMAKE(subdir-objects)
#指定$(top_srcdir)的值
AC_CONFIG_SRCDIR([config.h.in])
AC_CONFIG_HEADERS([config.h])

# Checks for programs.編譯器檢測
AC_PROG_CC
AC_PROG_CPP
AC_PATH_PROG(PKG_CONFIG, pkg-config, no)
#製作.a/.so庫需要
AC_PROG_LIBTOOL

LIBNOTIFY_REQUIRED_VERSION=0.7.0
GLIB_REQUIRED_VERSION=2.17.3

dnl ------------------------------
dnl check for libnotify 使用pkg-config定義LIBNOTIFY的相關變量
dnl ------------------------------
PKG_CHECK_MODULES(LIBNOTIFY,libnotify >= $LIBNOTIFY_REQUIRED_VERSION)
AC_SUBST(LIBNOTIFY_CFLAGS)
AC_SUBST(LIBNOTIFY_LIBS)

dnl ------------------------------
dnl check for glib-2.0 使用pkg-config定義GLIB2的相關變量
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
                test/Makefile])

AC_OUTPUT

4、項目的總Makefile.am文件

NULL =

#項目中存在空目錄time,因爲其不需要參與編譯,所以這裏不需要列舉出來
#test目錄源文件需要依賴src下的源碼,所以src寫在前面
SUBDIRS = \
    src \
    test \
    $(NULL)

5、子目錄下的Makefile.am文件

1)src目錄下的Makefile.am文件(這個文件是本篇文章想表達的重點

#表示最終要生成庫文件 .a .so
lib_LTLIBRARIES = libshow-notify.la

# $(includdir)的值由autoconf爲我們自動生成,默認是'/urs/include' or '/usr/local/include'
libshow_notify_la_CPPFLAGS = \
    -I$(includedir) \
    $(GLIB2_CFLAGS) \
    $(LIBNOTIFY_CFLAGS) \
    $(NULL)

#未研究這個,讀者可自行研究
#libshow_notify_la_LDFLAGS=\
#   --no-undefined \
#   $(NULL)

libshow_notify_la_LIBADD = \
    $(GLIB2_LIBS) \
    $(LIBNOTIFY_LIBS) \
    $(NULL)

#指定make install要安裝的頭文件具體路徑
#在生成的Makefile文件中,會自動加上$(DESTDIR)前綴
libshow_notify_includedir=$(includedir)
#指定make install要安裝哪些頭文件
libshow_notify_include_HEADERS = \
    show-notify.h \
    $(NULL)

libshow_notify_la_SOURCES = \
    show-notify.h \
    show-notify.c \
    $(NULL)

# 開啓對DESTDIR的定義後,執行make install會將庫、.h 文件安裝到項目目錄下 $(abs_top_srcdir)/usr/local/
# 若不開啓,sudo make install可以將庫、.h文件安裝到系統目錄下/usr/local/
#DESTDIR = $(abs_top_srcdir)

2)test目錄下的Makefile.am文件

#注意 = 後面沒有空格
NULL =

#表示要生成一個可執行二進制程序
bin_PROGRAMS = \
    test-show-notify \
    $(NULL)

# _CPPFLAGS指定gcc預處理階段頭文件的查找路徑(gcc -I)
test_show_notify_CPPFLAGS = \
    -I$(top_srcdir)/src \
    $(NULL)

# _LDADD指定gcc鏈接階段要鏈接的庫文件(gcc -l)
test_show_notify_LDADD = \
    $(top_srcdir)/src/libshow-notify.la \
    $(NULL)

#生成二進制要依賴的源碼文件
test_show_notify_SOURCES = \
    main.c \
    $(NULL)

#讀者可對比開啓下面定義後,運行make install會有哪些差異
#DESTDIR = $(abs_top_srcdir)

6、細節點播:

讀者可以自行對比這個案例中test目錄下生成的可執行文件與之前2個案例生成的可執行文件(使用file命令檢測):
1)之前2個目錄生成的可執行文件是ELF二進制文件(vim打開時亂碼);該案例test目錄下可執行文件是個shell腳本。

2)關於該案例中可執行文件運行的問題:

  • test目錄下shell腳本可以運行且生效。

  • 定義DESTDIR=$(abs_top_srcdir)後,make install安裝到項目根目錄,運行./usr/local/bin/test-show-nofity會報錯:libshow-notidy.so.0找不到

  • 不定義DESTDIR,sudo make install默認安裝到系統目錄,/usr/local/bin/test-show-nofity可以成功運行且生效。

    原因解析:

    1. shell腳本會根據腳本中的內容在當前目錄 .deps .libs 目錄下查找依賴
    2. 運行ELF文件默認會從系統目錄下尋找依賴的libshow-notify.so文件,如果系統目錄下不存在該文件,則運行失敗,這是install到項目根目錄下和系統目錄下的區別。(使用ldd命令查看ELF文件依賴的庫)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章