Cmake常用模板和makefile常用模板

1.Cmake常用模板

常用模板

/*
cmake版本
必选项。放在第一行,指定cmake最低版本。
*/
cmake_minimum_required(VERSION 3.10)  # 必须
/*
指定语言版本
这里其实是用set给默认变量CMAKE_CXX_STANDARD & CMAKE_C_STANDARD 赋值。
*/
set(CMAKE_CXX_STANDARD 14)	# C++14

/*
设置工程名字
这个应该可以必选项。工程名后面可选 加 语言类型。
指定的工程名,在后面可以通过变量${PROJECT_NAME}获取此值。
project(HelloWorld CXX)   # 可选指明是C++
project(HelloWorld C CXX) # C & C++
*/
project(HelloWorld)  #工程名

/*
指定头文件目录
include_directories后可以可以加SYSTEM标志,这个标志是告诉编译器将此目录视为系统目录,跳过某些编译检查。
一般不用加SYSTEM。
include_directories("../third-party/include/")
include_directories(SYSTEM "/usr/local/include/") # 可选SYSTEM

*/
include_directories("/usr/local/include/") # 头文件目录

/*
指定链接库目录
动态库或者静态目录

我查到了有两个函数link_libraries和target_link_libraries,这两者区别是 前者需放生成目标之前,后者放在生成目标之后。
link_libraries(pthread)   # 在add_executable前面
add_executable(${PROJECT_NAME} main.cpp)
或者
add_executable(${PROJECT_NAME} main.cpp)
target_link_libraries(${PROJECT_NAME} pthread) # 在add_executable后面,且第一参数为目标名。
Clion工程采用的是第一种方式。要是按照 编译-链接 的顺序,还是后者比较好理解。
*/
link_directories("/usr/local/lib/") # 链接库目录

/*
指明源码文件
可以用aux_source_directory(目录名 变量)来检索此目录下所有源文件。
或者使用FILE()函数检索。
aux_source_directory(. SRCS)          # 当前目录
aux_source_directory(../common/ SRCS)  # 上级目录

FILE(GLOB SRCS ${PROJECT_SOURCE_DIR}/*.cpp)  # 匹配源码目录所有.cpp文件
FILE(GLOB_RECURSE SRCS ${PROJECT_SOURCE_DIR}/*.cpp )  # 递归搜索匹配源码目录和其子目录下的.cpp文件
*/
aux_source_directory(. SRCS) # 源文件
aux_source_directory(./abc SRCS)

/*
生成可执行文件
add_executable(可执行文件名 源文件),源文件可以是变量形式,或者后面加了一串源文件名。
*/
add_executable(${PROJECT_NAME} ${SRCS}) # 生成可执行文件,这里程序名即为功能名

/*
见上
*/
target_link_libraries(${PROJECT_NAME} pthread) # 链接库

/*
一般开源项目需要安装的,都有make install命令,这个命令是通过install函数实现的。

安装的时候一般都需要指定安装路径,cmake里面通过设置CMAKE_INSTALL_PREFIX来实现的,可以在执行cmake的时候直接指定,
比如cmake .. -DCMAKE_INSTALL_PREFIX=./local,Linux环境默认是/usr/local目录。

# 安装动态库到lib目录
install(TARGETS ${PROJECT_NAME} LIBRARY DESTINATION lib)  # 安装在 /usr/local/lib目录
install(TARGETS ${PROJECT_NAME} ARCHIVE DESTINATION lib)  # 多用于静态库

# 安装对外头文件
install(TARGETS ${XXXX} PUBLIC_HEADER DESTINATION include)

*/
# 下面使用install作为项目打包使用
set(CMAKE_INSTALL_PREFIX ./dist)  # 自定义安装目录,打包使用
install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION bin) # 打包二进制文件,安装在 /usr/local/bin目录

set(CONFIGS ${PROJECT_SOURCE_DIR}/hello.cf) 
install(FILES ${CONFIGS} DESTINATION config) # # 安装其他文件,比如配置文件


===============其他==============
/*
多级目录多个工程
可以使用add_subdirectory编译子目录中的cmake工程。
*/
add_subdirectory(subdir)

/*
输出方式
message函数输出,可以指定输出消息类型STATUS WARNING DEBUG等。
*/
message("hello")
message(STATUS ${PROJECT_NAME})

/*
常见宏(默认变量)
*/
	宏					说明
