Macros, target_link_library, target_sources evaluation questions

I am developing a set of practices to facilitate commonality in our projects. One of them, to facilitate unit tests, is that for a given executable, all the sources except for “main” should be in a “library” (OBJECT library is fine). This makes it easier to write unit tests in a sub-directory without awkward cross-directory references.

The basic construct looks like this:

set(myTarget foo) # for the "foo" executable
set(myDepend ${myTarget}Lib) # testable sources

add_library( ${myDepend} OBJECT ...  )
add_executable( ${myTarget} ... )
target_link_libraries( ${myTarget} ${myDepend} ...)

To facilitate this pattern, I’ve created a macro in the top-level CMakeLists.txt:

macro( DeclProg target )
  set( myTarget ${target} )
  set( myDepend ${myTarget}Lib )

  add_library( ${myDepend} OBJECT )
  add_executable( ${myTarget} )
  target_link_libraries( ${myTarget} PRIVATE {$myDepend} )
endmacro()

Then, in the “foo/CMakeLists.txt”, I just do

DeclProg( foo )

target_sources( ${myDepend} PUBLIC foo1.cc )
target_sources( ${myTarget} PRIVATE main.cc )

# as needed
target_link_libraries( ${myDepend} PUBLIC
  #any libraries needed
)

Unfortunately, this is causing linker errors with multiple definitions of code. Running make VERBOSE=1 I can see this link line (line breaks added for readability):

c++ -g "CMakeFiles/foo.dir/main.cpp.o"
 "CMakeFiles/foo.dir/foo1.cpp.o"
 "CMakeFiles/foo.dir/foo1.cpp.o"
 CMakeFiles/foo.dir/cmake_device_link.o
 -o foo
 -L/usr/local/cuda/targets/x86_64-linux/lib  <elided various libraries>

Why is foo1.cpp.o being listed twice on the link line?

CMake: 3.26.1
RHEL 9
gcc 12.2.1
CUDA 12.1.0 (the cuda code is in static libraries, which triggers the cmake_device_link.o file)

PUBLIC sources are added to the target itself and anything that links to it. Use PRIVATE instead.

Thanks @ben.boeckel . That was the ticket.