Add external headers and sources

Hello,
I am trying to figure out how to include files into my project, that are outside of the project directory. The files structure on the system looks the following:

So my CMakeLists.txt is in MyProject dir, while the files directory is in some other, unrelated dir (MyLib). That dir also has subdirectories.

MyProject directory has no source or header files at all.

I would appreciate all help!

This looks quite strange. Why do you want the CMake code to live so far away from the sources?

Hi,
Its because source files are in a repo and I cannot commit my cmake file to the repo (I want to keep them in a separate repo).

Then I would suggest adding the repo as a submodule (or whatever your VCS calls nested repositories) and keep the CMake code “above” where the sources live.

In that case I would need to keep a repo inside of a repo on purpose with gitignore- thats possible, but I am wondering- doesnt cmake support the way of manually providing the directory that is outside of the tree?

CMake has notions about what is “in the source tree” and not based on the relationship to the top-level CMakeLists.txt in use for the build. These assumptions are in many places, so doing this is likely to trip over odd behaviors. You can make it work, but it isn’t as easy.

You can certainly give absolute paths to the sources to add to targets in the projects directory, but I suspect you’ll always get things like absolute paths to source files rather than any relative paths (for example).

I see, thank you for the explanation. So keeping this in mind, would this scheme be correct?

And now, assuming I would like to have a separate project for the library and an executable that uses that library:

  1. Do I need 2 separate CMakeLists.txt files?
  2. Does the library project dir has to be contained by the executable project dir

You can do it with one CMakeLists.txt; that’s fine. There’s no nesting requirements within a project either as all non-IMPORTED add_{library,executable} targets are global in scope.

Could you provide a minimum working example?

Not really because I don’t have your source code :slight_smile: . But something like this (based on your image):

cmake_minimum_required(VERSION 3.16) # pick whatever version has the features you want
project(MyProject)

add_library(Submodule1
  MyLib/Submodule1/foo.c
  MyLib/Submodule1/foo.c)
add_library(Submodule2
  MyLib/Submodule2/foo.c
  MyLib/Submodule2/foo.c)

add_library(MyLib
   MyLib/foo.c
   MyLib/foo.h)
target_link_libraries(MyLib PRIVATE # Choose the visibility as needed
  Submodule1 Submodule2)

That should at least start a build going. You’ll probably need boilerplate for testing, installation, flags, options, etc. The tutorial has examples to follow.

1 Like

Thanks for that! But just a question- in your example, do you assume that the Submodule1 and Submodule1 will be compiled as separate shared libraries? Or is it just an intermediate step and it is the target_link_libraries line which creates the output? Or in other words, is this:

add_library(Submodule1
  MyLib/Submodule1/foo.c
  MyLib/Submodule1/foo.h)
add_library(Submodule2
  MyLib/Submodule2/foo.c
  MyLib/Submodule2/foo.h)

add_library(MyLib
   MyLib/foo.c
   MyLib/foo.h)
target_link_libraries(MyLib PRIVATE # Choose the visibility as needed
  Submodule1 Submodule2)

Equal to this?

add_library(MyLib
   MyLib/Submodule1/foo.c
   MyLib/Submodule1/foo.c)
   MyLib/Submodule2/foo.c
   MyLib/Submodule2/foo.h)
   MyLib/foo.c
   MyLib/foo.h)

Those are two separate effects. One makes 2 libraries and an executable (which links to them). The other makes a single executable. I would recommend going through the Tutorial.

By “an executable (which links to them)” did you mean a shared library, or actual executable? Because from what I understand, in the end both scripts produce a shared lib?

I have already started the tutorial- no doubt I need it.

Sorry, I thought I used add_executable (too much copy pasta). They’re all libraries in that example, yes. Use add_executable for executables.

So are the outputs of the 2 listings the same? Both produce the same shared lib output?

No. One makes 3 shared libraries and the other makes 1.

Ok, now understood- thanks.