Ошибка пути ссылки Cmake при соединении stati c lib - PullRequest
2 голосов
/ 14 апреля 2020

У меня есть проект cmake, который состоит из моей собственной библиотеки stati c и исполняемого файла. Упрощенная структура проекта:

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-файл для библиотеки stati c (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 ищет подчиненные зависимости моих прямых зависимостей (gif в данном случае - это либо tesseract из leptonica) внутри папки leptonica, когда их путь отличается, как вы можете видеть из LibsPath.cmake? Я знаю, что это не проблема tess или leptonica speci c, потому что, если я изменю эти библиотеки на любые другие, шаблон останется, и я все еще получаю ту же ошибку, но с другими библиотеками. Так что, должно быть, что-то не так в моих файлах 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
)

1 Ответ

3 голосов
/ 18 апреля 2020

Следующее может быть полезно, Цитата из "mastering cmake by kitware":

CMAKE_PREFIX_PATH: Это указывает путь, который будет использоваться командами FIND_XXX (). Он содержит «базовые» каталоги для команд FIND_XXX () для добавления соответствующих подкаталогов. FIND_PROGRAM () добавляет / bin к каждому из каталогов в пути; FIND_LIBRARY () добавляет / lib к каждому из каталогов в пути

Из-за этого я обычно просто делаю какой-то скрипт импорта библиотеки и использую PATHS / HINTS для find_library (), чтобы указать правильный каталог. Насколько мне известно, самый надежный способ импортировать цели библиотеки - это не использовать find_library () как есть, а использовать cmake INSTALL (), сгенерированные сценариями импорта из этой библиотеки, если они доступны. См. Find_library () docs .

Кроме того, связывание stati c libs немного странно. Они компилируются, но ничто на самом деле не связывается с ними до тех пор, пока не будет создан финальный двоичный файл. Частные библиотеки означают, что связанные символы запечатаны внутри stati c lib и зависимость не будет перенесена дальше. Затем PUBLI C просто добавляет библиотеку lib в целевое свойство LINK_INTERFACE_LIBRARIES / LINK_LIBRARIES, и зависимости переносятся до тех пор, пока не будет создан конечный двоичный файл. (совместно используемая библиотека или исполняемый файл)

Обратите внимание, что у меня есть * nix-фон, и я, возможно, неправильно понял некоторые детали, если использовал windows.

...