首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >链接静态库时的Cmake链接路径错误

链接静态库时的Cmake链接路径错误
EN

Stack Overflow用户
提问于 2020-04-14 12:39:27
回答 1查看 1.2K关注 0票数 2

我有一个cmake项目,它由我自己的静态库和可执行文件组成。简化的项目结构是:

最高级别的cmake:

代码语言:javascript
运行
复制
cmake_minimum_required(VERSION 3.16)

project(mainproject 
    VERSION 0.0.1 
    DESCRIPTION ""
    LANGUAGES CXX
)

list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake")

#include libs
include(LibsPath)

add_subdirectory(teststaticlib)
add_subdirectory(testexe)

cmake/LibsPath.cmake:

代码语言:javascript
运行
复制
        set(CMAKE_PREFIX_PATH
            "C:/tesseract41_x64-static/leptonica_x64-windows-static"
            "C:/tesseract41_x64-static/tiff_x64-windows-static"
            "C:/tesseract41_x64-static/tesseract_x64-windows-static"
            "C:/tesseract41_x64-static/libpng_x64-windows-static"
            "C:/tesseract41_x64-static/libjpeg-turbo_x64-windows-static"
            "C:/tesseract41_x64-static/giflib_x64-windows-static"
            "C:/tesseract41_x64-static/libwebp_x64-windows-static"
            "C:/opencv4_x64-windows-static"
            "C:/protobuf_x64-windows-static"
            "C:/hdf5_x64-windows-static"
            "C:/szip_x64-windows-static"
    )

基本上,项目直接依赖的路径- tesseractopencv及其依赖项。

用于静态库的Cmake文件(teststaticlib/CMakeLists.txt):

代码语言:javascript
运行
复制
cmake_minimum_required(VERSION 3.16)

project(teststaticlib)

set(CMAKE_GENERATOR "Ninja")
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake")

#enable unicode
add_definitions(-DUNICODE -D_UNICODE)

set(SOURCE_FILES
    #...source files
)
set(PRIVATE_HEADER_FILES 
    #... header files
)
set(PUBLIC_HEADER_FILES
    #... header files
)
add_library(teststaticlib STATIC ${SOURCE_FILES} ${PRIVATE_HEADER_FILES} ${PUBLIC_HEADER_FILES})
add_library(teststaticlib::teststaticlib ALIAS teststaticlib)
set_target_properties(teststaticlib PROPERTIES OUTPUT_NAME teststaticlib)
target_include_directories(teststaticlib 
    PRIVATE 
        ${CMAKE_CURRENT_SOURCE_DIR}/src
    PUBLIC
        ${CMAKE_CURRENT_SOURCE_DIR}/include
)

#precompiled headers
target_precompile_headers(teststaticlib PRIVATE src/pch.h)

#link libs
find_package(tesseract CONFIG REQUIRED)
find_package(opencv CONFIG REQUIRED core imgproc highgui)

include_directories(${Tesseract_INCLUDE_DIRS})
include_directories(${OpenCV_INCLUDE_DIRS})
target_link_libraries(teststaticlib 
    PRIVATE 
        ${Tesseract_LIBRARIES}
        ${OpenCV_LIBS}
)

到目前为止一切都很顺利。teststaticlib.lib构建得很好,没有任何错误。但是,当我将任何可执行文件添加到项目并将teststaticlib链接到项目时:

testexe/CMakeLists.txt

代码语言:javascript
运行
复制
cmake_minimum_required(VERSION 3.16)

project(testexe)

set(SOURCE_FILES
    main.cpp
)
add_executable(testexe ${SOURCE_FILES})

target_link_libraries(testexe 
    PRIVATE 
        teststaticlib::teststaticlib
)

我在构建时会出现以下错误:

ninja: error:调试/mainproject/testexe.exe所需的'C:/tesseract41_x64-static/leptonica_x64-windows-static/debug/lib/gif.lib',,缺少并没有任何已知的规则来创建它

为什么我要得到这个错误,以及如何修复它?为什么cmake要在轻子文件夹中查找我的直接依赖项的子依赖项(在本例中,giftesseract of leptonica的依赖项),而它们的路径与LibsPath.cmake不同?我知道这不是tessleptonica特有的问题,因为如果我将这些库更改为其他库,模式就会保持不变,而且我仍然会得到相同的错误,但是使用其他库。所以我的cmake文件肯定出了什么问题,但是我不知道错误在哪里。

编辑:尝试更改我的库链接到PUBLIC并向exe添加相同的依赖项。即使尝试将子依赖项gif链接到exe -仍然会得到相同的错误。

teststaticlib/CMakeLists.txt:

代码语言:javascript
运行
复制
target_link_libraries(teststaticlib 
PUBLIC 
    ${Tesseract_LIBRARIES}
    ${OpenCV_LIBS}
)

testexe/CMakeLists.txt

代码语言:javascript
运行
复制
    cmake_minimum_required(VERSION 3.16) 
project(testexe)

set(SOURCE_FILES
    main.cpp
)
add_executable(testexe ${SOURCE_FILES})

    find_package(tesseract CONFIG REQUIRED)
    find_package(opencv CONFIG REQUIRED core imgproc highgui)
    find_package(gif REQUIRED)
    include_directories(${Tesseract_INCLUDE_DIRS})
    include_directories(${OpenCV_INCLUDE_DIRS})
    include_directories(${GIF_INCLUDE_DIRS})

target_link_libraries(testexe 
    PRIVATE 
        ${GIF_LIBRARIES}
        ${Tesseract_LIBRARIES}
        ${OpenCV_LIBS}
        basicemul::basicemul
)
EN

回答 1

Stack Overflow用户

发布于 2020-04-18 03:02:23

以下是“用小工具掌握cmake”的引文,可能会有所帮助:

CMAKE_PREFIX_PATH:这指定了FIND_XXX()命令将使用的路径。它包含FIND_XXX()命令的“基本”目录,以便将适当的子目录附加到其中。FIND_PROGRAM()将/bin添加到路径中的每个目录;FIND_LIBRARY()将/lib附加到路径中的每个目录

因此,我通常只需编写某种类型的库导入脚本,并使用find_library()命令的路径/提示来指向正确的目录。据我所知,导入库目标的最健壮的方法是不按原样使用find_library(),而是使用cmake ()命令从该库生成导入脚本(如果可用的话)。参见find_library() 文档

另外,链接静态库也有点奇怪。它们会被编译,但是在生成最终的二进制文件之前,实际上没有任何东西被链接到它们。私有库意味着链接符号被密封在静态库中,并且依赖项不会被进一步传递。PUBLIC然后简单地将lib添加到LINK_INTERFACE_LIBRARIES/LINK_LIBRARIES目标属性中,然后将依赖项传递到生成最终的二进制文件。(共享库或可执行文件)

请注意,我有*nix背景,如果在windows上构建,我可能会得到很少的细节错误。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61207911

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档