iT邦幫忙

2025 iThome 鐵人賽

DAY 18
0
Software Development

30 天精通 C 語言建置與除錯:從 Makefile 到 CMake 跨平台實戰系列 第 18

[Day 18] [make → cmake] makefile在大型專案中的問題

  • 分享至 

  • xImage
  •  

makefile的缺點

可攜性差、容易綁平台

主要原因在於 makefile 容易被寫成 shell 指令字串的串接器,就是一旦把它當成跑 shell 指令的工具 的工具的話,他就會被 shell/OS語法或是版本的差異綁死。
雖然 [Day 13]有介紹到makefile強大的地方在於可以適應不同環境的編譯器,例如可以透過偵測環境的部分選擇要用clang 或是 gcc做編譯之類的,
不過這樣的話就會造成專案維護日益困難,例如:

  • GCC/Clang/VS 的旗標差很多;Windows(MinGW/MSYS/MSVC)常要分開來寫,而有些平台甚至語法差異極大
  • 其實就有點像是你要自己刻一個羅塞塔石碑一樣,除非是精通各種語言的高手,一般平常人其實很難去完成
  • 另外還有一點是makefile支援的編譯器版本越多,小改動都要驗三套以上情境,維護成本極高
  • 舉例說明: 可以看到各種編譯器其實語法差異就很大了,光是編譯就可以無限長的延伸....
CC   ?= cc
CXX  ?= c++
AR   ?= ar
RANLIB ?= ranlib

UNAME_S := $(shell uname -s 2>/dev/null || echo Unknown)

# 嘗試判斷 MSVC(最穩是讓使用者以環境變數帶入)
# 簡單法:若偵測到 cl.exe(Visual Studio 的編譯器)
MSVC := $(shell where cl 1>nul 2>nul && echo 1 || echo 0)

ifeq ($(MSVC),1)
  # MSVC 旗標
  CC   := cl
  CXX  := cl
  AR   := lib
  RANLIB := echo (msvc-no-ranlib)

  CFLAGS   := /nologo /W4 /EHsc /std:c11
  CXXFLAGS := /nologo /W4 /EHsc /std:c++17
  LDFLAGS  :=

  # 產物命名/路徑(Windows 用反斜線也要小心)
  EXE_EXT := .exe
else
  # GCC/Clang 旗標
  CFLAGS   := -std=c11   -Wall -Wextra -O2
  CXXFLAGS := -std=c++17 -Wall -Wextra -O2
  LDFLAGS  :=
  EXE_EXT  :=
endif

很容易產生 不完整相依圖

  • 若沒有系統性使用 -MMD -MP 產生 .d 檔並正確 -include標頭改了卻沒重編很常發生
  • [Day 14] 有介紹到的遞迴 make,雖然可以更有效的管理檔案間的編譯流程,分段建置make,但如果不注意 會常導致不完整相依圖:某些跨目錄的依賴沒被正確串起來,這樣重建行為就會有點像是未爆彈一樣不可預期。

工具鏈與功能偵測繁瑣

  • 另外就是不是每個編譯器都可以支援make裡面的 旗標或是函數符號,加上make自己本身也沒有一套很清楚的查詢工具,就會變成規則都要自己探詢,大量耗費時間且容易 出錯

外部函式庫管理不便

IDE/工具整合弱

  • 這個是 最重要且主要的原因,因為沒有相關的extension或是工具,所以makefile往往都要透過自己手刻的方式,這樣會大大降低撰寫的效率

不好模組化

  • 因為makefile 編譯流程往往是寫死的,所以如果要加上新的東西,就要常常想一套新的更有效的建置流程以防破壞原始的編譯流程,所以技術門檻偏高

而上面提到的問題往往Cmake就可以迎刃而解!!


上一篇
[Day 17][make] 用make編譯出靜態/動態檔
下一篇
[Day 19] [make→cmake] 用cmake補足makefile的限制
系列文
30 天精通 C 語言建置與除錯:從 Makefile 到 CMake 跨平台實戰23
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言