靜態編譯makefile
① Makefile.am 規則和實例詳解
編寫linux C 程序的時候,自己來寫Makefile著實的讓人很頭疼,如果是簡單的項目自己寫寫也就罷了,但是如果遇到大項目自己寫Makefile,那是要弄死人的,所以最近在研究Autotools工具自動生成Makefile,在用到autotools工具生成Makefile的時候,還是有一部分需要自己來完成的,那就是Makefile.am文件。
項目中寫在源文件里的Makefile.am是一種比我們了解的Makefile更高層次的編譯規則,它可以和編寫的configure.in(了解更多configure.in的規則請閱讀《 configure.ac (configure.in)詳解 》)文件一起通過調用automake命令,來生成Makefile.in文件,然後再調用./configure,將Makefile.in文件自動的生成Makefile文件。所以Makefile.am文件是要自動生成Makefile必不可少的元素,下面鵬博客就來和大家著重的學習下Makefile.am的寫法和規則。
先來說下Makefile.am中常見的文件編譯類型,詳細的編譯類型和全局變數鵬博客會在下面在圖表中列出:
PROGRAMS 表示可執行文件
SOURCES 表示源文件
HEADERS 頭文件。
LIBRARIES 表示庫文件
LTLIBRARIES 這也是表示庫文件,前面的LT表示libtool。
DATA 數據文件,不能執行。
SCRIPTS 腳本文件,這個可以被用於執行。如:example_SCRIPTS,如果用這樣的話,需要我們自己定義安裝目錄下的example目錄,很容易的,往下看。
一、基本寫法
下面就直接引入一個例子進行詳細講解,如下:
AUTOMAKE_OPTIONS = foreign
bin_PROGRAMS = client
client_SOURCES = key.c connect.c client.c main.c session.c hash.c
client_CPPFLAGS = -DCONFIG_DIR=\「$(sysconfdir)\」 -DLIBRARY_DIR=\」$(pkglibdir)\」
client_LDFLAGS = -export-dynamic -lmemcached
noinst_HEADERS = client.h
INCLUDES = -I/usr/local/libmemcached/include/
client_LDADD = $(top_builddir)/sx/libsession.la \
$(top_builddir)/util/libutil.la
上面就是一個Makefile.am示例文件,這個文件是用於生成client可執行應用程序,引用了兩個靜態庫和MC等動態庫的連接。
先來看個圖表一(列出了可執行文件、靜態庫、頭文件和數據文件,四種書寫Makefile.am文件個一般格式。):
對於可執行文件和靜態庫類型,如果只想編譯,不想安裝到系統中,可以用noinst_PROGRAMS代替bin_PROGRAMS,noinst_LIBRARIES代替lib_LIBRARIES。以此類推。
根據這個圖表一來分析下具體內容:
AUTOMAKE_OPTIONS :這個是用來設定automake的選項。automake主要是幫助開發GNU軟體的人員維護軟體套件,一般在執行automake時會檢查目錄下是否存在標准GNU套件中應具備的文件檔案,例如NEWS、AUTHOR、ChangeLog等,設成foreign時,automake會改用一般軟體套件標准來檢查,而gnu是預設設置,該級別下將盡可能地檢查包是否服從GNU標准,gnits是嚴格標准,不推薦。
bin_PROGRAMS :表示要生成的可執行應用程序文件,這里的bin表示可執行文件在安裝時需要被安裝到系統中,如果只是想編譯。不想被安裝到系統中,可以用noinst_PROGRAMS來代替。
那麼整個第一行 bin_PROGRAMS=client 詳細表示什麼意思那,解釋如下:
PROGRAMS知道這是一個可執行文件。
client表示編譯的目標文件。
bin表示目錄文件被安裝到系統的目錄。
如程序和圖片所示,包括頭文件,靜態庫的定義等等都是這種形式,如lib_LIBRARIES=util,表示將util庫安裝到lib目錄下。
繼續解釋文件內容:
client_SOURCES :表示生成可執行應用程序所用的所有源文件源文件,多個就空格隔開,我們注意到client_是由前面的bin_PROGRAMS指定的,如果前面是生成example, 那麼這里也就變成example_SOURCES,其它的規則類似標識也是一樣。
client_CPPFLAGS :這個和我們寫Makefile的時候意思是一樣的,都表示C語言的預處理器參數,這里指定了DCONFIG_DIR,以後在程序中,就可以直接使用CONFIG_DIR,不要把這個和另一個CFLAGS混淆,後者表示編譯器參數。
client_LDFLAGS :表示在連接時所需要的庫文件選項標識。這個也就是對應一些如-l,-shared等選項。
noinst_HEADERS :表示該頭文件只是參加可執行文件的編譯,而不用安裝到安裝目錄下。如果需要安裝到系統中,可以用include_HEADERS來代替。
INCLUDES :表示連接時所需要的頭文件。
client_LDADD :表示連接時所需要的庫文件,這里表示需要兩個庫文件的支持,下面會看到這個庫文件又是怎麼用Makefile.am文件後成的。
如圖表二:
全局變數 ,可能有人注意到文件中的$(top_builddir)等全局變數,其實這個是Makefile.am系統定義的一個基本路徑變數,表示生成目標文件的最上層目錄,如果這個Makefile.am文件變成其它的Makefile.am文件,那麼這個就表示其它的目錄,而不是這個當前目錄。我們還可以使用$(top_srcdir),這個表示工程的最頂層目錄,其實也是第一個Makefile.am的入口目錄,因為Makefile.am文件可以被遞歸性的調用。
如圖表三:(在Makefile.am中盡量使用相對路徑,系統預定義了兩個基本路徑)
$(sysconfdir) :在系統安裝工具的時候,我們經常能遇到配置安裝路徑的命令,如:./configure –prefix=/install/apache 其實在調用這個之後,就定義了一個變數$(prefix), 表示安裝的路徑,如果沒有指定安裝的路徑,會被安裝到默認的路徑,一般都是/usr/local。在定義$(prefix),還有一些預定義好的目錄,其實這一些定義都可以在頂層的Makefile文件中可以看到,如下面一些值:
bindir = $(prefix)/bin。
libdir = $(prefix)/lib。
datadir=$(prefix)/share。
sysconfdir=$(prefix)/etc。
includedir=$(prefix)/include。
這些量還可以用於定義其它目錄,例如我想 將client.h安裝到include/client目錄下 ,這樣寫Makefile.am文件:
clientincludedir=$(includedir)/client
clientinclude_HEADERS=$(top_srcdir)/client/client.h
這就達到了我的目的,相當於定義了一個安裝類型,這種安裝類型是將文件安裝到include/client目錄下。
我們自己也可以 定義新的安裝目錄下的路徑 ,如我在應用中簡單定義的:
devicedir = ${prefix}/device
device_DATA = package
這樣的話,package文件會作為數據文件安裝到device目錄之下,這樣一個可執行文件就定義好了。注意,這也相當於定義了一種安裝類型:devicedir,所以你想怎麼安裝就怎麼安裝,後面的XXXXXdir,dir是固定不變的。
二、配置靜態庫
下面我們來說下編譯靜態庫和編譯動態庫,我們說下靜態庫,下面這個例子比較簡單。直接指定 XXXX_LTLIBRARIES或者XXXX_LIBRARIES就可以了。同樣如果不需要安裝到系統,將XXXX換成noinst就可以。
一般推薦使用libtool庫編譯目標,因為automake包含libtool,這對於跨平台可移植的庫來說,是一個很好的事情。
看例子如下:
noinst_LTLIBRARIES = libutil.la
oinst_HEADERS = inaddr.h util.h compat.h pool.h xhash.h url.h device.h
ibutil_la_SOURCES = access.c config.c datetime.c hex.c inaddr.c log.c device.c pool.c rate.c sha1.c stanza.c str.c xhash.c
ibutil_la_LIBADD = @LDFLAGS@
第一行的noinst_LTLIBRARIES,這里要注意的是LTLIBRARIES,另外還有LIBRARIES,兩個都表示庫文件。前者表示libtool庫,用法上基本是一樣的。如果需要安裝到系統中的話,用lib_LTLIBRARIES。
.la 為libtool自動生成的一些共享庫,vi編輯查看,主要記錄了一些配置信息。可以用如下命令查看*.la文件的格式 $file *.la
.a 為靜態庫,是好多個.o合在一起,用於靜態連接
如果想編譯 .a 文件,那麼上面的配置就改成如下結果:
noinst_LTLIBRARIES = libutil.a
oinst_HEADERS = inaddr.h util.h compat.h pool.h xhash.h url.h device.h
ibutil_a_SOURCES = access.c config.c datetime.c hex.c inaddr.c log.c device.c pool.c rate.c sha1.c stanza.c str.c xhash.c
ibutil_a_LIBADD = @LDFLAGS@
注意:靜態庫編譯連接時需要其它的庫的話,採用XXXX_LIBADD選項,而不是前面的XXXX_LDADD。編譯靜態庫是比較簡單的,因為直接可以指定其類型。
三、配置動態庫
如果想要編譯XXX.so動態庫文件,需要用到_PROGRAMS類型,有一個關於安裝路徑的問題,如果希望將動態庫安裝到lib目錄下,按照前面所說的,只需要寫成lib_PROGRAMS就可以了,lib表示安裝的路徑,但是automake不允許這樣直接定義,所以可以採用下面的辦法,同樣是將動態庫安裝到lib目錄下:
projectlibdir=$(libdir)//新建一個目錄,就是該目錄就是lib目錄
projectlib_PROGRAMS=project.so
project_so_SOURCES=xxx.C
project_so_LDFLAGS=-shared -fpic//GCC編譯動態庫的選項
這個動態庫的編譯寫法是鵬博客網上總結的,希望有要的人自己來驗證下。
四、SUBDIRS功能用法
SUBDIRS 這是一個很重要的詞,我們前面生成了一個目標文件,但是一個大型的工程項目是由許多個可執行文件和庫文件組成,也就是包含多個目錄,每個目錄下都有用於生成該目錄下的目標文件的Makefile.am文件,但頂層目錄是如何調用,才能使下面各個目錄分別生成自己的目標文件呢?就是SUBDIRS關鍵詞的用法了。
看一下我的工程項目,這是頂層的Makefile.am文件
EXTRA_DIST = Doxyfile.in README.win32 README.protocol contrib UPGRADE
devicedir = ${prefix}/device
device_DATA = package
SUBDIRS = etc man
ifUSE_LIBSUBST
SUBDIRS += subst
endif
SUBDIRS += tools io sessions util client dispatch server hash storage sms
SUBDIRS表示在處理目錄之前,要遞歸處理哪些子目錄,要注意處理的順序。比如配置中的client對sessions和utils這兩上目標文件有依賴關系,就在client之前需要處理這兩個目標文件。
EXTRA_DIST :將哪些文件一起打包。
五、打包處理
Automake會自動的打包 ,自動打包的內容如下:
所有程序的源文件。
所有子目錄里的的Makefile.am文件。
Makefile.am中包含的文件。
./configure所要讀取的文件。
EXTRA_DIST所指定的文件。
dist和nodist指定的文件,也可將其中一個源文件指定為不打包:
例如: nodist_client_SOURCES = client.c
六、最後
這里是鵬博客總結的一些比較實用的Makefile.am的寫法和規則,看完了這篇文章已經可以很詳細的理解這個文件的內容,寫起來也應該不會陌生,但automake還有許多其他的規則需要掌握,鵬博客將會繼續全面的總結關於autotools 的一些規則和寫法,希望對大家有用處。也歡迎大家指出問題,幫我完善這個博客,希望大家支持!
automake的Makefile.am Makefile.am寫法
② makefile 生成動態庫和靜態庫的區別
生成動態庫的時候要注意,編譯生成目標文件的時候加上-fPIC參數,生成位置無關的可重定位代碼,然後鏈接的時候加上-shared生成動態共享庫。比如一個hello.c,生成靜態庫:
gcc-ohello.o-chello.c
arrcslibhello.ahello.o
生成動態庫的命令:
gcc-fPIChello.o-chello.c
gcc-shared-olibhelllo.sohello.o
還有一個區別是:靜態庫參與鏈接過程,而動態庫不鏈接到可執行文件中,可執行程序在運行的時候,對應的動態庫也要載入到內存中,否則可執行程序運行不了。
更多詳細細節,可以網路搜索視頻教程:Makefile工程實踐
③ makefile的選項CFLAGS,CPPFLAGS,LDFLAGS和LIBS的區別
Linux內核的配置系統由三個部分組成,分別是:Makefile:分布在 Linux 內核源代碼中的 Makefile,定義 Linux 內核的編譯規則; 配置文件(config.in):給用戶提供配置選擇的功能; 配置工具:包括配置命令解釋器(對配置腳本中使用的配置命令進行解釋)和配置用戶界面(提供基於字元界面、基於 Ncurses 圖形界面以及基於 Xwindows 圖形界面的用戶配置界面,各自對應於 Make config、Make menuconfig 和 make xconfig)。這些配置工具都是使用腳本語言,如 Tcl/TK、Perl 編寫的(也包含一些用 C 編寫的代碼)。本文並不是對配置系統本身進行分析,而是介紹如何使用配置系統。所以,除非是配置系統的維護者,一般的內核開發者無須了解它們的原理,只需要知道如何編寫 Makefile 和配置文件就可以。所以,在本文中,我們只對 Makefile 和配置文件進行討論。另外,凡是涉及到與具體 CPU 體系結構相關的內容,我們都以 ARM 為例,這樣不僅可以將討論的問題明確化,而且對內容本身不產生影響。2. Makefile2.1 Makefile 概述Makefile 的作用是根據配置的情況,構造出需要編譯的源文件列表,然後分別編譯,並把目標代碼鏈接到一起,最終形成 Linux 內核二進制文件。由於 Linux 內核源代碼是按照樹形結構組織的,所以 Makefile 也被分布在目錄樹中。Linux 內核中的 Makefile 以及與 Makefile 直接相關的文件有:Makefile:頂層 Makefile,是整個內核配置、編譯的總體控制文件。 .config:內核配置文件,包含由用戶選擇的配置選項,用來存放內核配置後的結果(如 make config)。 arch/*/Makefile:位於各種 CPU 體系目錄下的 Makefile,如 arch/arm/Makefile,是針對特定平台的 Makefile。 各個子目錄下的 Makefile:比如 drivers/Makefile,負責所在子目錄下源代碼的管理。 Rules.make:規則文件,被所有的 Makefile 使用。 用戶通過 make config 配置後,產生了 .config。頂層 Makefile 讀入 .config 中的配置選擇。頂層 Makefile 有兩個主要的任務:產生 vmlinux 文件和內核模塊(mole)。為了達到此目的,頂層 Makefile 遞歸的進入到內核的各個子目錄中,分別調用位於這些子目錄中的 Makefile。至於到底進入哪些子目錄,取決於內核的配置。在頂層 Makefile 中,有一句:include arch/$(ARCH)/Makefile,包含了特定 CPU 體系結構下的 Makefile,這個 Makefile 中包含了平台相關的信息。位於各個子目錄下的 Makefile 同樣也根據 .config 給出的配置信息,構造出當前配置下需要的源文件列表,並在文件的最後有 include $(TOPDIR)/Rules.make。Rules.make 文件起著非常重要的作用,它定義了所有 Makefile 共用的編譯規則。比如,如果需要將本目錄下所有的 c 程序編譯成匯編代碼,需要在 Makefile 中有以下的編譯規則:%.s: %.c$(CC) $(CFLAGS) -S $< -o $@有很多子目錄下都有同樣的要求,就需要在各自的 Makefile 中包含此編譯規則,這會比較麻煩。而 Linux 內核中則把此類的編譯規則統一放置到 Rules.make 中,並在各自的 Makefile 中包含進了 Rules.make(include Rules.make),這樣就避免了在多個 Makefile 中重復同樣的規則。對於上面的例子,在 Rules.make 中對應的規則為:%.s: %.c$(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(CFLAGS_$(*F)) $(CFLAGS_$@) -S $< -o [email protected] Makefile 中的變數頂層 Makefile 定義並向環境中輸出了許多變數,為各個子目錄下的 Makefile 傳遞一些信息。有些變數,比如 SUBDIRS,不僅在頂層 Makefile 中定義並且賦初值,而且在 arch/*/Makefile 還作了擴充。常用的變數有以下幾類:1) 版本信息版本信息有:VERSION,PATCHLEVEL, SUBLEVEL, EXTRAVERSION,KERNELRELEASE。版本信息定義了當前內核的版本,比如 VERSION=2,PATCHLEVEL=4,SUBLEVEL=18,EXATAVERSION=-rmk7,它們共同構成內核的發行版本KERNELRELEASE:2.4.18-rmk72) CPU 體系結構:ARCH在頂層 Makefile 的開頭,用 ARCH 定義目標 CPU 的體系結構,比如 ARCH:=arm 等。許多子目錄的 Makefile 中,要根據 ARCH 的定義選擇編譯源文件的列表。3) 路徑信息:TOPDIR, SUBDIRSTOPDIR 定義了 Linux 內核源代碼所在的根目錄。例如,各個子目錄下的 Makefile 通過 $(TOPDIR)/Rules.make 就可以找到 Rules.make 的位置。SUBDIRS 定義了一個目錄列表,在編譯內核或模塊時,頂層 Makefile 就是根據 SUBDIRS 來決定進入哪些子目錄。SUBDIRS 的值取決於內核的配置,在頂層 Makefile 中 SUBDIRS 賦值為 kernel drivers mm fs net ipc lib;根據內核的配置情況,在 arch/*/Makefile 中擴充了 SUBDIRS 的值,參見4)中的例子。4) 內核組成信息:HEAD, CORE_FILES, NETWORKS, DRIVERS, LIBSLinux 內核文件 vmlinux 是由以下規則產生的:vmlinux: $(CONFIGURATION) init/main.o init/version.o linuxsubdirs$(LD) $(LINKFLAGS) $(HEAD) init/main.o init/version.o --start-group $(CORE_FILES) $(DRIVERS) $(NETWORKS) $(LIBS) --end-group -o vmlinux可以看出,vmlinux 是由 HEAD、main.o、version.o、CORE_FILES、DRIVERS、NETWORKS 和 LIBS 組成的。這些變數(如 HEAD)都是用來定義連接生成 vmlinux 的目標文件和庫文件列表。其中,HEAD在arch/*/Makefile 中定義,用來確定被最先鏈接進 vmlinux 的文件列表。比如,對於 ARM 系列的 CPU,HEAD 定義為: HEAD := arch/arm/kernel/head-$(PROCESSOR).o arch/arm/kernel/init_task.o表明 head-$(PROCESSOR).o 和 init_task.o 需要最先被鏈接到 vmlinux 中。PROCESSOR 為 armv 或 armo,取決於目標 CPU。 CORE_FILES,NETWORK,DRIVERS 和 LIBS 在頂層 Makefile 中定義,並且由 arch/*/Makefile 根據需要進行擴充。 CORE_FILES 對應著內核的核心文件,有 kernel/kernel.o,mm/mm.o,fs/fs.o,ipc/ipc.o,可以看出,這些是組成內核最為重要的文件。同時,arch/arm/Makefile 對 CORE_FILES 進行了擴充:# arch/arm/Makefile# If we have a machine-specific directory, then include it in the build.MACHDIR := arch/arm/mach-$(MACHINE)ifeq ($(MACHDIR),$(wildcard $(MACHDIR)))SUBDIRS += $(MACHDIR)CORE_FILES := $(MACHDIR)/$(MACHINE).o $(CORE_FILES)endifHEAD := arch/arm/kernel/head-$(PROCESSOR).o arch/arm/kernel/init_task.oSUBDIRS += arch/arm/kernel arch/arm/mm arch/arm/lib arch/arm/nwfpeCORE_FILES := arch/arm/kernel/kernel.o arch/arm/mm/mm.o $(CORE_FILES)LIBS := arch/arm/lib/lib.a $(LIBS)5) 編譯信息:CPP, CC, AS, LD, AR,CFLAGS,LINKFLAGS在 Rules.make 中定義的是編譯的通用規則,具體到特定的場合,需要明確給出編譯環境,編譯環境就是在以上的變數中定義的。針對交叉編譯的要求,定義了 CROSS_COMPILE。比如:CROSS_COMPILE = arm-linux-CC = $(CROSS_COMPILE)gccLD = $(CROSS_COMPILE)ld......CROSS_COMPILE 定義了交叉編譯器前綴 arm-linux-,表明所有的交叉編譯工具都是以 arm-linux- 開頭的,所以在各個交叉編譯器工具之前,都加入了 $(CROSS_COMPILE),以組成一個完整的交叉編譯工具文件名,比如 arm-linux-gcc。CFLAGS 定義了傳遞給 C 編譯器的參數。LINKFLAGS 是鏈接生成 vmlinux 時,由鏈接器使用的參數。LINKFLAGS 在 arm/*/Makefile 中定義,比如:# arch/arm/MakefileLINKFLAGS :=-p -X -T arch/arm/vmlinux.lds6) 配置變數CONFIG_*.config 文件中有許多的配置變數等式,用來說明用戶配置的結果。例如 CONFIG_MODULES=y 表明用戶選擇了 Linux 內核的模塊功能。.config 被頂層 Makefile 包含後,就形成許多的配置變數,每個配置變數具有確定的值:y 表示本編譯選項對應的內核代碼被靜態編譯進 Linux 內核;m 表示本編譯選項對應的內核代碼被編譯成模塊;n 表示不選擇此編譯選項;如果根本就沒有選擇,那麼配置變數的值為空。2.3 Rules.make 變數前面講過,Rules.make 是編譯規則文件,所有的 Makefile 中都會包括 Rules.make。Rules.make 文件定義了許多變數,最為重要是那些編譯、鏈接列表變數。O_OBJS,L_OBJS,OX_OBJS,LX_OBJS:本目錄下需要編譯進 Linux 內核 vmlinux 的目標文件列表,其中 OX_OBJS 和 LX_OBJS 中的 "X" 表明目標文件使用了 EXPORT_SYMBOL 輸出符號。M_OBJS,MX_OBJS:本目錄下需要被編譯成可裝載模塊的目標文件列表。同樣,MX_OBJS 中的 "X" 表明目標文件使用了 EXPORT_SYMBOL 輸出符號。O_TARGET,L_TARGET:每個子目錄下都有一個 O_TARGET 或 L_TARGET,Rules.make 首先從源代碼編譯生成 O_OBJS 和 OX_OBJS 中所有的目標文件,然後使用 $(LD) -r 把它們鏈接成一個 O_TARGET 或 L_TARGET。O_TARGET 以 .o 結尾,而 L_TARGET 以 .a 結尾。
④ 如何編譯靜態鏈接的程序,通過./configure 把參數-static傳入Makefile。
./configure LDFLAGS=-static
⑤ Linux2.6 如何編寫Makefile,使驅動程序能夠編譯鏈接靜態庫
就我的感覺,靜態庫是編譯好的.o文件,你只要將靜態庫(mylib.a)放置於 /lib 以及/usr/lib 文件夾下,然後在gcc編譯器的變數中 加上 -lmylib,就可以了。
⑥ 多級目錄makefile,靜態庫
在lib 目錄下編譯需要生成動態庫的文件,生成動態庫,並安裝到系統的標准庫中,供
程序調用。具體步驟如下:
(1) 編寫Makefile.am 文件
AUTOMAKE_OPTIONS=foreign
lib_LTLIBRARIES=libhello.la
libhello_la_SOURCES=test.c
這里lib_LTLIBRARIES 的意思是生成的動態庫,然後指定動態庫依賴的源文件
test.c ,若有多個源文件用空格隔開。
(2) 在lib 目錄下,用命令autoscan 產生configure.scan 文件,並改名為configure.in。 這
里需加上宏AC_PROG_LIBTOOL,表示利用libtool 來自動生成動態庫
#configure.in
# Process this file with autoconf to proce a configure script.
AC_PREREQ(2.59)
AC_INIT(hello,1.0, [[email protected]])
AM_INIT_AUTOMAKE
AC_CONFIG_SRCDIR([test.c])
#AC_CONFIG_HEADER([config.h])
# Checks for programs.
AC_PROG_CC
# Checks for header files.
# Checks for typedefs, structures, and compiler characteristics.
# Checks for library functions.
AC_PROG_LIBTOOL
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
(3) 執行命令aclocal、libtoolize -f -c 、autoconf、automake --add-missing、./configure、
make、make install 將動態庫安裝到系統的標准庫中,以供調用(一般為/usr/local/lib)。
註:libtoolize 提供了一種標準的方式來將libtool 支持加入一個軟體包,而GNU libtool 是
一個通用庫支持腳本,將使用動態庫的復雜性隱藏在統一、可移植的介面中。
4. 生成src 目錄下的hello 可執行文件
(1) 編寫src/Makefile.am 文件
AUTOMAKE_OPTIONS=foreign
INCLUDES= -I../include
bin_PROGRAMS=hello
hello_SOURCES=hello.c
hello_LDADD=-lhello
-ldir 指定編譯時搜索庫的路徑。與靜態庫不同的是,創建動態庫時不用指定庫路
徑,編譯器自動在標准庫中查找libhello.so 文件。
(2) 執行autoscan 生成configure.scan 文件,將它重命名為configure.in 並修改其內容。
# configure.in
# Process this file with autoconf to proce a configure script.
AC_PREREQ(2.59)
AC_INIT(hello,1.0, [[email protected]])
AM_INIT_AUTOMAKE
AC_CONFIG_SRCDIR([hello.c])
#AC_CONFIG_HEADER([config.h])
# Checks for programs.
AC_PROG_CC
# Checks for header files.
# Checks for typedefs, structures, and compiler characteristics.
# Checks for library functions.
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
(3) 在src 目錄下編譯並生成目標文件,執行命令aclocal、libtoolize -f -c 、autoconf、
automake --add-missing、./configure、make,此時你一定會覺得,成功近在咫尺了。再
執行目標文件./hello,結果卻在你的意料之外:
./hello: error while loading shared libraries: libhello.so.0 : cannot open shared object file:
No such file or directory
在執行目標文件的時候,Shell 找不到共享庫的位置,需要我們手工載入庫路徑。
5. shell 搜索動態庫路徑位置的兩種方法
(1) 使用命令導入動態庫的路徑,命令如下:
export LD_LIBRARY_PATH=dir (如/usr/local/lib)
(2) 修改/etc/ld.so.conf 文件,加入搜索路徑,修改後用ldconfig 命令載入修改。
將自己可能存放庫文件的路徑都加入到/etc/ld.so.conf 中是明智的選擇 ^_^。添加
方法也極其簡單,將庫文件的絕對路徑直接寫進去就OK 了,一行一個。例如:
/usr/local/lib
/usr/lib
/lib
需要注意的是:這種搜索路徑的設置方式對於程序連接時的庫(包括共享庫和靜態
庫)的定位已經足夠了,但是對於使用了共享庫的程序的執行還是不夠的。這是 因為
為了加快程序執行時對共享庫的定位速度,避免使用搜索路徑查找共享庫的低效率,所
以是直接讀取庫列表文件 /etc/ld.so.cache 從中進行搜索的。/etc/ld.so.cache 是一個非
文本的數據文件,不能直接編輯,它是根據 /etc/ld.so.conf 中設置的搜索路徑由
/sbin/ldconfig 命令將這些搜索路徑下的共享庫文件集中在一起而生成的(ldconfig 命令
要以 root 許可權執行)。因此,為了保證程序執行時對庫的定位,在 /etc/ld.so.conf 中
進行了庫搜索路徑的設置之後,還必須要運行 /sbin/ldconfig 命令更新 /etc/ld.so.cache
文件之後才可以。ldconfig ,簡單的說,它的作用就是將/etc/ld.so.conf 列出的路徑下的庫
文件 緩存到/etc/ld.so.cache 以供使用。因此當安裝完一些庫文件,(例如剛安裝好glib),
或者修改ld.so.conf 增加新的庫路徑後,需要運行一下/sbin/ldconfig 使所有的庫文件都
被緩存到ld.so.cache 中,如果沒做,即使庫文件明明就在/usr/lib 下的,也是不會被使
用的,結果編譯過程中報錯,缺少xxx 庫,去查看發現明明就在那放著,搞的想大罵
computer 蠢豬一個^_^。極力推薦使用這種方法!
利用gcc 創建和使用動態庫
1. 用下面的命令將mylib.c 程序創建成一個動態庫:
gcc –fPIC –o mylib.o –c mylib.c
gcc –shared –o libtt.so mylib.o
-fPIC 作用於編譯階段,告訴編譯器產生與位置無關代碼(Position-Independent Code),
則產生的代碼中,沒有絕對地址,全部使用相對地址,故而代碼可以被載入器載入到內存的
任意位置,都可以正確的執行。這正是共享庫所要求的,共享庫被載入時,在內存的位置不
是固定的。
-shared 作用於鏈接階段,實際傳遞給鏈接器ld,讓其添加作為共享庫所需要的額外描
述信息,去除共享庫所不需的信息。
也可以直接使用下面一條命令:
gcc –fPIC –shared –o libtt.so mylib.c
2. 將動態庫拷貝到linux 的標准庫中,usr/local/lib 或者/usr/lib 或者/lib:
cp libttt.so /usr/local/lib
3. 編譯src 目錄下的源程序時,指定動態庫文件的目錄,調用動態庫中的函數
gcc –o test test.c /usr/lib/libttt.so
4. 設置shell 動態庫搜索路徑,運行生成的可執行文件。
⑦ 如何將第三方靜態庫加入Makefile.am中
將庫和對應的頭文件放到指定目錄,然後編譯的時候,指定這個庫路徑,鏈接使用這個庫即可。
⑧ makefile如何鏈接靜態庫
makefile 裡面寫法,同你的編譯器 如何鏈接靜態庫的方法有關。例如:指定庫名
VC++ 用 編譯選項 /MT 鏈接 LIBCMT.LIB 就是 鏈接靜態庫。
-----
unix/linux makefile 裡面,例如
LIBS = libmine.a -lpthread 這里寫你要鏈接的靜態庫庫名
CXXFILES = pthreads.cpp 程序名字們
CXXFLAGS = -O3 -o prog -rdynamic -D_GNU_SOURCE -L./libmine 編譯選項
LIBS = libmine.a -lpthread 庫名
all:
$(CXX) $(CXXFILES) $(LIBS) $(CXXFLAGS)
clean:
rm -f prog *.o