1)如果子目录代码文件相对独立,也就是没有引用其他子目录的文件,可以单独编译成库文件
上层CMakeLists.txt通过link_libraries()来添加这个库文件
2)如果子目录代码引用了其他子目录的文件,建议在上一层编译(前提也是相对独立)
上层CMakeLists.txt通过aux_source_directory()来添加子目录文件
举个例子,假设有个src目录下的代码结构如下
src
├── CMakeLists.txt
├── main.c
├── utils
│ ├── utils.h
│ └── utils.c
└── log├── CMakeLists.txt├── log.h└── log.c
其中,log模块相对独立,而utils模块调用了log模块。
log.h(在log目录)
#pragma oncevoid log1( const char* text );
log.c(在log目录)
#include "log.h"
#include <stdio.h>void log1( const char* text ){printf("[DEBUG] %s\n",text);
}
log目录下的CMakeLists.txt
cmake_minimum_required(VERSION 3.16)
project(log)#搜索当前目录下所有源文件
aux_source_directory(./ SRC)#编译静态库文件
add_library(log ${SRC})
utils.h(在utils目录)
#pragma oncevoid doSomething();
utils.c(在utils目录)
#include "utils.h"
#include "log.h"void doSomething(){log1("--doSomething--");
}
utils目录下没有CMakeLists.txt
src目录(log和utils目录的上一级目录)下的main.c
#include "utils.h"
#include "log.h"
int main(int argc, char** argv ){log1("--main--");doSomething();return 0;
}
src目录的CMakeLists.txt
cmake_minimum_required(VERSION 3.16)
project(test)#添加头文件搜索路径
include_directories(${PROJECT_SOURCE_DIR}/log)
include_directories(${PROJECT_SOURCE_DIR}/utils)#添加和构建子目录,会执行子目录的CMakeLists.txt
add_subdirectory(log)#连接静态库
link_libraries(log)#搜索utils子目录源代码文件(名), 记在UTILS_SRC变量
aux_source_directory(${PROJECT_SOURCE_DIR}/utils UTILS_SRC)#生成可执行文件
add_executable(demo main.c ${UTILS_SRC})
注意到,对log模块的处理方式是
#添加和构建子目录,会执行子目录的CMakeLists.txt
add_subdirectory(log)#连接静态库
link_libraries(log)
对utils模块的处理方式是
#搜索utils子目录源代码文件(名), 记在UTILS_SRC变量
aux_source_directory(${PROJECT_SOURCE_DIR}/utils UTILS_SRC)#生成可执行文件
add_executable(demo main.c ${UTILS_SRC})
也就是通过UTILS_SRC来记录utils的所有源文件名,通过${UTILS_SRC}来引用。
然后,构建工程&编译
cd src
cmake . -B build
cmake --build build
cmake . -B build 作用是 构建工程并且把中间文件保存在build目录,子目录的中间文件也会存到里面
cmake --build build 作用是在build目录编译&链接生成目标文件(此处是demo)
最后,可以在build目录下看到demo这个程序。
如果要删除 build目录,这条命令:rm -rf build (也就是普通删除文件夹命令)
末了,切记,要根据实际情况来配置CMakeLists.txt,不要生搬硬套别人的做法,此文只是抛砖引玉。