C ++项目组织(有gtest,cmake和doxygen) [英] C++ project organisation (with gtest, cmake and doxygen)

查看:207
本文介绍了C ++项目组织(有gtest,cmake和doxygen)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是一个新的编程一般所以我决定,我将开始在C + +中创建一个简单的向量类。但是,我想从一开始就进入良好的习惯,而不是稍后尝试修改我的工作流程。



我目前只有两个文件 vector3.hpp vector3.cpp 。这个项目将慢慢开始增长(使它更像一个通用的线性代数库),因为我变得更加熟悉一切,所以我想采用一个标准项目布局,使以后的生活更容易。所以经过环顾四周我找到了两种方法来组织hpp和cpp文件,第一个是:

  project 
└──src
├──vector3.hpp
└──vector3.cpp


$ b b

,第二个是:

 项目
├──inc
│└──项目
│└──vector3.hpp
└──src
└──vector3.cpp

您会推荐什么和为什么?



其次,我想使用Google C ++测试框架来单元测试我的代码相当容易使用。您建议将其与我的代码捆绑在一起,例如在 inc / gtest contrib / gtest 文件夹中?如果捆绑了,您是否建议使用 fuse_gtest_files.py 脚本来减少文件数量或保留原样?如果没有捆绑,如何处理这个依赖关系?



在编写测试时,这些一般是如何组织的?我想为每个类有一个cpp文件( test_vector3.cpp 例如),但所有编译成一个二进制,使他们都可以轻松地一起运行? p>

由于gtest库通常是使用cmake和make构建的,我想我的项目也是这样建的吗?如果我决定使用以下项目布局:

 ├──CMakeLists.txt 
├──contrib
│└──gtest
│├──gtest-all.cc
│└──gtest.h
├──docs
│└──Doxyfile
├──inc
│└──项目
│└──vector3.cpp
├──src
│└──vector3.cpp
└ ──test
└──test_vector3.cpp

如何 CMakeLists.txt 必须看看,以便它可以只构建库或库和测试?此外,我已经看到了相当多的项目有一个构建 bin 目录。构建是否在构建目录中发生,然后二进制文件移到bin目录中?测试和图书馆的二进制文件是否在同一个地方?或者更有意义的结构如下:

  test 
├──bin
├ ──build
└──src
└──test_vector3.cpp

我也想使用doxygen记录我的代码。是否可以让它自动运行cmake和make?



对不起,这么多问题,但我没有找到一本C ++的书,令人满意地回答这些类型问题。

解决方案

C ++构建系统有点黑色的艺术,老的项目
更奇怪的东西你可以发现,所以很奇怪,很多
的问题出现了。我将逐一解释这些问题,并提及一些关于构建C ++库的一般性事项。



在目录中分离头文件和cpp文件。这只是
必要的,如果你正在构建一个组件,应该使用
作为一个库,而不是一个实际的应用程序。您的标题是
的基础,用户可以与您提供的内容进行互动,并且必须安装
。这意味着他们必须在一个子目录(没有人想要
许多标题结束在顶层 / usr / include / )和你的
头文件必须能够包含这样的设置。

 └──prj 
├──include
│└──prj
│├──header2.h
│└──header.h
└──src
└──x.cpp

可以很好地工作,因为包含路径工作,你可以使用简单
globbing安装目标。



绑定依赖:我认为这在很大程度上取决于
的能力,构建系统定位和配置依赖,以及
如何依赖你的代码单版本是。这也取决于你的用户如何
,以及在
平台上安装依赖关系有多容易。 CMake附带了用于Google
Test的 find_package 脚本。这使事情更容易。如果有必要,我会去捆绑只有



如何构建:避免源代码构建。



我想你也想使用CTest来为你的系统运行测试它
也带有对GTest的内置支持)。
目录布局和测试组织的一个重要决定是:你最终得到
子项目吗?如果是这样,在设置CMakeLists
时需要更多的工作,应该将你的子项目分成子目录,每个子目录都有
自己的 include src 文件。也许他们自己的doxygen运行和
输出(组合多个doxygen项目是可能的,但不容易
或漂亮)。



具有类似于以下的内容:

 └──prj
├──CMakeLists.txt < - (1)
├──include
│└──prj
│├──header2.hpp
│└──header.hpp
├──src
│├──CMakeLists.txt < - (2)
│└──x.cpp
└──test
├──CMakeLists.txt < - (3 )
├──data
│└──testdata.yyy
└──testcase.cpp

其中




  • (1)配置依赖项,平台详细信息和输出路径

  • (2)配置要构建的库

  • (3)配置测试可执行文件和测试用例



如果你有子组件,我建议添加另一个层次结构,并使用上面的树为每个子项目。然后事情变得棘手,因为你需要决定子组件是否搜索和配置他们的依赖项,或者如果你在顶层做。这应该根据具体情况决定。



Doxygen:在你设法完成配置舞蹈
doxygen之后,它是微不足道的使用CMake add_custom_command 添加
doc目标。



这是我的项目结束,已经看过一些非常相似的项目,但是这当然不是全部治疗。



附录在某些时候,你会想生成一个 config.hpp
文件包含一个版本定义,也许定义某些版本
控制标识符(一个Git散列或SVN修订版本号)。 CMake有
模块来自动发现这些信息并生成
文件。您可以使用CMake的 configure_file
模板文件中的变量替换为 CMakeLists.txt



