# How to find\_package(... OPTIONAL) in CMake 3?

**URL:** https://discourse.cmake.org/t/how-to-find-package-optional-in-cmake-3/15309
**Category:** Code
**Created:** [November 15, 2025, 7:45pm UTC](https://discourse.cmake.org/t/how-to-find-package-optional-in-cmake-3/15309 "2025-11-15T19:45:22Z")
**Posts on this page:** 4
**Page:** 1

<div class="post-metadata">

### Author: ![a\_toldaiev](https://discourse.cmake.org/user_avatar/discourse.cmake.org/a_toldaiev/32/5496_2.png) [@a\_toldaiev](https://discourse.cmake.org/u/a_toldaiev)
#### Post date: [November 15, 2025, 7:45pm UTC](https://discourse.cmake.org/t/how-to-find-package-optional-in-cmake-3/15309/1 "2025-11-15T19:45:22Z")

</div>

I would like to check whether `Catch2` is installed, and if not then `FetchContent` it. CMake 4 has [the `OPTIONAL` keyword](https://cmake.org/cmake/help/latest/command/find_package.html#basic-signature) to try `find_package` without throwing a warning. So, you can do something like this:

```auto
# get Catch2
if(TARGET Catch2::Catch2)
  message(STATUS "${PROJECT_NAME} > GOT Catch2 from parent project")

else()
  find_package(Catch2 3 OPTIONAL)
  message(STATUS "${PROJECT_NAME} > tried find_package(Catch2 3) ${Catch2_FOUND}")

  if(TARGET Catch2::Catch2)
    message(STATUS "${PROJECT_NAME} > Top level - got Catch2 by find_package")

  else()
    message(STATUS "${PROJECT_NAME} > Top level - FetchContent Catch2")

    include(FetchContent)
    FetchContent_Declare(
      Catch2
      GIT_REPOSITORY https://github.com/catchorg/Catch2.git
      GIT_TAG v3.8.1 # or a later release
    )
    FetchContent_MakeAvailable(Catch2)
  endif()
endif()

```

But CMake 3 will throw an _error_:

> `find_package` called with invalid argument “OPTIONAL”.

If you just omit `OPTIONAL`, then you will get a warning in the case when the package is not installed:

> By not providing “FindCatch2.cmake” in `CMAKE_MODULE_PATH`…

What is the right way to check whether `FindCatch2.cmake` is provided in the system?

---

<div class="post-metadata">

### Author: ![ClausKlein](https://discourse.cmake.org/user_avatar/discourse.cmake.org/clausklein/32/352_2.png) [@ClausKlein](https://discourse.cmake.org/u/ClausKlein)
#### Post date: [November 15, 2025, 8:06pm UTC](https://discourse.cmake.org/t/how-to-find-package-optional-in-cmake-3/15309/2 "2025-11-15T20:06:54Z")

</div>

You may use **QUIET** instead of **OPTIONAL** with all cmake versions.

---

<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: [November 15, 2025, 8:23pm UTC](https://discourse.cmake.org/t/how-to-find-package-optional-in-cmake-3/15309/3 "2025-11-15T20:23:31Z")

</div>

Since CMake 3.24, FetchContent has built-in support for trying `find_package()` first before falling back to fetching the content with the supplied details. Add the `FIND_PACKAGE_ARGS` keyword to your `FetchContent_Declare()` call. For example:

```cmake
include(FetchContent)
FetchContent_Declare(
  Catch2
  GIT_REPOSITORY https://github.com/catchorg/Catch2.git
  GIT_TAG v3.8.1 # or a later release
  FIND_PACKAGE_ARGS 3
)
FetchContent_MakeAvailable(Catch2)

```

---

<div class="post-metadata">

### Author: ![a\_toldaiev](https://discourse.cmake.org/user_avatar/discourse.cmake.org/a_toldaiev/32/5496_2.png) [@a\_toldaiev](https://discourse.cmake.org/u/a_toldaiev)
#### Post date: [November 16, 2025, 3:58pm UTC](https://discourse.cmake.org/t/how-to-find-package-optional-in-cmake-3/15309/4 "2025-11-16T15:58:48Z")

</div>

Thanks a lot! I will mark the `QUIET` keyword as the solution, because it should cover more versions. (I think we have CMake 3.14 in one of situations.) But the FetchContent `FIND_PACKAGE_ARGS` is awesome.