PROJECT_NAME			project()设置的工程名
PROJECT_SOURCE_DIR		工程源码目录,例如 ~/Hello/
PROJECT_BINARY_DIR		生成文件目录,例如 ~/Hello/build

使用方法

  • cmake工程一般都不在源码目录直接编译,通常新建目录进行编译,配置失败可以直接删除新目录再重新配置。
    比如有个hello工程
cd hello
mkdir build
cd build
cmake ..
make

2.makefile常用模板

单文件项目

  • 假设有hello.c文件。
all: Hello
Hello:
	gcc -o Hello hello.c
clean:
	rm -rf Hello

====单文件项目进阶版(多文件)====
.PHONY:clean all
CC=gcc
CPP=g++
CFLAGS=-Wall -g
BIN=codedump_OSSPopLogque ip const_cpp:const_cpp
CFLAGS_MORE=-pthread
all:$(BIN)
%.o:%.c
       $(CC) $(CFLAGS) -c $< -o $@

%.o:%.cpp
        $(CPP) $(CFLAGS) -c $< -o $@

codedump_OSSPopLogque:codedump_OSSPopLogque.o
        $(CC) ${$(CFLAGS_MORE)} $^ -o $@
ip:ip.o
        $(CC) $(CFLAGS) $^ -o $@
const_cpp:const_cpp.o
        $(CPP) $(CFLAGS) $^ -o $@

clean:
        rm -f $(BIN) *.o

多文件项目

  • 假设一个工程下,有main.c和有多个.c源文件以及同名的.h头文件
# .PHONE伪目标,具体含义百度一下一大堆介绍
.PHONY:all clean

# 方便起见一般都会先定义编译器链接器
CC = gcc 
LD = gcc

# -I指定头文件目录
INCLUDE = -I./include
# -L指定库文件目录,-l指定静态库名字(去掉文件名中的lib前缀和.a后缀)
LIB = -L./libs -ltomcrypt
# 开启编译warning和设置优化等级
CFLAGS = -Wall -O2 -g

# 可执行文件的名字
TARGET = Hello

# 要生成的目标文件
all: $(TARGET)

#链接
# 第一行依赖关系:冒号后面为依赖的文件,相当于Hello: main.o a.o b.o
# 第二行规则:$@表示目标文件,$^表示所有依赖文件,$<表示第一个依赖文件
$(TARGET): $(OBJS)
	$(LD) $^ -o $@ $(LIB)

##下面两个等价
## 正则表达式表示目录下所有.c文件,相当于:SRCS = main.c a.c b.c
#SRCS = $(wildcard *.c)
## OBJS表示SRCS中把列表中的.c全部替换为.o,相当于:OBJS = main.o a.o b.o
#OBJS = $(patsubst %c, %o, $(SRCS))
## 上一句目标文件依赖一大堆.o文件,这句表示所有.o都由相应名字的.c文件自动生成
##编译
%.o:%.c
	$(CC) ${INCLUDE} $(CFLAGS) -c $< -o $@

# make clean删除所有.o和目标文件
clean:
	rm -f $(OBJS) $(TARGET)

多个文件,多个程序(建议使用单文件的进化版)

  • 把a.c/b.c/d.c都要编译成可执行文件a/b/c
C_SRC = $(wildcard *.c)
C_OBJ = $(patsubst %c, %o, $(C_SRC))
# 目标文件也是多个
TARGETLIST = $(patsubst %.c, %, $(C_SRC))

.PHONY:all clean
# 这句不写规则的语句可以自动把相应的a.c b.c编译成a b
all:${TARGETLIST}

clean:  
	rm -f ${TARGETLIST} *.o 

遍历执行子目录下的Makefile

  • 有这么个应用场景,当前目录下有多个子目录,且每个子目录下都有独立的Makefile文件,相当于目录下有多个独立的工程,现在需要执行make把各个子目录下的工程全部编译
  • 赋值符号,=基本赋值,:=覆盖之前的指,?=如果没有值则赋值,+=继续添加后面的值
.PHONY:all clean
# 排除目录
exclude_dirs := .git
# 显示深度为1的子目录
dirs := $(shell find . -type d -maxdepth 1)
# 去掉获取到目录名称前面的./
dirs := $(basename $(patsubst ./%, %, $(dirs)))
# 过滤指定目录
dirs := $(filter-out $(exclude_dirs), $(dirs))

all:
    $(foreach N,$(dirs),make -C $(N);)
clean:
    $(foreach N,$(dirs),make -C $(N) clean;)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

喜欢打篮球的普通人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值