链接 Google Test 时,_ITERATOR_DEBUG_LEVEL 和 MDd_DynamicDebug 的链接错误 LNK2038 是什么?

问题描述 投票:0回答:1

我相信这不是这篇文章的骗局,因为我的情况似乎与链接文章中描述的相反:OP的问题是链接他的调试版本时的链接错误(他们的发布版本很好) ;我的错误在于链接我的发布版本(我的调试版本没问题)。

我正在学习 CMake,在 Windows 环境中工作,我的学习材料让我下载 Google Test(至

C:\libs\googletest-release-1.11.0
)并按如下方式构建/安装它:

  1. cmake -DCMAKE_INSTALL_PREFIX=build\install-dir -Dgtest_force_shared_crt=ON -S . -B build
  2. cmake --build build
  3. cmake --build build --target install

此过程显示成功:我没有看到任何错误,并且安装包已安装到

C:\libs\googletest-release-1.11.0\build\install-dir

我创建了(从学习材料下载)一个使用已安装的 Google Test 的 CMake 项目。
项目构建并通过调试构建成功运行其单元测试。
但是,当我尝试构建发布版本时,我遇到了链接错误,我无法识别这些链接错误是我的项目的一部分,而且我无法弄清楚问题是什么。

以下是我如何在调试配置中成功构建项目并运行单元测试:

  1. cmake -DCMAKE_PREFIX_PATH=C:/libs/googletest-release-1.11.0/build/install-dir -S . -B build
  2. cmake --build build --config Debug
  3. .\build\out\Debug\CalculatorTests.exe

    (我看到正常的谷歌测试标准)

以下是我尝试在发布配置中构建项目的方法:

  1. cmake -DCMAKE_PREFIX_PATH=C:/libs/googletest-release-1.11.0/build/install-dir -S . -B build
  2. cmake --build build --config Release

第 2 步是我收到链接错误的地方,我根本不认识或不知道如何处理:

gmock_maind.lib(gtest-all.obj) : error LNK2038: mismatch detected for '_ITERATOR_DEBUG_LEVEL': value '2' doesn't match value '0' in CalculatorTests.obj [C:\linking_to_external_libraries\build\src\calculator\test\CalculatorTests.vcxproj]
gmock_maind.lib(gtest-all.obj) : error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MDd_DynamicDebug' doesn't match value 'MD_DynamicRelease' in CalculatorTests.obj [C:\linking_to_external_libraries\build\src\calculator\test\CalculatorTests.vcxproj]
gmock_maind.lib(gmock_main.obj) : error LNK2038: mismatch detected for '_ITERATOR_DEBUG_LEVEL': value '2' doesn't match value '0' in CalculatorTests.obj [C:\linking_to_external_libraries\build\src\calculator\test\CalculatorTests.vcxproj]
gmock_maind.lib(gmock_main.obj) : error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MDd_DynamicDebug' doesn't match value 'MD_DynamicRelease' in CalculatorTests.obj [C:\linking_to_external_libraries\build\src\calculator\test\CalculatorTests.vcxproj]
gmock_maind.lib(gmock-all.obj) : error LNK2038: mismatch detected for '_ITERATOR_DEBUG_LEVEL': value '2' doesn't match value '0' in CalculatorTests.obj [C:\linking_to_external_libraries\build\src\calculator\test\CalculatorTests.vcxproj]
gmock_maind.lib(gmock-all.obj) : error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MDd_DynamicDebug' doesn't match value 'MD_DynamicRelease' in CalculatorTests.obj [C:\linking_to_external_libraries\build\src\calculator\test\CalculatorTests.vcxproj]
LINK : warning LNK4098: defaultlib 'MSVCRTD' conflicts with use of other libs; use /NODEFAULTLIB:library [C:\linking_to_external_libraries\build\src\calculator\test\CalculatorTests.vcxproj]
gmock_maind.lib(gtest-all.obj) : error LNK2019: unresolved external symbol __imp__invalid_parameter referenced in function "class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __cdecl std::operator+<char,struct std::char_traits<char>,class std::allocator<c
har> >(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > &&,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > &&)" (??$?HDU?$char_traits@D@std@@V?$allocator@D@1@@std@@YA?AV?$basic_string@DU?$char_traits@D@std@@V?$all
ocator@D@2@@0@$$QEAV10@0@Z) [C:\linking_to_external_libraries\build\src\calculator\test\CalculatorTests.vcxproj]
gmock_maind.lib(gmock-all.obj) : error LNK2001: unresolved external symbol __imp__invalid_parameter [C:\linking_to_external_libraries\build\src\calculator\test\CalculatorTests.vcxproj]
gmock_maind.lib(gtest-all.obj) : error LNK2019: unresolved external symbol __imp__CrtSetDbgFlag referenced in function "public: __cdecl testing::internal::`anonymous namespace'::MemoryIsNotDeallocated::MemoryIsNotDeallocated(void)" (??0MemoryIsNotDeallocated@?A0xd01e04df@internal@testing@@QE
AA@XZ) [C:\linking_to_external_libraries\build\src\calculator\test\CalculatorTests.vcxproj]
gmock_maind.lib(gtest-all.obj) : error LNK2019: unresolved external symbol __imp__calloc_dbg referenced in function "char * __cdecl std::_Maklocstr<char>(char const *,char *,struct _Cvtvec const &)" (??$_Maklocstr@D@std@@YAPEADPEBDPEADAEBU_Cvtvec@@@Z) [C:\linking_to_external_libraries\build\
src\calculator\test\CalculatorTests.vcxproj]
gmock_maind.lib(gmock_main.obj) : error LNK2001: unresolved external symbol __imp__calloc_dbg [C:\linking_to_external_libraries\build\src\calculator\test\CalculatorTests.vcxproj]
gmock_maind.lib(gmock-all.obj) : error LNK2001: unresolved external symbol __imp__calloc_dbg [C:\linking_to_external_libraries\build\src\calculator\test\CalculatorTests.vcxproj]
gmock_maind.lib(gtest-all.obj) : error LNK2019: unresolved external symbol __imp__CrtDbgReport referenced in function "class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __cdecl std::operator+<char,struct std::char_traits<char>,class std::allocator<char>
>(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > &&,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > &&)" (??$?HDU?$char_traits@D@std@@V?$allocator@D@1@@std@@YA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocato
r@D@2@@0@$$QEAV10@0@Z) [C:\linking_to_external_libraries\build\src\calculator\test\CalculatorTests.vcxproj]
gmock_maind.lib(gmock-all.obj) : error LNK2001: unresolved external symbol __imp__CrtDbgReport [C:\linking_to_external_libraries\build\src\calculator\test\CalculatorTests.vcxproj]
gmock_maind.lib(gtest-all.obj) : error LNK2019: unresolved external symbol __imp__CrtSetReportFile referenced in function "public: int __cdecl testing::UnitTest::Run(void)" (?Run@UnitTest@testing@@QEAAHXZ) [C:\linking_to_external_libraries\build\src\calculator\test\CalculatorTests.vcxproj]
gmock_maind.lib(gtest-all.obj) : error LNK2019: unresolved external symbol __imp__CrtSetReportMode referenced in function "public: int __cdecl testing::UnitTest::Run(void)" (?Run@UnitTest@testing@@QEAAHXZ) [C:\linking_to_external_libraries\build\src\calculator\test\CalculatorTests.vcxproj]
C:\linking_to_external_libraries\build\out\Release\CalculatorTests.exe : fatal error LNK1120: 6 unresolved externals [C:\linking_to_external_libraries\build\src\calculator\test\CalculatorTests.vcxproj]

