My code works, I don’t know why.

國王的耳朵是驢耳朵

從Autotools Tarball打包deb套件: 不嚴謹style

| Comments

deb 檔案是Debian系列安裝套件檔案格式。這次將示範使用不嚴謹的兩種方式將一個auto tool打包的tarball打包成deb檔案。這兩種方式的差別只有在產生套件相關的source code tarball的方式不同。

注意,這些方法完全沒有去更動Debain相關設定檔,也就是說很多細節都被省略而使用預設設定

目錄


概論

簡單敘述產生deb套件流程如下

  • 取得tarball,依照Debian規範設定目錄名稱
  • 解壓縮後,執行dh_make在解壓縮目錄下面產生debian目錄
  • 更改debian目錄下面的設定
  • 執行dpkg-buildpackage產生deb檔和其他檔案

debian目錄下面雖然我測試時偷懶都不改,不過還是值得提一下。

  • 重要檔案
    • control – 套件metadata如相依性,套件官方網站,套件描述等
    • rules – 編譯套件的規範
    • copyright – 版權宣告,預設為GPL2。可以自行更動。另外dh-make可以下參數指定版權宣告如bsd等
    • changelog – 套件更動訊息
  • 其他如安裝script,想要apply的patch等

從一個autotool的tarball xxx.tar.gz經過打包工具後最少要產生下面四個檔案:

  • xxx_原始套件版本號-Debian套件版本號.dsc
    • 套件的metadata
  • xxx_原始套件版本號.orig.tar.gz
    • 原始tarball
  • xxx_原始套件版本號-Debian套件版本號.debian.tar.gz
    • 前面dh_make產生的debian目錄壓縮檔
  • xxx原始套件版本號-Debian套件版本號平台.deb
    • 生成的套件
  • xxx原始套件版本號-Debian套件版本號平台.changes
    • 描述整個產生的檔案資訊,要上傳到Debian套件主機會用到。

以下是使用之前的auto tools為範例產生出來的檔案列表:這邊我們可以看到

  • 原始套件版本號為0
  • Debian套件版本號為1
Two level tree view
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
$ tree -L 2
.
├── testautotools-0
│   ├── aclocal.m4
│   ├── config.guess
│   ├── config.h
│   ├── config.h.in
│   ├── config.log
│   ├── config.status
│   ├── config.sub
│   ├── configure
│   ├── configure.ac
│   ├── debian
│   ├── depcomp
│   ├── include
│   ├── install-sh
│   ├── libs
│   ├── libtool
│   ├── ltmain.sh
│   ├── Makefile
│   ├── Makefile.am
│   ├── Makefile.in
│   ├── missing
│   ├── src
│   └── stamp-h1
├── testautotools_0-1_amd64.changes
├── testautotools_0-1_amd64.deb
├── testautotools_0-1.debian.tar.gz
├── testautotools_0-1.dsc
└── testautotools_0.orig.tar.gz

方法一

  • 在原本的auto tools開發套件目錄中make dist產生tarball,搬移到測試的空目錄
  • 把tarball 從xxx.tar.gz更改成xxx_版本號.orig.tar.gz
  • 解壓縮
  • 務必要確認目錄名稱要符合xxx-原始套件版本號的格式!不符合請自行rename
  • 切換到解壓縮目錄
  • echo -e "\n" | dh_make -s
    • -s表示tarball產生全部的binary都會放在同一份deb檔案
    • 執行完畢會產生debian目錄,存放和套件有關的metadata,應該要手動確認修改資料,如套件說明、原來軟體官方網頁、聯絡方式等。
  • dpkg-buildpackage
    • 產生套件相關檔案,因為無法sign所以不嚴謹。更嚴謹可以使用debuild,它會做許多額外的檢查,這種情況下我的測試tarball是無法通過debuild檢查的。自用可以加入-uc -us參數省略sign。

方法二

  • 在原本的auto tools開發套件目錄中make dist產生tarball
  • 直接解壓縮tarball 到測試的空目錄
  • 務必要確認目錄名稱要符合xxx-原始套件版本號的格式!不符合請自行rename
  • 切換到解壓縮目錄
  • echo -e "\n" | dh_make -s --createorig
    • -s表示tarball產生全部的binary都會放在同一份deb檔案
    • --createorig會讓工具幫你產生orig的tarball
    • 執行完畢會產生debian目錄,存放和套件有關的metadata,應該要手動確認修改資料,如套件說明、原來軟體官方網頁、聯絡方式等。
  • dpkg-buildpackage
    • 產生套件相關檔案,因為無法sign所以不嚴謹。更嚴謹可以使用debuild,它會做許多額外的檢查,這種情況下我的測試tarball是無法通過debuild檢查的。自用可以加入-uc -us參數省略sign。

