CMake跨目标循环依赖问题:如何避免多次运行CMake编译?
This is a classic CMake dependency ordering issue—here's what's happening and how to fix it:
When CMake runs the first time, it processes add_subdirectory(foo) first. At that point, the bar target hasn't been defined yet (since add_subdirectory(bar) comes later). So when foo's CMakeLists tries to create a test executable that links against bar, CMake can't resolve that target immediately. On the second run, since bar exists in the cache, it fills in the missing dependency and everything works.
The cleanest fixes avoid this "chicken-and-egg" scenario entirely. Here are two practical approaches:
1. Move cross-dependent tests to a parent directory
Since your foo tests need bar's functionality, move them out of the foo subdirectory and define them in the libs/CMakeLists.txt after both foo and bar are added. This ensures both targets exist when the test is created:
# libs/CMakeLists.txt add_subdirectory(foo) # Process foo first (bar depends on it) add_subdirectory(bar) # Now bar is fully defined # Add foo's tests that depend on bar add_executable(foo_feature_test foo/test/new_feature_tests.cpp # Path to your test files ) target_link_libraries(foo_feature_test PRIVATE foo # Link against foo's library bar # Link against bar's library (now exists!) ) # Register the test with CTest add_test(NAME FooNewFeatures COMMAND foo_feature_test)
Then, remove the test-related code from foo/CMakeLists.txt. This way, CMake resolves all dependencies in a single run.
2. Refactor to eliminate cross-test dependencies (if possible)
If moving tests feels messy, see if you can extract the bar functionality needed by foo's tests into a small, shared utility library that both foo and bar depend on. For example:
- Create a
libs/utilsubdirectory with its own CMakeLists.txt - Move the shared code into
util - Update
fooandbarto link againstutil - Now foo's tests can link against
fooandutilinstead ofbar, avoiding the need to wait for bar to be processed.
Why this works
CMake processes add_subdirectory calls sequentially, so targets defined in later subdirectories aren't available to earlier ones. By defining the cross-dependent test after both libraries are set up, you avoid the "target not found" state that triggers the need for a second CMake run.
内容的提问来源于stack exchange,提问作者lesurp

