# FILE\_SET include directory manipulation

**URL:** https://discourse.cmake.org/t/file-set-include-directory-manipulation/10648
**Category:** Usage
**Created:** [April 12, 2024, 8:20pm UTC](https://discourse.cmake.org/t/file-set-include-directory-manipulation/10648 "2024-04-12T20:20:02Z")
**Posts on this page:** 6
**Page:** 1

<div class="post-metadata">

### Author: ![pjfasano](https://discourse.cmake.org/user_avatar/discourse.cmake.org/pjfasano/32/4488_2.png) [@pjfasano](https://discourse.cmake.org/u/pjfasano)
#### Post date: [April 12, 2024, 8:20pm UTC](https://discourse.cmake.org/t/file-set-include-directory-manipulation/10648/1 "2024-04-12T20:20:02Z")

</div>

I am trying to understand how to correctly install using `FILE_SET` for a very simple (i.e. flat) directory structure:

```plaintext
myproj/
|--- CMakeLists.txt
|--- foo.h
|--- foo.cpp

```

After installation, I want the file tree to be:

```plaintext
${PREFIX}/
|--- include/
| |--- myproj/
| | |--- foo.h
|--- lib/
| |--- libfoo.a

```

I tried doing this very simply (following [cmake-buildsystem](https://cmake.org/cmake/help/latest/manual/cmake-buildsystem.7.html#id42))

```cmake
cmake_minimum_required(VERSION 3.23)

project(myproj CXX)

add_library(foo foo.cpp)
target_sources(
  foo PUBLIC
  FILE_SET HEADERS
    TYPE HEADERS
    FILES foo.h
)

install(
  TARGETS foo
  DESTINATION ${CMAKE_INSTALL_LIBDIR}
  INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
  EXPORT myprojTargets
  FILE_SET HEADERS DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/myproj
)

install(
  EXPORT myprojTargets
  NAMESPACE myproj::
  FILE myprojTargets.cmake
  DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/myproj
)

```

This seems to put the files into the correct place, but if I then use this with `find_package(myproj)` and link against `myproj::foo`, I get `${PREFIX}/include/myproj` in the include directories rather than simply `${PREFIX}/include`.

How can I install header files (using `FILE_SET`) where I need to use `${CMAKE_CURRENT_SOURCE_DIR}` itself as part of the installed path?

(For reference, I am trying to adapt an existing project where libraries were set up such that you could simply do a `git clone` directly into `/usr/local/include` and get the headers in the “right” place.)

EDIT: It seems as though the include path when imported is defined by `FILE_SET DESTINATION`.

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)
#### Post date: [April 12, 2024, 9:13pm UTC](https://discourse.cmake.org/t/file-set-include-directory-manipulation/10648/2 "2024-04-12T21:13:52Z")

</div>

Yes. The idea is that if `myproj/` is part of the path to be included, it would be under the “BASE\_DIRS” rather than straddling it. I think you want `BASE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/.." FILES foo.h` (with `myproj` coming from the name of the current directory) and then a `DESTINATION include`.

---

<div class="post-metadata">

### Author: ![pjfasano](https://discourse.cmake.org/user_avatar/discourse.cmake.org/pjfasano/32/4488_2.png) [@pjfasano](https://discourse.cmake.org/u/pjfasano)
#### Post date: [April 12, 2024, 9:21pm UTC](https://discourse.cmake.org/t/file-set-include-directory-manipulation/10648/3 "2024-04-12T21:21:30Z")

</div>

> [@ben.boeckel](#):
>
> I think you want `BASE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/.." FILES foo.h` (with `myproj` coming from the name of the current directory) and then a `DESTINATION include`.

Yeah, I was just tinkering more and had come up with

```cmake
cmake_path(GET CMAKE_CURRENT_SOURCE_DIR PARENT_PATH parent_path)
target_sources(
  foo PUBLIC
  FILE_SET HEADERS
    TYPE HEADERS
    BASE_DIRS "${parent_path}"
    FILES foo.h
)

install(
  TARGETS foo
  DESTINATION ${CMAKE_INSTALL_LIBDIR}
  INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
  EXPORT myprojTargets
  FILE_SET HEADERS DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)

```

I think that’s equivalent? One could also do `cmake_path(SET parent_path NORMALIZE "${CMAKE_CURRENT_SOURCE_DIR}/..")` and should(?) get the same thing.

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)
#### Post date: [April 12, 2024, 9:48pm UTC](https://discourse.cmake.org/t/file-set-include-directory-manipulation/10648/4 "2024-04-12T21:48:16Z")

</div>

Yep, that should all be equivalent.

---

<div class="post-metadata">

### Author: ![craig.scott](https://discourse.cmake.org/user_avatar/discourse.cmake.org/craig.scott/32/20_2.png) [@craig.scott](https://discourse.cmake.org/u/craig.scott)
#### Post date: [April 12, 2024, 10:00pm UTC](https://discourse.cmake.org/t/file-set-include-directory-manipulation/10648/5 "2024-04-12T22:00:59Z")

</div>

You shouldn’t use the name of the top level directory for your `BASE_DIRS`. That is not a directory name your project controls, the user could use a different name. If you’re using file sets, you pretty much MUST put your headers in a subdirectory.

Note also that you should avoid using your top level source directory as a `BASE_DIRS` too. It is quite common for CI systems and often CMake presets too to specify a build directory that is a subdirectory of the top level source directory. If you ever need to add a part of the build directory as a `BASE_DIRS` to a file set (which you would if you were using something like `generate_export_header()` from the `GenerateExportHeader` module), you won’t be able to if the top level source directory is already a base directory of the file set. File sets cannot have overlapping `BASE_DIRS`.

---

<div class="post-metadata">

### Author: ![pjfasano](https://discourse.cmake.org/user_avatar/discourse.cmake.org/pjfasano/32/4488_2.png) [@pjfasano](https://discourse.cmake.org/u/pjfasano)
#### Post date: [April 12, 2024, 10:10pm UTC](https://discourse.cmake.org/t/file-set-include-directory-manipulation/10648/6 "2024-04-12T22:10:14Z")

</div>

> [@craig.scott](#):
>
> You shouldn’t use the name of the top level directory for your `BASE_DIRS`.

I don’t disagree, but this is a slow migration to CMake from a custom build system which made _heavy_ use of Git submodules. It also made a point of not separating headers from sources, but instead grouped headers and sources into “libraries”. That is, a typical structure would be:

```plaintext
project/
|- Makefile
|- project.mk
|- libraries/
| |- foo/
| | |- module.mk
| | |- foo1.h
| | |- foo1.cpp
| | |- foo2.h
| | |- foo2.cpp
| |- bar/
| | |- module.mk
| | |- bar1.h
| | |- bar1.cpp
| | |- bar2.h
| | |- bar2.cpp
|- programs/
| |- tools/
| | |- module.mk
| | |- tool1.cpp
| | |- tool2.cpp
| |- utils/
| | |- module.mk
| | |- util1.cpp
| | |- util2.cpp

```

When one of the “libraries” (like `foo` or `bar`) got too big or needed to be used somewhere else, it would just get pulled out into its own repository and added to `project/libraries/` as a (Git) submodule. Of course, that meant that now all of the headers and sources needed to be at top level of the new Git repository, since it had just been a subdirectory of a larger project.

EDIT: And, of course, it didn’t have a separate build tree, so object files would get scattered across all of those directories!

EDIT2: Even further, the old build system didn’t even have installing headers as an option – of course you would always build everything from scratch every time!
