1. 程式人生 > >Linux學習筆記——例說makefile 增加自定義共享庫

Linux學習筆記——例說makefile 增加自定義共享庫

0.前言    從學習C語言開始就慢慢開始接觸makefile,查閱了很多的makefile的資料但總感覺沒有真正掌握makefile,如果自己動手寫一個makefile總覺得非常吃力。所以特意藉助部落格總結makefile的相關知識,通過例子說明makefile的具體用法。    例說makefile分為以下幾個部分,更多內容請參考【例說makefile索引博文】    1.只有單個C檔案       2.含有多個C檔案        3.需要包括標頭檔案路徑    4.增加巨集定義    5.增加系統共享庫    6.增加自定義共享庫    7.一個實際的例子    程式碼倉庫位於bitbucket,可藉助TortoiseHg(GUI工具)克隆程式碼或者在網頁中直接下載zip包。    【本例說明】    本例分為兩個過程,先製作一個共享庫,然後在使用這個共享庫。共享庫採用動態連結方式,字尾為.so。1.gcc複習
    【1】gcc指令中使用共享庫使用字首-l,共享庫查詢目錄使用-L。    【2】一般情況下DLIBS中加入共享庫,而LDFLAGS中加入共享庫查詢目錄。2.共享庫原始檔    和生成共享庫有關的檔案位於libtest目錄中,在makefile最後把共享庫複製到同級的lib目錄中。具體內容請參考程式碼倉庫並複製zip包。    【libtest.h】    指定介面,給出相應宣告
#ifndef __LIBTEST_H
#define __LIBTEST_H
int sub(int a, int b);
int add(int a, int b);
#endif
    【test-add.c】
int add(int a, int b)
{
    return a+b;
}
    【test-sub.c】
int sub(int a, int b)
{
    return a-b;
}
3.共享庫的makefile    請替換其中的[tab],並以程式碼倉庫中的makefile檔案為主。
# 指令編譯器和選項
CC = gcc
CFLAGS = -Wall -std=gnu99

# 目標檔案
TARGET = libtest.so
# C檔案
SRCS = test-add.c test-sub.c
# 目標檔案
OBJS = $(SRCS:.c=.o)

# 連結為可執行檔案
$(TARGET):$(OBJS)
[tab]$(CC) -shared -o [email protected]
$^ [tab]mv $(TARGET) ../lib clean: [tab]rm -rf $(TARGET) $(OBJS) # 編譯規則 [email protected]代表目標檔案 $< 代表第一個依賴檔案 %.o:%.c [tab]$(CC) $(CFLAGS) -o [email protected] -fPIC -c $<
    【說明】    【1】目標為libtest.so,請務必以lib開頭 .so結尾,在使用該共享庫時系統會自動的去除lib和.so,使用時寫成-ltest。    【2】多數內容和學習筆記中的多個檔案相同。    【3】在連結過程中加入-shared引數,意為共享形式的目標檔案。    【4】在編譯過程中加入-fPIC引數,意為生成和地址無關的目標檔案。    【5】在連結完成之後,通過mv指令把libtest.so移動到同級的lib目錄中。    【6】如果有必要,可以把libtest.so複製到/usr/lib目錄中,這樣使用起來會更加方便。
    【驗證】
    ldd test
    linux-vdso.so.1 =>  (0x00007fffde960000)
    libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007ffe55b18000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007ffe55750000)
    /lib64/ld-linux-x86-64.so.2 (0x00007ffe55e38000)
    【編譯和執行】    make clean && make 
    【控制檯輸出】rm -rf libtest.so test-add.o test-sub.o
gcc -Wall -std=gnu99 -o test-add.o -fPIC -c test-add.c
gcc -Wall -std=gnu99 -o test-sub.o -fPIC -c test-sub.c
gcc -shared -o libtest.so test-add.o test-sub.o
mv libtest.so ../lib
    【1】編譯過程中加入了-fPIC選項。
    【2】連結過程中加入-shared選項。
    【3】共享庫為libtest.so。
    【4】最後,共享庫被移動到上一級的lib目錄中。
   4.原始檔    呼叫共享庫指定的介面,add和sub函式。
#include <stdio.h>
#include <libtest.h>
int main(void)
{
    int a = 3;
    int b = 2;
       
    printf("a=%d\n", a);
    printf("b=%d\n", b);
   
    printf("a+b=%d\n", add(a, b));
    printf("a-b=%d\n", sub(a, b));
    return 0;
}
5.makefile    請替換其中的[tab],並以程式碼倉庫中的makefile檔案為主。    
# 指令編譯器和選項
CC = gcc
CFLAGS = -Wall -std=gnu99

