FYI, this function appears to work for me with one caveat: there appears to be a bug where SYSTEM_INCLUDE_DIRECTORIES are not handled properly so you can't use this function if you need that property to be propagated.
I filed https://gitlab.kitware.com/cmake/cmake/issues/18940 for that. I think I'll submit this as an enhancement request and see what the CMake devs think of it. It could be there are issues that I haven't thought of. On Sat, 2019-02-16 at 17:46 -0500, Paul Smith wrote: > 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} $<TARGET_PROPERTY:${lib},INTERFACE_${t}>) > endif() > if(${mode} STREQUAL "PUBLIC" OR ${mode} STREQUAL "INTERFACE") > set_property(TARGET ${tgt} APPEND PROPERTY > INTERFACE_${t} $<TARGET_PROPERTY:${lib},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} $<TARGET_PROPERTY:${lib},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 more information on each offering, please visit: CMake Support: http://cmake.org/cmake/help/support.html CMake Consulting: http://cmake.org/cmake/help/consulting.html CMake Training Courses: http://cmake.org/cmake/help/training.html Visit other Kitware open-source projects at http://www.kitware.com/opensource/opensource.html Follow this link to subscribe/unsubscribe: https://cmake.org/mailman/listinfo/cmake