有什么问题吗?为什么使用 Release 配置构建项目失败?

我刚刚学习 CMake,所以我的理解可能不完整且不稳定,但我的印象是 CMake 应该抽象出链接到正确的构建配置特定版本的库的细节,以及在 CMake 配置之后/生成步骤,所期望的就是使用所需的配置运行

cmake --config ...


MCVE 所需的项目资源(计入此 udemy 课程):
(我认为项目源代码与该问题并不是非常相关,但我提供了完整性。我认为问题出在 CMake、Windows 共享库,也许还有多配置构建领域)

C:\linking_to_external_libraries>tree /f
Folder PATH listing for volume Windows
Volume serial number is 748B-8737
C:.
│   CMakeLists.txt
│
└───src
    │   CMakeLists.txt
    │
    ├───application
    │       CMakeLists.txt
    │       main.cpp
    │
    ├───calculator
    │   │   Calculator.cpp
    │   │   Calculator.h
    │   │   CMakeLists.txt
    │   │
    │   └───test
    │           CalculatorTests.cpp
    │           CMakeLists.txt
    │
    └───library
            CMakeLists.txt
            ServerProvider.cpp
            ServerProvider.h
# ./CMakeLists.txt
cmake_minimum_required(VERSION 3.20)
project(FindingExternalLibraries LANGUAGES CXX VERSION 2.5.0)

set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/out")

add_subdirectory(src)
# ./src/CMakeLists.txt
add_subdirectory(library)
add_subdirectory(calculator)
add_subdirectory(application)
# ./src/application/CMakeLists.txt
set(SOURCE_FILES main.cpp)

add_executable(Application ${SOURCE_FILES})

target_link_libraries(Application PUBLIC MyLibrary)
target_link_libraries(Application PUBLIC Calculator)

target_compile_definitions(Application PRIVATE APP_PROJECT_VERSION="${CMAKE_PROJECT_VERSION}")
// ./src/application.main.cpp
#include <iostream>

#include <ServerProvider.h>
#include <Calculator.h>

