CMake、子目录与Google Test(Mock)链接异常:测试未被检测到
Let’s dig into this—this kind of linking problem with nested CMakeLists is a super common gotcha, and the fact that you’re seeing the #warning in your test file means the test target is being compiled, but the linking step isn’t behaving as expected. Let’s break down the most likely causes and fixes:
First, Confirm the Core Problem
If removing the source library from target_link_libraries doesn’t trigger an undefined reference error, one of two things is happening:
- Your test file (
test_Some.cpp) isn’t actually calling any functions/classes from the source library (so there’s no symbol to resolve), or - CMake isn’t properly associating your test executable with the source library target at all.
Let’s rule out the first one first: add an explicit call to a function from your source library in test_Some.cpp (e.g., MySourceLib::someFunction()), then rebuild. If you still don’t get an undefined reference error, we know the issue is on the CMake side.
Step-by-Step CMake Configuration Checks
1. Verify Directory Structure & Subdirectory Inclusion
Make sure your parent CMakeLists files are correctly including child directories:
- Root
ProjectFolder/CMakeLists.txtmust haveadd_subdirectory(source)to process the source directory’s config. ProjectFolder/source/CMakeLists.txtmust haveadd_subdirectory(test)to process the test directory’s config.
If either of these is missing, your test target might be getting built in a context that can’t see the source library.
2. Check the Source Library Definition
In ProjectFolder/source/CMakeLists.txt, ensure you’re properly creating the library target and exposing its headers:
# Replace "MySourceLib" with your actual library name add_library(MySourceLib STATIC # Or SHARED, depending on your needs # List your source files here, e.g.: src/YourCoreCode.cpp include/YourCoreHeader.h ) # Critical: Make headers accessible to dependent targets (like your test) target_include_directories(MySourceLib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include )
The PUBLIC keyword here ensures that any target linking against MySourceLib also gets access to its header files.
3. Validate the Test Target’s Linking
In ProjectFolder/source/test/CMakeLists.txt, double-check your test executable and linking setup:
add_executable(sourceTest test_Some.cpp # Add other test files here if needed ) # Link against the source library—use EXACTLY the same target name as defined in source/CMakeLists.txt target_link_libraries(sourceTest PRIVATE MySourceLib )
Common mistakes here: typos in the library target name, or using a path to a library file instead of the CMake target name (which bypasses CMake’s dependency tracking).
4. Inspect the Build Command Verbose Output
Run a verbose build to see exactly what’s happening during linking:
cmake --build . --verbose
Look for the linking step for sourceTest—you should see your source library (e.g., libMySourceLib.a or MySourceLib.lib) listed in the command. If it’s missing, CMake isn’t adding it, which means your target_link_libraries line is either incorrect or the library target isn’t visible to the test directory.
5. Ensure Target Visibility
CMake allows child directories to reference targets created in parent directories, but only if the parent directory’s target is defined before the child directory is added. Since you’re adding test as a subdirectory of source, this should work—but double-check that your add_library call in source/CMakeLists.txt comes before add_subdirectory(test). If you add the test subdirectory first, the library target won’t exist yet when the test config runs.
Example Working Configuration
To tie this all together, here’s a minimal working setup matching your directory structure:
ProjectFolder/CMakeLists.txt:
cmake_minimum_required(VERSION 3.16) project(MyProject) add_subdirectory(source)
ProjectFolder/source/CMakeLists.txt:
add_library(MySourceLib STATIC src/Core.cpp include/Core.h ) target_include_directories(MySourceLib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include ) # Add test subdirectory AFTER defining the library add_subdirectory(test)
ProjectFolder/source/test/CMakeLists.txt:
add_executable(sourceTest test_Some.cpp ) target_link_libraries(sourceTest PRIVATE MySourceLib ) # Optional: Add the test to CTest for easy running add_test(NAME SourceTest COMMAND sourceTest)
Final Checks
- If you’re using
INTERFACElibraries: If your source library is defined asadd_library(MySourceLib INTERFACE), it only provides headers, not compiled code—so removing it from linking won’t trigger errors. Switch toSTATICorSHAREDif you have compiled code. - Clean your build directory: Sometimes cached CMake configurations cause weird issues. Delete your
buildfolder, re-runcmake .., and rebuild from scratch.
内容的提问来源于stack exchange,提问作者Daan Timmer

