23

I managed to build llvm and clang and now I am trying to create a ClangTool according to clang docs. But I am getting the following error when I am trying to build it:

CMake Error at tools/clang/tools/loop-convert/CMakeLists.txt:6 (target_link_libraries):
  The keyword signature for target_link_libraries has already been used with 
  the target "loop-convert".  All uses of target_link_libraries with a target
  must be either all-keyword or all-plain.

  The uses of the keyword signature are here:

    * cmake/modules/LLVM-Config.cmake:105 (target_link_libraries)
    * cmake/modules/AddLLVM.cmake:771 (target_link_libraries)

My current CMakeLists.txt is:

set(LLVM_LINK_COMPONENTS support)

add_clang_executable(loop-convert
  LoopConvert.cpp
)

target_link_libraries(loop-convert
  clangTooling
  clangBasic
  clangASTMatchers
)
einpoklum
  • 118,144
  • 57
  • 340
  • 684
Horatiu Vultur
  • 265
  • 2
  • 6

2 Answers2

18

You need to use keyword signature of target_link_libraries; effectively, you need to add PRIVATE to the target_link_libraries statement in your CMakeLists.txt:

target_link_libraries(loop-convert PRIVATE
  clangTooling
  clangBasic
  clangASTMatchers
)

This is because add_llvm_executable uses such signature and you can't mix them in CMake.

ssc
  • 9,528
  • 10
  • 64
  • 94
arrowd
  • 33,231
  • 8
  • 79
  • 110
0

IMHO, CMake should have just printed a pedantic warning rather than hard-breaking the API people have been relying on. The following code makes the function backward-compatible, while still allowing the newer signature to be used. It prints a warning to remind you to upgrade your code.

function(target_link_libraries target)
    if(ARGV1 MATCHES "^(PRIVATE|PUBLIC|INTERFACE)$")
        _target_link_libraries(${target} ${ARGN})
    else()
        _target_link_libraries(${target} PUBLIC ${ARGN})
        message(AUTHOR_WARNING "target_link_libraries: missing PRIVATE, PUBLIC or INTERFACE for target ${target}. Defaulting to PUBLIC.")
    endif()
endfunction()
Johan Boulé
  • 1,936
  • 15
  • 19
  • There is no "hard-breaking the API". It is perfectly allowed to use `target_link_libraries` without a keyword (PUBLIC/PRIVATE/INTERFACE) and CMake won't warn about that. But mixing keyword and non-keyword calls to `target_link_libraries` for a single target was never allowed. Also, a non-keyword call is NOT strictly equivalent to PUBLIC keyword: https://stackoverflow.com/questions/51396608/what-is-default-target-link-libraries-privacy-setting. (In many aspects non-keyword and PUBLIC keyword behaves similarly. But for backward compatibility non-keyword has specifics in complex cases.) – Tsyvarev Apr 17 '23 at 18:36
  • Ah, thanks for the clarification as to when exactly the problem starts to occur. So, my wrapper only works most of the time, but there's no guarantee that it's bug-for-bug compatible with older cmake scripts :/ – Johan Boulé Apr 26 '23 at 14:10