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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

要学好 C 语言 / C++ ,Makefile 可少不了

發布時間:2024/4/14 c/c++ 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 要学好 C 语言 / C++ ,Makefile 可少不了 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、Makefile 簡介

1. Makefile 是什么?

Makefile 通常指的是一個含有一系列命令(directive)的,通過 Make 自動化編譯工具,幫助 C/C++ 程序實現自動編譯目標文件的文件。這個文件的默認命名是 “Makefile”。

2. 為什么要使用 Makefile?

Makefile 文件描述了整個工程的編譯、鏈接的規則。

為工程編寫 Makefile 的好處是能夠使用一行命令來完成“自動化編譯”。只需提供一個(通常對于一個工程來說會是多個)正確的 Makefile,接下來每次的編譯都只需要在終端輸入“make”命令,整個工程便會完全自動編譯,極大提高了效率。尤其是在編譯一個僅有一小部分文件被改動過的大項目的情況下。

絕大多數的 IDE 開發環境都會為用戶自動編寫 Makefile。

3. Make 是怎么工作的?

Make 工作的原則就是:

一個目標文件當且僅當在其依賴文件(dependencies)的更改時間戳比該目標文件的創建時間戳新時,這個目標文件才需要被重新編譯。

Make 工具會遍歷所有的依賴文件,并且把它們對應的目標文件進行更新。編譯的命令和這些目標文件及它們對應的依賴文件的關系則全部儲存在 Makefile 中。

Makefile 中也指定了應該如何創建,創建出怎么樣的目標文件和可執行文件等信息。

除此之外,你甚至還可以在 Makefile 中儲存一些你想調用的系統終端的命令,像一個 Shell 腳本一樣使用它。

二、簡單了解編譯連接與執行

1. 實驗介紹

按照 GNU make 官方手冊中采用的教學模式,在正式的學習 Makefile 知識之前,本次實驗先介紹一些簡單的前導知識。實驗詳細介紹了 GNU GCC 編譯和鏈接的基本方法,通過編譯、鏈接、靜態鏈接、動態鏈接的實驗內容讓用戶學習和理解 GCC 的基本使用方法。同時,用戶也將在實驗過程中體會到手動編譯鏈接的低效,從而體會到自動編譯的在項目工程管理中的重要性。

知識點

  • GCC 編譯的使用方式
  • GCC 鏈接的使用方式
  • GCC 靜態鏈接的使用方式
  • GCC 動態鏈接的使用方式
  • GCC 靜態鏈接 + 動態鏈接混用的方式

代碼獲取

通過在 Terminal 中輸入以下命令可以將本課程所涉及到的所有源代碼下載到在線環境中,作為參照對比進行學習。

wget http://labfile.oss.aliyuncs.com/courses/849/make_example-master.zip && unzip make_example-master.zip && rm make_example-master.zip

命令執行后 WebIDE 的工作區中將會出現一個名為 make_example-master 的文件夾,文件夾中包含了課程所涉及到的源代碼,目錄結構如圖所示:

2. 實驗步驟

本章節的源代碼位于 /home/project/make_example-master/chapter0 目錄中,請在 Terminal 中通過 cd 命令切換至該目錄后再進行實驗學習。

項目涉及到的代碼文件:
(1)main.c: 主要文件
(2)add_minus.c add_minus.h: 加減法 API 及實現
(3)multi_div.c multi_div.h: 乘除法 API 及實現

項目涉及到的 gcc 參數:

參數描述
-c編譯、匯編指定的源文件(也就是編譯源文件),但是不進行鏈接
-o用來指定輸出文件
-L為 gcc 增加一個搜索鏈接庫的目錄
-l用來指定程序要鏈接的庫

這一章節我們將正式開始進行簡易四則預算程序的編譯實驗,分步驟進行。

主程序的編譯、鏈接與執行

打開 chapter0 文件夾查看 main.c 文件,內容如下:

#include <stdio.h>int main(void) {printf("Hello Cacu!\n");return 0; }

點擊 chapter0 文件夾并右鍵選擇 Open in Terminal 在終端中打開 main.c 所在的文件夾。