# 目標檔案
TARGET = test
# C檔案
SRCS = test.c
# 標頭檔案查詢路徑
INC = -I.
# 庫檔案和庫查詢路徑
DLIBS = -ltest
LDFLAGS = -L./lib
# 指定執行時的庫檔案路徑
RPATH = -Wl,-rpath=./lib

# 目標檔案
OBJS = $(SRCS:.c=.o)

# 連結為可執行檔案
$(TARGET):$(OBJS)
[tab]$(CC) -o [email protected] $^ $(LDFLAGS) $(DLIBS) $(RPATH)

clean:
[tab]rm -rf $(TARGET) $(OBJS)

# 連續動作,請清除再編譯連結,最後執行
exec:clean $(TARGET)
[tab]@echo 開始執行
[tab]./$(TARGET)
[tab]@echo 執行結束

# 編譯規則 [email protected]代表目標檔案 $< 代表第一個依賴檔案
%.o:%.c
[tab]$(CC) $(CFLAGS) $(INC) -o [email protected] -c $<
6.具體說明    【1】DLIBS = -ltest 指定共享庫,請注意共享庫的名稱為libtest.so,而-l引數只取test部分,去掉字首lib和字尾.so。    【2】LDFLAGS = -L./lib 指定共享庫路徑,請注意上一步中已經把共享庫複製到lib目錄中。    【3】INC = -I./lib  指定libtest.h目錄,也可把libtest.h複製到test.c所在的目錄。    【4】$(CC) -o [email protected] $^ $(LDFLAGS) $(DLIBS) 連結過程指定共享庫查詢路徑,指定共享庫名稱。    【5】第【1】和第【2】點只在連結過程有效,在執行過程中需要通過-Wl,-rpath=<path>指定共享庫路徑。    【編譯和連結】    make clean && make    【控制檯輸出】rm -rf test test.o
gcc -Wall -std=gnu99 -I./lib -o test.o -c test.c 
gcc -o test test.o -L./lib -ltest -Wl,-rpath=./lib    【執行】    在執行之前還可以通過ldd test檢視libtest是否連結成功。./test
a=3
b=2
a+b=5
a-b=1    從控制檯的輸出結果可以看出,共享庫執行正常。7.總結    【1】-l指定共享庫名稱,-L指定共享庫路徑。8.參考資料    

相關推薦

Linux學習筆記——makefile 增加定義共享

0.前言    從學習C語言開始就慢慢開始接觸makefile,查閱了很多的makefile的資料但總感覺沒有真正掌握makefile,如果自己動手寫一個makefile總覺得非常吃力。所以特意藉助部落格總結makefile的相關知識,通過例子說明makefile的具體用法。

Linux學習筆記——makefile 增加巨集定義

rm -rf test test.o ./test-add/test-add.o ./test-sub/test-sub.ogcc -Wall -std=gnu99 -DTEST_ADD -DTEST_SUB=1 -I./test-add -I./test-sub -o test.o -c test.cgcc

Zynq-Linux移植學習筆記之31-使用者定義I2C驅動

1、背景介紹 板子上通過ZYNQ的I2C-0控制器連線了三片DBF晶片和一片Ti的226測功耗晶片,示意圖如下: 如上圖所示,三塊DBF晶片的I2C地址分別為2,4,8,Ti 226晶片的I2C地址為0x40.現在需要ZYNQ通過I2C匯流排讀寫這四塊晶片的暫存器數值

AngularJs學習筆記(4)——定義指令

ref 告訴 ack 生命周期 .com bsp ctrl 參數變量 ng- 對指令的第一印象:它是一個自定義標簽! 先來看一個簡單的指令: <!doctype html> <html ng-app="myApp"> <head>

Linux學習筆記10——管道和重定義

管道重定義計算機的組成有:運算器,控制器,存儲器,輸入輸出設備。於是就有了地址總線,數據總線,控制總線。事實上在機器裏面總線是復用的,一個總線三種功能。地址總線:內存尋址數據總線:傳輸數據控制總結:控制指令 寄存器:CPU暫時存儲器 程序在運行時要從輸入設備獲取指令,通過輸出設備輸出作為人機交互。那麽系統在什

Ehcache學習筆記(2)--定義ehcache工具類

二:自定義EhcacheUtils 1、CacheUtils package cn.kexq.commons.utils; import net.sf.ehcache.Cache; import net.sf.ehcache.CacheManager; import net.sf.eh