如果您正在构建库,您还需要一个导出定义到
获得编译器之间的区别,例如 __ declspec 在GCC / clang上的MSVC
属性。


I am new to programming in general so I decided that I would start by making a simple vector class in C++. However I would like to get in to good habits from the start rather than trying to modify my workflow later on.

I currently have only two files vector3.hpp and vector3.cpp. This project will slowly start to grow (making it much more of a general linear algebra library) as I become more familiar with everything, so I would like to adopt a "standard" project layout to make life easier later on. So after looking around I have found two ways to go about organizing hpp and cpp files, the first being:

project
└── src
    ├── vector3.hpp
    └── vector3.cpp

and the second being:

project
├── inc
│   └── project
│       └── vector3.hpp
└── src
    └── vector3.cpp

Which would you recommend and why?

Secondly I would like to use the Google C++ Testing Framework for unit testing my code as it seems fairly easy to use. Do you suggest bundling this with my code, for example in a inc/gtest or contrib/gtest folder? If bundled, do you suggest using the fuse_gtest_files.py script to reduce the number or files, or leaving it as is? If not bundled how is this dependency handled?

When it comes to writing tests, how are these generally organized? I was thinking to have one cpp file for each class (test_vector3.cpp for example) but all compiled in to one binary so that they can all be run together easily?

Since the gtest library is generally build using cmake and make, I was thinking that it would make sense for my project to also be built like this? If I decided to use the following project layout:

├── CMakeLists.txt
├── contrib
│   └── gtest
│       ├── gtest-all.cc
│       └── gtest.h
├── docs
│   └── Doxyfile
├── inc
│   └── project
│       └── vector3.cpp
├── src
│   └── vector3.cpp
└── test
    └── test_vector3.cpp

How would the CMakeLists.txt have to look so that it can either build just the library or the library and the tests? Also I have seen quite a few projects that have a build and a bin directory. Does the build happen in the build directory and then the binaries moved out in to the bin directory? Would the binaries for the tests and the library live in the same place? Or would it make more sense to structure it as follows:

test
├── bin
├── build
└── src
    └── test_vector3.cpp

I would also like to use doxygen to document my code. Is it possible to get this to automatically run with cmake and make?

Sorry for so many questions, but I have not found a book on C++ that satisfactorily answers these type of questions.

解决方案

C++ build systems are a bit of a black art and the older the project the more weird stuff you can find so it is not surprising that a lot of questions come up. I'll try to walk through the questions one by one and mention some general things regarding building C++ libraries.

Separating headers and cpp files in directories. This is only essential if you are building a component that is supposed to be used as a library as opposed to an actual application. Your headers are the basis for users to interact with what you offer and must be installed. This means they have to be in a subdirectory (no-one wants lots of headers ending up in top-level /usr/include/) and your headers must be able to include themselves with such a setup.

└── prj
 ├── include
 │   └── prj
 │       ├── header2.h
 │       └── header.h
 └── src
     └── x.cpp

works well, because include paths work out and you can use easy globbing for install targets.

Bundling dependencies: I think this largely depends on the ability of the build system to locate and configure dependencies and how dependent your code on a single version is. It also depends on how able your users are and how easy is the dependency to install on their platform. CMake comes with a find_package script for Google Test. This makes things a lot easier. I would go with bundling only when necessary and avoid it otherwise.

How to build: Avoid in-source builds. CMake makes out of source-builds easy and it makes life a lot easier.

I suppose you also want to use CTest to run tests for your system (it also comes with build-in support for GTest). An important decision for directory layout and test organization will be: Do you end up with subprojects? If so, you need some more work when setting up CMakeLists and should split your subprojects into subdirectories, each with its own include and src files. Maybe even their own doxygen runs and outputs (combining multiple doxygen projects is possible, but not easy or pretty).

You will end up with something like this:

└── prj
    ├── CMakeLists.txt <-- (1)
    ├── include
    │   └── prj
    │       ├── header2.hpp
    │       └── header.hpp
    ├── src
    │   ├── CMakeLists.txt <-- (2)
    │   └── x.cpp
    └── test
        ├── CMakeLists.txt <-- (3)
        ├── data
        │   └── testdata.yyy
        └── testcase.cpp

where

  • (1) configures dependencies, platform specifics and output paths
  • (2) configures the library you are going to build
  • (3) configures the test executables and test-cases

In case you have sub-components I would suggest adding another hierarchy and use the tree above for each sub-project. Then things get tricky, because you need to decide if sub-components search and configure their dependencies or if you do that in the top-level. This should be decided on a case-by-case basis.

Doxygen: After you managed to go through the configuration dance of doxygen, it is trivial to use CMake add_custom_command to add a doc target.

This is how my projects end up and I have seen some very similar projects, but of course this is no cure all.

Addendum At some point you will want to generate a config.hpp file that contains a version define and maybe a define to some version control identifier (a Git hash or SVN revision number). CMake has modules to automate finding that information and to generate files. You can use CMake's configure_file to replace variables in a template file with variables defined inside the CMakeLists.txt.

If you are building libraries you will also need an export define to get the difference between compilers right, e.g. __declspec on MSVC and visibility attributes on GCC/clang.

这篇关于C ++项目组织(有gtest,cmake和doxygen)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