參考資料

安裝unstable Release Debian方式

| Comments

想安裝Unstable release Debian,跑去官方網站看,發現ISO檔只有stable和testing兩種。網路搜尋後發現原來unstable沒有ISO檔*,後來決定從已經安裝的Debian系統切換過去。

測試環境:Debian “wheezy” 7.5

如果您的系統是stable release的話,第一步要把release從stable切換到testing。切換方式為

  • /etc/apt/sources.list中的wheezy更換成jessie
  • sudo apt-get update
  • sudo apt-get dist-upgrade
  • sudo reboot

如果您已經是testing或是從stable切換到testing的話,也是做類似的事情。

  • /etc/apt/sources.list中的下面描述
1
2
deb http://ftp.debian.org/debian jessie main
deb-src http://ftp.debian.org/debian jessie main

換成

1
2
deb http://ftp.debian.org/debian sid main
deb-src http://ftp.debian.org/debian sid main

請注意URL不一定會相同,但是jessie main以及sid main會相同 至於為何不全部換呢?請看這邊解釋。

然後執行 * sudo apt-get update * sudo apt-get dist-upgrade * sudo reboot * 重開後從終端機執行lsb_release -a結果應為

1
2
3
4
Distributor ID:  Debian
Description:  Debian GNU/Linux unstable (sid)
Release:  unstable
Codename: sid

sid 的sources.list分析

/etc/apt/sources.list存放APT套件管理系統存取遠端套件資訊。裏面的格式為

  • type url 目錄名稱 元件
    • 範例deb http://ftp.debian.org/debian jessie main contrib non-free

根據這邊的描述,遠端資料是放在主機URL的dists下面(範例)。我們瀏覽該URL下面的的dists目錄,就會發現下面的目錄和目錄名稱相同。

回到主題:為何從testing換成unstable只有改一個repository?原因是其他的repository並沒有unstable版本。確認如下:

  • URL/dists中(範例),你會發現sid只有一個目錄。不像jessie或是wheezy會有幾個用這個Code name開頭的目錄。
  • Security套件團隊沒有處理unstable release (出處)

參考資料

在Autotools使用Libtool編譯函式庫

| Comments

前面討論了AutotoolsLibtool,今天就來合體一下。其實只要把原本Autotools範例做少部份的修改就可以了。

目錄:


前情提要

先複習一下

  • Autotools

    • 目的是協助處理不同平台相依性的問題。
    • Autotools 產生
      • scripts用來偵測環境,最終產生平台相依的Makefile。
      • config.h存放不同設定。
    • 使用者最低限度的需要自己寫/更改
      • 每個需要目錄中的Makefile.am 給automake產生Makefile.in。
      • configure.ac給autotools中工具使用。
  • Libtool

    • 協助處理不同平台編譯以及link時相依性的問題。 (我自己想的,可能不精確。)
      • 是一個script
    • 編譯會產生
      • 原始檔衍生出來的兩個object 檔案,一個為標準object檔案,另外為PIC版本
        • *.lo檔案描述該原始檔的metadata
      • library
        • *.la檔案描述library的metadata

更動說明

configure.ac

更動如下:

  • 拿掉AC_PROG_RANLIB,這邊libtool會幫忙處理
  • 加入LT_INIT告訴autotool會使用libtool
configure.ac.diff
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
diff --git a/configure.ac b/configure.ac
index 7763f37..edec020 100644
--- a/configure.ac
+++ b/configure.ac
@@ -6,8 +6,8 @@ AC_INIT([Test_Autotools], [0], [test])
 AM_INIT_AUTOMAKE([foreign -Wall -Werror])
 AC_CONFIG_HEADERS([config.h])

-# Use static libary
-AC_PROG_RANLIB
+# USE libtool
+LT_INIT

 # Makefiles
 AC_CONFIG_FILES([Makefile src/Makefile libs/Makefile])

libs/Makefile.am

更動如下:

  • LIBRARIES改成LTLIBRARIES
  • 產生的目標為從.a改成.la
