2

CMake has a find_package() backed by a bunch of FindXYZ scripts (which you can also add to).

What mechanism, if any, is available to me to tell cmake: "Find this package, and if you haven't found it, download it and trigger its build" - with the downloading and building part also backed by per-package scripts or settings (so that downloading could be with wget or git clone, building could be with cmake or maven or a package-specific command, etc.) ?

einpoklum
  • 118,144
  • 57
  • 340
  • 684

2 Answers2

1

Yeah, I was bitten by that Friday.

So, CMake has an ExternalProject directive, meant for exactly that, get/update if necessary, configure, build and install this and that external project. Awesome!

Sadly, CMake isn't that awesome.

You can't use the target defined by ExternalProject as a library in target_link_libraries. I've really tried to.

The basic problem is that the updating, building and installation of the external project happens at build time, whereas CMake insists on only using libraries that it found during pre-build (i.e. during the CMake run); you can't re-detect stuff while running make/ninja/msvc… .

You can define a custom target, tell it where the .so you'd want to link against later will be, and try to coerce CMake into believing you without checking at pre-build. Sadly, at least in the CMake versions I had, that broke dependency tracking, so that it simply didn't build the external library, because nothing needed it.

From the error messages you get when trying to use an external project in target_link_library, it seems CMake assumes you'd only want to install tools you need at build time that way, not libraries. A bummer.

Marcus Müller
  • 34,677
  • 4
  • 53
  • 94
  • What about double-cmake'ing? Like we do in LaTeX? – einpoklum Aug 20 '17 at 13:13
  • Ha! That worked for me very sporadically. Most of the times, the cached "I didn't find that library" value was re-used. I couldn't figure out how to reliably re-trigger finding. – Marcus Müller Aug 20 '17 at 13:15
  • huh, didn't think of that :) but then again, does `rm ${CMAKE_BIN_DIR}/CMakeCache.txt` from *within a CMakeLists* sound like a good idea? – Marcus Müller Aug 20 '17 at 13:26
  • From within a `CMakeLists.txt` - probably not. I'd use a wrapper shell script for invoking cmake repeatedly. – einpoklum Aug 20 '17 at 13:27
  • Then, just `git cloning` on demand from that shell script is probably *a lot* easier than integrating this into the CMake flow itself. Unless your external library is also a CMake Project – then you might get away with simply including it as subdirectory. – Marcus Müller Aug 20 '17 at 13:28
  • 1
    I was trying to avoid shell scripts, because, you know, Windows. – Marcus Müller Aug 20 '17 at 13:29
0

You can roll your own version of download-on-demand using execute_process() (which runs on the CMake configure step) with ${CMAKE_COMMAND} as the command invoked on a CMakeLists.txt containing ExternalProject_Add().

You could even either configure_file() the CMakeLists.txt to fill out custom variables or dynamically create the CMakeLists.txt file.

utopia
  • 1,477
  • 8
  • 7