Определите определения компиляции в библиотечных зависимостях для нескольких целей - PullRequest
1 голос
/ 09 ноября 2019

Есть ли способ установить определения компиляции для цели связанной библиотеки, но с разными наборами определений для библиотеки, используемой каждой целью (определения компиляции являются взаимоисключающими для библиотеки, связанной с каждой целью)?

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

target_compile_definitions() позволяет вам только определять определения для цели, но если она установлена ​​для цели библиотеки, она будет установлена ​​для обеих целей.

Единственный способ, которым я могу думать об этом, - это создатьфункция для добавления новых библиотечных целей, поэтому можно определить несколько библиотечных целей с разными определениями компиляции.

1 Ответ

1 голос
/ 09 ноября 2019

Это может работать в простом случае, который вы изложили, предполагая, что lib - еще одна цель, созданная в том же дереве сборки CMake. Вы можете использовать get_target_property(), чтобы получить список свойств LINK_LIBRARIES для TargetA и TargetB. Если lib находится в списке зависимостей ссылок первого уровня, вы можете добавить определение компиляции в 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()

Обратите внимание, это работает, только если lib является зависимость цели первого уровня, не рекурсивно ищет зависимости, как показано в этом ответе . Кроме того, если lib является интерфейсной библиотекой, вам нужно вместо этого получить свойство INTERFACE_LINK_LIBRARIES.


РЕДАКТИРОВАТЬ Основано на ответной реакции: если определения компиляции DEF_A и DEF_B являются взаимоисключающими в цели lib. Самым чистым подходом может быть создание отдельной цели lib, одна из которых предназначена для TargetA, а другая - для TargetB. Это может выглядеть примерно так:

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)
...