【问题标题】:The right way to structure my c++ project with cmake?用 cmake 构建我的 c++ 项目的正确方法?
【发布时间】:2012-01-19 17:22:28
【问题描述】:

我已经为此苦苦挣扎了很长一段时间,而我在 cmake 的冒险只是导致了我很确定是不正确的骇人听闻的解决方案。

我创建了一个包含几个文件的库,如下:

-libfolder
  -codepart1folder
    -CMakeLists.txt
    -codepart1.cpp
    -codepart1.hpp
  -codepart2folder
  -codepart3folder
  -lib.cpp
  -lib.hpp
  -CMakeLists.txt

我写了一个 CMakeLists 文件来编译这个库(经过一些实验),我可以生成一个 lib.a 文件。现在我想将此代码作为库包含在其他项目中,并通过 lib.hpp 中的接口访问它。就目录结构而言,最好的方法是什么?我需要在根项目的 CMakeLists.txt 中添加什么?

我目前的尝试是将 -libfolder 作为子文件夹添加到我当前的项目中,并添加命令:

include_directories(${PROJECT_SOURCE_DIR}/libfolder)
link_directories(${PROJECT_BINARY_DIR}/libfolder)
add_subdirectory(libfolder)
target_link_libraries(project lib)

当我运行make时,库编译正常,但是当project.cpp编译时,它抱怨找不到codepart1.hpp(包含在lib.hpp中,包含在project.cpp中)。

我怀疑这是错误的做法,但我无法浏览 CMake 文档并找到有关设置此类项目的好教程。请帮助,CMake 大师!

【问题讨论】:

  • 对于 cmake per-see 可能不是很有帮助,但我建议你看一下 premake。它已经接近成熟,并且对 cmake 有很多优势(一个是它的速度要快得多,尤其是如果你已经知道 lua 的话)。你可以在industriousone.com/what-premake查看。
  • 那么,你想让你的新项目使用以前构建的库,还是想从一个元项目中构建两者?

标签: c++ compilation makefile cmake


【解决方案1】:

将一个 CMake 项目导入另一个 CMake 项目的简洁方法是通过 find_package 命令。包声明是通过使用export 命令完成的。使用 find_package 的一个优点是它无需对包文件的路径进行硬编码。

关于丢失的 hpp 文件,您没有包含 codepart1 文件夹,因此它不在包含路径上。

【讨论】:

  • 好的...从这个答案中,我并不清楚 find_package 和 export 在这种情况下是否正确使用,或者我将如何使用。能详细点吗?
  • 使用 include_directories(${PROJECT_SOURCE_DIR}/libfolder/codepart1folder)
【解决方案2】:

好的,所以在咨询了我的一位 CMake 专家同事后,似乎 CMake 不支持我正在尝试做的事情,留下 3 个选项:

  1. 将所有依赖项添加到父项目 CMakeLists.txt - 不是很干净,但它会让事情正常工作。您必须为添加代码的每个项目执行此操作,并在您的库发生更改时返回并修复问题。

  2. 清理你的库头文件。这是通过一些编译器骇客来完成的。这个想法是前向声明每个类,并且只使用指针或 boost::shared_ptr,然后只在 cpp 文件中包含依赖项。这样您就可以使用所有 findpackage 的东西来构建 cpp 文件,并且您可以通过仅包含标头和链接到库来获得能够使用库的好处。

  3. 查看构建系统。具有复杂依赖项的可移植代码和快速代码编译并不是一个已解决的问题!从我的调查来看,它变得非常复杂。我最终采用了我的同事构建系统,该系统是他在 cmake 中创建的,使用的是他从 Google 获取的东西。

【讨论】:

  • +1,因为清理你的界面使其不需要3 rdparty include-dirs 更好。
【解决方案3】:

你可能错过了

include_directories(${PROJECT_SOURCE_DIR}/libfolder/codepart1folder)

在这种情况下,您可能希望set( CMAKE_INCLUDE_CURRENT_DIR on) 将所有文件夹添加到包含目录路径变量中。

在命令行检查 cmake 的输出是否设置了正确的包含文件夹。此外,您始终可以使用 message() 作为 cmake 变量的“打印调试”。 但是,在包含目录的情况下,您需要阅读目录属性以查看包含目录中的实际内容。

get_property(inc_dirs DIRECTORY PROPERTY INCLUDE_DIRECTORIES)
message("inc_dirs = ${inc_dirs}")

我希望这可以帮助您找出缺少的内容。

编辑

我刚刚看到您关于在 libfolder 中添加 codepart1folder 的评论。它仅在 libfolder 的 include_directory 路径中可用,不会传播到根文件夹。 由于包含 codepart1.hpp 存在于 lib.hpp 中,但是您需要在项目路径中也提供它,否则在构建项目时会出现缺少声明错误。

【讨论】:

  • 好的,这是我的问题。我觉得我不应该去将我所有的子文件夹重新包含在父项目中。 lib 是一段自包含的代码,有自己的 CMakeLists.txt,可以很好地编译成 lib.a。我不想将它全部连接到我想使用它的每个项目中。
  • 那么你应该正确地连接你的库。
【解决方案4】:

查看您的帖子,您似乎没有将“codepart1folder”添加到任何地方的包含中。您如何将 codepart1.hpp 包含为:

#include <codepart1.hpp>
#include "codepart1folder/codepart1.hpp"

我认为构建 cmake 项目没有标准的公认方法。我查看了一堆 cmake 存储库,它们往往存在差异。我个人执行以下操作:

-project
    CMakeLists.txt
    -build
    -cmake
         OptionalCmakeModule.cmake
    -src
        -Main
            Main.cpp
            Main.hpp
        -DataStructs
            SomeTree.hpp
            SomeObject.hpp
        -Debug
            Debug.hpp
        -UI
            Window.hpp
            Window.cpp

基本上将所有源代码转储到 1 个目录中,然后在项目根文件夹中使用以下命令执行源外构建:'mkdir build && cd build && cmake .. && make'。

如果您有单独的库作为项目的一部分,那么您可能需要一个单独的库目录,其中包含您的特定库的另一个子文件夹。

如果您想查看 CMakeLists.txt 文件,我有一些我的存储库:https://github.com/dcbishop/

我的项目结构的主要问题是我使用 FILE_GLOB,这显然是“错误”的做事方式(如果您在运行 'cmake ..' 后添加文件,那么它们就不会了' 'ma​​ke' 时不会被捡起)。我还没有弄清楚“正确”的做法是什么(据我所知,它涉及保留一个单独的文件列表)我也只使用 1 个 CMakeLists.txt 文件。

有些项目还选择将它们的 cpp 和 hpp 文件分开到单独的目录中。因此,您将拥有一个 include 和 src 文件夹(至少对于打算在外部使用的 hpp 文件)。我认为这主要适用于主要是大型图书馆的项目。也会使安装头文件变得更加容易。

【讨论】:

  • codepart1folder 包含在 libfolder 内的 CMakeLists.txt 文件中。对我来说,必须在项目文件夹的 CmakeLists.txt 中添加所有子文件夹、包含和链接似乎是错误的,因为 project.cpp 不依赖于它们中的任何一个 - 只有 lib.hpp 依赖。在您的树中,假设有一个 project2 定义了一个库,我想将 project2 用作项目的子部分。
  • @JohnSavage。但这是正确的方法......我会在 lib-project 中创建一个 LIB_INCLUDE_DIRS 变量,该变量被“导出”到包含所有必要的依赖包含目录的 CMakeCache。然后假设在 cmake-ing Project 时该变量将存在。
猜你喜欢
  • 2019-11-23
  • 2020-06-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多