Derek
Derek

Reputation: 93

Link errors when using CMake and VCPKG with GoogleTest

As a bit of background, I have a project that I have been developing with Visual Studio and VCPKG manifest mode for some time, it contains one static library project and one unit test project. Everything has been working correctly. I'm now trying to migrate this solution to use CMake, this is my first time using CMake.

With CMake the VCPKG dependencies install correctly, and both the static library and unit tests compile, however it fails on the linking step with a large number of linker errors all related to the GoogleTest library. Here is the first, as an example:

CppSlippiTest.obj : error LNK2019: unresolved external symbol "class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __cdecl testing::internal::FormatMatcherDescription(bool,char const *,class std::vector<char const*,class std::allocator<char const *> > const &,class std::vector<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::allocator<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > > > const &)" (?FormatMatcherDescription@internal@testing@@YA?AV$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@_NPEBDAEBV?$vector@PEBDV$allocator@PEBD@std@@@4@AEBV?$vector@V?$basic_string@DU?$char_traits@D@std@@V$allocator@D@2@@std@@V?$allocator@V?$basic_string@DU$char_traits@D@std@@V?$allocator@D@2@@std@@@2@@4@@Z) referenced in function "private: class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __cdecl cpp_slippi::MatchOptionalMatcherP2<class testing::internal::Eq2Matcher,class std::optional<unsigned char> >::gmock_Impl<class std::optional<unsigned char> const &>::FormatDescription(bool)const " (?FormatDescription@$gmock_Impl@AEBV?$optional@E@std@@@$MatchOptionalMatcherP2@VEq2Matcher@internal@testing@@V?$optional@E@std@@@cpp_slippi@@AEBA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@_N@Z) [C:\Users\Derek\Projects\CppSlippi\build\Test.vcxproj]

There are 36 more of these.

Here is my CMakeLists.txt, slightly abridged for clarity:

cmake_minimum_required(VERSION 3.12...3.24)

# Must be before project()
set(VCPKG_TARGET_TRIPLET x64-windows-static)

project(CppSlippi
    VERSION 1.0
    DESCRIPTION "Slippi replay file parsing library for C++."
    LANGUAGES CXX)

set(CMAKE_CXX_STANDARD_REQUIRED ON)

find_package(GTest CONFIG REQUIRED)
find_package(nlohmann_json CONFIG REQUIRED)

add_library(CppSlippi STATIC
    CppSlippi/src/CppSlippi.cpp
    CppSlippi/src/CppSlippi.h
    ...)
target_include_directories(CppSlippi PUBLIC CppSlippi/src)
target_compile_features(CppSlippi PUBLIC cxx_std_20)
target_compile_options(CppSlippi PUBLIC /MTd)
set_target_properties(CppSlippi PROPERTIES CXX_EXTENSIONS OFF)
target_link_libraries(CppSlippi PUBLIC nlohmann_json::nlohmann_json)

if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
    include(CTest)
    include(GoogleTest)
endif()

if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME AND BUILD_TESTING)
    add_executable(Test
        Test/src/CppSlippiTest.cpp
        ...)
    target_include_directories(Test PUBLIC Test/src)
    target_compile_features(Test PUBLIC cxx_std_20)
    target_compile_options(Test PRIVATE /bigobj /MTd)
    set_target_properties(Test PROPERTIES CXX_EXTENSIONS OFF)
    target_link_libraries(Test PUBLIC
        CppSlippi
        nlohmann_json::nlohmann_json
        GTest::gtest_main)

    gtest_discover_tests(Test)
endif()

Here is my VCPKG manifest:

{
    "$schema": "https://raw.githubusercontent.com/microsoft/vcpkg/master/scripts/vcpkg.schema.json",
    "name": "cpp-slippi",
    "version": "1.0.0",
    "description": "C++ Slippi replay parser.",
    "builtin-baseline": "68b7fec22eb5fd9c0236b1e42b3c0deb8e771b37",
    "dependencies": [
        "gtest",
        "nlohmann-json"
    ],
    "supports": "windows"
}

And to build this I am running:

cmake --build build --target Test

I turned on --verbose to get more information, and this is the link command that CMake is running:

Link:
  C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.34.31933\bin\HostX64\x64\link.exe /ERRORREPO
  RT:QUEUE /OUT:"C:\Users\Derek\Projects\CppSlippi\build\Debug\Test.exe" /INCREMENTAL /ILK:"Test.dir\Debug\Test.ilk" /N
  OLOGO /NATVIS:"C:\Users\Derek\Projects\CppSlippi\build\vcpkg_installed\x64-windows-static\share\nlohmann_json\nlohman
  n_json.natvis" Debug\CppSlippi.lib "vcpkg_installed\x64-windows-static\debug\lib\manual-link\gtest_main.lib" "vcpkg_i
  nstalled\x64-windows-static\debug\lib\gtest.lib" kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib
   oleaut32.lib uuid.lib comdlg32.lib advapi32.lib /MANIFEST /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /manifes
  t:embed /DEBUG /PDB:"C:/Users/Derek/Projects/CppSlippi/build/Debug/Test.pdb" /SUBSYSTEM:CONSOLE /TLBID:1 /DYNAMICBASE
   /NXCOMPAT /IMPLIB:"C:/Users/Derek/Projects/CppSlippi/build/Debug/Test.lib" /MACHINE:X64  /machine:x64 Test.dir\Debug
  \CppSlippiTest.obj ...

Note the presence of gtest_main.lib and gtest.lib, these are the libraries that I believe should include the missing functions. I have checked that these files are present at the locations shown.

I know that in Visual Studio using the GoogleTest main requires adding an AdditionalDependency manually, but from all the instructions I can find this should not be necessary in CMake and the .lib is already in the command line. I did try using target_link_directories anyways, but this did not help.

At this point I am baffled and searching on Google and Stack Overflow has failed to turn up any help.

Upvotes: 0

Views: 1374

Answers (1)

3CxEZiVlQ
3CxEZiVlQ

Reputation: 38863

You link only one of 4 GoogleTest libraries to your app

target_link_libraries(Test PUBLIC
    CppSlippi
    nlohmann_json::nlohmann_json
    GTest::gtest_main)

Depending on the application needs, it should be linked to at least one more library

target_link_libraries(Test PUBLIC
    CppSlippi
    nlohmann_json::nlohmann_json
    GTest::gtest_main
    GTest::gtest)

Or

target_link_libraries(Test PUBLIC
    CppSlippi
    nlohmann_json::nlohmann_json
    GTest::gmock_main
    GTest::gmock 
    GTest::gtest)

Upvotes: 1

Related Questions