简体   繁体   English

CMake 用于 C++/Qt 项目中的外部库

[英]CMake for external library in C++/Qt project

I'm trying to build a small C++/Qt test program for reading files of various encodings and I am trying to use the Compact Encoding Detection (CED) library from Google: https://github.com/google/compact_enc_det There are many similar questions, but none of them seem to work or reflect my problems.我正在尝试构建一个小型 C++/Qt 测试程序来读取各种编码的文件,我正在尝试使用 Google 的紧凑编码检测 (CED) 库: https://github.com/google/compact_enc_det有很多类似的问题,但它们似乎都不起作用或反映我的问题。

CED is building fine as an independent project, but I'm struggling to incorporate it as an external library to my project. CED 作为一个独立项目构建得很好,但我正在努力将它作为一个外部库合并到我的项目中。 I'm used to QMake, working in QtCreator, but this will only work with CMake so I started looking around but I'm a bit lost (QMake seems a lot simpler in that regard).我习惯了 QMake,在 QtCreator 中工作,但这只适用于 CMake 所以我开始环顾四周,但我有点迷路(QMake 在这方面似乎更简单)。

I managed to get my C++/Qt project working with CMake under QtCreator, and also managed to build and test CED (CMake then produces a library: libced.a).我设法让我的 C++/Qt 项目在 QtCreator 下与 CMake 一起工作,并且还设法构建和测试 CED(CMake 然后生成一个库:libced.a)。

Here is my small (working) CMakeLists file:这是我的小(工作)CMakeLists 文件:

cmake_minimum_required(VERSION 3.1.0)

project(FileTestCMakeCED)

set(CMAKE_AUTOMOC ON)

find_package(Qt5 COMPONENTS Core Widgets REQUIRED)

set(FileTest_src
    ${CMAKE_CURRENT_LIST_DIR}/src/mainwindow.cpp
    ${CMAKE_CURRENT_LIST_DIR}/src/main.cpp
)

add_executable(${PROJECT_NAME} ${FileTest_src})

# Use the Widgets module from Qt 5
target_link_libraries(${PROJECT_NAME} Qt5::Widgets)

I'm not pasting CED's CMakeLists, it's a bit longer and it's on the GitHub page: https://github.com/google/compact_enc_det/blob/master/CMakeLists.txt我没有粘贴CED的CMakeLists,它有点长,它在GitHub页面上: https://github.com/google/compact_enc_det/blob/master/CMakeLists.txt

I would like to either just use CED as a static library (but I tried many ways and none of them worked) or incorporate the sources to have them compile along my project when needed (I've tried linking CED as an external project outside of my source tree, but I could move it in the same source tree if it's easier).我想要么将 CED 用作 static 库(但我尝试了很多方法,但都没有用),要么合并源代码,以便在需要时将它们与我的项目一起编译(我尝试将 CED 作为外部项目链接到我的源代码树,但如果更容易的话,我可以将它移动到同一源代码树中)。

One promising thing I tried was this:我尝试过的一件有前途的事情是:

include_directories(../compact_enc_det)
add_library(ced STATIC IMPORTED)
set_target_properties(ced PROPERTIES IMPORTED_LOCATION ../compact_enc_det/lib/libced.a)
...
target_link_libraries(${PROJECT_NAME} Qt5::Widgets ced)

But I get a " no rule to make target.../libced.a " error, even though I just want to use the precompiled library.但是我得到一个“ no rule to make target.../libced.a ”错误,即使我只想使用预编译库。

The only thing I managed to get working is to start from the CED project made by Google and paste my sources in there and have CED's CMakeLists generate an extra executable for my program, but it's kind of the opposite of what I would like in terms of code and project structure.我唯一设法开始工作的是从谷歌制作的 CED 项目开始并将我的源代码粘贴到那里,并让 CED 的 CMakeLists 为我的程序生成一个额外的可执行文件,但这与我想要的相反代码和项目结构。 If I try the other way around (including CED into my project), I always run into path problems for the sources and includes of CED.如果我尝试相反的方法(将 CED 包括到我的项目中),我总是会遇到 CED 的源和包含的路径问题。

