Hi Gammasoft,
Thank you so much for your work again on this library! It's exciting to have a C++ GUI library made for modern C++.
I've spent the morning installing the library, and I noticed it's installing a number of dependencies manually. This is definitely appropriate for dependencies like wxWidgets, which are rather large, but I that a feature added in CMake 3.14 might be able to help with some of the dependency management!
NB: it was originally added in CMake 3.11, but FetchContent_MakeAvailable, which is extremely useful, was added in CMake 3.14
Please see here for a link to the documentation: https://cmake.org/cmake/help/latest/module/FetchContent.html
Essentially, you can use FetchContent to download and link against a library directly from a git repository! I usually use it by wrapping it in a function called find_or_fetch
, which will check to see if a package already exists on the system before downloading anything.
Here is a short example that uses find_or_fetch
to look for 3 dependencies. If it finds them on the system, it'll use the system version; otherwise, it'll clone the github repository and build & link against that.
# Find the benchmark library, or download it in build/_deps
find_or_fetch(
benchmark
https://github.com/google/benchmark.git
main)
find_or_fetch(
fmt
https://github.com/fmtlib/fmt.git
master)
find_or_fetch(
Catch2
https://github.com/catchorg/catch2.git
devel)
FetchContent_MakeAvailable(${remote_dependencies})
This will:
- Look for the google benchmark library,
- Look for libfmt,
- And look for the Catch2 unit test library.
For each one, if it can't find it on the system, then it'll add it to a list called remote_dependencies
. It will also clone each github repo into a _deps
folder inside the build directory. Once we have all the dependencies, we call FetchContent_MakeAvailable
, which will introduce each library into the scope of the current CMakeLists.txt.
Then, we can target the libraries as usual:
target_link_libraries(<your target>
benchmark::benchmark
fmt::fmt
Catch2::Catch2WithMain)
This is the definition of find_or_fetch
that I wrote. It provides an ALWAYS_FETCH
option that can be passed to CMake if a user wishes to always fetch these libraries, rather than using the system ones.
set(remote_dependencies "")
# If ALWAYS_FETCH is ON, then find_or_fetch will always fetch any remote
# dependencies rather than using the ones provided by the system. This is
# useful for creating a static executable.
option(
ALWAYS_FETCH
"Tells find_or_fetch to always fetch packages"
OFF)
include(FetchContent)
# find_or_fetch will search for a system installation of ${package} via
# find_package. If it fails to find one, it'll use FetchContent to download and
# build it locally.
function(find_or_fetch package repo tag)
if (NOT ALWAYS_FETCH)
find_package(${package} QUIET)
endif()
if (ALWAYS_FETCH OR NOT ${${package}_FOUND})
message("Fetching dependency '${package}' from ${repo}")
FetchContent_Declare(
"${package}"
GIT_REPOSITORY "${repo}"
GIT_TAG "${tag}"
)
list(APPEND remote_dependencies "${package}")
set (remote_dependencies ${remote_dependencies} PARENT_SCOPE)
else()
message("Using system cmake package for dependency '${package}'")
endif()
endfunction()
I just thought I'd share this because it made my life a lot easier, and I thought it might help you too!