0

I am still learning cmake and am struggling with a dependency I am trying to set up.

I discovered FetchContent while setting up googletest, and that worked fine so I am trying to do the same thing for a new dependency I am trying to configure for can-utils.

In the CMakeLists.txt file in the source directory for the code that I want to use can-utils with, I added:

include(FetchContent)
FetchContent_Declare(
  can-utils
  GIT_REPOSITORY https://github.com/linux-can/can-utils.git
  GIT_TAG        e602e391a56e681b03506c2f0890eb128192ec3d
)
FetchContent_MakeAvailable(can-utils)

The project configures and builds,and I can see that cmake put the can-utils repo in to my build directory... However, unlike with googletest, where after doing the FetchContent I was able to #include <gtest/gtest.h>, I can't seem to #include "anything/resembling/can-utils"

I suspect that the difference is that googletest is set up with FetchContent in mind and can-utils is not. My question is: How would I know if I can use FetchContent for a given library?

Any guidance is very much appreciated!

  • I feel that the title is overly broad and could mislead future readers into thinking that it will answer a problem they are facing which is very different from the quite specific problem you are facing. Hopefully my answer has been insightful that you can describe the problem more specifically. I'd appreciate it you tried to :) I don't have enough reputation to be heavy-handed here. – starball Sep 02 '22 at 04:12
  • Done. Your answer was great, thank you! – KevbotInControl Sep 02 '22 at 07:41

1 Answers1

1

FetchContent eventually calls add_subdirectory on the fetched content. The location of the downloaded contents is written to a variable named <lowercaseName>_SOURCE_DIR, which IIRC is by default under a binary dir.

Looking at can-utils/CMakeLists.txt, it does the following at what is currently line 22:

include_directories (.)
include_directories (./include)

include_directories is not attached to any target. See its docs:

The include directories are added to the INCLUDE_DIRECTORIES directory property for the current CMakeLists file. They are also added to the INCLUDE_DIRECTORIES target property for each target in the current CMakeLists file. The target property values are the ones used by the generators.

Since (IIRC,) the default value of ${can-utils_SOURCE_DIR} will be under some binary dir of your generated buildsystem, unless some crazy coincidence happens with an in-source build, your targets are probably not going to inherit those include_directories values.

As a bandaid-solution, you should be able to do something like:

# this must go after the call to FetchContent_MakeAvailable and before your targets are created and in a same-or-parent directory of the directories of the CMakeLists.txt files creating your targets.
include_directories("${can-utils_SOURCE_DIR}/..")

Which should then allow you do include the headers like:

#include <value_of_can-utils_SOURCE_DIR/lib.h>

And if you don't like whatever ${can-utils_SOURCE_DIR} is, I think you could do some symlinking to work around it.

A better bandaid-solution would be to use target_include_directories to add it per-target of can-utils like they preferably should have done.

If you want, you can raise an issue/PR to the maintainer of the project to switch from include_directories to use target_include_directories, which should be okay especially since they're using cmake_minimum_required(VERSION 3.3)

You could also ask/PR them to place their header files under a subdirectory named can-utils inside their repo so that you don't have do either deal with the value of ${can-utils_SOURCE_DIR} or do symlink workarounds.

starball
  • 20,030
  • 7
  • 43
  • 238