How to mark GMock as a required component

I’m using CMake 3.27 and use both GTest and GMock in a package.

There are a few options I’ve seen to pull this in:

  1. With the FindGTest module
include(FindGTest)
  1. Directly with find_package
find_package(GTest CONFIG REQUIRED COMPONENTS GTest GMock)
  1. With FetchContent as recommended by GTest, which doesn’t allow us to use the system package version

On Ubuntu 22, libgtest-dev and libgmock-dev are distributed as separate packages. It’s common to have libgtest-dev and not libgmock-dev. In that situation,

  • GTest::gtest will exist
  • GTest::gmock will not exist

The libgmock-dev package comes with /usr/lib/x86_64-linux-gnu/cmake/GTest/GMockTargets.cmake

My usage:

add_executable(MyTest
    main.cpp
)
set(CMAKE_FIND_DEBUG_MODE ON)
find_package(GTest CONFIG REQUIRED COMPONENTS GTest GMock)
set(CMAKE_FIND_DEBUG_MODE OFF)

target_link_libraries(MyTest
    PRIVATE
    ${PROJECT_NAME}::MyLibrary
    GTest::gtest
    GTest::gmock
)

Logs when building tests:

CMake Debug Log at testbench/CMakeLists.txt:10 (find_package):
    /usr/lib/x86_64-linux-gnu/cmake/GTest/GTestConfig.cmake



-- Configuring done (0.3s)
CMake Error at testbench/CMakeLists.txt:13 (target_link_libraries):
  Target "MyTest" links to:

    GTest::gmock

  but the target was not found.  Possible reasons include:

    * There is a typo in the target name.
    * A find_package call is missing for an IMPORTED target.
    * An ALIAS target is missing.

Why is there not an error in find_package when I specify GMock as a required component? I would expect an error that the component was not found and a find_package result of failure.

It works fine:

$ cmake -B build -S . -G Ninja --debug-find-pkg=GTest
Running with debug output on for the 'find' commands for package(s) GTest.
CMake Debug Log at /home/klein_cl/.local/lib/python3.10/site-packages/cmake/data/share/cmake-3.28/Modules/CMakeFindDependencyMacro.cmake:76 (find_package):
  find_package considered the following paths for FindThreads.cmake:

  The file was found at

    /home/klein_cl/.local/lib/python3.10/site-packages/cmake/data/share/cmake-3.28/Modules/FindThreads.cmake

Call Stack (most recent call first):
  /usr/lib/x86_64-linux-gnu/cmake/GTest/GTestConfig.cmake:39 (find_dependency)
  CMakeLists.txt:6 (find_package)


CMake Debug Log at CMakeLists.txt:6 (find_package):
    /usr/lib/x86_64-linux-gnu/cmake/GTest/GTestConfig.cmake



-- Configuring done (0.0s)
-- Generating done (0.0s)
-- Build files have been written to: /home/klein_cl/Workspace/cpp/test/build

$ tree /usr/lib/x86_64-linux-gnu/cmake/GTest/
/usr/lib/x86_64-linux-gnu/cmake/GTest/
├── GMockTargets-none.cmake
├── GMockTargets.cmake
├── GTestConfig.cmake
├── GTestConfigVersion.cmake
├── GTestTargets-none.cmake
└── GTestTargets.cmake

0 directories, 6 files

Uninstall GMock, and try again? That’s when it exhibited poor behavior for me.

I guess it is a problem with find_dependency()

Replace in /usr/lib/x86_64-linux-gnu/cmake/GTest/GTestConfig.cmake find_dependency(x) with find_package(x REQUIRED) and try again.

Also, it seems odd at the end of that file, it says that the GMockTargets.cmake file is optional

include("${CMAKE_CURRENT_LIST_DIR}/GMockTargets.cmake" OPTIONAL)

Shouldn’t the optional keyword be added if <PackageName>_FIND_COMPONENTS ie, GTest_FIND_COMPONENTS is missing GMock?
Reference:
https://cmake.org/cmake/help/latest/command/find_package.html#package-file-interface-variables