libs/Makefile.am.diff
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
diff --git a/libs/Makefile.am b/libs/Makefile.am
index f173ac6..230fa34 100644
--- a/libs/Makefile.am
+++ b/libs/Makefile.am
@@ -1,7 +1,8 @@
 AM_CFLAGS = -I../include
-lib_LIBRARIES = liba.a libb.a
-liba_a_SOURCES = liba.c
-libb_a_SOURCES = libb.c
+lib_LTLIBRARIES = liba.la libb.la
+liba_la_SOURCES = liba.c
+libb_la_SOURCES = libb.c
+

 include_HEADERS = ../include/liba.h ../include/libb.h

src/Makefile.am

更動如下:

  • 指定link *.la
src/Makefile.am.diff
1
2
3
4
5
6
7
8
9
10
diff --git a/src/Makefile.am b/src/Makefile.am
index 75a5199..b8b29bf 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,4 +1,4 @@
-LDADD = ../libs/liba.a ../libs/libb.a
+LDADD = ../libs/liba.la ../libs/libb.la
 AM_CFLAGS = -I../include

 bin_PROGRAMS = test

執行結果

簡單來說,autotool使用libtool產生.a和.so檔案

  • 執行
src/Makefile.am.diff
1
make distclean; autoreconf --install; ./configure --prefix=/tmp/test; make; make install
  • 先看/tmp/test安裝的檔案tree view
src/Makefile.am.diff
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
├── bin
│   └── test
├── include
│   ├── liba.h
│   └── libb.h
└── lib
    ├── liba.a
    ├── liba.la
    ├── liba.so -> liba.so.0.0.0
    ├── liba.so.0 -> liba.so.0.0.0
    ├── liba.so.0.0.0
    ├── libb.a
    ├── libb.la
    ├── libb.so -> libb.so.0.0.0
    ├── libb.so.0 -> libb.so.0.0.0
    └── libb.so.0.0.0
  • make library 結果節錄
