Make
Makefile
由 make
命令使用,make
命令可以指定參數,以確定要執行 makefile
中的哪個條目,如果不指定參數,則默認執行第一個條目。
編譯 main.cpp
的 Makefile
內容如下:
# 定義變量(變量名隨意,內容隨意),給後面的代碼使用
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.txt
由 cmake
命令使用,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