使用CMake创建C ++库 [英] Creating C++ library with CMake

查看:97
本文介绍了使用CMake创建C ++库的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试创建一个合理的库结构和CMake文件,以使其他CMake项目可以轻松地包含此库。我发现了很多类似的问题,但是似乎没有一个问题能解决我的确切问题。



我当前的结构如下:

  / * MyLibrary / 
├──CMakeLists.txt(包括lib子目录)
├──外部/
│└──googletest /
├──lib /
│├─ ──common /
││├──CMakeList.txt(创建静态lib common)
││├──include / common / *。h
││└──src / *。 cpp
│├──密码/
││├──CMakeList.txt(创建静态lib密码)
││├──include / cipher / *。h
│ │└──src / *。cpp
└──test /
├──main.cpp(用于执行Google测试的代码)
├──CMakeLists.txt(创建unittest可执行文件)
├──common / * Test.cpp
└──cipher / * Test.cpp
* /

现在我想创建一个具有类似目录结构的项目,但是当我想在该项目中创建一个与<中的静态库之一同名的静态库时,就会出现问题。 code> MyLibrary (例如 common )。



我当时正在考虑使用项目CMakeList中的 add_subdirectory(external / MyLibrary)将库包含到项目中,但这失败了,因为静态库的名称冲突。



即使我通过重命名库解决了这个问题(我实际上也不认为这是一个优雅的解决方案),但我还是遇到了googletest冲突,因为两者库和我的项目,都取决于googletest。



有什么办法可以轻松解决吗?我在想两种可能性:




  • MyLibrary 中,我会从所有名为 libMyLibrary.a 的子库中创建一个静态库,并仅包含该库(首选选项,但是我不知道如何在CMake中实现它)


  • 强制库的用户安装它,并且不将该库包含为项目子模块(我会选择的最后一个选择)




还有其他合理的解决方法可以使我的库与大多数CMake项目兼容吗?如果没有,我如何至少实现上述选项之一?



简而言之:如何为库创建CMake文件?因此该库很容易包含在其他CMake项目中?



如何处理googletest之类的冗余依赖项?

解决方案


如何为一个库创建CMake文件,以便该库易于包含在其他CMake项目中?


没有通用的方法。



通过 add_subdirectory(),您将项目内部开放给其他项目。除了可以使图书馆的目标物做好连接的优势之外,这种方法也有劣势。 Target的冲突,缓存变量的冲突以及其他一些问题将是您的头痛。



如果您希望将项目包含在 add_subdirectory中,请避免为目标使用通用名称。例如,使用< my_project_name> _common 代替 common



某些无法重命名的目标(例如 gtest )。如果您的项目确实不需要这些目标,请创建一个禁用它们的选项:

  option(< my_project_name> ; _TESTING启用测试开启)
if(< my_project_name> _TESTING)
add_subdirectory(external / googletest)
endif()


另请参见我的答案是关于目标名称冲突的类似问题。


I am trying to create a reasonable library structure and CMake file which would allow other CMake projects to easily include this library. I've found a lot of similar questions, however, none of them seems to address my exact problem.

My current structure is the following:

/*MyLibrary/
├── CMakeLists.txt (including lib subdirectories)
├── external/
│   └── googletest/
├── lib/
│   ├── common/
│   │   ├── CMakeList.txt (creates static lib common)
│   │   ├── include/common/*.h
│   │   └── src/*.cpp
│   ├── cipher/
│   │   ├── CMakeList.txt (creates static lib cipher)
│   │   ├── include/cipher/*.h
│   │   └── src/*.cpp
└── test/
    ├── main.cpp (code for executing google test)
    ├── CMakeLists.txt (creates unittest executable)
    ├── common/*Test.cpp
    └── cipher/*Test.cpp
*/

Now I want to create a project with a similar directory structure but the problem occurs when I want to create a static library in that project with the same name as one of the static libraries in MyLibrary (common for example).

I was thinking of including the library into the project using add_subdirectory(external/MyLibrary) in the projects CMakeLists, but that fails because the names of the static libraries collide.

Even when I solve this issue by renaming the library (which I don't in fact believe is an elegant solution), I end up with googletest conflicts because both, the library and my project, are dependent on googletest.

Is there any way to solve this easily? I was thinking of 2 possibilities:

  • In the MyLibrary I would create one static library from all the sub-libraries called libMyLibrary.aand include only that library (preferred option, but I don't have a clue how to achieve it in CMake)

  • Forcing the users of the library to install it and don't include the library as a project submodule (last option I would go for)

Is there some other reasonable way to solve it which would make my library compatible with most CMake projects? If not, how can I achieve at least one of the mentioned options?

In short: how can I create a CMake file for a library so the library is easy to include in other CMake projects?

How can I deal with redundant dependencies such as googletest?

解决方案

How can I create a CMake file for a library so the library is easy to include in other CMake projects?

There is no universal approach for that purpose.

By including your project into another one with add_subdirectory(), you "open" internals of your project to other one. Aside of advantage in having the library's target ready for linking, this approach has disadvantages too. Target's collisions, cached variables collisions will be your headache, among with some other problems.

If you want your project to be included into other with add_subdirectory, avoid using "generic" names for your targets. E.g., use <my_project_name>_common instead of common.

Some targets you cannot rename (like gtest). If those targets aren't really required for your project to work, create an option for disable them:

option(<my_project_name>_TESTING "Enable testing" ON)
if(<my_project_name>_TESTING)
    add_subdirectory(external/googletest)
endif()

See also my answer to the similar question about targets' names collision.

这篇关于使用CMake创建C ++库的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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