1. 程式人生 > >一次心血來潮的C程式編譯 && makefile

一次心血來潮的C程式編譯 && makefile

前言

想複習下資料結構,所以看了看相關的課程後打算手寫一些東西,比如連結串列或者說其他的常用資料結構。

環境

  • MacOSX
  • VSCode

本來打算在xcode上直接寫純C的程式的,但是寫了幾行就發現。。真雞兒麻煩啊,而且我xcode用的也不好,各種快捷鍵也不熟就被勸退了。然後看到公司同事(server)很多都在用VSCode,可能是因為大家都在用mac筆記本的原因裝visualstudio基本上就是扯淡,然後vscode也比較不錯就採用了這個ide。

前置條件

  • 安裝外掛 外掛安裝 其實也就是這三個c/c+ c/c++ Clang CodeRunner

  • 編譯環境配置

    1. vscode下:command+shift+p 調出控制中心 輸入Tasks: Configure Task 來配置任務在這裡插入圖片描述
    2. vscode除錯介面選中齒輪設定按鈕 選擇c/c++(也就是一開始我們安裝的那幾個外掛提供的)在這裡插入圖片描述 基本不需要改動就是program也就是執行程式裡我改成了alex也就是我的這個程式名,這個隨意。

以上就具備了在vscode下除錯c/c++程式的功能了

編寫程式碼

  • list.h 連結串列標頭檔案 宣告 結構體 以及幾個 連結串列操作方法在這裡插入圖片描述
  • list.c 連結串列普通操作方法的實現在這裡插入圖片描述
  • main.c 入口檔案 引入list.h在這裡插入圖片描述

問題暴露

要想執行一個c的程式必須經過 編譯+連結+執行 這三個階段至於每個階段都幹了什麼可以搜尋其他相關文文章。這裡我開始只是想簡單的編譯跑一下,那個時候我還沒有使用makefile的方式,而是命令列(配置在task中)截圖看下:在這裡插入圖片描述

這樣的方式,大家可以看到和我上面寫的command有個很大的不同,上面的是make的方式也就是採用makefile,這裡這個是直接命令列通過g++來進行編譯檔案,這個是我參考大佬們來學習的大佬文章地址 。很簡單,就是你當前焦點的檔案進行g++ 編譯 -g選項是為了debug除錯 -o是為了給生成的目標檔案重新命名。 在這樣的前提下,我就跑的我的程式,在main.c下按鍵command+shift+B來編譯程式在這裡插入圖片描述 可以看到報錯了,執行了task g++ xxxx -o xxx -g 下面為什麼報錯,因為insert也好display_list這些標記(方法)都不存在,為什麼?這就是我一開始犯錯的原因了。這個main.c 以來了list,但是我這裡編譯命令裡並沒有如何編譯以來的內容,所以造成了這個報錯現象。

解決方案MakeFile

發現了上面暴露的問題之後,我就開始搜尋相關的內容和文章來看如何把以來檔案也進行編譯。找到了幾篇相關的文章 linux+vsCode+makefile – 除錯C Makefile簡易教程 我這裡是根據第二篇文章進行學習的,第一篇文章給了我啟發。

MakeFile

一個普通的makefile

calc: main.c getch.c getop.c stack.c
	gcc -o calc main.c getch.c getop.c stack.c 

它主要分成了三個部分,第一行冒號之前的calc,我們稱之為目標(target),被認為是這條語句所要處理的物件,具體到這裡就是我們所要編譯的這個程式calc。冒號後面的部分(main.c getch.c getop.c stack.c),我們稱之為依賴關係表,也就是編譯calc所需要的檔案,這些檔案只要有一個發生了變化,就會觸發該語句的第三部分,我們稱其為命令部分,相信你也看得出這就是一條編譯命令。現在我們只要將上面這兩行語句寫入一個名為Makefile或者makefile的檔案,然後在終端中輸入make命令,就會看到它按照我們的設定去編譯程式了。 但是這個問題很多 ex: 沒能解決當我們只修改一個檔案時就要全部重新編譯的問題 ex: 如果我們需要往工程中新增一個.c或.h,可能同時就要再手動為obj常量再新增第一個.o檔案,如果這列表很長,程式碼會非常難看

一個最終的makefile

cc = gcc
prom = alex
deps = $(shell find ./ -name "*.h")
src = $(shell find ./ -name "*.c")
obj = $(src:%.c=%.o) 

$(prom): $(obj)
	$(cc) -o $(prom) $(obj)

%.o: %.c $(deps)
	$(cc) -g -c $< -o [email protected]

clean:
	rm -rf $(obj) $(prom)

這裡解釋一下makefile裡的特殊符號

  • %.o:%.c,這是一個模式規則,表示所有的.o目標都依賴於與它同名的.c檔案(當然還有deps中列出的標頭檔案)
  • $<代表的是依賴關係表中的第一項(如果我們想引用的是整個關係表,那麼就應該使用$^),具體到我們這裡就是%.c。
  • [email protected]代表的是當前語句的目標,即%.o。這樣一來,make命令就會自動將所有的.c原始檔編譯成同名的.o檔案。不用我們一項一項去指定了。
  • shell函式主要用於執行shell命令,具體到這裡就是找出當前目錄下所有的.c和.h檔案。
  • $(src:%.c=%.o)則是一個字元替換函式,它會將src所有的.c字串替換成.o,實際上就等於列出了所有.c檔案要編譯的結果

終於跑起來

按照makefile的方式編輯好後,在main.c下按鍵command+shift+B來編譯工程在這裡插入圖片描述 可以看到根據我們編寫的makefile逐步處理ex:我們編譯alex這個程式需要mian.c list.c … 這裡就會逐個編譯list.c->list.o 一次類推,最後生成我們的目標檔案-o alex 以來 xxx.o xx.o。 同樣因為我們在命令里加了-g所以可以在vscode裡進行除錯(反之我們去掉-g就不能除錯了)在這裡插入圖片描述