[PATCH 1/1] build/cmake: Fix CMP0023 warning with libffi

Brad King brad.king at kitware.com
Wed Sep 3 16:51:19 PDT 2014

On 9/3/2014 5:22 PM, Dan Liew wrote:
> I'm a little confused as to why the PUBLIC, PRIVATE and INTERFACE
> exist at all. Even if the library has an implementation-only
> dependency any user of that library still needs to link against that
> dependency, so there isn't anything "PRIVATE" about it.

They are for usage requirements beyond just linking.  If dependent
code does not include the headers of the private implementation
dependency then it does not need any usage requirement such as
include directories or preprocessor definitions.

Conceptually it is a private implementation dependency.  It is only
an implementation detail that dependents need to link the private
dependencies of a static library transitively.  Private dependencies
of SHARED libraries are not propagated even for linking.

The cmake-buildsystem(7) manual in CMake 3.0 explains in more detail.

> I tried using PUBLIC, INTERFACE and PRIVATE and the libffi library is
> in the list of libraries for the INTERFACE_LINK_LIBRARIES property of
> LLVMInterpreter exported target in
> ``share/llvm/cmake/LLVMExports.cmake`` in all three cases.

Linking is necessary when LLVMInterpreter is a static library
so the dependency is always listed in INTERFACE_LINK_LIBRARIES.
In the PRIVATE case ffi should appear in a LINK_ONLY generator
expression.  This suppresses usage requirements besides linking.

> Thanks for that information. I'm not entirely sure what "usage
> requirements" are

CMake can now automatically propagate compile definitions, include
dirs, and a few other things to the compilation rules of sources
in targets that "use" a given library.  This allows one to do things

 add_executable(myexe myexe.c)
 target_link_libraries(myexe Foo::SomeLib)

and get myexe.c compiled with the include dirs for SomeLib without
any manual include_directories(${Foo_INCLUDE_DIRS}) call.  They
come as usage requirements of the Foo::SomeLib imported target.

> but [1] seems to suggest they are the INTERFACE_*
> (e.g.  INTERFACE_COMPILE_DEFINITIONS) target properties set by
> ``target_include_directories(), target_compile_definitions() and
> target_compile_options()``. INTERFACE_LINK_LIBRARIES doesn't seem to a
> usage requirement. Is that right?

INTERFACE_LINK_LIBRARIES is the main usage requirement: it specifies
transitive link dependencies.  The other usage requirements must be
propagated from the targets in the transitive closure of the link
interface graph.

> Reading a little further on the example in [2] seems to suggest that
> actually the PUBLIC, INTERFACE and PRIVATE keywords for
> target_link_libraries() actually controls how these "usage
> requirements" are propagated and actually has nothing to do with
> setting the INTERFACE_LINK_LIBRARIES property at all.

INTERFACE_LINK_LIBRARIES is affected, just less so for static libs
than for shared libs.  Also note that the INTERFACE_LINK_LIBRARIES
of a library does not affect how it is built: that is LINK_LIBRARIES,
which is not populated by the INTERFACE keyword.


More information about the llvm-commits mailing list