Can someone enlighten me as to what the best practice is for this kind of problem?有人可以启发我解决此类问题的最佳做法吗? Also, as I said, I'm new to CMake, so a light solution would be appreciated.另外,正如我所说,我是 CMake 的新手,因此我们将不胜感激。 I'm on Debian Stretch if that matters.如果重要的话,我正在拨打 Debian Stretch。

Thanks very much,非常感谢,

One quick solution is to give full path to the libced.a library: 一种快速的解决方案是提供libced.a库的完整路径:

target_link_libraries(${PROJECT_NAME} Qt5::Widgets /path/to/libced.a)

The drawback of this approach is that your CMakeLists.txt has become specific to the machine that you are working on right now. 这种方法的缺点是您的CMakeLists.txt变得特定于您正在使用的计算机。 If you distribute your code, other people will not be able to configure their build without changing the source code CMakeLists.txt . 如果分发代码,其他人将无法在不更改源代码CMakeLists.txt情况下配置其构建。

Generally, external libraries are located in CMake using find_package() . 通常,外部库使用find_package()位于CMake中。 For this function to work the package you are trying to link to must provide either a <package>Config.cmake or a Find<package>.cmake file somewhere CMake can find it. 为了使此功能起作用,您尝试链接的包必须在CMake可以找到它的位置提供<package>Config.cmakeFind<package>.cmake文件。 These files are already present for many popular packages in your CMake installation (look under /usr/lib/cmake, for example). 这些文件已经存在于CMake安装中的许多流行软件包中(例如,在/ usr / lib / cmake下查找)。 But writing your own may be a non-trivial solution if you are just starting with CMake because in these files you try to write a script that does many system dependent checks to locate the package and set appropriate variables that can be used further in the build process. 但是,如果只是从CMake开始,编写自己的脚本可能不是一个简单的解决方案,因为在这些文件中,您尝试编写一个脚本,该脚本执行许多与系统有关的检查以定位包并设置可以在构建中进一步使用的适当变量处理。 You can read about it more on the linked documentation page. 您可以在链接的文档页面上了解更多信息。

Another solution is to use find_library() where you can provide a hint or environment variable for the location of the required library. 另一种解决方案是使用find_library() ,您可以在其中为所需库的位置提供提示或环境变量。 If the library is not found, you can print a message or error that asks the user to set a particular hint variable which your CMakeLists.txt can use to locate the library. 如果找不到该库,则可以打印一条消息或错误,要求用户设置特定的提示变量,您的CMakeLists.txt可用于查找该库。 For example, in your CMakeLists.txt you can do 例如,在您的CMakeLists.txt您可以执行

find_library(CED_LIBRARY ced HINTS ${CED_ROOT})
if( ${CED_LIBRARY} STREQUAL "CED_LIBRARY-NOTFOUND")
    message("Please set CED_LIBRARY variable to location of libced")
endif()

[code edited with two small fixes] [使用两个小补丁编辑的代码]

The above snippet instructs CMake to find the file path to a library ced and store the path in CED_LIBRARY variable. 上面的代码片段指示CMake查找ced库的文件路径,并将该路径存储在CED_LIBRARY变量中。 If file is not found it will store CED_LIBRARY-NOTFOUND in that variable. 如果找不到文件,它将在该变量中存储CED_LIBRARY-NOTFOUND If the library is found then you can link with it using 如果找到该库,则可以使用进行链接

target_link_libraries(${PROJECT_NAME} Qt5::Widgets ${CED_LIBRARY})

find_library() is smart enough to try various prefixes and suffixes on its own so you don't need to write libced . find_library()非常聪明,可以自己尝试各种前缀和后缀,因此您无需编写libced For example, on Windows it may try to find libced.dll , for a shared library on Unix it will search for libced.so etc. 例如,在Windows上,它可能会尝试找到libced.dll ;对于Unix上的共享库,它将搜索libced.so等。

It has been a long time since the question was posted but I am leaving this one just for reference.自问题发布以来已经有很长时间了,但我将这个问题留作参考。 I have a blog post describing step-by-step almost what you (or anyone else) were trying to do.我有一篇博客文章逐步描述了您(或其他任何人)正在尝试做的事情。 Please check here: https://michae9.wordpress.com/2022/09/01/shared-lib-to-be-used-by-client-programs-with-cmake/请在此处查看: https://michae9.wordpress.com/2022/09/01/shared-lib-to-be-used-by-client-programs-with-cmake/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM