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