Object File Propragating: CMake Debug Help

We have a few core libraries that are really large as they’re used for modeling. If we need to add support for a new thing to model, then a small team will build modeling support for that thing. This was a great use for object libraries. But, there are three hierarchies.

Let’s say we’re modeling vehicles for a game simulation:

add_library(Vehicle ${vehicle_sources})
add_library(Ford OBJECT ${ford_sources})
add_library(FordFocus OBJECT ${fordfocus_sources})

target_sources(Ford  PRIVATE $<TARGET_OBJECTS:FordFocus >)

target_link_library(Vehicle PUBLIC Ford)

With this approach, I expect the object files from FordFocus and Ford to both be in the archive for Vehicle. For some reason that I can’t figure out, these object file sources are being propagated above Vehicle. It doesn’t happen on every target that links to Vehicle but on some. I would imagine the likely cause is a messed up rule I’m having a hard time tracking down.

What is a good method for trying to debug something like this?
The issue isn’t duplicate symbols, but incredibly long linking commands where some targets are trying to link the object files that shouldn’t be available in that form after Vehicle. Ninja and Make both are failing on this. Eventually, the command becomes && clang ++ -g ...,

In a similar note, I’ve tried printing the LINKED_LIBRARIES properties from a few different targets, but it fails in Ninja. Some libraries have generator expressions as part of their LINKED_LIBRARIES which has two effects in both Ninja and Make. The common failure is that some expressions aren’t evaluated. So you might get TARGET_PROPERTY:FordFocus,custom_proeprty>>;FordFocus.../. In these cases, Ninja complains about $ not being correctly escaped: ninja: error: build.ninja:35038: bad $-escape (literal $ must be written as $$)

function(print_target_linked_libraries Target)
    set(targetName "print_target_linked_libraries_${Target}")
    set(space "  ")
    set(linked_libraries "$<TARGET_PROPERTY:${Target},LINK_LIBRARIES>") 
    set(linked_librraies "$<GENEX_EVAL:${linked_libraries}>")
    # set(linked_libraries "$<JOIN:${linked_libraries}, ${space}>")

    add_custom_target(${targetName} 
        COMMAND ${CMAKE_COMMAND} -E cmake_echo_color --cyan ${Target}:libraries: "${linked_libraries}"
        COMMAND_EXPAND_LISTS
    )

endfunction() 

While typing I realized I had used target_sources instead of target_link_libraries. Not sure why this made a difference, but I’m not encountering any issues when properly linking these object files using the generator expressions and not adding to target sources.

If someone could still shed light on the Ninja issue and handling properties that have a mix of generator expressions and non-generator expressions, that would be great.

OBJECT libraries only give their objects to targets directly linking to them. If the target is found through a transitive dependency, they are not added (otherwise they’d duplicate every time a new target finds them in their transitive closure).

However, in your case, I think you “know” that Ford will only be directly used by Vehicle (though I think you’d need target_link_libraires(Vehicle PRIVATE Ford) to avoid duplicate symbols). You can then do target_sources(Ford INTERFACE $<TARGET_OBJECTS:FordFocus>). I think this will work, but you might need something like this feature which would allow you to then just model them as STATIC libraries instead.