Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/cmake/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 链接静态库时发生Cmake链接路径错误_C++_Cmake_Static_Lib - Fatal编程技术网

C++ 链接静态库时发生Cmake链接路径错误

C++ 链接静态库时发生Cmake链接路径错误,c++,cmake,static,lib,C++,Cmake,Static,Lib,我有一个cmake项目,它由我自己的静态库和可执行文件组成。简化的项目结构是: 顶级cmake: 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 inc

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

顶级cmake:

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:

        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"
    )
基本上是项目直接依赖项的路径-
tesseract
opencv
及其依赖项

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

到目前为止,一切都很顺利<代码>teststaticlib.lib构建良好,没有任何错误。 但是,一旦我向项目中添加任何可执行文件并将
teststaticlib
链接到它:

testexe/CMakeLists.txt

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
)
    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
)
我在生成时遇到此错误:

忍者:错误:“debug/mainproject/testexe.exe”需要“C:/tesseract41_x64-static/leptonica_x64-windows-static/debug/lib/gif.lib”,缺少且没有已知的规则

为什么会出现此错误以及如何修复它? 为什么cmake在leptonica文件夹中查找我的直接依赖项的子依赖项(
gif
,在这种情况下是
tesseract
leptonica
)的依赖项,而它们的路径与您从
LibsPath.cmake
中看到的路径不同? 我知道这不是
tess
leptonica
特定的问题,因为如果我将这些库更改为任何其他库,该模式仍然存在,并且我仍然会得到相同的错误,但会使用其他库。 因此,我的cmake文件中一定有错误,但我不知道错误在哪里

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

teststaticlib/CMakeLists.txt:

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}
)
target_link_libraries(teststaticlib 
PUBLIC 
    ${Tesseract_LIBRARIES}
    ${OpenCV_LIBS}
)
testexe/CMakeLists.txt

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
)
    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
)

引用“通过kitware掌握cmake”一文,以下内容可能会有所帮助:

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

正因为如此,我通常只是简单地制作一个某种类型的库导入脚本,并使用路径/提示来查找_library()命令以指向正确的目录。 据我所知,导入库目标最可靠的方法是不按原样使用find_library(),而是使用cmake INSTALL()命令从该库生成导入脚本(如果可用)。 请参阅查找库()

链接静态libs也有点奇怪。它们被编译,但在生成最终二进制文件之前,实际上没有任何东西与它们链接。私有lib意味着链接的符号被密封在静态lib中,并且依赖关系将不再继续。PUBLIC只需将lib添加到LINK_INTERFACE_LIBRARIES/LINK_LIBRARIES target属性,并将依赖项一直保留到生成最终二进制文件为止。(共享库或可执行文件)


请注意,我有*nix背景,如果在windows上构建,我可能会弄错一些细节。

因为您正在构建一个静态库,所以它不会“链接”依赖项。如果可执行文件需要使用它们,还需要为可执行文件显式列出它们。一个修复方法可能很简单,就是更改
target\u link\u库(teststaticlib PRIVATE${Tesseract\u libraries}${OpenCV\u LIBS})
调用
PUBLIC
@squareskittles我尝试过,但没有帮助。编辑主要帖子。另外,在本例中,我的可执行文件是一个简单的main.cpp文件,主函数为空,不使用teststaticlib中的任何函数。错误本身表示此库“丢失”,您是否检查了
C:/tesseract41_x64-static/leptonica\u x64-windows-static/debug/lib/gif.lib
是否确实存在?@squareskittles我检查过,不,它不存在。我的问题是,当添加到cmake_PREFIX_路径的gif库路径为“C:/tesseract41_x64-static/giflib_x64-windows-static”时,为什么cmake在该特定路径上查找gif。为什么它只在将teststaticlib链接到exe时才在那里寻找GIF库,而在构建teststaticlib本身时却不在那里寻找。@estw272似乎您已经找到了问题所在。您的Cmake文件很好,这很正常,建议调试和发布使用不同的链接,并且调试构建尝试查找相应的调试库。安装lib的调试版本,或者手动破解lib附带的cmake文件。此外,我个人更喜欢直接设置Tesseract_DIR,而不是使用CMAKE_PREFIX_PATH。还可以将Tesseract_DIR创建为系统环境变量。