Please see the below minimal example
cmake_minimum_required(VERSION 3.20)
project(sample)
add_library(libA A.cpp A.h)
add_library(libB B.cpp B.h)
add_executable(${PROJECT_NAME} main.cpp)
# Given it is known that libA and libB is incompatible,
# is it possible to write some extra cmake code to show error while doing cmake config,
# instead of having to compile to discover the error?
target_link_libraries(${PROJECT_NAME} libA libB) --> need to show error
# target_link_libraries(${PROJECT_NAME} libA) --> ok
# target_link_libraries(${PROJECT_NAME} libB) --> ok
Given that I can't alter the source of libA
and libB
to make them compatible, how can I discover the error earlier in the CMake configuration stage instead of having to compile the huge codebase to find out the error?
CodePudding user response:
Yes! This is actually possible using a little-known feature called Compatible Interface Properties.
You'll define a custom property with an arbitrary name. Here I'll call it ABI_GROUP
and use two different GUIDs for the values. Then you'll add that property to COMPATIBLE_INTERFACE_STRING
. See the code below:
cmake_minimum_required(VERSION 3.23)
project(example)
add_library(libA A.cpp A.h)
set_property(TARGET libA PROPERTY INTERFACE_ABI_GROUP "5c6142b9-9b60-4327-bd71-122bd29a9646")
set_property(TARGET libA APPEND PROPERTY COMPATIBLE_INTERFACE_STRING ABI_GROUP)
add_library(libB B.cpp B.h)
set_property(TARGET libB PROPERTY INTERFACE_ABI_GROUP "e291a3cd-50e4-44dc-a90c-66899d34bde5")
set_property(TARGET libB APPEND PROPERTY COMPATIBLE_INTERFACE_STRING ABI_GROUP)
add_executable(example main.cpp)
target_link_libraries(example PRIVATE libA libB)
This results in the following error:
CMake Error: The INTERFACE_ABI_GROUP property of "libB" does
not agree with the value of ABI_GROUP already determined
for "example".
The values of all properties in the COMPATIBLE_INTERFACE_STRING
list must either be empty or match among the transitive set of targets that are linked together. There are also a few other modes:
COMPATIBLE_INTERFACE_BOOL
- same as string, but tolerant to "truthy" values, i.e.ON
and1
are considered compatibleCOMPATIBLE_INTERFACE_NUMBER_MAX
- the property evaluates to the largest number among the transitive target set.COMPATIBLE_INTERFACE_NUMBER_MIN
- same as above, but smallest