一、靜態庫和動態庫,Makefile專案管理
函式庫:本質:一組函式。具有相近的功能或操作同一資料結構。strcpy/strcmp/strcat/strlen/strstr/strchr/strtok... <string.h>
bubble_sort / select_sort / quick_sort / insert_sort <mysort.h>
作用:
- 程式碼複用:軟體開發的大部分時間用在應用程式設計上。而不是花在處理底層的細節上。(物件導向程式設計也體現了程式碼複用)
硬體——系統呼叫——標準庫——使用者庫——應用程式 (層層複用)
- 程式積累
釋出形式:
- 原始碼形式釋出
缺點:1. 保密性差 2. 編譯程式耗時、平臺、編譯器版本
優點:方便使用者學習和研究
- 二進位制形式
優缺點 與上相反 標準C庫libc.so.6
一、靜態庫:
機制:複製靜態庫作為程式程式碼段的一部分。
優點:將函式庫中的函式本地化。定址方便,速度快。(庫函式呼叫效率 == 自定義函式使用效率)
缺點:消耗系統資源較大。每個程式使用靜態庫都要複製一份。無端浪費記憶體
使用場景:多應用於核心程式,保證時效性,可以忽視空間。
製作:
1. gcc add.c sub.c mul.c -c ——>得到*.o
2. ar rs libmymath.a add.o sub.o mul.o ——>得到靜態庫
(libmymath.a命名規範必須是lib開頭 .a結尾)
ar工具不包含在gcc中
r更新、c建立、s建立索引
file libmymath.a ——>檢視庫資訊
3. gcc main.c -o app -L ./ -l mymath -I ./ ——>使用靜態庫(./ 表示當前資料夾 )
使用:L:指定靜態庫所在目錄位置;l:指定靜態庫名字 I:指定標頭檔案所在目錄位置
二、動態庫(共享庫):
機制:共享程式碼(不共享資料)
優點:節省記憶體(共享)、易於更新(動態連結) ./a.out 《--- libc.so
缺點:相較於靜態庫函式呼叫速度略慢(延遲繫結機制)
使用場景:
- 對程式執行速度要求不是很強烈,而相對於系統資源有一定要求的場景
- 對於更新比較頻繁的程式
1)停止執行程式
2)使用新庫覆蓋舊庫(保證新舊庫名稱一致,介面一致) “介面”
3)重新啟動程式。
重點強調:
- 動態庫是否載入到記憶體,取決於程式是否執行
- 動態庫載入到記憶體的位置不固定----動態連結器
製作:
1. gcc -fPIC add.c mul.c sub.c -c (-fPIC:生成“與位置無關”的目標檔案*.o)
2. gcc -shared -o libmymath.so add.o mul.o sub.o
3. gcc main.c -L庫路徑 -l庫名 -I標頭檔案名 -o app
4. ./app --> 出錯
原因:動態聯結器 ld-linux.so.2 搜尋動態庫的路徑未指定,
執行ldd app發現動態連結器找不到 libmymath 庫。
指定方法:
1. 環境變數法:export LD_LIBRARY_PATH=./ 將當前目錄加入環境變數,但是終端退出了就無效了。
2. 配置檔案法:將上條寫入家目錄下.bashrc檔案中 (永久生效,設定到~/.bashrc)
3. 拷貝法:直接將libmymath.so檔案拷貝到/usr/lib/目錄下。(受libc庫的啟發)
4. 快取檔案法:將libmymath.so所在絕對路徑加入到/etc/ld.so.conf檔案,
使用sudo ldconfig -v 動態更新/etc/ld.so.cache檔案(2進位制檔案)
*5. 指定動態庫的soname
gcc -shared -Wl,-soname,libmymath.so.1 -o libmymath.so.1.10 add.o mul.o sub.o
*6. 建立動態庫的LinkerName
ln -s libmymath.so.1.10 libmymath.so
動-靜態庫共存時:
編譯器預設使用.so的動態庫,找不到才使用靜態庫。
-static可以直接指定使用靜態庫。
objdump -dS app > out
注意比較加了static和沒有加static的可執行檔案大小,及內部printf的地址。
gdb:
使用場景:程式編譯無誤,但是有邏輯錯誤。
加-g 編譯 ---> gdb xxx (gcc gcbtest.c -o app -g)
list l ---> b 行號 (設定斷點 b 22 if i = 5 條件斷點)
info b 檢視斷點資訊。
disable/enable 斷點號——設定斷點非使能/使能。
delete 斷點號——刪除斷點
b 行號 if i=5 設定條件斷點,只有i=3時斷點生效。
run ---- start
p 變數名——檢視變數值
display——跟蹤變數
undisplay——取消跟蹤
ptype 變數名——檢視變數型別
bt 檢視當前程式函式棧幀使用基本情況
函式的棧幀儲存區域性變數和臨時值,形參,與區域性變數等價。
info locals 檢視當前棧幀上變數的儲存值。
frame 棧幀編號檢視變數的值
s——step
n——next
finish 終止當前函式
continue 結束當前斷點除錯
p *陣列名@10 列出陣列前10個元素值
p 陣列名[n]@m 從下標n開始向後列印m個元素。
三、makefile專案管理
3.1用途
- 專案程式碼編譯管理
- 節省編譯專案時間
- 一次編寫終身受益
- 操作示例檔案:add.c sub.c mul.c dive.c main.c
3.2基本規則
Makefile由一組規則組成,規則如下:
目標:依賴
(tab)命令
如:add.o:add.c
(一個tab縮排)gcc –Wall –g –c add.c –o add.o
目標:要生成的目標檔案
依賴(條件):目標檔案由哪些檔案生成
命令:通過執行該命令由依賴檔案生成目標
3.3Makefile工作原理
基本原則:
1.若想生成目標,檢查規則中的依賴條件是否存在,如不存在,則尋找是否有規則用來生成該依賴檔案
2.檢查規則中的目標是否需要更新,必須先檢查它的所有依賴,依賴中有任一個被更新,則目標必須更新
- 分析各個目標和依賴之間的關係
- 根據依賴關係自底向上執行命令
- 根據修改時間比目標新,確定更新
- 如果目標不依賴任何條件,則執行對應命令,以示更新
3.5Makefile變數
在Makefile中使用變數有點類似於C語言中的巨集定義,使用該變數相當於內容替換,使用變數可以使Makefile易於維護,修改內容變得簡單
變數定義及使用:
foo = abc
bar = $(foo)
定義了兩個變數:foo、bar,其中bar的值是foo變數值的引用。
1、變數定義直接用'='
2、使用變數值用$(變數名)
通常我們在Makefile中會定義一些變數,方便Makefile的修改維護
src = main.c func1.c func2.c
CC = gcc #arm-linux-gcc
CPPFLAGS : C預處理的選項如:-I
CFLAGS:C編譯器的選項–Wall –g -c
LDFLAGS :連結器選項–L -l
自動變數:
$@:表示規則中的目標
$<:表示規則中的第一個條件
$^:表示規則中的所有條件,組成一個列表,以空格隔開,如果這個列表中有重複的項則消除重複項。
模式規則:
至少在規則的目標定義中要包含'%','%'表示一個或多個,在依賴條件中同樣可以使用'%',依賴條件中的'%'的取值,取決於其目標.
模式規則示例:
%.o:%.c
$(CC) –c $(CFLAGS) $(CPPFLAGS) $< -o $@
其中,“$@”表示依次取出目標值,$<表示依次取出依賴條件。
注意:只有寫成模式規則的時候,$<才表示了所有依賴條件的依次取值
否則只是取依賴條件中的第一個。
3.5Makefile 函式
src = $(wildcard *.c)
找到當前目錄下所有字尾為.c的檔案,賦值給src
obj = $(patsubst %.c,%.o, $(src))
把src變數裡所有字尾為.c的檔案替換成.o
3.6clean
- 用途:清除編譯生成的中間.o檔案和最終目標檔案
- make clean 如果當前目錄下有同名clean檔案,則不執行clean對應的命令
- 偽目標宣告:.PHONY:clean
- clean命令中的特殊符號
– “-”此條命令出錯,make也會繼續執行後續的命令。如:“-rm main.o”
– “@”不顯示命令本身,只顯示結果。如:“@echo”clean done“” - 其它
– make 預設執行第一個出現的目標,可通過make dest指定要執行的目標
– distclean目標
– install目標
– make -C 指定目錄進入指定目錄,呼叫裡面的Makefile
– make -n:只列印要執行的命令,不會真正執行命令
– make -p:顯示隱含規則資料庫中的資訊
– make -C:切換到另一個目錄中執行該目錄下的Makefile
– make -f:-f執行一個makefile檔名稱,使用make執行指定的makefile
3.7例子
#src = add.c sub.c mul.c main.c
src = $(wildcard *.c) #wildcard *.c 在當前資料夾找到所有.c字尾的檔案
#obj = add.o sub.o mul.o main.o
obj = $(patsubst %.c,%.o,$(src))
CC = gcc
target = app
ALL:$(target)
$(obj):%.o:%.c
$(CC) -c $< -o $@
$(target):$(obj)
$(CC) $^ -o $@
clean:
-rm -rf app $(obj)
.PHONY:clean ALL
3.8例題
1.完成該專案圖的makefile
#src = add.c sub.c mul.c main.c
src = $(wildcard ./src/*.c) #wildcard:get all file which name end in .c in this file
obj = $(patsubst ./src/%.c,./obj/%.o,$(src)) #obj = add.o sub.o mul.o main.o
inc_path = ./inc/
CC = gcc
target = app
CFLAGES = -I
ALL:$(target)
$(obj):./obj/%.o:./src/%.c #./obj/add.o ./obj/sub.o ./obj/mul.o : ./src/*.c
$(CC) -c $< -o $@ $(CFLAGES) $(inc_path)
$(target):$(obj)
$(CC) $^ -o $@
clean:
-rm -rf app $(obj)
.PHONY:clean ALL
2.make生成三個不同的app
src = $(wildcard *.c) #a.c b.c c.c gdbtest.c
target = $(patsubst %.c,%,$(src)) #a b c gdbtest
ALL:$(target)
CFLAGES = -Wall
$(target):%:%.c
gcc $< -o $@ $(CFLAGES)
clean:
-rm -rf $(target)
.PHONY:clean ALL
相關文章
- ios靜態庫和動態庫iOS
- cmake:生成靜態庫和動態庫
- 靜態庫與動態庫
- iOS動態庫和靜態庫的運用iOS
- android下java的靜態庫和動態庫AndroidJava
- 簡述Linux下的靜態庫和動態庫Linux
- 動靜態庫
- Linux共享庫、靜態庫、動態庫詳解Linux
- iOS中的動態庫,靜態庫和framework介紹iOSFramework
- Android NDK祕籍--淺析靜態庫和動態庫Android
- linux下的靜態庫與動態庫Linux
- [Linux]動靜態庫Linux
- socket動態庫專案
- 動態連結庫與靜態連結庫
- linux 動態庫 靜態庫 函式覆蓋Linux函式
- 筆記: 判斷lib庫是動態庫還是靜態庫筆記
- 靜態庫和動態庫的製作以及Bundle資原始檔的使用
- CMake和靜態庫順序
- 靜態庫生成
- linux下靜態連結庫和動態連結庫的區別有哪些Linux
- Android NDK祕籍--編譯靜態庫、呼叫靜態庫Android編譯
- 自建 iOS 靜態庫並用 pod 管理iOS
- iOS 靜態庫 與私有庫iOS
- 關於MNN工程框架編譯出來的靜態庫和動態庫的使用框架編譯
- Android:JNI與NDK(二)交叉編譯與動態庫,靜態庫Android編譯
- iOS - 靜態庫.a 和 framework 詳解iOSFramework
- FFmpeg—專案匯入FFmpeg動態庫(二)
- 偽靜態、靜態和動態的區別
- 靜態連結動態連結的連結順序問題和makefile示例
- C靜態庫的建立與使用--為什麼要引入靜態庫?
- 封裝動態庫dll與靜態庫lib(原理及簡單例項)封裝單例
- 靜態資源公共庫
- iOS的Framework靜態庫iOSFramework
- 靜態路由和動態路由路由
- 靜態代理和動態代理
- 狀態管理庫MobX和reactReact
- 狀態管理庫 MobX 和 reactReact
- 資料庫靜態脫敏資料庫