Since the question is about CMake, let me propose an alternative from CMake perspective.
With CMake you can construct your tests to compile your source file to be tested (SUT) together with your test instead of linking with the target being tested.
This would add some extra compilation time as the source file needs to be recompiled within the test. If this is a problem please, you might stop reading.
Assuming this is not an issue for you, then you can simply pull in the PUBLIC header dependencies without pulling in their implementations. You can then implement mocks/fakes for dependencies used in your test file.
Here is an example source file include/foo.h, foo.c, and CMakeLists.txt.
#include <ext_decl.h> //Declares struct ext_lib_struct_t in a CMake target ext_decl_lib
int foo(struct ext_lib_struct_t a);
#include <foo.h> //Declares void* foo();
#include <ext_impl.h> //This is the header declaring extlibcall in a CMake target ext_impl_lib
int foo(struct ext_lib_struct_t a) {
return extlibcall(a); //A mock will be used for this call.
}
add_library(foo_lib)
target_sources(foo_lib
PRIVATE
foo.c
)
target_link_libraries(foo_lib
PUBLIC
ext_decl_lib
PRIVATE
ext_impl_lib
)
target_include_directories(foo_lib
PUBLIC
include # Where foo.h is.
)
Here is your test file, testfoo.c. Customize this with your favorite unit testing framework.
#include <foo.h>
#include <assert.h>
int test_data;
int extlibcall() {
return test_data;
}
void testA() { //Replace this with test cases from your favorite unit testing platform.
test_data = 2;
int tr = foo();
ASSERT(test_data == tr); //Use your favorite assert utility.
}
int main(void)
{
testA();
return 0;
}
And finally CMake instructions for your test, which can go into a CMakeLists.txt file in your test directory.
add_executable(testlibfoo)
target_sources(testlibfoo
PRIVATE
testfoo.c
$<TARGET_PROPERTY:foo_lib,SOURCE_DIR>/foo.c
)
target_include_directories(test_unity_sall_mgm_join
PRIVATE
include
$<TARGET_PROPERTY:foo_lib,INCLUDE_DIRECTORIES>
)
target_link_libraries(test_unity_sall_mgm_join
PRIVATE
assert_lib
#Add your favorite unit test framework and/or other libraries used in the test
)
Test code compiles foo.c only once since foo_lib is not linked. However, it will probably be recompiled later for your production code when some other library links to foo_lib.