我将不断混淆这个CMake的概念。我已经阅读了几篇描述如何编写CMake文件的文章。但是我发现的解释很少。
要点1 -我是否必须为每个文件夹分别创建CMakeLists.txt(是的,为简单起见,我们将其称为文件夹)?
第2点-显然,第1点的答案为否。我发现这些命令可以自动搜索*.cpp
个文件
# get all *.cpp files recursively
file(GLOB_RECURSE SRC_LIST *.c* *.h*)
第3点-似乎无需提及*.hpp
文件。 (这是模糊点)
我已尝试编译最简单的 Hello World! 程序
CMakeLists.txt
src
| - main.cpp (here I included #include "XYZ/abc.hpp")
| - XYZ
| - abc.cpp (included #include "XYZ/abc.hpp")
| - abc.hpp
为此,CMake是
cmake_minimum_required(VERSION 3.10)
project(CMAkeSample)
add_executable(hello src/main.cpp src/XYZ/abc.cpp)
这表明,将所有.cpp
文件以及路径添加到add_executable
中,就可以完成了。
这是真的吗?
要点4 -现在,我有一个相对较大的项目(出于任何原因而在eclipse中开发)。但是我需要为其创建cmake文件,因此不要使用Eclipse进行构建。
下面是文件系统,我只想制作一次CMakeLists.txt
(如果可能)
CMakeLists.txt
src
| - main.cpp (here I included #include "File0.hpp" and #include "Folder1/File1.hpp")
| - File0.cpp (here I included #include "File0.hpp")
| - File0.hpp (here I included #include "Folder1/File1.hpp" and #include "Folder2/File2.hpp")
| - Folder1
| - File1.cpp (included #include "File1.hpp")
| - File1.hpp
| - Folder2
| - File2.cpp (included #include "File2.hpp")
| - File2.hpp
现在,如何在不手动在每个文件夹中写入cmake的情况下获取所有.cpp
文件。有什么建议吗?
更新1:
我已经添加了如图所示的CMakeLists.txt
ProjectFolder
CMakeLists.txt
src
| - CMakeLists.txt
| - main.cpp (here I included #include "File0.hpp" and #include "Folder1/File1.hpp")
| - File0.cpp (here I included #include "File0.hpp")
| - File0.hpp (here I included #include "Folder1/File1.hpp" and #include "Folder2/File2.hpp")
| - Folder1
| - CMakeLists.txt
| - File1.cpp (included #include "File1.hpp")
| - File1.hpp
| - Folder2
| - CMakeLists.txt
| - File2.cpp (included #include "File2.hpp")
| - File2.hpp
在 ProjectFolder> src> CMakeLists.txt
add_library(main main.cpp File0.cpp File0.hpp)
target_link_libraries(main File1)
在 ProjectFolder> src> File1> CMakeLists.txt
add_library(File1 File1.cpp File1.hpp)
target_link_libraries(File1 File2)
在 ProjectFolder> src>文件> CMakeLists.txt
add_library(File2 File2.cpp File2.hpp)
毕竟,我得到的错误是
-- Configuring done
-- Generating done
-- Build files have been written to: /path/to/ProjectFolder
[ 33%] Built target main
[ 44%] Building CXX object CMakeFiles/ProjectFolder.dir/src/main.cpp.o
[ 55%] Linking CXX executable ProjectFolder
/usr/lib64/gcc/x86_64-suse-linux/7/../../../../x86_64-suse-linux/bin/ld: cannot find -lFile1
更新2:
继续进行,要使其正常工作,这里和这里几乎没有进行任何更改(如 UPDATE 1 中所述,并在项目文件夹的CMakeLists.txt中以
的形式手动添加了链接)set(GCC_LINK_FLAGS "-lpthread -lcurl -lgobject-2.0 -lgstreamer-1.0 -lglib-2.0 -lssl -lcrypto -lboost_thread -lboost_system")
add_subdirectory(src)
add_subdirectory(src/Folder1)
add_subdirectory(src/Folder2)
add_executable(ProjectFolder src/main.cpp)
target_link_libraries(ProjectFolder main ${GCC_LINK_FLAGS})
程序执行完美。但是显然,这是编写链接的非常粗糙的方式。寻找 Point2 的解决方案。
答案 0 :(得分:1)
第1点-我是否必须为每个文件夹分别创建CMakeLists.txt(是的,为简单起见,我们将其称为文件夹)?
您应该为每个库或可执行文件创建一个单独的文件夹。 (尽管,也可以在一个文件夹中为可执行文件构建多个项目。有时我将此选项用于具有多个小型测试应用程序的文件夹。)
对于带有子文件夹的文件夹,您可能需要一个仅包含add_subdirectory()
命令的CMakeLists.txt。 (请参见下面的示例。)
甚至可以制作一个CMakeLists.txt文件,其中考虑来自多个子文件夹的来源。我曾经为此写过一个答案。 (SO: Single CMakeLists.txt enough for my project?)不过,请看一下选票–没有多少人认为这是个好主意。 ;-)
第2点-显然,第1点的答案是“否”。我发现这些命令可以自动搜索* .cpp文件
我们广泛使用它,但也建议不要使用它。
缺点是,添加新资源后,构建链将无法自动识别。如果您在CMakeLists.txt中明确命名所有源,则可以授予该权限。
来自CMake doc.:
注意:我们不建议您使用GLOB从源代码树中收集源文件列表。如果在添加或删除源时没有CMakeLists.txt文件更改,则生成的生成系统无法知道何时要求CMake重新生成。
CONFIGURE_DEPENDS
标志可能无法在所有生成器上可靠地工作,或者如果将来添加了不支持它的新生成器,则使用该生成器的项目将被卡住。即使CONFIGURE_DEPENDS
可以可靠地工作,在每次重新构建时都要进行检查。
因此,使用file(GLOB
,一旦添加,移动或删除文件,您就永远不会忘记明确地重新运行CMake。
第3点-似乎无需提及* .hpp文件。 (这是模糊的点)
是的,没有必要,因为cpp文件中提到了包含文件。另一方面,我们将CMake与VS2013结合使用。如果在resp中找到所有标头,那就太好了。 VS项目文件夹。因此,我建议也提及包括在内。 (看来CMake足够聪明,可以将它们与源分开。因此,它不会为头文件创建构建命令。)
第4点-现在,我有一个相对较大的项目(无论出于何种原因,都在Eclipse中开发)。但是我需要为其创建cmake文件,因此不要使用Eclipse进行构建。
CMake是一个构建脚本构建器。我们用它来生成VS解决方案和项目。我确信它也能够为Linux构建Makefile。不幸的是,我对此没有实际经验。 (实际上,这就是为什么我们改用CMake的原因-有了一种可移植的方式来构建可移植的书面源代码。
顺便说一句。 cmake.org
上有一个介绍:
示例:
想象一下应用程序myApp
的以下目录树:
└─ MyApp/
├─ main/
│ ├─ CMakeLists.txt
│ └─ myApp.cc
├─ gui/
│ ├─ CMakeLists.txt
│ ├─ guiMainWindow.cc
│ └─ guiMainWindow.h
├─ model/
│ ├─ CMakeLists.txt
│ ├─ model.cc
│ └─ model.h
└─ CMakeLists.txt
MyApp/CMakeLists.txt
对任何源代码都不负责,但是它收集子文件夹的构建脚本。看起来可能像这样:
# MyApp/CMakeLists.txt
# make a project
project(MyApp)
# This will generate a MyApp solution for VisualStudio
# containing all involved projects.
# add sub-folders which have to be considered
add_subdirectory(main)
add_subdirectory(gui)
add_subdirectory(model)
MyApp/model
可以为MyApp
的基本数据模型提供一个库,而无需进一步依赖。因此,MyApp/model/CMakeLists.txt
可能看起来像这样:
# MyApp/model/CMakeLists.txt
# build rule for library libmodel
add_libary(model
model.cc model.h)
MyApp/gui
可以为MyApp
的GUI提供依赖于libmodel
的另一个库。 MyApp/gui/CMakeLists.txt
可能看起来像这样:
# MyApp/gui/CMakeLists.txt
# build rule for library libgui
add_libary(gui
guiMainWindow.cc guiMainWindow.h)
# dependencies
target_link_libraries(gui
model)
最后,MyApp/main
提供了main()
的{{1}}函数的源代码并生成了可执行文件。 MyApp
可能看起来像这样:
MyApp/main/CMakeLists.txt