int main()
{
    std::cout << "Application version: " << APP_PROJECT_VERSION << std::endl;

    std::cout << "Connecting to " << ServerProvider::getHostName() << std::endl;

    std::cout << "3 + 6 = " << Calculator::sum(3, 6) << std::endl;

    return 0;
}
// ./src/calculator/Calculator.cpp
#include "Calculator.h"

namespace Calculator
{

int sum(int a, int b)
{
    return a + b;
}

}
// ./src/calculator/Calculator.h
#pragma once

namespace Calculator
{
    int sum(int a, int b);
};
# ./src/calculator/CMakeLists.txt
set(SOURCE_FILES Calculator.cpp)

add_library(Calculator STATIC ${SOURCE_FILES})

target_include_directories(Calculator INTERFACE .)

add_subdirectory(test)
// ./src/calculator/test/CalculatorTests.cpp
#include <gtest/gtest.h>

#include <Calculator.h>

TEST(SimpleTest, ExampleTestCase)
{
    // given:
    int a = 5;
    int b = 10;

    // when:
    const auto result = Calculator::sum(a, b);

    // expected:
    EXPECT_EQ(result, 15);
}
# ./src/calculator/test/CMakeLists.txt
set(TEST_FILES CalculatorTests.cpp)

find_package(GTest CONFIG REQUIRED)

add_executable(CalculatorTests ${TEST_FILES})

target_link_libraries(CalculatorTests PRIVATE GTest::gmock_main)
target_link_libraries(CalculatorTests PRIVATE Calculator)
# ./src/library/CMakeLists.txt
set(SOURCE_FILES ServerProvider.cpp)

set(APP_CONFIGURATION_TYPE "Development" CACHE STRING "Configuration type")
set_property(CACHE APP_CONFIGURATION_TYPE PROPERTY STRINGS Development Test Production)

option(APP_BUILD_LIB_AS_SHARED "Decides if MyLibrary is build as shared lib" ON)

if ($CACHE{APP_BUILD_LIB_AS_SHARED})
    add_library(MyLibrary SHARED ${SOURCE_FILES})
    if (MSVC)
        target_compile_definitions(MyLibrary PRIVATE "APP_LIBRARY_API=__declspec(dllexport)")
        target_compile_definitions(MyLibrary INTERFACE "APP_LIBRARY_API=__declspec(dllimport)")
    else ()
        target_compile_definitions(MyLibrary PUBLIC "APP_LIBRARY_API=")
    endif ()
else ()
    add_library(MyLibrary STATIC ${SOURCE_FILES})
    target_compile_definitions(MyLibrary PUBLIC "APP_LIBRARY_API=")
endif ()

target_include_directories(MyLibrary INTERFACE .)

if ($CACHE{APP_CONFIGURATION_TYPE} STREQUAL "Development")
    target_compile_definitions(MyLibrary PRIVATE APP_HOSTNAME="http://127.0.0.1")
elseif($CACHE{APP_CONFIGURATION_TYPE} STREQUAL "Test")
    target_compile_definitions(MyLibrary PRIVATE APP_HOSTNAME="http://test.com")
else()
    target_compile_definitions(MyLibrary PRIVATE APP_HOSTNAME="http://clientdatabaseadress.com")
endif ()
// ./src/library/ServerProvider.cpp
#include "ServerProvider.h"

namespace ServerProvider
{

std::string getHostName()
{
    return APP_HOSTNAME;
}

}// namespace ServerProvider
// ./src/library/ServerProvider.h
#pragma once

#include <string>

namespace ServerProvider
{
    APP_LIBRARY_API std::string getHostName();
};
cmake shared-libraries googletest
1个回答
0
投票

我通过实验偶然发现了这一点;在我的学习材料中没有明确指出这是必要的,但我通过将不同的想法放在一起来猜测它:

看起来当我为其发布配置构建项目时,它需要与 Google 测试发布配置共享库链接。 IE。我需要执行以下操作来构建 Google 测试:

  1. cmake -DCMAKE_INSTALL_PREFIX=build\install-dir -Dgtest_force_shared_crt=ON -S . -B build
  2. cmake --build build
  3. cmake --build build --config Release --target install

猜测这会构建并安装Google测试共享库的发布配置,这与调试配置共享库有显着不同;想必不仅仅是调试符号的存在/不存在。

我只是猜测这个联系;我不完全明白发生了什么,所以我希望另一个回答者能够出现并填补空白:我以前从未见过这个“符号不匹配”的问题(我主要在Linux上开发;Windows有点新)对我来说)。

我不明白为什么

gmock_maind.lib(gtest-all.obj)
CalculatorTests.obj
都会有
_ITERATOR_DEBUG_LEVEL
的定义:通常一段代码定义一个符号,而其他人使用它。我的项目源代码中没有明确使用
_ITERATOR_DEBUG_LEVEL

© www.soinside.com 2019 - 2024. All rights reserved.