shiro學習筆記(3)--定義realm、授權

一:自定義Realm 1、繼承AuthorizingRealm(因為該類中有認證、授權的抽象方法,實現簡單) public class MyRealm1 extends AuthorizingRealm{ @Override public String getName(

Android學習筆記之為Dialog定義佈局,並說明空指標問題

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

Vue:學習筆記(七)-定義指令

提醒 原帖完整收藏於IT老兵驛站,並會不斷更新。 前言 前面總結到了元件,對混入也進行了研究,不過感覺沒有啥需要總結的,就先總結指令吧,參考這裡,記錄筆記。 正文 簡介 全域性註冊 // 註冊一個全域性自定義指令 `v-focus` Vue.di

springmvc學習筆記(26)——定義型別轉換器

資料繫結流程 使用springmvc框架有諸多好處,其中較為突出的就是它的資料繫結。 當我們的前端傳過來一個表單的時候,我們只需要使用一個類物件(如Student物件)就接收,springmvc將幫我們把屬性一一對應的填充進去。這就是資料繫結。 資料繫結過程中,springmvc幫我們把前端

springmvc學習筆記(28)——定義攔截器

1. 自定義攔截器 所謂的攔截器,就是用來攔截請求,因此我們可以對使用者發來的請求做處理。  寫一個類,實現攔截器的介面 import javax.servlet.http.HttpServletRequest; import javax.servlet.http.H

類的學習筆記(3)——定義裝飾器及裝飾器的理解

例一: 實現多加100 def fun1(x):      def fun2(y):           return x(y)+100       return fun2              #裝飾器 def ff(y):       return y*y   

react native學習筆記24——Modal實現定義彈出對話方塊

前言 上一篇文章介紹React Native系統提供的兩個彈出框的api——Alert與AlertIOS,Alert可以在雙平臺通用,但是隻能展示資訊量有限功能單一的文字對話方塊。AlertIOS比Alert稍微豐富一點,可以展示供使用者輸入的對話方塊,但只能

iPhone開發學習筆記005——使用XIB定義一個UIView,然後將這個view新增到controller的view

一、新建一個single view application型別的iOS application工程,名字取為CustomView,如下圖,我們不往CustomViewViewController.xib中新增任何控制元件:  二、新建一個CustomView.xib,過程如下:然後往介面上拖一個label和

Maven學習筆記(一)——定義maven變數以及maven內建常量

在建立Maven工程後,外掛配置中通常會用到一些Maven變數,因此需要找個地方對這些變數進行統一定義,下面介紹如何定義自定義變數。 在根節點project下增加properties節點,所有自定義變數均可以定義在此節點內,如下所示: <!-- 全域性屬性配置 --

Hadoop學習筆記—8.Combiner與定義Combiner

一、Combiner的出現背景 1.1 回顧Map階段五大步驟   在第四篇博文《初識MapReduce》中,我們認識了MapReduce的八大步湊,其中在Map階段總共五個步驟,如下圖所示:   其中,step1.5是一個可選步驟,它就是我們今天需要了解的 Map規約 階段。現在,我們再來看看前一

Hadoop學習筆記—7.計數器與定義計數器

一、Hadoop中的計數器 計數器:計數器是用來記錄job的執行進度和狀態的。它的作用可以理解為日誌。我們通常可以在程式的某個位置插入計數器,用來記錄資料或者進度的變化情況,它比日誌更便利進行分析。   例如,我們有一個檔案,其中包含如下內容: hello you hello me

Hadoop學習筆記—9.Partitioner與定義Partitioner

一、初步探索Partitioner 1.1 再次回顧Map階段五大步驟   在第四篇博文《初識MapReduce》中,我們認識了MapReduce的八大步湊,其中在Map階段總共五個步驟,如下圖所示:   其中,step1.3就是一個分割槽操作。通過前面的學習我們知道Mapper最終處理的鍵值對&l

torch學習筆記1:實現定義

當我們要實現自己的一些idea時,torch自帶的模組和函式已經不能滿足,我們需要自己實現層(或者類),一般的做法是把自定義層加入到已有的torch模組中。 實現 lua實現 如果自定義層的功能可以通過呼叫torch中已有的函式實現,那就只需要用l

Shader學習筆記(三)定義光照模型,經典光照模型Lambert與HalfLambert

自定義光照模型 #pragma surface surfaceFaction lightModel surfaceFaction:著色器程式碼的方法的名字 lightModel:光照模型的名稱 自