CMake: Alternates to target_link_libraries(PUBLIC)

While I have been working for target_include_directories, I have noticed it would be smarter that interfaces of compilation may be propagated as PUBLIC.

OTOH, PUBLIC shall break CMAKE_LINK_WHAT_YOU_USE in BUILD_SHARED_LIBS.

I propose a few compatible options for this.

Introduce “direct link only for SHARED and EXECUTABLE”

  • Don’t use target_link_libraries(PUBLIC) by default.
  • Use $<COMPILE_ONLY> for SHARED libs.
    • $<COMPILE_ONLY> will be introduced in the next release of CMake.
    • I can emulate it with a weird genex.
      add_library(foo SHARED)
      target_link_libraries(foo PRIVATE bar)
      target_link_libraries(foo INTERFACE $<IF:$<BOOL:$<LINK_ONLY:1>>:,,bar>
      
  • Use INTERFACE/PUBLIC for STATIC.

Introduce the rule to propagate PUBLIC INTERFACE libs

  • Define add_library(INTERFACE) for PUBLIC interfaces. Assume tablegen targets.
  • Propagate INTERFACE libs manually to traverse dependents in AddLLVM.cmake.
    • Re-add INTERFACE libs manually as PUBLIC/INTERFACE

Background

When I was playing CMake a decade years ago, target_link_libraries(PUBLIC) behaved messily. I introduced target_link_libraries(INTERFACE) to avoid such messiness.

I supposed then I could maintain complexity due to INTERFACE. (Sorry I had abandoned for long time)

For several years, CMake has been improved.

  • Isolate dependencies between compilation and linking (3.9)
  • Introduce CMAKE_OPTIMIZE_DEPENDENCIES (3.19)

Then I concluded we could use PRIVATE.

That said, I strongly disagree introducing PUBLIC unconditionally, due to the reason for SHARED, above.