find_package for non-installer third party module/library/package

Hey guys,

I’ve got a project which requires a fast-dds library (GitHub - eProsima/Fast-DDS: The most complete DDS - Proven: Plenty of success cases.). This library relies on several third party libraries. Those are included in the “thirdparty” directory as git submodules or the module allows to use system wide libraries.

However, fast-dds relies also on foonathan-memory-vendor package (GitHub - eProsima/foonathan_memory_vendor: foonathan/memory vendor package for Fast DDS.) which is not part of the repository compared to other libraries + it turns out to be some sort of wrapper around memory package.

I want to be able to build my project, which relies on fast-dds without the need of manually downloading and installing any of the third party packages and I would like to configure the build system in such a way, it uses local packages.

So I’ve created a testing directory like this:

my_project
|--3rdparty
|   |--Fast-DDS # git submodule
|   |--foonathan_memory_vendor # git submodule
|--CMakeLists.txt

My CMakeLists.txt file looks following way:

1 cmake_minimum_required (VERSION 3.16)
2
3
4
5 set (THIRDPARTY ON CACHE STRING “” FORCE)
6 set (BUILD_SHARED_LIBS OFF CACHE STRING “” FORCE)
7
8 add_subdirectory(3rdparty/foonathan_memory_vendor)
9 add_subdirectory(3rdparty/Fast-DDS)

Invoking cmake under my_project like:

$ cmake -S . -B build

leads to following issue:

Could not find a package configuration file provided by
“foonathan_memory_vendor” with any of the following names:

foonathan_memory_vendorConfig.cmake
foonathan_memory_vendor-config.cmake

Add the installation prefix of “foonathan_memory_vendor” to
CMAKE_PREFIX_PATH or set “foonathan_memory_vendor_DIR” to a directory
containing one of the above files. If “foonathan_memory_vendor” provides a
separate development package or SDK, be sure it has been installed.

After investigating the issue I found out, that fast-dds CMakeLists.txt file invokes “find_package(foonathan_memory_vendor)”, however, the package is not installed on the system, thus package configuration file is missing and thus it’s not able to locate it.

I was reading the find_package documentation and it feels, like find_package is only for installed packages or am I wrong?

I’ve tried to invoke cmake on the foonathan_memory_vendor ($ cmake -S . -B build) package and the foonathan_memory_vendor-config.cmake becomes part of the build directory, however, the package requires the foonathan_memory package and it “includes” it using “externalproject_add” command.

So my question to this topic and also a generic question would be:
How does one incorporates a third party library, which uses find_package to search for additional packages, but I don’t have and don’t want to install those packages system wide. I just want to build those packages as part of the whole build of my project locally.

I recommend a superbuild approach using ExternalProject. However, FetchContent may be a more preferable way of doing it.

Cc: @craig.scott

Hi Ben,

thank you a lot for your response. I’ve tried FetchContent, but the issue persists. The third party module relying on another module, which gets “included” by find_package( ) fails due to the fact, that the module is not installed. Not sure this can be solved by FetchContent? It’s true that I haven’t experimented with the FIND_PACKAGE_ARGS parameter of FetchContent_Declare, as my CMake version is 3.16.
However, I don’t think this will work as well, as the foonathan_memory_vendor package is not installed?

To be honest, I don’t understand all the relationships etc. happening there. From what I understand, the package must! be installed to be foundable?

Regarding ExternalProject I’m afraid I’m in the same trap, as one package requires another package, which is not available at build configuration and ExternalProject makes it available during build time, not configuration time?

Here, all projects would use ExternalProject (a “superbuild”) and would consume each other’s install trees.

Alas, I’m not familiar enough with FetchContent to add much here without just parroting the docs at you.

FetchContent isn’t going to help here unless you are pulling in the missing dependency with FetchContent before the other things that need it.

Ok, so I’ve created a testing repository:

https://github.com/Renegade85/cmake_test

One has to invoke:

git submodule update --init --recursive

I would like to automate this in the future with cmake, but right now I would like to focus on the issue about dependencies between third party libs.

As I’m just a cmake newbie, the propsed solution using ExternalProject seems to be a bit complex?

Just to be clear, is my assumption correct, that I can’t use the current configuration because Fast-DDS uses find_package( ), but the library is not installed?

Can this be solved by installing the package somehow locally using cmake in the repository and use it for the Fast-DDS repo somehow?

Another idea was to patch the CMakeLists.txt file of the Fast-DDS repo and replace:

find_package(foonathan_memory_vendor)

by:

add_subdirectory(…/…/3rdparty/foonathna_memory_vendor …/…/build)

However, with no success so far. As the foonathan_memory_vendor seems to be just a wrapper around foonathan_memory, I was thinking to use that repository/package directly. According to the README of memory it should be sufficient to use add_subdirectory( ) in your project and you should be good to go, but if that solution is used, I get:

CMake Error in 3rdparty/Fast-DDS/src/cpp/CMakeLists.txt:
export called with target “fastrtps” which requires target
“foonathan_memory” that is not in any export set.