在处理大型项目时,如果项目目录下存在大量源文件,逐个添加会非常耗时。要解决这个问题,我们可以利用Cmake提供的其他命令,例如文件搜索命令。通过这些命令,我们可以轻松地解决这个问题,提高构建效率。
在CMake中,提供了搜索文件的命令,可通过aux_source_directory命令或file命令进行操作。
在CMake中,aux_source_directory命令是一个非常实用的工具,它可以帮助我们收集指定路径下的所有源文件的文件名,并将这些文件名存储在指定的变量中。这在处理大型项目时,尤其显得方便,因为我们无需逐个列出所有的源文件,就可以直接使用变量中的文件名。
aux_source_directory命令的基本使用方法是:
aux_source_directory(< dir > < variable >)
其中,dir表示要搜索的目录,variable则是将从dir目录下搜索到的源文件列表存储到该变量中。在需要用到源文件的地方,我们只需要使用variable变量即可,无需再逐个列出每个源文件的名称。
值得一提的是,CMake还提供了一个内置变量CMAKE_CURRENT_SOURCE_DIR,它表示当前处理的CMakeLists.txt所在的目录的绝对路径。我们可以通过这个变量来获取目录的路径,从而简化aux_source_directory命令的编写。例如,我们可以这样使用aux_source_directory命令
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/??SRT_LIST)
这样,我们就不需要定义额外的变量来表示源文件,直接通过命令就可以搜索到源文件。
总的来说,aux_source_directory命令在CMake中的使用,大大提高了我们的工作效率,同时也使得源文件的管理等操作变得更加简洁明了。掌握这个命令的使用,对于CMake初学者来说,无疑是一大利器。在实际的项目开发中,我们可以根据需要灵活运用这个命令,从而提高我们的开发效率。
修改完我们可以再重新编译一下,发现同样我们可以构建整个项目,编译出可执行文件。
?
这是第一种方式,另外一个方式就是用file命令,file命令是CMake内置的一个命令,用于对文件和目录进行操作。需要注意的是,file命令是一个强大且灵活的命令,可以满足各种不同的需求,并不仅仅只是查找文件或者目录那么简单。
在CMake中,我们通过使用file命令来查找符合指定模式的文件和目录。它的语法格式是这样的:
file(GLOB/GLOB_RECURSE 变量名 要搜索的文件路径和文件类型)
这个命令有三个参数,第一个参数是指定如何去搜索,这里有两个选项GLOB和GLOB_RECURSE来查找符合指定模式的文件和目录。GLOB选项只匹配当前目录下的文件和目录,而GLOB_RECURSE选项则递归查找所有子目录中的文件和目录。
当我们使用file命令找到匹配的文件或目录后,会将结果输出到一个包含文件名或目录名的列表。这个列表会赋值给第二个参数,也就是一个变量。搜索完毕之后,这个变量里面就有我们想要的值了。
第三个参数指定了要搜索的文件的路径和文件后缀类型。首先需要指定要搜索的路径,然后指定要搜索的文件后缀。这里的文件后缀指的就是文件名的扩展名。比如我们要搜索以 ?.docx结尾的文件,就可以使用字符 ?* ?来代表任意字符,这里的*就相当于通配符。如果要搜索以 ?.txt结尾的文件,则可以使用 ?*.txt的方式来指定搜索的文件后缀。
通过这种方式,我们可以搜索到指定路径下所有指定后缀的文件。这个功能在项目管理、文件整理等方面非常有用。不仅能够帮助我们快速找到所需的文件,还可以提高工作效率。
我们使用CMake的file()函数搜索目录上的所有.cpp文件,并通过内置变量CMAKE_CURRENT_SOURCE_DIR获取目录路径:
file(GLOB ?LIST ?${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
这段代码的作用是在当前源目录(CMAKE_CURRENT_SOURCE_DIR)下搜索所有以.cpp结尾的文件,并将搜索结果存储在变量LIST中。
我们该如何在编写完设置后确认其准确性呢?如何知道变量LIST是否涵盖了所有的.cpp文件呢?无论是在日常编程还是在编写各种脚本的过程中,我们都需要通过添加打印语句,如printf或echo,来验证我们的变量或逻辑是否正确。在CMake中,我们同样需要调试我们的CMakeLists.txt文件中的变量和进度信息等。那么,在CMake中,我们如何实现这一目标呢?
CMake提供了一个非常有用的命令:message。这个命令允许我们在控制台输出一条消息。如果我们想要输出一个变量的值,我们可以使用以下的语法:
message("Files: ${LIST}")
这里的${LIST}将被替换为变量LIST的实际值。但是需要注意的是,message命令仅在生成构建系统时执行,并不会在编译过程中执行。
为了验证变量是否设置正确,我们可以将这个打印信息语句添加到CMakeLists.txt中。这样,每次执行CMake命令时,我们都可以查看变量的值是否符合预期。此外,我们还可以在CMakeLists.txt中添加其他的调试信息,如进度消息、错误消息等,以便于我们在调试过程中更好地理解项目的进展情况。
通过使用message命令,我们可以轻松地在CMake中输出相关信息,从而验证我们的设置是否正确。无论是在编程还是在编写脚本,添加调试信息都能帮助我们更快地发现问题,提高开发效率。通过合理使用message命令,我们可以更轻松地监控和管理CMakeLists.txt中的变量和进度消息,从而确保项目的顺利进行。 ???????????????
?
这个时候,我们需要重新编译整个项目,执行cmake构建系统时我们就会打印出变量LIST的值了。
?
这时我们就能看见LIST的值没有问题。好了通过这两种方式我么就可以非常轻松的获取到想要的源文件了。
在第一篇CMake博客中,我们讨论了如何面对一个成熟的项目,对其进行合理的目录结构规划。在实际操作中,我们通常需要在项目的目录中创建一个子目录,用于存放源代码文件,这个目录通常被称为src目录。同时,还需要为一个项目添加头文件,这些头文件一般会被放置在include目录下。
这样的目录结构安排有着明显的优势。首先,将源代码和头文件分开存放,可以使项目结构更加整洁,避免源代码和头文件混杂在一起,从而提高项目的可维护性。其次,将文件移入它们所待的房间,有助于提高项目的可读性,便于开发人员查找、编辑和维护代码。此外,有序的目录结构还有助于降低出现问题的概率。
另外,不同的操作系统和编译器对头文件和源文件的搜索路径有不同的规定。将头文件和源文件放在标准位置,可以提高代码在不同平台上的可移植性。因此,将源代码文件存放在src目录下,将头文件存放在include目录下,已经成为了一种较为通用的代码组织方式。
在完成文件移除后,我们还需要对CMakeLists.txt文件进行相应的修改。由于源文件的位置已经发生变化,搜索源文件的目录也需要重新设置。这将确保CMakeLists.txt文件与实际的项目结构保持一致,从而确保构建系统的顺利进行。
?
在完成修改后,我们将重新构建项目,并测试是否能成功构建并编译为可执行文件。然而,在编译过程中,出现了错误,提示无法找到clock.h文件。
?
出现此问题,是因为我们将源文件和头文件分别放置在两个不同的目录中。因此,编译器在寻找头文件时遇到了困难,无法找到它。
编译器在处理源文件时,若源文件与头文件位于同一目录下,则能自动找到并引入头文件。这是由于编译器预设的搜索路径中已包含源文件所在的目录。因此,当编译器需要引用头文件时,会自动在源文件所在的目录中查找相应的头文件。
但在某种情况下,若源文件与头文件不在同一目录,或需引用第三方头文件,则需利用指令指明头文件所在路径。这样才能确保在编译过程中,编译器能够准确找到这些头文件,从而顺利完成编译。
此时,CMake这个强大的构建系统就可以派上用场。在CMake中,我们可以通过一个简单的命令——include_directories来设置需要包含的目录,从而引用头文件。这个命令的使用方法非常简单,只需指定头文件所在的目录即可。如下所示:
include_directories(${PROJECT_SOURCE_DIR}/include)
在这个构造中,我们再次涉及到CMake的一个预定义变量,PROJECT_SOURCE_DIR。这个变量表示的是当前项目的源代码根目录。它的值在项目配置阶段会自动设置。PROJECT_SOURCE_DIR和前面提到的MAKE_CURRENT_SOURCE_DIR在CMakeLists.txt文件中都是常用的。尽管它们有相似的意义,但PROJECT_SOURCE_DIR更侧重于整个CMake项目的顶级目录,也就是CMakeLists.txt文件所在的目录,这个目录在项目配置时由project命令自动设定。因此,PROJECT_SOURCE_DIR指向的是项目的根目录,对于一个包含多个子目录的项目,这个路径是固定的。而CMAKE_CURRENT_SOURCE_DIR则表示当前使用的CMakeLists.txt所在的目录。如果有多个CMakeLists.txt文件分布在不同的子目录中,那么CMAKE_CURRENT_SOURCE_DIR可以表示不同的源代码根目录。因此,CMAKE_CURRENT_SOURCE_DIR的值在不同的CMakeLists.txt文件中可能会有所变化。这里我们再次强调这两者之间的区别。
?
重新编译一下,我们发现已经可以生成可执行文件了。
?