1.4.1 makefile,cmake

小李小李快乐不已 2025-01-10 17:20:46

目录

  • 1.4.1 makefile,cmake
  • 1. makefile
  • 1. 简单makefile
  • 1. 变量赋值
  • 2. 规则(Rule)
  • 3. 特殊变量
  • 4. 伪目标(Phony Targets)
  • 6. 导入外部 Makefile
  • 2. makefile工作原理
  • 1. make 的工作流程
  • 3. 例子
  • 1.
  • 2.
  • 4. 安装
  • 2. cmake
  • 1. 安装
  • 2. 使用
  • 1. CMakeLists.txt,这个文件是 cmake 的构建定义文件,文件名是大小写相关的,如果工程存在多个目录,需要确保每个要管理的目录都存在一个CMakeLists.txt
  • 2. 基本语法规则
  • 3. 常用指令
  • 4. 内部构建和外部构建
  • 3. 示例
  • 1. 单个目标文件
  • 2. 多个目录
  • 加载所有的源码,和makefile wildcard类似
  • SET(DIR_SRCS dir1.c dir12.c)
  • 默认是静态库
  • ADD_LIBRARY (dir1 ${DIR_SRCS})
  • 单个目录实现
  • CMake 最低版本号要求
  • 工程
  • 手动加入文件
  • 添加头文件路径
  • 相对路径的方式
  • 添加 dir1 子目录
  • 添加头文件路径
  • 添加 dir2 子目录
  • 将执行文件安装到bin目录
  • 3. 动态库,静态库,调用
  • 项目名称和支持的语言
  • 设置 C++ 标准
  • 添加 lib1 和 lib2 子目录
  • 添加可执行文件,main.cpp 是根目录下的源文件
  • 链接静态库 lib1 和动态库 lib2 到最终可执行文件
  • 4. 设置执行目录,并为 ZLToolKit 工程创建 Debug 和 Release 版本的构建配置

1.4.1 makefile,cmake

1. makefile

1. 简单makefile

三要素:目标,依赖,命令

1. 变量赋值

=:普通赋值,用于设置变量。
:=:立即展开赋值,表示变量的值在赋值时立即被计算。
?=:仅当变量未定义时才赋值。
+=:在变量的现有值后追加内容。

CC = gcc
CFLAGS = -Wall
SRC = main.c utils.c
OBJ = $(SRC:.c=.o)

2. 规则(Rule)

  1. 规则格式:
    target: dependencies
     command
    
    target:目标文件,通常是你想要生成的文件(如 .o 或可执行文件)。
    dependencies:依赖文件,表示生成目标所需的文件或其他目标。
    command:用于生成目标的命令。
  2. 例子
    myprogram: main.o utils.o
     gcc -o myprogram main.o utils.o
    

    3. 特殊变量

    $@:表示当前规则中的目标文件。
    $<:表示第一个依赖文件(通常是源文件)。
    $^:表示所有依赖文件的列表,去除重复项。
    $?:表示所有比目标文件新的依赖文件。
    %.o: %.c
     gcc -c $< -o $@
    

    4. 伪目标(Phony Targets)

    伪目标是没有实际文件名的目标,通常用于清理或强制执行某些任务。
    ```makefile
    .PHONY: clean all

all: myprogram

clean:
rm -f *.o myprogram

#### 5. 条件判断
Makefile 支持条件判断,以决定是否执行某些部分。

- ifeq / ifneq:条件判断,判断两个值是否相等或不相等。
- ifdef / ifndef:判断某个变量是否已定义。
```makefile
ifeq ($(CC),gcc)
    CFLAGS += -O2
else
    CFLAGS += -O0
endif

#1. ifeq ($(CC),gcc)
#这个条件判断检查变量 CC 是否等于 gcc,也就是判断使用的编译器是否是 gcc(GNU 编译器)。#如果 CC 的值是 gcc,则执行 ifeq 语句中的代码块,否则执行 else 语句中的代码。
#2. CFLAGS += -O2
#如果编译器是 gcc,就给 CFLAGS 变量添加 -O2 编译选项。-O2 是 GCC 的优化选项,它启用中
#等级别的优化,在编译过程中提高程序的执行效率,但不会过度增加编译时间。
#3. CFLAGS += -O0
#如果编译器不是 gcc,则给 CFLAGS 变量添加 -O0 编译选项。-O0 表示禁用所有优化,通常在调#试阶段使用,这样可以避免优化对调试过程的干扰
  1. 循环
    Makefile 支持简单的循环结构,通常用于批量处理文件。
