日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > linux >内容正文

linux

Linux命令【三】gcc编译+静态库+动态库+makefile+gdb调试

發(fā)布時(shí)間:2023/11/30 linux 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux命令【三】gcc编译+静态库+动态库+makefile+gdb调试 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

用C編譯器編譯源文件:gcc 源文件 -o 可執(zhí)行文件名
詳細(xì)步驟:

  • gcc -E a.c -o a.i預(yù)處理器將頭文件展開,宏替換,去掉注釋
  • gcc -S a.i -o a.s編譯器將C文件變成匯編文件
  • gcc -c a.s -o a.o匯編器將會(huì)變文件變成二進(jìn)制文件
  • gcc a.o -o a鏈接器進(jìn)行鏈接

ESc+鏈接
如果不使用參數(shù)-o 則自動(dòng)生成a.out

制定頭文件的路徑gcc a.c -I 頭文件的目錄 -o 生成可執(zhí)行文件的名字在比較舊的版本上-I和頭文件目錄之間不能有空格,現(xiàn)版本無所謂
指定宏-D 宏名
優(yōu)化-O1/O2/O3O3優(yōu)化速度最高
輸出警告信息-Wall
生成調(diào)試信息-g

靜態(tài)庫

  • 命名規(guī)則
    lib+庫的名字+.a
  • 制作步驟
    生成對應(yīng)的.o文件,直接使用參數(shù)-c得到.o文件,記得不要使用-o參數(shù),否則將會(huì)直接生成可執(zhí)行文件
    將生成的.o文件進(jìn)行打包,需要使用軟件ar將.o打包為.a
  • ar rcs 靜態(tài)庫名稱 所有的.o
  • 發(fā)布和使用靜態(tài)庫
    打包靜態(tài)庫和頭文件,將所有的靜態(tài)庫放到lib文件夾中,將所有的頭文件放到include文件夾中,制作好靜態(tài)庫以后可以發(fā)送這兩個(gè)文件夾。
    用戶通過頭文件知道有哪些函數(shù)接口。通過直接和源文件編譯靜態(tài)庫使用。
  • gcc 源文件 靜態(tài)庫 -o 可執(zhí)行文件 -Iinclude gcc 源文件 -Iinclude -L lib -l 靜態(tài)庫文件名(去掉頭部lib和尾部.a) -o 可執(zhí)行文件
  • 靜態(tài)庫的優(yōu)缺點(diǎn)
  • nm 靜態(tài)庫文件 //查看靜態(tài)庫

    打包的最小單元為.o
    優(yōu)點(diǎn):

  • 庫已經(jīng)打包在程序中,不需要再提供
  • 庫的加載速度比較快
    缺點(diǎn):
  • 可執(zhí)行文件會(huì)比較大
  • 如果庫發(fā)生了改變需要重新編譯
  • 動(dòng)態(tài)庫/共享庫

  • 命名規(guī)則
    lib+名字+.so
  • 制作步驟
    (1) 生成與位置無關(guān)的代碼(.o)
  • gcc -fPIC -c *.c -Iinlcude

    (2) 將.o打包成共享庫
    Linux每一個(gè)運(yùn)行的程序操作系統(tǒng)都會(huì)為其分配一個(gè)0-4G的地址空間。Linux下可執(zhí)行文件格式:ELF

    gcc -shared -o libname.so *.o -Iinclude

    再講lib中的.so文件和include中的頭文件發(fā)送給用戶

  • 用戶使用
  • gcc main.c lib/libname.so -o main -Iinclude gcc main.c -Iinclude -L lib -l name -o main//需要注意的是這里的name是不包含lib和后綴.so的

    使用ldd查看可執(zhí)行文件所依賴的所有的共享庫的名字

    動(dòng)態(tài)庫的使用需要動(dòng)態(tài)鏈接器幫助。我們需要讓動(dòng)態(tài)鏈接器找到我們自己的動(dòng)態(tài)鏈接庫

    正常情況下使用會(huì)出現(xiàn)動(dòng)態(tài)庫無法找到的問題。然后就需要我們?nèi)ソ鉀Q。
    可是我自己嘗試的時(shí)候沒有遇到這個(gè)情況。。。我也不清楚為什么,可能是現(xiàn)在版本的gcc已經(jīng)智能地解決這個(gè)問題了。

    (1)將動(dòng)態(tài)庫放到系統(tǒng)的lib文件夾中
    (2) 配置環(huán)境變量LD_LIBRARY_PATH(如果你的動(dòng)態(tài)庫沒有在默認(rèn)的環(huán)境變量中,會(huì)先在這個(gè)環(huán)境變量中查找)
    用于臨時(shí)測試

    echo $LD_LIBRARY_PATH //$從環(huán)境變量中取值 查看環(huán)境變量 export LD_LIBRARY_PATH=./lib //將當(dāng)前目錄下的lib文件夾導(dǎo)入到環(huán)境變量中

    關(guān)掉終端后失效
    (3)

    ls -a vi .bashrc 在里面加上export LD_LIBRARY_PATH=動(dòng)態(tài)庫目錄 重啟終端

    永久
    (4)工作中更加常用的方法

    • 找到動(dòng)態(tài)鏈接器的配置文件
      /etc/ld.so.conf
      需要使用管理員權(quán)限

    • 將動(dòng)態(tài)庫的路徑寫到配置文件中

    • 更新sudo ldconfig -v -v是提示信息

    動(dòng)態(tài)庫沒有加載到源文件中,而是在需要使用的位置加上了一個(gè)標(biāo)記,在使用的時(shí)候才進(jìn)行訪問。
    優(yōu)點(diǎn):

  • 執(zhí)行程序很小
  • 動(dòng)態(tài)庫更新方便
    缺點(diǎn):
  • 需要將動(dòng)態(tài)庫發(fā)布給用戶
  • 加載庫的時(shí)候速度較慢
  • gdb 調(diào)試

    • l 默認(rèn)展示包含main()的文件
    • l 文件名:行號(hào) 展示以行號(hào)為中心上下文件的內(nèi)容
    • l 文件名:函數(shù)名 展示文件中的函數(shù),輸入l繼續(xù)展示后面的內(nèi)容,然后后面再直接按回車,會(huì)繼續(xù)向下展示文件,一次展示10行
    • break 行號(hào)在某一行打斷點(diǎn)b 行號(hào)
    • b 行號(hào) if 條件條件斷點(diǎn),條件斷點(diǎn)只能設(shè)置在循環(huán)內(nèi)部,如果設(shè)置在邊界不會(huì)停止
    • b filename:行號(hào)在某個(gè)文件的某一行設(shè)置斷點(diǎn)
    • info break i b查看斷點(diǎn)信息
    • start gdb開始運(yùn)行程序,每次運(yùn)行一行,n單步調(diào)試,c繼續(xù)執(zhí)行到斷點(diǎn)
    • s下一步,會(huì)進(jìn)入函數(shù)體內(nèi)部(step)
    • n下一步,不會(huì)進(jìn)入函數(shù)內(nèi)部
    • run直接運(yùn)行到斷點(diǎn),如果沒有斷點(diǎn)直接運(yùn)行結(jié)束
    • p 變量 展示某個(gè)變量的值
    • ptype 變量 展示變量的類型
    • display 變量追蹤某個(gè)變量的值
    • undisplay 變量編號(hào)取消追蹤某個(gè)變量
    • info display 打印所有追蹤變量的信息
    • u將循環(huán)運(yùn)行結(jié)束,結(jié)束循環(huán)
    • finish 跳出當(dāng)前函數(shù),需要將函數(shù)中的斷點(diǎn)消除
    • d 斷點(diǎn)編號(hào)刪除斷點(diǎn)(del)
    • set var 變量=x直接運(yùn)行到變量為x的時(shí)候
    • quit退出gdb

    makefile

    makefile項(xiàng)目管理工具,用于管理源代碼

    簡單makefile文件

  • 命名規(guī)則
    (1) makefile
    (2) Makefile

  • 編寫規(guī)則
    makefile 一般情況下要和.c文件在一個(gè)文件夾中,如果不在需要絕對路徑
    三要素:

  • 目標(biāo):依賴 //目標(biāo)就是想要生成文件的名字 依賴:`.c`文件命令(必須要有Tab縮進(jìn)):gcc a.c b.c c.c -o 目標(biāo)
  • 使用
    make
  • 進(jìn)階makefile文件

    當(dāng)一些文件修改以后需要重新編譯,為了解決這個(gè)問題:
    例如:

    app:main.o add.o sub.o mul.o //終極目標(biāo),默認(rèn)第一條語句是終極目標(biāo)gcc main.o add.o sub.o mul.o -o app //如果依賴中的文件沒有發(fā)現(xiàn),就去下面的子目標(biāo)中查找有沒有相關(guān)的規(guī)則用于生成文件 main.o:main.c gcc main.c -c add.o:add.cgcc add.c -c sub.o:sub.cgcc sub.c -c mul.o:mul.cgcc mul.c -c

    上面的寫法會(huì)自動(dòng)查找文件是否修改,如果沒有修改就不會(huì)編譯,從而提高效率
    工作原理:通過比較修改時(shí)間,目標(biāo)應(yīng)該比依賴的修改時(shí)間遲,如果發(fā)現(xiàn)目標(biāo)比依賴的修改時(shí)間早則重新生成目標(biāo)。

    進(jìn)進(jìn)階makefile文件

    上面的寫法有些冗余,通過變量來將寫法變得簡潔

    obj=main.o add.o sub.o mul.o target=app $(target):$(obj) //$取obj變量中的值gcc $^ -o $@ //模式規(guī)則 %.o:%.cgcc -c $< -o &@

    makefile中的自動(dòng)變量:

    • $<規(guī)則中的第一個(gè)依賴
    • $@規(guī)則中的目標(biāo)
    • $^規(guī)則中的所有依賴
    • 只能夠在規(guī)則中的命令來使用
      makefile自己維護(hù)的變量:
    • 都是大寫,例如CC,CPPFLAGS,CFLAGS,LDFLAGS

    進(jìn)進(jìn)進(jìn)階makefile文件

    在makefile中的函數(shù)都是有返回值的

    • 獲取指定目錄下所有的.c文件
    src=$(wildcard 所需要查找的目錄/*.c)
    • 獲取指定目錄下所有的.o文件
    obj=$(patsubst ./%.c , ./%.o , $(src)) #模式匹配
    • 自動(dòng)刪除以前生成的目標(biāo)文件
    clean:rm $(target) -f #如果不存在也會(huì)強(qiáng)制刪除,不會(huì)彈出提示信息

    生成文件 時(shí)候:

    make clean #會(huì)刪除目標(biāo)文件,只會(huì)執(zhí)行生成clean的語句

    如果目錄中真的存在clean目標(biāo),則會(huì)提示目標(biāo)是最新的而不會(huì)運(yùn)行。

    .PHONY:clean #聲明clean為偽目標(biāo),不會(huì)與目錄中的目標(biāo)進(jìn)行比較

    在命令前面加上-,則命令執(zhí)行失敗以后也不會(huì)停下來,繼續(xù)向后執(zhí)行

    總結(jié)

    以上是生活随笔為你收集整理的Linux命令【三】gcc编译+静态库+动态库+makefile+gdb调试的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。