【发布时间】:2020-04-14 12:39:27
【问题描述】:
我有一个由我自己的静态库和可执行文件组成的 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):
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
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:错误:'C:/tesseract41_x64-static/leptonica_x64-windows-static/debug/lib/gif.lib','debug/mainproject/testexe.exe'需要,缺少并且没有已知的规则来制作它
为什么会出现此错误,如何解决?
为什么 cmake 会在 leptonica 文件夹中查找我的直接依赖项的子依赖项(在这种情况下,gif 是 tesseract 或 leptonica 的依赖项),而它们的路径与 LibsPath.cmake 中的不同?
我知道这不是tess 或leptonica 特定的问题,因为如果我将这些库更改为任何其他库,模式仍然存在,但我仍然会遇到相同的错误,但使用其他库。
所以我的cmake文件一定有问题,但我不知道错误在哪里。
编辑:
试图更改链接到PUBLIC 的库并将相同的依赖项添加到exe。甚至尝试将子依赖项 gif 链接到 exe - 仍然得到相同的错误。
teststaticlib/CMakeLists.txt:
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})
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
)
【问题讨论】:
-
因为您正在构建一个 static 库,所以它不会“链接”依赖项。如果可执行文件需要使用它们,您还需要为可执行文件显式列出它们。一种解决方法可能很简单,只需将您的
target_link_libraries(teststaticlib PRIVATE ${Tesseract_LIBRARIES} ${OpenCV_LIBS})调用更改为PUBLIC。 -
@squareskittles 我试过了,没有帮助。编辑了主帖。在这种情况下,我的可执行文件也是一个简单的 main.cpp 文件,主函数为空,不使用 teststaticlib 中的任何函数。
-
错误本身说这个库“丢失”,你检查
C:/tesseract41_x64-static/leptonica_x64-windows-static/debug/lib/gif.lib是否真的存在? -
@squareskittles 我做了,不,它不存在。我的问题是,当添加到 CMAKE_PREFIX_PATH 的 GIF lib 的路径是“C:/tesseract41_x64-static/giflib_x64-windows-static”时,为什么 cmake 会在该特定路径上寻找 gif。为什么它只在将 teststaticlib 链接到 exe 时而不是在构建 teststaticlib 本身时才在那里寻找 GIF lib。
-
@estw272 看来您已经找到了问题所在。你的 Cmake 文件没问题,这很正常,建议 debug 和 release 使用不同的链接,并且 debug build 尝试找到相应的 debug 库。安装 lib 的调试版本,或者手动破解 lib 附带的 cmake 文件。另外,我个人更喜欢直接设置 Tesseract_DIR 而不是使用 CMAKE_PREFIX_PATH。您还可以创建 Tesseract_DIR 作为系统环境变量。