链接静态库

时间:2020-04-14 12:39:27

标签: 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
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"
    )

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

静态库的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
)

构建时出现此错误:

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

为什么会出现此错误以及如何解决? 如您所见,为什么cmake在leptonica文件夹中查找我直接依赖项的子依赖项(在这种情况下,giftesseract的{​​{1}}的依赖项)来自leptonica? 我知道这不是LibsPath.cmaketess的特定问题,因为如果我将这些库更改为其他任何库,则模式仍然存在,并且我仍然遇到相同的错误,但使用其他库。 因此,我的cmake文件中肯定有问题,但是我无法弄清楚错误在哪里。

编辑: 试图更改我的库链接到leptonica并将相同的依赖项添加到exe。甚至尝试将子依赖项PUBLIC链接到exe-仍然会收到相同的错误。

teststaticlib / CMakeLists.txt:

gif

testexe / CMakeLists.txt

target_link_libraries(teststaticlib 
PUBLIC 
    ${Tesseract_LIBRARIES}
    ${OpenCV_LIBS}
)

1 个答案:

答案 0 :(得分:3)

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

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

因此,我通常只是简单地制作某种类型的库导入脚本,然后使用PATHS / HINTS来find_library()命令指向正确的目录。 据我所知,导入库目标的最可靠方法是不按原样使用find_library(),而是使用cmake INSTALL()命令从该库生成的导入脚本(如果可用)。 参见find_library()docs

也链接静态库有点奇怪。它们会被编译,但是在生成最终二进制文件之前,没有实际上与它们链接。 PRIVATE库的意思是链接的符号被密封在静态库中,并且依赖项将不会继续进行下去。然后,PUBLIC只需将库添加到LINK_INTERFACE_LIBRARIES / LINK_LIBRARIES目标属性中,并将依赖项保留下来,直到生成最终二进制文件为止。 (共享的库或可执行文件)

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