在 Terminal 中執行以下命令,對 main.c 文件只編譯而不鏈接。

gcc -c main.c

可以發現在當前目錄中生成了一個新的文件 main.o。

通過 file 命令查看 main.o 的文件格式:

file main.o

輸出結果如圖所示:

這說明 main.o 實際上是一個 relocatable object 文件。

通過以下命令為 main.o 文件賦予可執行的權限:

chmod 777 main.o

chmod 命令用于改變文件的讀寫以及運行許可設置,詳細解紹參考 Permissions

輸入以下命令嘗試執行 main.o 文件:

./main.o

Terminal 輸出可執行文件格式錯誤,如圖所示:

說明 relocatable object 文件是不可執行的。

接下來通過 GCC 對 main.o 文件進行鏈接操作,從而生成一個可執行的程序 main。

在 Terminal 中輸入以下命令將 main.o 鏈接為 main 文件:

gcc -o main main.o

可以發現當前目錄新增了一個名為 main 的文件。

通過 file 命令查看 main 的文件格式:

file main

輸出結果如圖所示:

說明 main 文件是一個可執行的文件,于是通過以下命令來執行 main 文件:

./main

輸出結果如圖所示:

說明程序得到了正確的執行。

靜態鏈接

編寫 add_minus.h 文件,在文件中對函數 add() 和 minus() 進行聲明,不過在 chapter0 文件夾中已經提供編寫好的 add_minus.h 文件,我們可以拿來直接使用。

文件內容如下:

#ifndef __ADD_MINUS_H__ #define __ADD_MINUS_H__int add(int a, int b); int minus(int a, int b);#endif /*__ADD_MINUS_H__*

編寫 add_minus.c 文件,實現函數 add() 和 minus() ,同樣的在 chapter0 文件夾中已經有編寫好的 add_minus.c 文件,我們可以拿來直接使用。

文件內容如下:

#include "add_minus.h"int add(int a, int b) {return a+b; }int minus(int a, int b) {return a-b;

對 add_minus.c 文件進行編譯,生成 add_minus.o 文件。

gcc -c add_minus.c

修改 main.c 文件,為其增加加減法運算并編譯這個文件。

執行以下命令給 main.c 打上 v1.0.patch 補丁:

patch -p2 < v1.0.patch

patch 命令可以處理 diff 程序生成的補丁文件,補丁格式可以是四種比較格式中任意一種, 然后把這些差異融入到原始文件中,生成一個打過補丁的版本。-p 選項表示剝離層級,通過在 Terminal 中輸入 man patch 命令可獲取詳細說明。

此時 main.c 文件內容如下:

#include <stdio.h> #include "add_minus.h"int main(void) {int rst;printf("Hello Cacu!\n");rst = add(3,2);printf("3 + 2 = %d\n",rst);rst = minus(3,2);printf("3 - 2 = %d\n",rst);return

通過以下命令對 main.c 文件進行編譯和鏈接:

gcc -c main.c gcc -o main main.o

鏈接生成的 main.o 文件時,發現有錯誤出現,錯誤內容如圖所示:

原因在于鏈接過程中找不到 add 和 minus 這兩個 symbol。

現將 main.o 和 add_minus.o 鏈接成可執行文件并執行測試。

gcc -o main main.o add_minus.o

執行新生成的可執行文件 main。

./main

輸出結果如下:
說明程序得到了正常執行。

重新編譯 add_minus.c 生成 add_minus.o 文件。

gcc -c add_minus.c

通過 ar 命令將 add_minus.o 打包到靜態庫中。

ar rc libadd_minus.a add_minus.o

可以發現在當前目錄下,生成了一個名為 libadd_minus.a 的靜態庫文件。
用 file 命令查看 libadd_minus.a 的文件格式。

file libadd_minus.a

Terminal 輸出結果如圖所示:
實際上 libxxx.a 格式的文件可以簡單的看成指定的以 .o 結尾的文件集合。

鏈接 main.o 和靜態庫文件。