objects = main.o utils.o
all: $(objects)
    gcc -o myprogram $(objects)

6. 导入外部 Makefile

你可以在 Makefile 中使用 include 来导入外部的 Makefile 或配置文件。

include config.mk

2. makefile工作原理

1. make 的工作流程

make 根据以下步骤处理 Makefile:

  1. 读取 Makefile: make 读取当前目录下的 Makefile(或者通过 -f 选项指定其他文件)。Makefile 描述了所有的目标、依赖关系和命令。
  2. 检查目标的更新时间: make 会查看目标文件的修改时间,如果目标文件不存在或其依赖文件比目标文件更新,make 就会执行相应的命令来重新构建目标。
  3. 执行命令: 如果目标的依赖文件发生了变化,make 就会执行相应的命令(如编译或链接),并生成或更新目标文件。
  4. 递归处理依赖关系: make 会递归地检查每个依赖项的更新情况。如果某个依赖项本身也有依赖项,make 会继续检查这些依赖项,直到所有需要更新的目标文件都被重新生成。依赖从左到右依次编译

3. 例子

1.

.PHONY: clean
#.PHONY 是一个特殊的目标,表示 clean 不是一个文件名,而是一个伪目标。
#即使有一个名为 clean 的文件,Make 也会执行这个规则而不是认为它是一个过期的目标。
CC = gcc
RM = rm
EXE = simple
# 上述都是定义变量
#SRCS = main.c foo.c
SRCS = $(wildcard *.c)
#使用 wildcard 函数来列出当前目录下所有的 .c 文件。这个变量 SRCS 包含所有源文件名(例如:main.c, foo.c)。
# 把.c换成对应的.o
#OBJS = foo.o foo2.o main.o
OBJS = $(patsubst %.c,%.o,$(SRCS))

$(EXE): $(OBJS)
    $(CC) -o $@ $^
#这是链接命令,使用 gcc 编译器将目标文件 $(OBJS) 链接成最终的可执行文件。
#$@ 代表规则的目标,这里是 $(EXE)(即 simple)。
#$^ 代表规则的所有依赖文件,这里是 $(OBJS)(即所有的 .o 文件)
%.o: %.c
    $(CC) -o $@ -c $^
clean:
    $(RM) $(EXE) $(OBJS)
src: # 测试make src显示相应的xx.c
    @echo $(SRCS)
objs:# 测试make objs显示相应的xx.o
    @echo $(OBJS)

2.

CROSS =
#这里定义了一个名为 CROSS 的变量,但它为空。
#通常,这个变量用于交叉编译(cross-compilation)。例如,如果你需要为不同的架构(比如 ARM、x86、MIPS 等)编译程序,你可以设置 CROSS 为相应的编译前缀,如 arm-linux- 或 x86_64-。
#CROSS 为空,意味着默认使用系统的 gcc 和 g++ 编译器。
# 定义CC为gcc编译
CC = $(CROSS)gcc  
# 定义CXX为g++编译    
CXX = $(CROSS)g++     
# 定义DEBUG 方式为 -g -O2
DEBUG = -g -O2        
CFLAGS = $(DEBUG) -Wall -c
RM = rm -rf

