Home > Back-end >  Is it possible for CMake to show error when linking to two incompatible libraries?
Is it possible for CMake to show error when linking to two incompatible libraries?

Time:08-06

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 and 1 are considered compatible
  • COMPATIBLE_INTERFACE_NUMBER_MAX - the property evaluates to the largest number among the transitive target set.
  • COMPATIBLE_INTERFACE_NUMBER_MIN - same as above, but smallest
  • Related