src/Makefile.am.diff
1
2
3
4
5
6
7
8
9
10
11
12
make[2]: Entering directory `libs'
/bin/bash ../libtool --tag=CC   --mode=compile gcc -DHAVE_CONFIG_H -I. -I..    -I../include -g -O2 -MT liba.lo -MD -MP -MF .deps/liba.Tpo -c -o liba.lo liba.c
libtool: compile:  gcc -DHAVE_CONFIG_H -I. -I.. -I../include -g -O2 -MT liba.lo -MD -MP -MF .deps/liba.Tpo -c liba.c  -fPIC -DPIC -o .libs/liba.o
libtool: compile:  gcc -DHAVE_CONFIG_H -I. -I.. -I../include -g -O2 -MT liba.lo -MD -MP -MF .deps/liba.Tpo -c liba.c -o liba.o >/dev/null 2>&1
mv -f .deps/liba.Tpo .deps/liba.Plo
/bin/bash ../libtool --tag=CC   --mode=link gcc -I../include -g -O2   -o liba.la -rpath /usr/local/lib liba.lo
libtool: link: gcc -shared  -fPIC -DPIC  .libs/liba.o    -O2   -Wl,-soname -Wl,liba.so.0 -o .libs/liba.so.0.0.0
libtool: link: (cd ".libs" && rm -f "liba.so.0" && ln -s "liba.so.0.0.0" "liba.so.0")
libtool: link: (cd ".libs" && rm -f "liba.so" && ln -s "liba.so.0.0.0" "liba.so")
libtool: link: ar cru .libs/liba.a  liba.o
libtool: link: ranlib .libs/liba.a
libtool: link: ( cd ".libs" && rm -f "liba.la" && ln -s "../liba.la" "liba.la" )
  • 產生執行檔結果
src/Makefile.am.diff
1
2
3
4
gcc -DHAVE_CONFIG_H -I. -I..    -I../include -g -O2 -MT test.o -MD -MP -MF .deps/test.Tpo -c -o test.o test.c
mv -f .deps/test.Tpo .deps/test.Po
/bin/bash ../libtool --tag=CC   --mode=link gcc -I../include -g -O2   -o test test.o ../libs/liba.la ../libs/libb.la
libtool: link: gcc -I../include -g -O2 -o .libs/test test.o  ../libs/.libs/liba.so ../libs/.libs/libb.so
  • ls libs/.libs
src/Makefile.am.diff
1
2
$ ls libs/.libs/
liba.a  liba.la  liba.lai  liba.o  liba.so  liba.so.0  liba.so.0.0.0  libb.a  libb.la  libb.lai  libb.o  libb.so  libb.so.0  libb.so.0.0.0

參考資料

Richard Stallman: A Free Digital Society 台北演講筆記

| Comments

GCCGNU OS和FSF協會的創辦人Richard Stallman (RMS)在2014年五月在台灣大學發表演講,題目為:「 Free Digital Society 」。用兩光的英聽整理一下演講重點,應該有聽錯的部份,請自行斟酌:

先把數位自由的部份從裏面提出來,因為要了解RMS的自由概念,才能夠理解他從這樣的理念提出的看法。RMS認為軟體和使用者的關係要嘛是使用者控制操作軟體,或是被軟體控制操作;而自由指的是使用者控制操作的情況。所以他定義了使用者自由操作的四種要素:

  • 零. 使用者可以不受限制的執行的執行程式。
  • 壹. 使用者有研讀修改的權力。你可以隨意地更改程式碼。

以上兩個要素只能確保個人的控制軟體能力,但是各自單獨修改的力量和進步程度當然比不上合作修改還來大。因此他又加上兩項權利。

  • 貳. 重製散佈的權利。
  • 參. 更正,改進並散佈的權利。

現代數位自由威脅面向

  • 網路監控
    • 只要資料被蒐集,就有可能被濫用。
    • 在非自由設備下,資料就有可能被監控。就算使用自由設備,基礎設備也可能被用來監控。
    • 網路監控會讓匿名揭露者身份曝光,因而妨礙言論發表,進而危害民主。
    • 對於安全理由而安裝攝影機監控必須要有夠強烈的理由,並且要保證時間內要刪除資料。
    • 網路付費應該要有匿名付費方式以避免特定團體或政府追蹤資金來源作為政治報復手段。
  • 網路審查
  • 數位資料格式
    • Proprietary 格式、DRM、和有專利的資料格式,都會妨礙數位自由。因為你這妨礙讓你無法自由的使用數位內容。
  • Proprietary軟體
    • 惡意軟體形式
      • 內含監控、資料蒐集、以及間諜目的的軟體
      • 限制數位自由如妨礙分享的軟體
      • 後門軟體
    • Proprietary軟體的問題是你不知道他binary內部到底放什麼意思,無從認知他是否是惡意軟體。
    • GPLv3針對blob有加強要求要能夠讓使用者可以自行取代原本軟體內的可執行binary。(未查證)
  • 網站威脅
    • 網站的Javascript常常會安裝Proprietary軟體。
    • 網站的資料蒐集以及要求填寫個人資料。
    • 雲端運算服務也有不可控制的特性。
  • 數位政治選舉 (Public vote)
    • 太容易作假又極度難以防弊,這會威脅民主。
  • 資訊分享爭議
    • RMS提出可以想辦法平衡藝術創作收入和分享的金錢關係。例如計算數位分享次數,由政府從歲收中依比例付給藝術家。甚至可以調整付款公式計算讓最高的收入和一般收入不要差距到幾千幾萬倍。
    • 可以降低專利保護期限讓知識更快流通。
  • 數位權利
    • 現在的問題是基礎建設都是握在私人公司中,也就是說數位權利是有可能被商業掌控。因此政府不喜歡的網站一般存取就會被限制。
    • RMS提出common carrier system的概念防止上面的問題。

相關資料:

Makefile中Command敘述的Shell變數存取

| Comments

想說寫一個loop自動make變數內的目錄

錯誤的Makefile
1
2
3
4
DIRS = libs src

all:
  for i in ${DIRS}; do make -C $i; done

結果跑出來和想像不同

make結果
1
2
for i in lib src; do make -C ; done
make: option requires an argument -- 'C'

原因是$本身在Makefile有特殊意義。要使用$$才能在command敘述中顯示$,因此改進如下

正確的Makefile
1
2
3
4
DIRS = libs src

all:
  for i in ${DIRS}; do make -C $$i; done

參考資料

Libtool初探

| Comments

之前討論的autotools中,偷懶沒去看libtool。後來想到手上參考的資料沒有使用autotool產生shared library的方式。想要補充後發現和libtool有關。看來出來混還是要還的。

目錄


概論

autotool想要處理不同平台之間的移植性問題。而shared library部份的問題是:

  • 不同平台會有不同格式,舉例來說,在Linux下面的shared library的副檔名是so;而在Windows平台上面會是dll的副檔名。
  • 因為平台不同,shared library可能功能相同但是API稍有不同的
  • Header file可能名稱不同

處理這些問題,應用程式可能會寫了一堆很噁心的#ifdef來呼叫不同平台處理不同的shared library的API。這樣一來不但損害程式碼可讀性,也提高的程式碼的維護成本。所以GNU提出了libtool來解決這樣的問題。

這邊可以看到,GNU libtool使用下面的方式來處理平台移植性的中shared library的問題。

  • 用libtool這個script去封裝平台相依性以及提供存取介面
  • 使用者透過libtool這個script存取封裝的資料

因為libtool提供了和平台無關的share library統一介面。Shared library的使用者可以透過autotools安心使用shared library;而Shared library開發者可以安心的使用libtool產生不同平台使用的shared library。

libtool --help 可以看到有--mode參數。他的合法選項為

  • clean
    • 從build目錄刪除檔案
  • compile
    • 把原始碼編譯成libtool object
  • execute
    • 自動設定library path 並執行特定檔案
  • finish
    • 結束libtool library 安裝
  • install
    • 安裝library或是執行檔
  • link
    • 產生library或是執行檔
  • uninstall
    • 反安裝library或是執行檔

範例

  • 測試環境: Ubuntu 12.04.4

測試程式碼

範例程式細節在這邊,檔案各別重新分配到src, include, libs這三個目錄。不想看code只要知道每個檔案都有參考到某個自訂的header file就好了。重點在Makefile如何使用libtool的部份。

測試程式樹狀架構
1
2
3
4
5
6
7
8
9
10
11
├── include
│   ├── liba.h
│   └── libb.h
├── libs
│   ├── liba.c
│   ├── libb.c
│   └── Makefile
├── Makefile
└── src
    ├── Makefile
    └── test.c

測試Makefile

主要demo libtool的部份在這邊。 ./Makefile 主要只是按照指定目錄進入編譯或清除

./Makefile
1
2
3
4
5
6
7
8
9
10
COMPILE_DIRS = libs src
INC_DIR=$(shell pwd)/include

.PHONY: all

all:
  for i in $(COMPILE_DIRS); do make -C $$i INC_DIR=$(INC_DIR); done

clean:
  for i in $(COMPILE_DIRS); do make -C $$i INC_DIR=$(INC_DIR) clean; done

使用libtool編譯函式庫

libs/Makefile大概描述如下

  • 產生兩個libraries, liba.a(靜態函式庫)和libb.so(動態函式庫)
  • 編譯時使用–mode=compile作為參數
  • 連結時使用–mode=link作為參數,都是指定gcc產生*.la檔案
  • 靜態和動態的參數差別為是否有指定runtime elf搜尋路徑-rpath
    • -rpath加入後libtools會產生 動態和靜態兩種函式庫 ,不加看起來只有產生靜態函式庫
libs/Makefile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
LIBTOOL=libtool
SRCS = liba.c libb.c
OBJS = $(patsubst %.c, %.o, $(SRCS))
CFLAGS = -I$(INC_DIR)
CC = gcc

TARGET=liba.la libb.la

all: $(OBJS) $(TARGET)

liba.la: liba.lo
  $(LIBTOOL) --mode=link $(CC) $(CFLAGS) -o $@ $^

libb.la: libb.lo
  $(LIBTOOL) --mode=link $(CC) $(CFLAGS) -o $@ $^ -rpath /usr/local/lib

%.o:%.c
  $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) -c $^

clean:
  rm -rf $(OBJS) .libs *.lo $(TARGET) *.a

先來看編譯程式碼的輸出

libs/Makefile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
libtool --mode=compile gcc -I../include -c liba.c
libtool: compile:  gcc -I../include -c liba.c  -fPIC -DPIC -o .libs/liba.o
libtool: compile:  gcc -I../include -c liba.c -o liba.o >/dev/null 2>&1
libtool --mode=compile gcc -I../include -c libb.c
libtool: compile:  gcc -I../include -c libb.c  -fPIC -DPIC -o .libs/libb.o
libtool: compile:  gcc -I../include -c libb.c -o libb.o >/dev/null 2>&1
libtool --mode=link gcc -I../include -o liba.la liba.lo
libtool: link: ar cru .libs/liba.a .libs/liba.o
libtool: link: ranlib .libs/liba.a
libtool: link: ( cd ".libs" && rm -f "liba.la" && ln -s "../liba.la" "liba.la" )
libtool --mode=link gcc -I../include -o libb.la libb.lo -rpath /usr/local/lib
libtool: link: gcc -shared  -fPIC -DPIC  .libs/libb.o      -Wl,-soname -Wl,libb.so.0 -o .libs/libb.so.0.0.0
libtool: link: (cd ".libs" && rm -f "libb.so.0" && ln -s "libb.so.0.0.0" "libb.so.0")
libtool: link: (cd ".libs" && rm -f "libb.so" && ln -s "libb.so.0.0.0" "libb.so")
libtool: link: ar cru .libs/libb.a  libb.o
libtool: link: ranlib .libs/libb.a
libtool: link: ( cd ".libs" && rm -f "libb.la" && ln -s "../libb.la" "libb.la" )

如果把gcc換成cc會發現不會有FPIC參數跑出來,詳細原因不明。

可以看到

  • libtool產生兩種object檔
    • PIC版本放在libs/.libs
      • 一般的就放在工作目錄下

現在libs下面檔案除了object檔案外,還多了.lo和.la檔案。

libs/Makefile
1
2
$ ls libs
liba.c  liba.la  liba.lo  liba.o  libb.c  libb.la  libb.lo  libb.o  Makefile

我們先看lo檔,可以看到lo檔存放PIC和一般的object檔案位置資訊。

libs/Makefile
1
2
3
4
5
6
7
8
9
10
11
12
$ cat liba.lo
# liba.lo - a libtool object file
# Generated by libtool (GNU libtool) 2.4.2 Debian-2.4.2-1ubuntu1
#
# Please DO NOT delete this file!
# It is necessary for linking the library.

# Name of the PIC object.
pic_object='.libs/liba.o'

# Name of the non-PIC object
non_pic_object='liba.o'

而la檔案則是存放library資訊,我們可以看到靜態和動態主要的差別是有沒有指定so檔名稱以及存放路徑

libs/Makefile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
$ diff libs/libb.la  libs/liba.la
1c1
< # libb.la - a libtool library file
---
> # liba.la - a libtool library file
8c8
< dlname='libb.so.0'
---
> dlname=''
11c11
< library_names='libb.so.0.0.0 libb.so.0 libb.so'
---
> library_names=''
14c14
< old_library='libb.a'
---
> old_library='liba.a'
25,28c25,28
< # Version information for libb.
< current=0
< age=0
< revision=0
---
> # Version information for liba.
> current=
> age=
> revision=
41c41
< libdir='/usr/local/lib'
---
> libdir=''

使用libtool編譯執行檔

src/Makefile中主要就是連結的時候除了指定object檔案外,指定連結la檔案而不是.a或是.so檔案。libtool會幫你從la檔案中找到對的library binary。

src/Makefile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
LIBTOOL=libtool
SRCS = test.c
OBJS = $(patsubst %.c, %.o, $(SRCS)) ../libs/libb.la ../libs/liba.la
CFLAGS = -I$(INC_DIR)
CC = gcc

TARGET=test

$(TARGET): $(OBJS)
  $(LIBTOOL) --mode=link $(CC) $(CFLAGS) -o $@ $(OBJS)

%.o:%.c
  $(LIBTOOL) --mode=compile $(CC) $(CFLAGS) -c $^

clean:
  rm -rf $(OBJS) .libs *.lo $(TARGET)

安裝

  • 如果--mode=link有加-rpath資訊,libtool會支援安裝功能:
    • libtool –mode=install cp libs/libb.la /usr/local/lib
    • 另外值得一提的是安裝時la檔案是有被更動的。比對如下
src/Makefile
1
2
3
4
5
$ diff libs/libb.la  /usr/local/lib/libb.la
31c31
< installed=no
---
> installed=yes
  • 執行檔:

    • libtool –mode=install install -c src/.libs/my_test /usr/local/bin
  • 靜態函式庫部份目前還沒試出來,不確定是libtool只支援安裝動態函式庫還是沒有找到正確的方式。


應該有人會問怎麼沒看到autotool怎麼用,這當作下次題目吧。


參考資料及資源