Nick
Nick

Reputation: 4248

Define compile definitions in library dependencies for multiple targets

Is there a way to set compile definitions for a linked library target but with different sets of definitions for the library used by each target (compile defs are mutually exclusive for the lib linked with each target)?

Target A > lib with -DDEF_A only
Target B > lib with -DDEF_B only

target_compile_definitions() only allows you to set definitions on a target, but if set on the library target this would be set for both targets.

The only way I can think of doing it is to create a function to add new library targets, so multiple library targets can be defined with different compile definitions.

Upvotes: 2

Views: 1267

Answers (1)

Kevin
Kevin

Reputation: 18243

This could work with the simple case you've laid out, assuming lib is another target created within the same CMake build tree. You could use get_target_property() to get the LINK_LIBRARIES property list for TargetA and TargetB. If lib is in the list of first-level link dependencies, then you can add the compile definition to lib.

# Get the list of first-level link dependencies for TargetA and TargetB.
get_target_property(TARGETA_LIBS TargetA LINK_LIBRARIES)
get_target_property(TARGETB_LIBS TargetB LINK_LIBRARIES)

# Loop through the TargetA dependencies.
foreach(LIB ${TARGETA_LIBS})
    # Was the 'lib' library added as a dependency to TargetA?
    if (${LIB} STREQUAL lib)
        # Yes, so add the compile definitions to 'lib'.
        target_compile_definitions(${LIB} PRIVATE DEF_A)
    endif()
endforeach()

# Loop through the TargetB dependencies.
foreach(LIB ${TARGETB_LIBS})
    # Was the 'lib' library added as a dependency to TargetB?
    if (${LIB} STREQUAL lib)
        # Yes, so add the compile definitions to 'lib'.
        target_compile_definitions(${LIB} PRIVATE DEF_B)
    endif()
endforeach()

Note, this only works if lib is a first-level dependency of the target, it does not search dependencies recursively, as shown in this answer. Also, if lib is an interface library, you'll have to get the INTERFACE_LINK_LIBRARIES property instead.


EDIT Based on answer feedback: If the compile definitions DEF_A and DEF_B are mutually exclusive in the lib target. The cleanest approach may be to create a separate lib target, one catered for TargetA and another catered for TargetB. This could look something like this:

set(LIB_SOURCES 
    Class1.cpp
    ...
)

# Create the 'lib' target to link to TargetA.
add_library(lib_forTargetA SHARED ${LIB_SOURCES})
target_compile_definitions(lib_forTargetA PRIVATE DEF_A)

# Create the 'lib' target to link to TargetB.
add_library(lib_forTargetB SHARED ${LIB_SOURCES})
target_compile_definitions(lib_forTargetB PRIVATE DEF_B)

Upvotes: 1

Related Questions