gcc -o main2 main.o -L./ -ladd_minus

-L./:表明庫文件位置在當前文件夾。
-ladd_minus:表示鏈接 libadd_minus.a 文件,使用 -l 參數時,前綴 lib 和后綴 .a 是需要省略的。

執行 main2:

./main2

Terminal 輸出結果如圖所示:
說明程序的到了正確的執行。

動態鏈接

編寫 multi_div.h 文件,并在其中對函數 multi() 和 div() 進行聲明。由于提供的源代碼中已經包含了編寫好的 multi_div.h 文件,因此我們可以拿來直接使用。

multi_div.h 文件的內容如下:

#ifndef __MULTI_DIV_H__ #define __MULTI_DIV_H__int multi(int a, int b); int div(int a, int b);#endif /*__MULTI_DIV_H__*

編寫 multi_div.c 文件,實現函數 multi() 和 div(),同樣的由于提供的源代碼中已包含了編寫好的 multi_div.c 文件,我們可以直接拿來使用。

multi_div.c 文件內容如下:

#include "multi_div.h"int multi(int a, int b) {return a*b; }int div(int a, int b) {return a/b;

通過以下命令將 multi_div.c 文件編譯成動態鏈接庫。

gcc multi_div.c -fPIC -shared -o libmulti_div.so

-fPIC 選項作用于編譯階段,在生成目標文件時就得使用該選項,以生成位置無關的代碼。

命令執行結束后,在當前目錄下會生成一個名為 libmulti_div.so 的文件。
通過 file 命令來查看 libmulti_div.so 的文件格式。

file libmulti_div.so

Terminal 輸出結果如圖所示:
由此可知 libmulti_div.so 是一個 shared object 文件。

刪除之前的 main.c 文件,并編寫新的 main.c 文件,內容如下:

#include <stdio.h>int main(void) {printf("Hello Cacu!\n");return 0; }

通過以下命令為 main.c 打上 v2.0.patch 補丁:

patch -p2 < v2.0.patch

此時 main.c 文件的內容如下:

#include <stdio.h> /* #include "add_minus.h" */ #include "multi_div.h"int main(void) {int rst;printf("Hello Cacu!\n"); /*rst = add(3,2);printf("3 + 2 = %d\n",rst);rst = minus(3,2);printf("3 - 2 = %d\n",rst); */rst = multi(3,2);printf("3 * 2 = %d\n",rst);rst = div(6,2);printf("6 / 2 = %d\n",rst);return

編譯 main.c 生成 main.o:

gcc -c main.c

鏈接 main.o 與動態鏈接庫文件。

gcc -o main3 main.o -L./ -lmulti_div

執行生成的 main3 文件。

./main3

輸出結果出現錯誤,如圖所示:
出現錯誤的原因是我們生成的動態庫 libmulti_div.so 并不在庫文件搜索路徑中。

