Make 和 CMake

Make

Makefilemake 命令使用,make 命令可以指定參數,以確定要執行 makefile 中的哪個條目,如果不指定參數,則默認執行第一個條目。

編譯 main.cppMakefile 內容如下:

# 定義變量(變量名隨意,內容隨意),給後面的代碼使用
IN = main.cpp
OUT = main.out
# 定義變量(使用 OUT 變量的內容作爲本變量的內容)
RM_FILES = $(OUT)

# entry 是第一個條目(名字隨意),所以單純執行 make 命令,會默認調用該條目
# 該條目依賴 usage 文件,如果 usage 文件不存在,則會調用 usage 條目
# 調用完 usage 條目後,該條目什麼也不做,直接退出 make 命令
entry: usage

# 如果執行 make run 命令,則會調用該條目
# 該條目依賴 $(OUT) 文件,也就是 main.out 文件,如果 main.out 文件不存在,則會調用 $(out) 條目
# 調用完 $(out) 條目後,會輸出橫線,然後執行 ./main.out 命令,然後再輸出橫線,然後退出 make 命令
# @ 表示不顯示所執行的命令,只顯示執行結果,就像 DOS 批處理中的 @ 符號一樣
run: $(OUT)
	@echo ------------------------------
	@./$(OUT)
	@echo ------------------------------

# 本條目的名稱就是 main.out,爲了修改方便,定義成了變量 OUT,本條目依賴 $(IN),也就是 main.cpp
# 如果 main.out 不存在,則執行這裏的命令,如果 main.out 存在,但日期比 main.cpp 舊,也會執行這裏的命令
# 如果 main.out 存在,且日期比它所依賴的所有文件都新,則執行該條目後,該條目什麼也不做。
$(OUT): $(IN)
	clang++ -g -O3 $(IN) -o $(OUT)

# 如果執行 make clean 命令,則會調用該條目
# 該條目沒有依賴,所以每次調用都會執行下面的命令
# 這裏執行的是 Linux 命令,先判斷 RM_FILES 變量中指定的各個文件是否存在,如果存在就將其刪除
clean:
	@for i in $(RM_FILES); do if [ -f $$i ]; then rm $$i; fi; done

# 如果執行 make usage 命令,則會調用該條目
# 該條目沒有依賴,所以每次調用都會執行下面的命令
# 這裏執行的是 Linux 命令,會向終端輸出一些文本,如果是 Windows 平臺,則不應該使用引號
usage:
	@echo "用法:"
	@echo "  make run    # 編譯並運行"
	@echo "  make clean  # 清理臨時文件和結果文件"

# 命令前面必須有一個製表符,不能用空格代替
# 註釋前面不能是製表符,否則會被當作命令執行

另一個 Makefile,可以在所有子目錄中執行 make clean

# 獲取當前目錄下的所有子目錄列表(目錄名以數字開頭)
SUBDIR = $(shell find . -maxdepth 1 -type d | grep ^\./[0-9])

# 默認不執行任何操作
all:

# 在所有子目錄中執行 make clean
clean: $(SUBDIR)
	@for i in $(SUBDIR); do echo $$i; make --no-print-directory clean -C $$i; echo ------------------------------; done

CMake

CMakeLists.txtcmake 命令使用,cmake 命令需要指定 CMakeLists.txt 文件的路徑或 CMakeLists.txt 文件所在的目錄。

執行 cmake 路徑 後,會根據 CMakeLists.txt 生成 Makefile 文件,再執行 make 命令纔會得到最終的編譯結果。

下面的 CMakeLists.txt 用於編譯 OpenGL 示例文件 main.cpp

# 要求 cmake 低版不能低於指定版本
cmake_minimum_required(VERSION 3.0)

# 添加 C++11 標準支持
#set(CMAKE_CXX_FLAGS "-std=c++11")

# 聲明一個 cmake 工程
# 一個工程可以生成多個目標文件
project(main)

# 設置頭文件的搜索目錄,可以有多個
include_directories(
    ${PROJECT_SOURCE_DIR}/../include
)

# 自定義變量 SRC,內容爲要編譯的文件列表
set(SRC 
    ${PROJECT_SOURCE_DIR}/main.cpp
    ${PROJECT_SOURCE_DIR}/../include/glad.c
)

# 添加一個“可執行的”編譯目標 main 及其依賴 ${SRC}
add_executable(main ${SRC})

# 添加 libglfw3.a 靜態鏈接庫文件(linux 環境)
add_library(glfw STATIC IMPORTED)
set_property(TARGET glfw PROPERTY IMPORTED_LOCATION ${PROJECT_SOURCE_DIR}/../lib/libglfw3.a)

# 指定 main 程序所要鏈接的庫文件
target_link_libraries(main glfw dl GL X11 pthread)

CMakeLists.txt 旁邊創建 run.sh 腳本文件,該腳本可以快速編譯並運行上面的 main.cpp 程序,內容如下:

#!/bin/sh

# 創建臨時目錄,進入臨時目錄
mkdir build
cd build
# 執行 CMake,調用上級目錄中的 CMakeLists.txt
# 會在本目錄生成 makefile
cmake ..
# 執行 makefile
make --no-print-directory
# 編譯後的可執行文件
./main

或者使用一個 makefile 來調用 cmake

run: build/main
# 編譯後的可執行文件
	@build/main

build/main: main.cpp
# 創建臨時目錄,進入臨時目錄
	@if [ ! -d "./build" ]; then mkdir ./build; fi
# 執行 CMake,調用上級目錄中的 CMakeLists.txt
# 會在本目錄生成 makefile
	@cd build; cmake ..
# 執行 makefile
	@cd build; make --no-print-directory

clean:
	@if [ -d "./build" ]; then rm -r ./build; fi
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章