嵌入式 Makefile.am檔案的例項講解
Makefile.am是一種比Makefile更高層次的編譯規則,可以和configure.in檔案一起通過呼叫automake命令,生成Makefile.in檔案,再呼叫./configure的時候,就將Makefile.in檔案自動生成Makefile檔案了。所以Makefile.am檔案是比Makefile檔案更高的抽象。
下面我根據自己的工作中的一些應用,來討論Makefile.am的編寫。我覺得主要是要注意的問題是將編譯什麼檔案?這個檔案會不會安裝?這個檔案被安裝到什麼目錄下?可以將檔案編譯成可執行檔案來安裝,也可以編譯成靜態庫檔案安裝,常見的檔案編譯型別有下面幾種:
- PROGRAMS。表示可執行檔案
- LIBRARIES。表示庫檔案
- LTLIBRARIES。這也是表示庫檔案,前面的LT表示libtool。
- HEADERS。標頭檔案。
- SCRIPTS。指令碼檔案,這個可以被用於執行。如:example_SCRIPTS,如果用這樣的話,需要我們自己定義安裝目錄下的example目錄,很容易的,往下看。
- DATA。資料檔案,不能執行。
一,可執行檔案
先看一個例項:
[cpp] view plaincopyprint?- 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等動態庫的連線。分析一下:<span style="font-size:12px;">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</span>
bin_PROGRAMS:表示指定要生成的可執行應用程式檔案,這表示可執行檔案在安裝時需要被安裝到系統中,如果只是想編譯。不想被安裝到系統中,可以用noinst_PROGRAMS來代替。
一個簡單的問題是:bin_PROGRAMS=client 這一行表示什麼意思?解釋如下:
- PROGRAMS知道這是一個可執行檔案。
- client表示編譯的目標檔案。
- bin表示目錄檔案被安裝到系統的目錄。
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檔案可以被遞迴性的呼叫。
下面再說一下上文中出現的$(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檔案:
[html] view plaincopyprint?- clientincludedir=$(includedir)/client
- clientinclude_HEADERS=$(top_srcdir)/client/client.h
<span style="font-size:12px;">clientincludedir=$(includedir)/client
clientinclude_HEADERS=$(top_srcdir)/client/client.h</span>
這就達到了我的目的,相當於定義了一個安裝型別,這種安裝型別是將檔案安裝到include/client目錄下。
我們自己也可以定義新的安裝目錄下的路徑,如我在應用中簡單定義的:
[cpp] view plaincopyprint?- devicedir = ${prefix}/device
- device_DATA = package
<span style="font-size:12px;">devicedir = ${prefix}/device
device_DATA = package</span>
這樣的話,package檔案會作為資料檔案安裝到device目錄之下,這樣一個可執行檔案就定義好了。注意,這也相當於定義了一種安裝型別:devicedir,所以你想怎麼安裝就怎麼安裝,後面的XXXXXdir,dir是固定不變的。
二,靜態庫檔案
編譯靜態庫和編譯動態庫是不一樣的,我們先看靜態庫的例子,這個比較簡單。直接指定 XXXX_LTLIBRARIES或者XXXX_LIBRARIES就可以了。如果不需要安裝到系統,將XXXX換成noinst就可以。還是再羅嗦一下:
- 一般推薦使用libtool庫編譯目標,因為automake包含libtool,這對於跨平臺可移植的庫來說,肯定是一個福音。
看例子如下:
[cpp] view plaincopyprint?- noinst_LTLIBRARIES = libutil.la
- noinst_HEADERS = inaddr.h util.h compat.h pool.h xhash.h url.h device.h
- libutil_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
- libutil_la_LIBADD = @[email protected]
<span style="font-size:12px;">noinst_LTLIBRARIES = libutil.la
noinst_HEADERS = inaddr.h util.h compat.h pool.h xhash.h url.h device.h
libutil_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
libutil_la_LIBADD = @[email protected]
</span>
第一行的noinst_LTLIBRARIES,這裡要注意的是LTLIBRARIES,另外還有LIBRARIES,兩個都表示庫檔案。前者表示libtool庫,用法上基本是一樣的。如果需要安裝到系統中的話,用lib_LTLIBRARIES。
注意:靜態庫編譯連線時需要其它的庫的話,採用XXXX_LIBADD選項,而不是前面的XXXX_LDADD。編譯靜態庫是比較簡單的,因為直接可以指定其型別。
三,動態庫檔案
想要編譯XXX.so檔案,需要用_PROGRAMS型別,這裡一個關於安裝路徑要注意的問題是,我們一般希望將動態庫安裝到lib目錄下,按照前面所討論的,只需要寫成lib_PROGRAMS就可以了,因為前面的lib表示安裝路徑,但是automake不允許這麼直接定義,可以採用下面的辦法,也是將動態庫安裝到lib目錄下
[cpp] view plaincopyprint?- projectlibdir=$(libdir) //新建一個目錄,就是該目錄就是lib目錄
- projectlib_PROGRAMS=project.so
- project_so_SOURCES=xxx.C
- project_so_LDFLAGS=-shared -fpic //GCC編譯動態庫的選項
<span style="font-size:12px;">projectlibdir=$(libdir) //新建一個目錄,就是該目錄就是lib目錄
projectlib_PROGRAMS=project.so
project_so_SOURCES=xxx.C
project_so_LDFLAGS=-shared -fpic //GCC編譯動態庫的選項</span>
這個動態庫我沒有測試,在網上找的一些資料,然後整理的。
四,SUBDIRS的用法
這是一個很重要的關鍵詞,我們前面生成了一個一個的目標檔案,但是一個大型的工程專案是由許多個可執行檔案和庫檔案組成,也就是包含多個目錄,每個目錄下都有用於生成該目錄下的目標檔案的Makefile.am檔案,但頂層目錄是如何呼叫,才能使下面各個目錄分別生成自己的目標檔案呢?就是SUBDIRS關鍵詞的用法了。
看一下我的工程專案,這是頂層的Makefile.am檔案
[cpp] view plaincopyprint?- EXTRA_DIST = Doxyfile.in README.win32 README.protocol contrib UPGRADE
- devicedir = ${prefix}/device
- device_DATA = package
- SUBDIRS = etc man
- if USE_LIBSUBST
- SUBDIRS += subst
- endif
- SUBDIRS += tools io sessions util client dispatch server hash storage sms
<span style="font-size:12px;">EXTRA_DIST = Doxyfile.in README.win32 README.protocol contrib UPGRADE
devicedir = ${prefix}/device
device_DATA = package
SUBDIRS = etc man
if USE_LIBSUBST
SUBDIRS += subst
endif
SUBDIRS += tools io sessions util client dispatch server hash storage sms</span>
SUBDIRS表示在處理目錄之前,要遞迴處理哪些子目錄,這裡還要注意處理的順序。比如我的client對sessions和utils這兩上目標檔案有依賴,就在client之前需要處理這兩個目標檔案。
EXTRA_DIST:將哪些檔案一起打包。
五,關於打包
Automake會自動的打包,自動打包的內容如下:
- 所有原始檔。
- 所有的Makefile.am檔案。
- configure讀取的檔案。
- Makefile.am中包含的檔案。
- EXTRA_DIST指定的檔案。
- 採用dist及nodist指定的檔案,如可以將某一原始檔指定為不打包:
nodist_client_SOURCES = client.c
相關推薦
嵌入式 Makefile.am檔案的例項講解
Makefile.am是一種比Makefile更高層次的編譯規則,可以和configure.in檔案一起通過呼叫automake命令,生成Makefile.in檔案,再呼叫./configure的時候,就將Makefile.in檔案自動生成Makefile檔案了。所以Mak
例項講解php檔案操作
前言 本文主要講解php檔案的基本操作,包括檔案開啟、讀取、寫入、關閉、刪除。並通過這些知識實現一個簡易的商品訂購系統。 檔案建立/開啟 fopen:(建立並)開啟一個檔案或 URL 地址。(這
Struts2跟freemarker的配置例項講解(FTL檔案解析)
Freemarker 簡介 FreeMarker允許Java servlet保持圖形設計同應用程式邏輯的分離,這是通過在模板中密封HTML完成的。模板用servlet提供的資料動態地生成 HTML。模板語言是強大的直觀的,編譯器速度快,輸出接近靜態
例項講解:使用IBM heapAnalyzer分析heap dump檔案步驟
需求動機:解決 OOM( Object Out of Memory)問題以及系統調優 1.如何產生 java heap dump 當 JVM中物件過多, java堆( java heap)耗盡時,就會產生 java heap dump檔案。另外,可以使用工具或命令
懶人學習automake, Makefile.am,configure.ac
add mit cal view thread art programs 51cto readme 已經存在Makefile.am,如何生成Makefile? 步驟: [plain] view plain copy [[email
Makefile.am文件配置
目錄文件 靜態 使用 腳本 指定 ash 子目錄 str 數據文件 Makefile.am Makefile.am是一種比Makefile更高層次的編譯規則,可以和configure.in文件一起通過調用automake命令,生成Makefile.in文件,再調用./con
Python多執行緒、多程序和協程的例項講解
執行緒、程序和協程是什麼 執行緒、程序和協程的詳細概念解釋和原理剖析不是本文的重點,本文重點講述在Python中怎樣實際使用這三種東西 參考: 程序、執行緒、協程之概念理解 程序(Process)是計算機中的程式關於某資料集合上的一次執行活動,是系統進行資源分配和排程的基本單位,是作業系統結構的基礎。執
Python中模組的搜尋路徑例項講解
2018年3月1日13:26:09 最近在工作的時候遇到一個問題,我首先是拿到別人現成的程式碼,程式碼如下: import os,sys,re import datetime import threading import subprocess import configparser imp
Hive內部表、外部表、分割槽表以及外部分割槽表建立以及匯入資料例項講解
源資料格式: [[email protected]144113 zhang_dd_edw]$ more data.txt 25502#hdfs://ns1/user/dd_edw/adm.db/adm_dealer_order_list_di_big/dt=2015-07-
Android中的Intent例項講解
Intent 是由動作,資料,分類,元件和擴充套件資訊等組成。 組成 屬性 設定屬性的方法 獲取屬性的方法 動作 Action setAction() getAction()
SpringMVC Ajax上傳檔案例項
做了一個檔案上傳模組,因為傳統的form提交會有頁面重新整理,不符合我的使用要求,所以我採用Ajax提交方式,這裡說明下,我的應用程式前端為Ajax提交,後端SpringMVC接收處理。 傳統form提交檔案方式: <form id="uploadPic" action="/user/
思科交換機基本配置例項講解《一》
1、基本概念介紹 IOS: 網際網路作業系統,也就是交換機和路由器中用的作業系統 VLAN: 
54、Swing例項講解
學習目標: 1、Swing外掛的基本使用 學習過程: 下面我們完成一個簡單的計算機,大家可以自己動手完成這個功能。 一、後臺頁面邏輯。 新建com.dao包,新建一個Cal類。程式碼如下: 1 2 3 4 5 6 7 8 9 10
斷點續傳的原理剖析與例項講解
斷點續傳的原理剖析與例項講解 本文所要講的是Android斷點續傳的內容,以例項的形式進行了詳細介紹。 一、斷點續傳的原理 其實斷點續傳的原理很簡單,就是在http的請求上和一般的下載有所不同而已。  
python3:通過例項講解元類實現_ORM01
ORM全稱“Object Relational Mapping”,即物件-關係對映,就是把關係資料庫的一行對映為一個物件,也就是一個類對應一個表,這樣,寫程式碼更簡單,不用直接操作SQL語句。 明確下我們的需求: 我們要建立一個類,並把類對映到資料庫的一張表,並校驗資料庫每個欄位的取
例項講解啟動mysql server失敗的解決方法
MySQL 例項講解啟動mysql server失敗的解決方法 來源: 作者: 發表於: 2012-08-19 17:15 點選: 2470 啟動mysql
Jmeter-介面測試例項講解
一、測試需求描述 1、 本次測試的介面為http服務端介面 2、 介面的主要分成兩類,一類提供給查詢功能介面,一類提供儲存資料功能介面,這裡我們舉例2個儲存資料的介面,因為這兩個介面有關聯性,比較有代表性; 3、介面描述:
安卓專案實戰之關於獲取SD卡指定路徑和檔案的講解
前言 當我們將手機連線到電腦上時,我們發現在SD卡的根目錄下生成了成百上千的由各種應用程式建立的資料夾,導致我們也不知道哪個資料夾是用來幹嘛的,這正因為這樣安卓開發人員經常受到使用者的吐槽。 的確作為一個安卓開發者,我們的確不應該將我們應用的資料直接存到SD卡的根目錄下,這樣當手機安
Configure,Makefile.am, Makefile.in, Makefile
Configure,Makefile.am, Makefile.in, Makefile檔案之間關係 1.autoscan (autoconf): 掃描原始碼以搜尋普通的可移植性問題,比如檢查編譯器,庫,標頭檔案等,生成檔案configure.scan,它是configure.ac的一
Python進階(二十)-Python爬蟲例項講解
分享一下我的偶像大神的人工智慧教程!http://blog.csdn.net/jiangjunshow 也歡迎轉載我的文章,轉載請註明出處 https://blog.csdn.net/mm2zzyzzp Python進階(二十)-Python爬蟲例項講解