# FetchContent a directory but add a subdirectory

**URL:** <https://discourse.cmake.org/t/fetchcontent-a-directory-but-add-a-subdirectory/8603>\
**Category:** Code\
**Created:** [July 26, 2023, 9:15am UTC](https://discourse.cmake.org/t/fetchcontent-a-directory-but-add-a-subdirectory/8603 "2023-07-26T09:15:39Z")\
**Posts on this page:** 18\
**Page:** 1

<div class="post-metadata">

**Author:** ![rturrado](https://discourse.cmake.org/user_avatar/discourse.cmake.org/rturrado/32/3499_2.png) [@rturrado](https://discourse.cmake.org/u/rturrado)\
**Post date:** [July 26, 2023, 9:15am UTC](https://discourse.cmake.org/t/fetchcontent-a-directory-but-add-a-subdirectory/8603/1 "2023-07-26T09:15:40Z")

</div>

I have some code using git submodules that is:

1. Working on a full checkout of the `highs` library, let’s say in `deps/highs`.
2. Calling `add_subdirectory(deps/highs/src)`.

The `deps/highs/src/CMakeLists.txt` file contains references to `${HIGHS_SOURCE_DIR}`, which is `deps/highs`, i.e. the parent directory.

Is there a way to accomplish the same functionality with `FetchContent`? I.e. download everything but add only `src` subdirectory. Because using `SOURCE_SUBDIR src` in `FetchContent_Declare` will change `${HIGHS_SOURCE_DIR}` to `build/_deps/highs/src`, won’t it? I have tried that and it doesn’t seem to do the work.

Thanks!

---

<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:** [July 26, 2023, 4:52pm UTC](https://discourse.cmake.org/t/fetchcontent-a-directory-but-add-a-subdirectory/8603/2 "2023-07-26T16:52:05Z")

</div>

Can you just set it via `-D`? Skipping the top-level logic doesn’t seem like it’s something the project really supports.

---

<div class="post-metadata">

**Author:** ![rturrado](https://discourse.cmake.org/user_avatar/discourse.cmake.org/rturrado/32/3499_2.png) [@rturrado](https://discourse.cmake.org/u/rturrado)\
**Post date:** [July 26, 2023, 5:01pm UTC](https://discourse.cmake.org/t/fetchcontent-a-directory-but-add-a-subdirectory/8603/3 "2023-07-26T17:01:43Z")

</div>

Hi @ben.boeckel,

I’m sorry but I don’t understand your answer. Could you please elaborate a bit more on it?

Thanks!

---

<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:** [July 26, 2023, 6:13pm UTC](https://discourse.cmake.org/t/fetchcontent-a-directory-but-add-a-subdirectory/8603/4 "2023-07-26T18:13:41Z")

</div>

With `FetchContent`, add `-DHIGHS_SOURCE_DIR=<SOURCE_DIR>` to the `CMAKE_ARGS`.

---

<div class="post-metadata">

**Author:** ![rturrado](https://discourse.cmake.org/user_avatar/discourse.cmake.org/rturrado/32/3499_2.png) [@rturrado](https://discourse.cmake.org/u/rturrado)\
**Post date:** [July 26, 2023, 7:42pm UTC](https://discourse.cmake.org/t/fetchcontent-a-directory-but-add-a-subdirectory/8603/5 "2023-07-26T19:42:20Z")

</div>

OK, thanks!

I could hardcode that, yes, but I would also need to hardcode `HIGHS_BINARY_DIR`, and I wouldn’t be sure yet I would be missing something else.

---

<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:** [July 27, 2023, 2:58am UTC](https://discourse.cmake.org/t/fetchcontent-a-directory-but-add-a-subdirectory/8603/6 "2023-07-27T02:58:57Z")

</div>

Yeah, that’s a likely one. I’d take a look at the `CMakeLists.txt` to see what logic you might be skipping over at least.

---

<div class="post-metadata">

**Author:** ![rturrado](https://discourse.cmake.org/user_avatar/discourse.cmake.org/rturrado/32/3499_2.png) [@rturrado](https://discourse.cmake.org/u/rturrado)\
**Post date:** [July 27, 2023, 9:28am UTC](https://discourse.cmake.org/t/fetchcontent-a-directory-but-add-a-subdirectory/8603/7 "2023-07-27T09:28:35Z")

</div>

Sorry again, @ben.boeckel , but I don’t see how setting `-DHIGHS_SOURCE_DIR` can help here.

- FetchContent will set `HIGHS_SOURCE_DIR` to the root folder.
- If I tell CMake that `HIGHS_SOURCE_DIR` is the `src` folder within root, then, when it configures Highs, and it gets to `src/CMakeLists.txt`, the code in there will expect `HIGHS_SOURCE_DIR` to point to the root folder.

Couldn’t I use just `FetchContent_Declare` (or `ExteranalProject_Add`) plus `add_subdirectory("${HIGHS_SOURCE_DIR}/src")`?

---

<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:** [July 27, 2023, 10:05am UTC](https://discourse.cmake.org/t/fetchcontent-a-directory-but-add-a-subdirectory/8603/8 "2023-07-27T10:05:45Z")

</div>

> [@rturrado](#):
>
> FetchContent will set `HIGHS_SOURCE_DIR` to the root folder.

Why would it do that? These variables usually come from a `project(HIGHS)` call.

---

<div class="post-metadata">

**Author:** ![rturrado](https://discourse.cmake.org/user_avatar/discourse.cmake.org/rturrado/32/3499_2.png) [@rturrado](https://discourse.cmake.org/u/rturrado)\
**Post date:** [July 27, 2023, 11:03am UTC](https://discourse.cmake.org/t/fetchcontent-a-directory-but-add-a-subdirectory/8603/9 "2023-07-27T11:03:21Z")

</div>

Oh, sure, I wasn’t seeing that. FetchContent will set `highs_SOURCE_DIR` but not `HIGHS_SOURCE_DIR`. You’re right, thanks!

So is your suggestion then:

- FetchContent with `SOURCE_SUBDIR` pointing to `src`, plus
- Setting `HIGHS_SOURCE_DIR` to `${highs\_SOURCE\_DIR}/…" and “HIGHS\_BINARY\_DIR” to “${highs\_BINARY\_DIR}/…”?

---

<div class="post-metadata">

**Author:** ![rturrado](https://discourse.cmake.org/user_avatar/discourse.cmake.org/rturrado/32/3499_2.png) [@rturrado](https://discourse.cmake.org/u/rturrado)\
**Post date:** [July 27, 2023, 11:53am UTC](https://discourse.cmake.org/t/fetchcontent-a-directory-but-add-a-subdirectory/8603/10 "2023-07-27T11:53:31Z")

</div>

It seems the code below is working.

It uses your suggestion of setting `HIGHS_SOURCE_DIR` (BTW, the project I am modifying, which was managing dependencies via `git submodules`, was already doing that).

But it also uses:

- `FetchContent_Declare`, to declare dependencies,
- `FetchContent_Populate`, to download dependencies and set `highs_SOURCE_DIR` and `higs_BINARY_DIR`,
- `set(HIGHS_SOURCE_DIR)` and `set(HIGHS_BINARY_DIR)`, the two variables that are accessed by `src/CMakeLists.txt` and that have to point to the parent dir of `src`, and
- `add_subdirectory(src)`, to process only `src` subdir.

```auto
FetchContent_Declare(highs
    GIT_REPOSITORY https://github.com/ERGO-Code/HiGHS.git
    GIT_TAG "45a127b78060942721f75f46a04b274c2bb963d8"
)
FetchContent_Populate(highs)
set(HIGHS_SOURCE_DIR "${highs_SOURCE_DIR}")
set(HIGHS_BINARY_DIR "${highs_BINARY_DIR}")
add_subdirectory("${highs_SOURCE_DIR}/src" "${highs_BINARY_DIR}/src")

```

I might try doing the same with:

```auto
FetchContent_Declare(highs
    GIT_REPOSITORY https://github.com/ERGO-Code/HiGHS.git
    GIT_TAG "45a127b78060942721f75f46a04b274c2bb963d8"
    SOURCE_SUBDIR src
)
set(HIGHS_SOURCE_DIR "${highs_SOURCE_DIR}")
set(HIGHS_BINARY_DIR "${highs_BINARY_DIR}")
FetchContent_MakeAvailable(highs)

```

---

<div class="post-metadata">

**Author:** ![rturrado](https://discourse.cmake.org/user_avatar/discourse.cmake.org/rturrado/32/3499_2.png) [@rturrado](https://discourse.cmake.org/u/rturrado)\
**Post date:** [July 27, 2023, 4:10pm UTC](https://discourse.cmake.org/t/fetchcontent-a-directory-but-add-a-subdirectory/8603/11 "2023-07-27T16:10:25Z")

</div>

The first of the solutions from my last post, the one using `add_subdirectory`, has the problem that the subfolder is treated like a project’s folder. So, for example, if I build my project with warnings as errors, and the subproject raises some warnings, those will be treated as errors of my project.

Fortunately, it can be avoided using CMake 3.25’s `add_subdirectory(... SYSTEM)`.

---

<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:** [July 28, 2023, 3:51am UTC](https://discourse.cmake.org/t/fetchcontent-a-directory-but-add-a-subdirectory/8603/12 "2023-07-28T03:51:41Z")

</div>

Avoid calling `FetchContent_Populate()` directly. I plan to eventually deprecate that. Call `FetchContent_MakeAvailable()` instead.

Note also that you can add the `SYSTEM` keyword to `FetchContent_Declare()` starting with CMake 3.25 as well.

---

<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:** [July 28, 2023, 3:52am UTC](https://discourse.cmake.org/t/fetchcontent-a-directory-but-add-a-subdirectory/8603/13 "2023-07-28T03:52:45Z")

</div>

> [@rturrado](#):
>
> ```auto
> set(HIGHS_SOURCE_DIR "${highs_SOURCE_DIR}")
> set(HIGHS_BINARY_DIR "${highs_BINARY_DIR}")
> FetchContent_MakeAvailable(highs)
> 
> ```

That’s the wrong order. The `highs_SOURCE_DIR` and `highs_BINARY_DIR` variables won’t be populated until after the call to `FetchContent_MakeAvailable()`.

EDIT: Oh, I see that reordering would be a problem in this case. You need `HIGHS_SOURCE_DIR` and `HIGHS_BINARY_DIR` to be populated _before_ the downloaded source has been loaded. You could let FetchContent handle the downloading only, but take control of the `add_subdirectory()` part by setting `SOURCE_SUBDIR` to a non-existent subdirectory. That will prevent `FetchContent_MakeAvailable()` from calling `add_subdirectory()`. The main advantage to using `FetchContent_MakeAvailable()` is for the dependency provider and `find_package()` integrations, which might not be important to you right now, but may be in the future or for other consumers of your project.

---

<div class="post-metadata">

**Author:** ![rturrado](https://discourse.cmake.org/user_avatar/discourse.cmake.org/rturrado/32/3499_2.png) [@rturrado](https://discourse.cmake.org/u/rturrado)\
**Post date:** [July 28, 2023, 10:13am UTC](https://discourse.cmake.org/t/fetchcontent-a-directory-but-add-a-subdirectory/8603/14 "2023-07-28T10:13:45Z")

</div>

> [@craig.scott](#):
>
> EDIT: Oh, I see that reordering would be a problem in this case. You need `HIGHS_SOURCE_DIR` and `HIGHS_BINARY_DIR` to be populated _before_ the downloaded source has been loaded. You could let FetchContent handle the downloading only, but take control of the `add_subdirectory()` part by setting `SOURCE_SUBDIR` to a non-existent subdirectory. That will prevent `FetchContent_MakeAvailable()` from calling `add_subdirectory()`. The main advantage to using `FetchContent_MakeAvailable()` is

Many thanks for your comments @craig.scott.

Are you then proposing something like this?

```auto
FetchContent_Declare(highs
    GIT_REPOSITORY https://github.com/ERGO-Code/HiGHS.git
    GIT_TAG "45a127b78060942721f75f46a04b274c2bb963d8"
    SOURCE_SUBDIR this-directory-does-not-exist
)

# FechContentMakeAvailable will set
# highs_SOURCE_DIR to _deps/highs-src/this-directory-does-not-exist, and
# highs_BINARY_DIR to _deps/highs-build/this-directory-does-not-exist
FetchContent_MakeAvailable(highs)

# Properly setting
# highs_SOURCE_DIR to _deps/highs-src/src, and
# higs_BINARY_DIR to _deps/highs-build/src
set(highs_SOURCE_DIR "${highs_SOURCE_DIR}/../src")
set(highs_BINARY_DIR "${highs_BINARY_DIR}/../src")

# Now carry on doing what we were doing with FetchContent_Populate
set(HIGHS_SOURCE_DIR "${highs_SOURCE_DIR}/..")
set(HIGHS_BINARY_DIR "${highs_BINARY_DIR}/..")
add_subdirectory("${highs_SOURCE_DIR}/src" "${highs_BINARY_DIR}/src" SYSTEM)

```

---

<div class="post-metadata">

**Author:** ![rturrado](https://discourse.cmake.org/user_avatar/discourse.cmake.org/rturrado/32/3499_2.png) [@rturrado](https://discourse.cmake.org/u/rturrado)\
**Post date:** [August 1, 2023, 11:35am UTC](https://discourse.cmake.org/t/fetchcontent-a-directory-but-add-a-subdirectory/8603/15 "2023-08-01T11:35:24Z")

</div>

OK, I had it working with the following code:

```auto
FetchContent_Declare(highs
    GIT_REPOSITORY https://github.com/ERGO-Code/HiGHS.git
    GIT_TAG "45a127b78060942721f75f46a04b274c2bb963d8"
    SOURCE_SUBDIR this-directory-does-not-exist
)
FetchContent_MakeAvailable(highs)
set(HIGHS_SOURCE_DIR "${highs_SOURCE_DIR}")
set(HIGHS_BINARY_DIR "${highs_BINARY_DIR}")
add_subdirectory("${highs_SOURCE_DIR}/src" "${highs_BINARY_DIR}/src" SYSTEM)

```

---

<div class="post-metadata">

**Author:** ![dograt](https://discourse.cmake.org/user_avatar/discourse.cmake.org/dograt/32/5777_2.png) [@dograt](https://discourse.cmake.org/u/dograt)\
**Post date:** [August 22, 2025, 2:45am UTC](https://discourse.cmake.org/t/fetchcontent-a-directory-but-add-a-subdirectory/8603/16 "2025-08-22T02:45:19Z")

</div>

@craig.scott Hello sir! Is there a workaround for the case where we want to specify `SOURCE_DIR`? Specifically, all I want `FetchContent` to do is download my desired repository to a desired location. I want to then handle the `add_subdirectory` call myself from there.

I’m using `SOURCE_DIR` to designate the desired download location of my packages, because `DOWNLOAD_DIR` is (apparently) only used for URL-based `FetchContent` calls.

If I can’t specify `SOURCE_DIR`, then I can’t actually control where my code gets downloaded, but I also don’t want `FetchContent_MakeAvailable` invoking the dependency’s `CMakeLists.txt`.

I can try to get fancy, and move the content to my desired location, but CMake still populates the target.

```auto
add_library cannot create target "my_fetched_target" because another target
  with the same name already exists. The existing target is a static library
  created in source directory
  "/home/path/to/build/preset/_deps/my_package-src". See
  documentation for policy CMP0002 for more details.

```

Plus it’s ugly:

```auto
# this is a FetchContent-based dependency
include(FetchContent)

# configure find_package calls
set(MY_CONTENT_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/package")

set(FETCHCONTENT_QUIET FALSE)

# To preserve install behavior transitively, we add the subdirectory instead of actually finding the package
# declare dependency source
FetchContent_Declare(
	my_package
	GIT_REPOSITORY "${FETCHCONTENT_GITLAB_ORIGIN}/my_repo.git"
	GIT_TAG "main"
	GIT_SHALLOW TRUE
	GIT_PROGRESS TRUE
# OVERRIDE_FIND_PACKAGE
	EXCLUDE_FROM_ALL
)

# Download the content without making it available to the build.
# We will use add_subdirectory for that
set(my_package_POPULATED TRUE)
FetchContent_MakeAvailable(my_package)

if(IS_DIRECTORY "${my_package_SOURCE_DIR}")
	# Only try to move source directory if it exists
	file(REMOVE_RECURSE "${MY_CONTENT_SOURCE_DIR}")
	file(RENAME
		"${my_package_SOURCE_DIR}"
		"${MY_CONTENT_SOURCE_DIR}"
		RESULT rename_result
	)

	message(STATUS "Moved source directory: ${rename_result}")
endif()

add_subdirectory(package)

```

Edit: Seems like using `FetchContent_Populate` with the supported arguments from `FetchContent_Declare` gets me what I want. Huzzah!

---

<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:** [August 22, 2025, 3:46am UTC](https://discourse.cmake.org/t/fetchcontent-a-directory-but-add-a-subdirectory/8603/17 "2025-08-22T03:46:44Z")

</div>

Lots to unpack there. First up, `FetchContent_Populate()` shouldn’t be used directly from projects. I won’t go into the various reasons why (its history isn’t short, and it will distract this topic from its central focus). `FetchContent_Populate()` is not the path to happiness. You should be aiming to use `FetchContent_MakeAvailable()` instead.

What you’re after is setting `SOURCE_DIR` to where you want the source to be located, then set `SOURCE_SUBDIR` to a non-existent directory (these are in your call to `FetchContent_Declare()`). That will achieve your stated goal of downloading the content without `FetchContent_MakeAvailable()` calling `add_subdirectory()` on it.

Don’t try to move things after FetchContent has downloaded them. FetchContent expects things to stay where it put them, and you’re going to run into a variety of problems if you try to move things around. FetchContent uses time stamps to work out what steps it has done, and if you move things, you take things out from under its feet. If you really must specify where the source should be located, `SOURCE_DIR` is the right way to do that.

Normally, you should just let FetchContent put the source wherever it wants. You can always obtain the location of where it put it using the `<lowercaseDepName>_SOURCE_DIR` variable. This is usually preferable to trying to manually manage where to put things.

---

<div class="post-metadata">

**Author:** ![dograt](https://discourse.cmake.org/user_avatar/discourse.cmake.org/dograt/32/5777_2.png) [@dograt](https://discourse.cmake.org/u/dograt)\
**Post date:** [August 22, 2025, 4:54am UTC](https://discourse.cmake.org/t/fetchcontent-a-directory-but-add-a-subdirectory/8603/18 "2025-08-22T04:54:42Z")

</div>

I really wish I could read.. I’d conflated `SOURCE_DIR` with `SOURCE_SUBDIR`. What you’ve described works perfectly. Thank you, sir!
