installing a pre-built module and its various dependencies

Apologies in advance if this approach is completely wrong-headed. I could be missing obvious things but am just too tunnel-visioned to realize it. Anyway…

We have a pre-built .dll, called Foo.dll, that we load with LoadLibrary(). There’s no import library.

Foo.dll depends on various other (legacy) pre-built .dlls, as well as a data file called bar.bin and a config file called baz.conf.

I’ve created a Foo-config.cmake like so:

Foo-config.cmake
...
add_library(Foo::Foo MODULE IMPORTED)
set_target_properties(Foo::Foo PROPERTIES
    INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include"
    IMPORTED_LOCATION "${_IMPORT_PREFIX}/bin/Foo.dll"
)
...

The resulting .zip contains:

  • Foo.dll
  • All of its other .dll dependencies (about 5 other .dlls)
  • bar.bin and baz.conf
  • include/Foo.h
  • lib/cmake/Foo-config.cmake and lib/cmake/Foo-config-version.cmake

Now, I’m using cmake to create an application that depends on Foo.dll. I use FetchContent_* and find_package to pull the .zip from our internal artifactory and make it known to cmake. No problems there.

However, here’s what I’m not sure about:

  • How to associate Foo::Foo to my application’s target, if that’s even necessary. I’d like to do it, because the TARGET_RUNTIME_DLLS generator expression sounds promising here.
    • target_link_libraries doesn’t work because then Foo.dll is on the link line, which produces a link error.
    • As a result, Foo’s include directory also isn’t added to the application’s header search paths, and target_include_directories(App PUBLIC Foo) doesn’t seem to work, either.
  • The best way to install all of Foo.dll’s dependencies along with the application. I acknowledge that my Foo-config.cmake is likely missing some key things. Or, maybe I just need to use install(FILES ...), referencing the files relative to the source directory from FetchContent?

Can this use case be accomplished with cmake? Any guidance would be appreciated.

Right, the module is only loadable, so the linker doesn’t care about it.

I would make a second INTERFACE target with the compilation requirements. You can then add this to Foo::Foo’s interface (for whatever it’s worth) and use it in any consuming bit. Calling it Foo::Headers or Foo::SDK is probably apt.

file(GET_RUNTIME_DEPENDENCIES) should work here.

1 Like