无法使用 CMake 静态链接到 OpenCV 4.7.0

Failing to statically link to OpenCV 4.7.0 using CMake

提问人:Pedro 提问时间:10/25/2023 最后编辑:Christoph RackwitzPedro 更新时间:10/26/2023 访问量:52

问:

我使用.我查看了输出,它似乎正确地生成了静态库(就像我在 Windows 上一样)。BUILD_SHARED_LIBS=OFF.lib

但是,当我尝试使用 CMake 的机制链接到生成的文件时,它似乎告诉链接器寻找动态库,并且出现错误。find_packageLNK2038: mismatch detected for 'RuntimeLibrary': value 'MT_StaticRelease' doesn't match value 'MD_DynamicRelease'

以下是重现该问题的最低限度示例。

  1. 下载 OpenCV 4.7.0 并在 Windows 上使用以下命令进行构建:
cmake -S .\sources\ -B opencv-build-test -D BUILD_SHARED_LIBS=OFF
cmake --build .\opencv-build-test\

凌晨 1 点创建以下项目:

cmake_minimum_required(VERSION 3.26)

project(OpenCVStaticLinkingTest)

set(CMAKE_CXX_STANDARD 17)

find_package(OpenCV 4.7.0 REQUIRED EXACT)

add_executable(OpenCVStaticLinkingTest main.cpp)

target_link_libraries(OpenCVStaticLinkingTest  ${OpenCV_LIBS})

2乙.使用此主文件:

#include <iostream>
#include <opencv2/opencv.hpp>

int main() {
    // Create an OpenCV matrix
    cv::Mat testMatrix(5, 5, CV_32F);

    // Interact with it to show we've gone this far
    std::cout << "Value 1,1: " + std::to_string(testMatrix.at<float>(1,1)) << std::endl;
    return 0;
}
  1. 然后按如下方式构建:
cmake -S . -B example-build -D OpenCV_DIR=$WHEREVER_YOU_BUILT_IT
cmake --build example-build

我正在使用 VS 17 在 Windows 11 上进行编译,并且尝试了使用和不使用 Ninja。

网上的一切似乎都告诉我,编译应该是我需要做的,但显然有些不对劲。我试过:BUILD_SHARED_LIBS=OFF

  • 在有标志和没有标志的情况下进行编译OPENCV_GENERATE_PKGCONFIG=YES
  • 设置为“在我的项目上”OpenCV_STATIC
  • 设置为“在我的项目上”OpenCV_SHARED
  • 以上两者一起
  • 设置set(CMAKE_SHARED_LINKER_FLAGS "-static")
  • 设置
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd")

但到目前为止,总是遇到同样的问题。

C++ 可视化工作室 opencv cmake 链接器错误

评论

3赞 drescherjm 10/25/2023
BUILD_SHARED_LIBS=OFF并不意味着使用静态运行时。这意味着创建静态库而不是动态/共享库。
1赞 SpacePotatoes 10/26/2023
OpenCV: 的 CMakeLists 中有一个自定义 CMake 选项,如果 MSVC: github.com/opencv/opencv/blob/4.8.1/CMakeLists.txt#L493,则默认为 ON。如果要构建链接到共享 CRT 的静态 OpenCV 库:.BUILD_WITH_STATIC_CRT-DBUILD_SHARED_LIBS=OFF -DBUILD_WITH_STATIC_CRT=OFF
1赞 SpacePotatoes 10/26/2023
另一种解决方案是针对静态 CRT 构建自己的可执行文件,并链接到链接到静态 CRT 的静态 OpenCV。在针对自己的项目调用 cmake 配置时,您必须通过,否则它会针对共享 CRT 构建。恕我直言,OpenCV CMakeLists 在 OFF 时对默认 CRT BUILD_SHARED_LIBS很糟糕,它不遵守最小惊喜原则。-DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded
1赞 drescherjm 10/26/2023
@SpacePotatoes默认为 ON 对我来说很有趣。我认为这就是 OP 想要的,但很好奇为什么它不起作用。我一直忘记 msvc 显示此错误消息的顺序(因为我很少自己得到它/总是使用带有共享库的动态运行时)。该错误是否表明 OpenCV 具有动态运行时或 OP 正在构建的应用程序?BUILD_WITH_STATIC_CRT
2赞 SpacePotatoes 10/26/2023
我也不记得了。但是由于在 OpenCV 中是默认的(击败默认的 CMake 行为),我猜在 中,第二个提到的 CRT 指的是被链接的应用程序,而第一个 CRT 指的是应用程序链接到的库。换句话说,错误表示链接器在链接到应用程序的库中发现了与为应用程序指定的 CRT 不兼容的 CRT(第一个)。BUILD_WITH_STATIC_CRTONLNK2038: mismatch detected for 'RuntimeLibrary': value 'MT_StaticRelease' doesn't match value 'MD_DynamicRelease'

答: 暂无答案