解決辦法:

  • 將 libmulti_div.so 拷貝到 /lib/ 或 /usr/lib/ 文件夾下。
  • sudo cp libmulti_div.so /usr/lib
  • 在 LD_LIBRARY_PATH 變量中指定庫文件路徑,而動態鏈接庫文件存放在 /home/project/make_example-master/chapter0/ 路徑下。
  • 所以需要在 Terminal 中執行下面的命令:

    export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/project/make_example-master/chapter0/

    現在在 Terminal 中執行下面的命令:

    ./main3

    輸出結果如圖所示:
    說明程序得到了正確的執行。

    混合使用靜態鏈接與動態鏈接

    刪除舊的 main.c 文件,并編寫新的 main.c 文件,內容如下:

    #include <stdio.h>int main(void) {printf("Hello Cacu!\n");return 0; }

    為新的 main.c 文件打上 v3.0.patch 補丁。

    patch -p2 < v3.0.patch

    編譯 main.c 生成 main.o。

    gcc -c main.c

    測試執行混用靜態鏈接和動態鏈接的方式。

    gcc -o main4 main.o -L./ -ladd_minus -lmulti_div

    由于我們之前已經修改過 LD_LIBRARY_PATH 變量,所以此次無需再次修改。

    執行下面的命令:

    ./main4

    輸出結果如圖所示:
    說明程序得到正確的執行。

    盡管我們知道無論是靜態鏈接還是動態鏈接都能達到鏈接對象文件生成可執行文件的目的,但是我們還是得 z 注意靜態鏈接庫與動態鏈接庫之間的區別,詳細內容參考 Static, Shared Dynamic and Loadable Linux Libraries

    三、總結

    上述內容來自課程《Makefile 基礎入門實戰》,主要介紹了 GCC 編譯,鏈接的方法和靜態鏈接庫與動態鏈接庫的創建和使用方法。

    后續課程內容將學習以下內容:

    點擊《Makefile 基礎入門實戰》,即可可學習完整課程!

    總結

    以上是生活随笔為你收集整理的要学好 C 语言 / C++ ,Makefile 可少不了的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 精品国产一区二区三区久久 | 亚洲天堂av一区二区 | 日日爽爽 | 别揉我奶头啊嗯一区二区 | 波多野结衣1区2区3区 | 在线成人影视 | 一本色道久久88加勒比—综合 | 久久久av电影 | 国产一二区视频 | 国产精品国语对白 | 亚洲天堂三级 | 成人h在线| 天天射日 | 久久精品超碰 | 国产视频一区二区 | 久热精品在线 | 日韩欧美在线观看 | 国产一区二区三区四区在线观看 | 麻豆国产精品视频 | 337p亚洲精品色噜噜狠狠 | 亚洲经典在线观看 | 福利亚洲| 成人18视频免费69 | 亚洲一区二区不卡在线观看 | 夜夜爽爽 | 特黄1级潘金莲 | 欧美成人精品在线视频 | 视频一区在线观看 | 亚洲成人中文字幕 | 欧洲性生活片 | 毛片视屏 | 国产一国产精品一级毛片 | 老熟女重囗味hdxx69 | www.黄色网址.com | 最新国产精品视频 | 一区二区三区四区不卡 | 最新国产拍偷乱偷精品 | 夜夜操夜夜骑 | 熟女视频一区二区三区 | 成人性毛片 | 男人网站在线观看 | 欧美日韩不卡一区 | 香港av在线| 视频在线免费观看 | 五月婷婷激情综合网 | 中文在线观看免费高清 | www.亚洲综合 | 日韩av手机在线 | 91国内精品久久久久 | 人妻少妇精品无码专区二区 | 欧美日韩午夜激情 | 色婷婷久久一区二区三区麻豆 | 麻豆成人精品 | 综合国产精品 | 中文字幕亚洲乱码熟女1区2区 | 国产高清一级 | 蜜桃精品视频在线 | 欧美性受xxx黑人xyx性爽 | 国产中文字幕精品 | 午夜精品久久久久久久99热浪潮 | 天天操天天操天天干 | 黄色网页在线观看 | 亚洲色图另类 | 中文字幕人妻丝袜乱一区三区 | 国内视频一区二区三区 | 黄色不卡 | 美女视屏 | 亚洲成人精品在线观看 | 9久9久9久女女女九九九一九 | 亚洲精品久久久久久久久久 | 久久99免费| 国产精品国产三级国产专播精品人 | 黄色小视频链接 | 一级视频毛片 | 亚洲成人一区二区三区 | 亚洲精品影院在线 | 国产精品一区二区免费在线观看 | 国产成人精品一区二区三 | 国产一区精品视频 | 香蕉视频在线网站 | 亚洲美女色视频 | 黄在线免费看 | av导航网址 | 乳色吐息在线观看 | h视频在线看| 日韩国产欧美精品 | 中文字幕精品在线观看 | 99久久99久久精品国产片果冰 | 国产精品久久久久久久久动漫 | 岛国伊人 | 国产乱色| 中文字幕一区二区人妻痴汉电车 | 日韩综合在线 | 六月激情综合网 | 黄网免费视频 | 欧美激情综合 | 亚洲色图36p | 在线播放小视频 | 亚洲另类自拍 |