# /定义SRC为当前工程目录下所有的.cpp文件
SRCS = $(wildcard ./*.c)   
# 定义OBJS为SRCS对应的.o文件
OBJS = $(patsubst %.c, %.o, $(SRCS))    
# 定义HEADER_PATH为当前工程中的头文件路径
#-I 是 gcc 和 g++ 编译器的一个选项,用来指定 头文件的搜索路径。
HEADER_PATH = -I ./include/   
# 定义LIB_PATH为当前工程中的头文件路径 
#-L 是 gcc 和 g++ 编译器的一个选项,用来指定 库文件的搜索路径。
LIB_PATH = -L ./lib/        
# 输出当前LIB_PATH中的内容   
#$(warning ...) 是 make 的一个内置函数,用来在执行 make 时输出警告信息。
$(warning LIB_PATH)         
# 制定LIBS链接库的名称 
#用于指定 链接的库。
#-lpthread 是 gcc 和 g++ 的一个选项,用于链接 pthread 库,它提供了多线程相关的功能。
#-l 是一个链接选项,用来指定一个库,pthread 是要链接的库的名称(通常在 Linux 上会是 libpthread.so 或 libpthread.a)。
#作用:在链接阶段,gcc 会链接 pthread 库,允许程序使用多线程功能。
LIBS=-lpthread                 
# lib中的库文件名称为libpthread.so

# 定义当前生成的版本
VERSION = 1.0.0        
# 定义生成可执行文件的名称       
TARGET = simple.$(VERSION)       

$(TARGET) : $(OBJS)
# 告诉编译器生成可执行文件时库存放的目录,以及库的名字
    $(CXX) $^ -o $@ $(LIB_PATH) $(LIBS)    
#表示如何从源文件 .c 生成目标文件 .o。它意味着:对于每个 .c 文件,都会生成一个对应的 .o 文件。
$(OBJS):%.o : %.c
#告诉编译器生成中间文件时头文件的所在目录
    $(CXX) $(CFLAGS) $< -o $@ $(HEADER_PATH)  
clean:  
    $(RM) $(TARGET) *.o 

4. 安装

在 Linux 系统中,Makefile 是用于自动化构建过程的脚本。它并不需要单独的“安装”,因为 Makefile 本身是一个文本文件,而 make 是一个工具,通常已经预安装在大多数 Linux 发行版中。

  1. 安装 make 工具
    在 Debian/Ubuntu 系统中
    使用以下命令来安装 make 工具:
    sudo apt update
    sudo apt install make
    
  2. 验证安装
    安装完成后,可以通过以下命令检查 make 是否正确安装:
    make --version
    如果成功安装,你将看到类似以下输出:
    GNU Make 4.3

2. cmake

cmake基于makefile二次开发,难度较小

1. 安装

  1. 卸载已安装版本
    apt-get autoremove cmake
  2. 文件下载
    wget https://cmake.org/files/v3.21/cmake-3.21.3-linux-x86_64.tar.gz
  3. 解压
    tar zxvf cmake-3.21.3-linux-x86_64.tar.gz
  4. 软连接
    mv cmake-3.21.3-Linux-x86_64 /opt/cmake-3.21.3
    ln -sf /opt/cmake-3.21.3/bin/* /usr/bin/

2. 使用

1. CMakeLists.txt,这个文件是 cmake 的构建定义文件,文件名是大小写相关的,如果工程存在多个目录,需要确保每个要管理的目录都存在一个CMakeLists.txt

2. 基本语法规则

  1. 注释:使用 # 表示注释。

    # 这是一个注释
    
  2. 命令调用:CMake 命令不区分大小写,但通常使用小写。

    command(arg1 arg2 ...)
    
  3. 变量:使用 ${} 来引用变量。

    set(MY_VAR "Hello")
    message(${MY_VAR})  # 输出 Hello
    
  4. 变量使用和取值
    定义变量:使用 set() 命令定义变量。

    set(MY_VAR "Hello World")
    

    set( [CACHE [FORCE]])
    :变量名。
    :变量的值。
    CACHE:将变量存储在 CMake 缓存中,使其在多次运行 CMake 时保持不变。
    :变量的类型,常见类型包括 STRING、BOOL、PATH 等。
    :变量的描述信息。
    FORCE:强制覆盖缓存中的变量值(如果变量已存在)。

  5. 引用变量:使用 ${} 引用变量。

    message(${MY_VAR})  # 输出 Hello World
    
  6. 环境变量:使用 $ENV{} 引用环境变量。

    message($ENV{HOME})  # 输出当前用户的主目录
    

    3. 常用指令

  7. project():定义项目名称和版本。

    project(MyProject VERSION 1.0)
    
  8. message():打印消息。

    message("This is a message")
    

    MESSAGE([] "message text")
    :指定消息的类型,常见的模式有:
    STATUS:输出状态信息(通常以 -- 开头)。
    WARNING:输出警告信息。
    FATAL_ERROR:输出错误信息并停止 CMake 的执行。
    DEBUG:输出调试信息(仅在调试模式下可见)。
    "message text":要输出的消息内容。

  9. add_executable():定义可执行文件。

    add_executable(my_app main.cpp)
    
  10. add_library():定义库(静态库或动态库)。

    add_library(my_lib STATIC lib.cpp)  # 静态库
    add_library(my_lib SHARED lib.cpp)  # 动态库
    
  11. target_link_libraries():链接库到目标。

    target_link_libraries(my_app my_lib)
    
  12. 清理工具

    • 清理构建文件:CMake 生成的构建文件可以通过以下方式清理:
    • 删除 build 目录(如果使用外部构建)。就是创建一个build目录,然后在里面cmake ..去编译上一级目录,生成的乱七八糟会在build里面,直接删文件夹就行
    • 使用 make clean(如果使用 Makefile 生成器)。
    • 使用 cmake --build . --clean-first。

4. 内部构建和外部构建

  1. 内部构建:在源代码目录中直接构建。
cmake .
make
  1. 外部构建:在单独的目录中构建(推荐)。
    mkdir build
    cd build
    cmake ..
    make
    

3. 示例

1. 单个目标文件

# CMake 最低版本号要求
cmake_minimum_required (VERSION 2.8)
# 工程,他不是执行文件名
PROJECT(HIT)
# 手动加入文件 ${变量名}} ,比如${SRC_LIST}
SET(SRC_LIST main.c)
set(SRC_LIST2 main2.c)# 关键字无所谓大小写
# MESSAGE和echo类似 
MESSAGE(STATUS "PROJECT_BINARY_DIR DIR " ${PROJECT_BINARY_DIR})
# 输出类似:-- PROJECT_BINARY_DIR DIR /path/to/build/directory
MESSAGE(STATUS "PROJECT_SOURCE_DIR DIR " ${PROJECT_SOURCE_DIR})

# 生产执行文件名0voice  0voice2
ADD_EXECUTABLE(0voice ${SRC_LIST})
ADD_EXECUTABLE(0voice2 ${SRC_LIST2})


#ADD_SUBDIRECTORY 命令用于将一个子目录(如 src)添加到当前项目中,并使该子目录中的 CMakeLists.txt 文件被处理。这意味着,CMake 会递归地进入 src 子目录,执行该子目录中的 CMake 配置文件,并生成相关的构建文件(如 Makefile 或 Visual Studio 项目文件)。
# 添加子目录
ADD_SUBDIRECTORY(src)

#INSTALL(FILES COPYRIGHT README DESTINATION share/doc/cmake/0voice)
# 安装doc到  share/doc/cmake/0voice目录
# 默认/usr/local/
#指定自定义目录,比如 cmake -DCMAKE_INSTALL_PREFIX=/tmp/usr ..
INSTALL(DIRECTORY doc/ DESTINATION share/doc/cmake/0voice)
#这条命令会将 doc/ 目录及其内容安装到 share/doc/cmake/0voice 目录下。
#DIRECTORY:用于指定要安装的目录(doc/)。
#DESTINATION:指定安装的目标目录(share/doc/cmake/0voice)
#这种方式非常适合需要跨平台和模块化管理的项目,尤其是当你需要在多个目录下组织代码或将项目安装到指定位置时

2. 多个目录

将子目录编译成库文件,然后再给到上一级进行链接

HIT/                         # 项目的根目录
├── CMakeLists.txt               # 项目的 CMake 配置文件
├── src/                         # 存放源代码的子目录
│   ├── CMakeLists.txt           # src 子目录的 CMake 配置文件
│   ├── dir1/                    # 子目录 1
│   │   ├── CMakeLists.txt       # dir1 的 CMake 配置文件
│   │   └── dir1.c               # dir1 子目录中的源文件
│   └── dir2/                    # 子目录 2
│       ├── CMakeLists.txt       # dir2 的 CMake 配置文件
│       └── dir2.c               # dir2 子目录中的源文件
└── doc/                         # 文档文件夹
    ├── README.md                # 项目的文档
    └── COPYRIGHT                # 项目的版权信息
  1. dir1中CMakeLists.txt
    ```makefile

    加载所有的源码,和makefile wildcard类似

    AUX_SOURCE_DIRECTORY(. DIR_SRCS)
    #AUX_SOURCE_DIRECTORY 是一个特殊的 CMake 命令,用于在指定目录中查找所有源代码文件(如 .c 或 .cpp 文件),并将它们添加到 DIR_SRCS 变量中。DIR_SRCS 将包含当前目录下的所有源代码文件。
    #在此示例中,DIR_SRCS 将包含 src/dir1 或 src/dir2 目录下的所有源文件。

SET(DIR_SRCS dir1.c dir12.c)

默认是静态库

ADD_LIBRARY (dir1 SHARED ${DIR_SRCS})

ADD_LIBRARY (dir1 ${DIR_SRCS})


2. dir2中CMakeLists.txt
```makefile
AUX_SOURCE_DIRECTORY(. DIR_SRCS)
ADD_LIBRARY(dir2 ${DIR_SRCS})
#同上
  1. src中的CMakeLists.txt
    ```makefile

    单个目录实现

    CMake 最低版本号要求

    cmake_minimum_required (VERSION 2.8)

    工程

    PROJECT(HIT)

    手动加入文件

    SET(SRC_LIST main.c)
    MESSAGE(STATUS "THIS IS BINARY DIR " ${PROJECT_BINARY_DIR})
    #PROJECT_BINARY_DIR 是 CMake 内置的变量,表示二进制文件(即构建文件)所在的路径。
    MESSAGE(STATUS "THIS IS SOURCE DIR " ${PROJECT_SOURCE_DIR})
    #PROJECT_SOURCE_DIR 是 CMake 内置的变量,表示源代码目录的路径。

添加头文件路径

#CMAKE_CURRENT_SOURCE_DIR 是 CMake 内置的变量,表示当前 CMake 配置文件所在的目录。
INCLUDE_DIRECTORIES("${CMAKE_CURRENT_SOURCE_DIR}/dir1")

相对路径的方式

INCLUDE_DIRECTORIES(dir1)
MESSAGE(STATUS "CMAKE_CURRENT_SOURCE_DIR -> " ${CMAKE_CURRENT_SOURCE_DIR})

添加 dir1 子目录

ADD_SUBDIRECTORY("${CMAKE_CURRENT_SOURCE_DIR}/dir1")

添加头文件路径

INCLUDE_DIRECTORIES("${CMAKE_CURRENT_SOURCE_DIR}/dir2")

添加 dir2 子目录

ADD_SUBDIRECTORY("${CMAKE_CURRENT_SOURCE_DIR}/dir2")

ADD_EXECUTABLE(li ${SRC_LIST} )# 创建一个可执行文件li
TARGET_LINK_LIBRARIES(li dir1 dir2)
#将库文件链接到可执行文件。此处将 dir1 和 dir2 库链接到 li可执行文件。这样,lili就可以使用 dir1 和 dir2 中定义的函数和符号。

将执行文件安装到bin目录

INSTALL(TARGETS li RUNTIME DESTINATION bin)


4. 整体CMakeLists.txt
```makefile
# CMake 最低版本号要求
cmake_minimum_required (VERSION 2.8)
PROJECT(0VOICE)

ADD_SUBDIRECTORY(src)
# FILES代表文件
# DIRECTORY 代表目录
# INSTALL(FILES  README.md COPYRIGHT DESTINATION share/doc/cmake/0voice)
INSTALL(DIRECTORY doc/ DESTINATION share/doc/cmake/0voice)

3. 动态库,静态库,调用

  1. 项目目录结构
    MyProject/
    ├── CMakeLists.txt            # 根目录 CMake 配置文件
    ├── lib1/                     # 第一个子目录,生成静态库
    │   ├── CMakeLists.txt        # lib1 子目录的 CMake 配置文件
    │   └── lib1.cpp              # lib1 的源文件
    ├── lib2/                     # 第二个子目录,生成动态库
    │   ├── CMakeLists.txt        # lib2 子目录的 CMake 配置文件
    │   └── lib2.cpp              # lib2 的源文件
    └── main.cpp                  # 主源文件,链接到 lib1 和 lib2
    
  2. 根目录 CMakeLists.txt
    根目录的 CMakeLists.txt 文件负责设置基本的 CMake 配置,添加子目录,并定义最终的可执行文件。
    ```makefile
    cmake_minimum_required(VERSION 3.10)

项目名称和支持的语言

project(MyProject)

设置 C++ 标准

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED TRUE)

添加 lib1 和 lib2 子目录

add_subdirectory(lib1)
add_subdirectory(lib2)

添加可执行文件,main.cpp 是根目录下的源文件

add_executable(my_app main.cpp)

链接静态库 lib1 和动态库 lib2 到最终可执行文件

target_link_libraries(my_app PRIVATE lib1 lib2)

3. lib1/CMakeLists.txt (生成静态库)
在 lib1 目录中,创建一个静态库(lib1.a)。

```makefile
# lib1 的 CMake 配置文件

# 查找 lib1 目录下的所有源文件
set(LIB1_SRC lib1.cpp)

# 创建静态库 lib1
add_library(lib1 STATIC ${LIB1_SRC})

# 如果有头文件目录需要添加,可以在这里使用 INCLUDE_DIRECTORIES
# 例如:INCLUDE_DIRECTORIES("${CMAKE_CURRENT_SOURCE_DIR}/include")
  1. lib2/CMakeLists.txt (生成动态库)
    在 lib2 目录中,创建一个动态库(lib2.so 或 lib2.dll)。
# lib2 的 CMake 配置文件

# 查找 lib2 目录下的所有源文件
set(LIB2_SRC lib2.cpp)

# 创建动态库 lib2
add_library(lib2 SHARED ${LIB2_SRC})

# 如果有头文件目录需要添加,可以在这里使用 INCLUDE_DIRECTORIES
# 例如:INCLUDE_DIRECTORIES("${CMAKE_CURRENT_SOURCE_DIR}/include")
  1. main.cpp (主程序)
    这是项目的主源文件,使用 lib1 静态库和 lib2 动态库。
#include <iostream>
#include "lib1.h"  // 假设 lib1 提供了一个 lib1.h 头文件
#include "lib2.h"  // 假设 lib2 提供了一个 lib2.h 头文件

int main() {
    std::cout << "Hello from main!" << std::endl;
    
    // 使用 lib1 和 lib2 中的函数
    lib1_function();
    lib2_function();

    return 0;
}

4. 设置执行目录,并为 ZLToolKit 工程创建 Debug 和 Release 版本的构建配置

  1. 项目结构
    假设项目结构如下:
    ZLToolKit/
    ├── CMakeLists.txt               # 根目录 CMake 配置文件
    ├── src/                         # 源代码目录
    │   ├── CMakeLists.txt           # src 子目录的 CMake 配置文件
    │   ├── lib1.cpp                 # lib1 的源文件
    │   ├── lib2.cpp                 # lib2 的源文件
    │   └── main.cpp                 # 主程序
    └── build/                       # 用于构建的目录(运行 CMake 和 make 时生成)
    
  2. 根目录 CMakeLists.txt
    在根目录的 CMakeLists.txt 文件中,我们会设置工程的基本配置,处理不同的构建类型(Debug 和 Release),并设置执行文件的输出路径。
cmake_minimum_required(VERSION 3.10)

# 设置项目名称
project(ZLToolKit)

# 设置 C++ 标准
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED TRUE)

# 设置调试debug和发布release版本的输出目录
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}/debug_bin)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}/release_bin)

# 添加 src 子目录
add_subdirectory(src)

# 设置构建类型:如果没有指定,默认是 "Release"
if(NOT CMAKE_BUILD_TYPE)
    set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type" FORCE)
endif()

# 打印出当前的构建类型
message(STATUS "Build type: ${CMAKE_BUILD_TYPE}")
  1. src/CMakeLists.txt
    src/CMakeLists.txt 文件将会处理源代码的编译,并生成最终的可执行文件或库。
# src 子目录的 CMake 配置文件

# 设置源文件
set(SRC_LIST main.cpp lib1.cpp lib2.cpp)

# 创建可执行文件
add_executable(ZLToolKitApp ${SRC_LIST})

# 设置调试和发布版本的编译选项
target_compile_options(ZLToolKitApp PRIVATE 
    "$<$<CONFIG:Debug>:-g>"
    "$<$<CONFIG:Release>:-O3>"
)
#target_compile_options 用于指定目标(ZLToolKitApp)的编译选项。PRIVATE 表示这些编译选项只对目标 ZLToolKitApp 有效。
#$<$<CONFIG:Debug>:-g>:这表示如果构建类型是 Debug,则编译时添加 -g 选项,通常用于生成调试符号。
#$<$<CONFIG:Release>:-O3>:这表示如果构建类型是 Release,则编译时添加 -O3 选项,通常用于优化代码(更高的优化级别)。
#target_compile_options 是通过 generator expressions 来动态选择不同的编译选项。$<$<CONFIG:Debug>:-g> 是 CMake 的条件语法,意思是,如果当前构建类型是 Debug,则使用 -g 选项。

# 设置 CMake 自动选择链接库和头文件
target_include_directories(ZLToolKitApp PRIVATE ${CMAKE_SOURCE_DIR}/include)

# 根据构建类型设置不同的链接库
target_link_libraries(ZLToolKitApp PRIVATE 
    "$<$<CONFIG:Debug>:/path/to/debug/lib>"
    "$<$<CONFIG:Release>:/path/to/release/lib>"
)
  1. src/main.cpp
    这是项目的主源文件,它会调用 lib1 和 lib2 中的功能。
#include <iostream>
#include "lib1.h"  // 假设 lib1 提供了一个 lib1.h 头文件
#include "lib2.h"  // 假设 lib2 提供了一个 lib2.h 头文件

int main() {
    std::cout << "Hello from ZLToolKit!" << std::endl;
    
    // 使用 lib1 和 lib2 中的函数
    lib1_function();
    lib2_function();

    return 0;
}
  1. 构建
  • 首先在根目录创建一个构建目录,并切换到该目录:

    mkdir build
    cd build
    
  • 生成构建文件
    运行 CMake 配置命令:

    cmake ..
    

    这时 CMake 会根据 CMakeLists.txt 配置文件生成 Makefile(或适用于系统的构建文件)。

  • 构建项目
    然后运行 make 来编译项目:

    make
    

    CMake 会根据所选择的构建类型(Debug 或 Release)进行编译。如果没有手动指定构建类型,默认是 Release。

  • 调试版本 vs 发布版本
    CMake 会自动根据 CMAKE_BUILD_TYPE 变量切换到 Debug 或 Release 配置:
    Debug 版本:会添加 -g 编译选项生成调试符号,并将输出文件放在 ${CMAKE_BINARY_DIR}/debug_bin 目录中。
    Release 版本:会添加 -O3 编译选项进行优化,并将输出文件放在 ${CMAKE_BINARY_DIR}/release_bin 目录中。

例如,要生成 Debug 版本,执行:

cmake -DCMAKE_BUILD_TYPE=Debug ..
make

或者,要生成 Release 版本:

cmake -DCMAKE_BUILD_TYPE=Release ..
make
  • 输出目录
    在构建完成后,Debug 版本的可执行文件将位于 build/debug_bin/ 目录中,而 Release 版本的可执行文件将位于 build/release_bin/ 目录中。

https://github.com/0voice

...全文
34 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

400

社区成员

发帖
与我相关
我的任务
社区描述
零声学院,目前拥有上千名C/C++开发者,我们致力将我们的学员组织起来,打造一个开发者学习交流技术的社区圈子。
nginx中间件后端 企业社区
社区管理员
  • Linux技术狂
  • Yttsam
  • 零声教育-晚晚
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

请新加入的VIP学员,先将自己参加活动的【所有文章】,同步至社区:

【内容管理】-【同步至社区-【零声开发者社区】

试试用AI创作助手写篇文章吧