I wrote this function. At first attempt it seems to do what I want but
I've definitely not completed my work so I may well still find issues
with it.
Basically it does everything that target_link_libraries() does (at
least, it tries to as best as I understand it other than a bunch of
properties I don't know what they are and don't use) with one caveat:
it adds libraries to INTERFACE_* but not LINK_LIBRARIES:
function(static_link_libraries tgt mode)
foreach(lib ${ARGN})
# Import all the source-level properties as normal
foreach(t COMPILE_DEFINITIONS COMPILE_FEATURES COMPILE_OPTIONS
INCLUDE_DIRECTORIES SOURCES SYSTEM_INCLUDE_DIRECTORIES)
if(${mode} STREQUAL "PRIVATE" OR ${mode} STREQUAL "PUBLIC")
set_property(TARGET ${tgt} APPEND PROPERTY
${t} $)
endif()
if(${mode} STREQUAL "PUBLIC" OR ${mode} STREQUAL "INTERFACE")
set_property(TARGET ${tgt} APPEND PROPERTY
INTERFACE_${t} $)
endif()
endforeach()
# Import all the library-level properties as INTERFACE only
foreach(t LINK_DEPENDS LINK_DIRECTORIES LINK_OPTIONS)
set_property(TARGET ${tgt} APPEND PROPERTY
INTERFACE_${t} $)
endforeach()
# Import the library itself as INTERFACE only
set_property(TARGET ${tgt} APPEND PROPERTY
INTERFACE_LINK_LIBRARIES ${lib})
endforeach()
endfunction()
On Sat, 2019-02-16 at 23:03 +0100, Andreas Naumann wrote:
> Hi Paul,
>
> I understand the relationship between libraries as strict, such that you
> always build all dependent libraries before.
> In your use case I thought about splitting the libraries in the actual
> target and the interface one.
> For example, you could create an interface library foo_interface
> add_library(foo_interface INTERFACE )
> set the properties and then link foo and bar to this interface library
> using target_link_libraries.
>
> But be aware, that now every executable, which links against bar must
> manually link against foo. If your project is large, this seems not
> really desirable. But I think you could also split the library bar in
> two bar_withoutFoo and bar. The library bar_withoutFoo would link
> against foo_interface and compile the sources, whereas bar is an
> interface library which depends on bar_withoutFoo and foo.
> The developer could than build bar completely independent from foo and
> you could transport the transitive dependencies to the executable.
>
> I don't know if this doubled structure using pure interfaces libraries
> and the actual libraries is maintainable.
>
> Hope that helps a bit,
> Andreas
>
> Am 16.02.19 um 20:20 schrieb Paul Smith:
> > Hi all;
> >
> > I'm working on modernizing our large complex CMake environment. It
> > builds a number of different binaries from an even larger number of
> > static libraries, and these libraries depend on each other as well, in
> > that they need to include headers and, sometimes, -D options etc.
> >
> > I've used straightforward target_link_libraries() to declare the
> > relationship between these libraries; for example:
> >
> >add_library(foo STATIC ...)
> >target_include_directories(foo PUBLIC ...)
> >target_compile_definitions(foo PUBLIC ...)
> >target_compile_options(foo PUBLIC ...)
> >
> >add_library(bar STATIC ...)
> >target_link_libraries(bar PUBLIC foo)
> >
> >add_executable(one ...)
> >target_link_libraries(one PRIVATE bar)
> >
> > This works, in that everything builds properly but it has a side-effect
> > we want to avoid. Because the source tree is large many developers
> > have a habit of testing compilation of subsets of the code using
> > something like:
> >
> >make -jX bar
> >
> > and expect it to just build the static library bar. Because it's a
> > static library you don't need to actually build "foo" until link time.
> > But we do need all the include directories, compile definitions, and
> > compile options to be inherited from "foo" into "bar".
> >
> > However with the above formulation, building "bar" also forces the
> > compilation of "foo", which we don't need or want.
> >
> > I've played around with the different values of PUBLIC, PRIVATE, and
> > INTERFACE but there doesn't seem to be a straightforward way to say,
> > "take the interface values for includes, definitions, and options, but
> > don't depend on the generated target".
> >
> > I can write a function to do this myself but this seems like the most
> > common way someone would want to treat static libraries referencing
> > other static libraries, so I wondered if I was missing something
> > that would allow this in a simpler way.
> >
> > Thanks!
--
Powered by www.kitware.com
Please keep messages on-topic and check the CMake FAQ at:
http://www.cmake.org/Wiki/CMake_FAQ
Kitware offers various services to support the CMake community. For