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

时间:2018-07-28 20:01:56

标签: c++ qt cmake

我正在尝试构建一个小的C ++ / Qt测试程序来读取各种编码的文件,并且正在尝试使用Google的紧凑编码检测(CED)库:https://github.com/google/compact_enc_det 有很多类似的问题,但似乎没有一个起作用或反映了我的问题。

CED可以作为一个独立的项目很好地构建,但是我正在努力将其作为外部库合并到我的项目中。我曾经在QtCreator中使用过QMake,但是这只能在CMake中使用,所以我开始四处张望,但我有点迷茫(在这方面QMake似乎简单得多)。

我设法使我的C ++ / Qt项目在QtCreator下与CMake一起工作,并且还设法构建和测试CED(CMake然后生成一个库:libced.a)。

这是我的小(工作中)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)

我不是要粘贴CED的CMakeList,而是更长的时间,它在GitHub页面上:https://github.com/google/compact_enc_det/blob/master/CMakeLists.txt

我想只是将CED用作静态库(但我尝试了许多方法,但没有一个起作用),或者合并了源代码,以便在需要时在我的项目中对其进行编译(我尝试将CED作为外部链接)项目在我的源代码树之外,但如果方便的话,我可以将其移到同一源代码树中。

我尝试过的有前途的一件事是:

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)

但是,即使我只想使用预编译的库,也会出现“ no rule to make target .../libced.a”错误。

我唯一能做的就是从Google制作的CED项目开始并将我的源代码粘贴到那里,让CED的CMakeLists为我的程序生成一个额外的可执行文件,但这与我想要的相反在代码和项目结构方面。 如果我尝试其他方法(将CED包含到我的项目中),则总是会遇到CED的来源和包含的路径问题。

有人可以启发我解决此类问题的最佳做法吗? 另外,正如我所说,我是CMake的新手,所以很高兴提供一种简便的解决方案。 如果那很重要,我就在Debian Stretch上。

非常感谢

1 个答案:

答案 0 :(得分:0)

一种快速的解决方案是提供libced.a库的完整路径:

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

此方法的缺点是您的CMakeLists.txt特定于您当前正在使用的计算机。如果您分发代码,那么其他人将无法在不更改源代码CMakeLists.txt的情况下配置其构建。

通常,外部库使用find_package()位于CMake中。为了使此功能起作用,您尝试链接的包必须在CMake可以找到的地方提供<package>Config.cmakeFind<package>.cmake文件。这些文件已经存在于CMake安装中的许多流行软件包中(例如,在/ usr / lib / cmake下查找)。但是,如果只是从CMake开始,编写自己的脚本可能不是一个简单的解决方案,因为在这些文件中,您尝试编写一个脚本,该脚本执行许多与系统有关的检查以定位包并设置可以在构建中进一步使用的适当变量处理。您可以在链接的文档页面上详细了解它。

另一种解决方案是使用find_library(),您可以在其中为所需库的位置提供提示或环境变量。如果找不到该库,则可以打印一条消息或错误,要求用户设置特定的提示变量,您的CMakeLists.txt可以使用该变量来定位该库。例如,您可以在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()

[用两个小补丁编辑的代码]

以上代码段指示CMake查找库ced的文件路径并将该路径存储在CED_LIBRARY变量中。如果找不到文件,它将在该变量中存储CED_LIBRARY-NOTFOUND。如果找到了库,则可以使用

与它链接
target_link_libraries(${PROJECT_NAME} Qt5::Widgets ${CED_LIBRARY})

find_library()非常聪明,可以自行尝试各种前缀和后缀,因此您无需编写libced。例如,在Windows上,它可能会尝试找到libced.dll,对于Unix上的共享库,它将搜索libced.so等。