# \`FETCHCONTENT\_TRY\_FIND\_PACKAGE\_MODE\` for indvidual package

**URL:** https://discourse.cmake.org/t/fetchcontent-try-find-package-mode-for-indvidual-package/8101
**Category:** Development
**Created:** [May 11, 2023, 2:15pm UTC](https://discourse.cmake.org/t/fetchcontent-try-find-package-mode-for-indvidual-package/8101 "2023-05-11T14:15:56Z")
**Posts on this page:** 10
**Page:** 1

<div class="post-metadata">

### Author: ![Lecris](https://discourse.cmake.org/user_avatar/discourse.cmake.org/lecris/32/3193_2.png) [@Lecris](https://discourse.cmake.org/u/Lecris)
#### Post date: [May 11, 2023, 2:15pm UTC](https://discourse.cmake.org/t/fetchcontent-try-find-package-mode-for-indvidual-package/8101/1 "2023-05-11T14:15:56Z")

</div>

As far as I know there isn’t a way to overwrite this for an individual package (i.e. like `FETCHCONTENT_UPDATES_DISCONNECTED_<uppercaseName>` allows individual control). But in the meantime is there a way to hack around it?

---

<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: [May 11, 2023, 5:25pm UTC](https://discourse.cmake.org/t/fetchcontent-try-find-package-mode-for-indvidual-package/8101/2 "2023-05-11T17:25:02Z")

</div>

`ExternalProject` has a project-specific `UPDATES_DISCONNECTED` flag that could be populated using some mechanism. I don’t know if there’s a hacky way to plumb anything through right now though. Maybe just specify it along with the source arguments?

@craig.scott

---

<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: [May 11, 2023, 11:33pm UTC](https://discourse.cmake.org/t/fetchcontent-try-find-package-mode-for-indvidual-package/8101/3 "2023-05-11T23:33:57Z")

</div>

# Workaround 1:

Since FetchContent operates on a “first to define, wins” approach, you can call `FetchContent_Declare()` with whatever details you want early on. If this is something you want to do as a user, that can be in a file you include via `PROJECT_TOP_LEVEL_INCLUDES`, for example. That may mean you need to find what details to use for the other arguments in that call though, depending on how you want to define it.

# Workaround 2:

Another approach is to define your own [dependency provider](https://cmake.org/cmake/help/latest/guide/using-dependencies/index.html#dependency-providers). You could intercept `FetchContent_MakeAvailable()` calls and make it try `find_package()` yourself. This has the advantage that you get to see the `FetchContent_Declare()` arguments that were selected and then choose to act, rather than having to find them and lift them out to an earlier call to `FetchContent_Declare()` (the approach of workaround 1). One down side is you would have to check for `FIND_PACKAGE_ARGS` and form your call to `find_package()` using those, if present (not crazy hard). You also will end up seeing _all_ calls to `FetchContent_MakeAvailable()` for _all_ dependencies that go via that route, not just the one dependency that you really want to affect, so your logic would have to account for that.

---

<div class="post-metadata">

### Author: ![Lecris](https://discourse.cmake.org/user_avatar/discourse.cmake.org/lecris/32/3193_2.png) [@Lecris](https://discourse.cmake.org/u/Lecris)
#### Post date: [May 12, 2023, 3:48am UTC](https://discourse.cmake.org/t/fetchcontent-try-find-package-mode-for-indvidual-package/8101/4 "2023-05-12T03:48:55Z")

</div>

So the whole idea behind having a `FETCHCONTENT_TRY_FIND_PACKAGE_MODE` variable for an individual package is to give the user the option to choose whether one particular package should take precedence and either be `find_package` or `FetchContent` depending on the setting of that value. For that I think workaround 2 makes the most sense. I will have to check how to implement that, how to enforce it and how to forward the variables.

---

<div class="post-metadata">

### Author: ![Lecris](https://discourse.cmake.org/user_avatar/discourse.cmake.org/lecris/32/3193_2.png) [@Lecris](https://discourse.cmake.org/u/Lecris)
#### Post date: [May 12, 2023, 4:19am UTC](https://discourse.cmake.org/t/fetchcontent-try-find-package-mode-for-indvidual-package/8101/5 "2023-05-12T04:19:59Z")

</div>

After a quick research on [dependency provider manual](https://cmake.org/cmake/help/latest/command/cmake_language.html#provider-commands), I have found a dealbreaker:

> - If [`FETCHCONTENT_TRY_FIND_PACKAGE_MODE`](https://cmake.org/cmake/help/latest/module/FetchContent.html#variable:FETCHCONTENT_TRY_FIND_PACKAGE_MODE) is set to `NEVER`, any `FIND_PACKAGE_ARGS` will be omitted.

The whole idea is to be able to overwrite the preference of that value, e.g. if a package is intended to always be used from the system installed one by the user, but everything else should be downloaded, then it should be `FETCHCONTENT_TRY_FIND_PACKAGE_MODE_<package_name_upper> = ALWAYS`. But rthis conflicts with the logic of the quoted statement.

---

<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: [May 14, 2023, 8:51am UTC](https://discourse.cmake.org/t/fetchcontent-try-find-package-mode-for-indvidual-package/8101/6 "2023-05-14T08:51:51Z")

</div>

The purpose of the `FETCHCONTENT_TRY_FIND_PACKAGE_MODE` variable is to provide a global switch for overall behavior. It is primarily intended for when you want to use a package manager and force all `FetchContent_MakeAvailable()` calls to try `find_package()` with your package manager first, even if the `FetchContent_Declare()` call didn’t include `FIND_PACKAGE_ARGS` in its arguments.

You are looking for a finer-grained control than that. You are in effect looking for a way to selectively override some of the arguments to whichever `FetchContent_Declare()` call ends up being used for a particular dependency. We have some precedent for that with the variables `FETCHCONTENT_SOURCE_DIR_<uppercaseName>` and `FETCHCONTENT_UPDATE_DISCONNECTED_<uppercaseName>`. The former is often used, the latter not so much. I’d like to avoid the added complexity of introducing a `FETCHCONTENT_TRY_FIND_PACKAGE_MODE_<uppercaseName>` if we can though.

> [@Lecris](#):
>
> if a package is intended to always be used from the system installed one by the user, but everything else should be downloaded…

For that use case, I would recommend Workaround 1 in my earlier comment. You are in effect overriding the whole call, wanting to say “always get this dependency from the system”. The `FIND_PACKAGE_ARGS` part of the arguments isn’t quite that, it is only “try to…”, not “must get from…”. Your use case is actually “ignore all the arguments and force finding this using `find_package()`”. That’s clearer if you override the whole call, which is precisely what Workaround 1 does.

---

<div class="post-metadata">

### Author: ![Lecris](https://discourse.cmake.org/user_avatar/discourse.cmake.org/lecris/32/3193_2.png) [@Lecris](https://discourse.cmake.org/u/Lecris)
#### Post date: [May 16, 2023, 4:34pm UTC](https://discourse.cmake.org/t/fetchcontent-try-find-package-mode-for-indvidual-package/8101/7 "2023-05-16T16:34:13Z")

</div>

Let’s consider the following package situations, and an extreme case where we want all to be setup:

- User wants PkgA to always use system installed version, error if not found
- User wants PkgB to use the git submodule source, ignore system installed
- User wants PkgC to use the downloaded source, ignore system installed
- User wants PkgD to try the system installed version and if not possible default to git submodule source
- User wants PkgE to try the system installed version and if not possible default to downloaded source source

The project author designs all `PkgA-E` in a consistent manner, let’s say with `FetchContent` and `FIND_PACKAGE_ARGS`

I have thought about hacking something with `FETCHCONTENT_SOURCE_DIR_<uppercaseName>`, but couldn’t address these situations

### Case A

- `FETCHCONTENT_TRY_FIND_PACKAGE_MODE = ALWAYS/OPT_IN`
- Fails for PkgC because system will take precedence
- Maybe works for PkgA using `FETCHCONTENT_UPDATE_DISCONNECTED_<uppercaseName>`?

### Case B

- `FETCHCONTENT_TRY_FIND_PACKAGE_MODE = NEVER`
- Fails for PkgA, PkgD, PkgE fail

* * *

> Workaround 1:

So if I understand correctly that part is to override the other definitions e.g. overriding `find_package` using `FetchContent_Declare(OVERRIDE_FIND_PACKAGE)` and overriding `FetchContent` with `FetchContent_Declare(FIND_PACKAGE_ARGS)`. At first glance that could appear to work, but the issue is considering the cases above, there will still be failures like in CaseA.

We could make a project specific flag to switch between different `FetchContentDeclare` definitions for each dependency, but is that really the best we could do? It makes the `CMakeLists.txt` file hard to follow and would make it hard to integrate with other projects.

---

<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: [May 19, 2023, 4:17am UTC](https://discourse.cmake.org/t/fetchcontent-try-find-package-mode-for-indvidual-package/8101/8 "2023-05-19T04:17:04Z")

</div>

Ok that is a very specific set of requirements. All of that logic could be implemented in a dependency provider where you intercept both `find_package()` and `FetchContent_MakeAvailable()` calls. You would add your desired behavior for each of the special cases and simply let all others go through to their default built-in handling.

Note that dependency providers can choose to ignore `FETCHCONTENT_TRY_FIND_PACKAGE_MODE`, so you are not constrained by the setting of that variable. Dependency providers are essentially free to ignore just about everything about a dependency if they so wish, so you should be able to get whatever behavior you’re aiming for.

---

<div class="post-metadata">

### Author: ![Lecris](https://discourse.cmake.org/user_avatar/discourse.cmake.org/lecris/32/3193_2.png) [@Lecris](https://discourse.cmake.org/u/Lecris)
#### Post date: [May 19, 2023, 4:26am UTC](https://discourse.cmake.org/t/fetchcontent-try-find-package-mode-for-indvidual-package/8101/9 "2023-05-19T04:26:32Z")

</div>

> Note that dependency providers can choose to ignore `FETCHCONTENT_TRY_FIND_PACKAGE_MODE`, so you are not constrained by the setting of that variable.

How does this one work? What I am concerned is that when the user sets `FETCHCONTENT_TRY_FIND_PACKAGE_MODE = NEVER` then cmake does not pass `FIND_PACKAGE_ARGS` as indicated by the documentation so I wouldn’t be able to cover all situations in that case.

---

<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: [May 19, 2023, 4:41am UTC](https://discourse.cmake.org/t/fetchcontent-try-find-package-mode-for-indvidual-package/8101/10 "2023-05-19T04:41:20Z")

</div>

In your dependency provider, you control the `find_package()` arguments. Only PkgD and PkgE in your example would be needing these. You should be able to decide what `find_package()` arguments you want to use in this case, you are being very specific about what you want to get from where. You should be able to specify the precise details you want to use to look in your system for those two. While I acknowledge that the project might be providing arguments that you might otherwise want to use, you should have little trouble working out what those arguments would have been and updating your dependency provider accordingly. Remember, a dependency provider is defined by the user with full knowledge of what the project is and would request, so you can take that knowledge into however you implement your provider.
