# Optional dependencies with fpm

**URL:** <https://fortran-lang.discourse.group/t/optional-dependencies-with-fpm/8538>\
**Category:** Help\
**Created:** [August 30, 2024, 6:53pm UTC](https://fortran-lang.discourse.group/t/optional-dependencies-with-fpm/8538 "2024-08-30T18:53:21Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![milancurcic](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/milancurcic/32/2_2.png) [@milancurcic](https://fortran-lang.discourse.group/u/milancurcic)\
**Post date:** [August 30, 2024, 6:53pm UTC](https://fortran-lang.discourse.group/t/optional-dependencies-with-fpm/8538/1 "2024-08-30T18:53:21Z")

</div>

In neural-fortran I use a few different dependencies. Fpm makes this very easy to do via fpm.toml, e.g. see [neural-fortran/fpm.toml at main · modern-fortran/neural-fortran · GitHub](https://github.com/modern-fortran/neural-fortran/blob/main/fpm.toml).

Now, I want to make the HDF5 dependency optional, because a small fraction of users needs it, and because it adds considerable set-up complexity to build the project.

I figured out how to do this with CMake, where I block out sections of code with CPP macros, and tell CMake to not pull the dependencies if that macro is not defined.

How would I best do this with fpm?

I don’t think it’s possible to mark dependencies as optional in fpm, and then use an fpm flag for example.

A possible workaround could be to have two separate fpm.toml files, e.g. fpm.toml and fpm-with-hdf5.toml. Both would need to enable preprocessing, and the latter would need to define the macro. In that case in fpm.toml (no HDF5) I would have:

```auto
# no [build] rules
# no [dependencies] rules

[preprocess]
[preprocess.cpp]
suffixes = ["f90"]

```

and in fpm-with-hdf5.toml I would have:

```auto
[build]
external-modules = "hdf5"
link = ["hdf5", "hdf5_fortran"]

[dependencies]
functional = { git = "https://github.com/wavebitscientific/functional-fortran" }
h5fortran = { git = "https://github.com/geospace-code/h5fortran" }
json-fortran = { git = "https://github.com/jacobwilliams/json-fortran" }

[preprocess]
[preprocess.cpp]
macros = ["USE_KERAS_HDF5"]
suffixes = ["f90"]

```

However, in the first case, I still get

```auto
 $ fpm build
 + mkdir -p build/dependencies
<ERROR> *cmd_build* Target error: Unable to find source for module dependency: "functional" used by "././src/nf/nf_keras_submodule.f90"
STOP 1

```

I guess that this is because fpm doesn’t preprocess the source files before establishing the dependencies.

Any advice on how to work around this with the current fpm? This is with v0.10.1.

Thanks!

---

<div class="post-metadata">

**Author:** ![gnikit](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/gnikit/32/1213_2.png) [@gnikit](https://fortran-lang.discourse.group/u/gnikit)\
**Post date:** [August 30, 2024, 8:03pm UTC](https://fortran-lang.discourse.group/t/optional-dependencies-with-fpm/8538/2 "2024-08-30T20:03:37Z")

</div>

I had to do the same with PETSc a while back for some training courses at Imperial with fpm. I can’t remember off the top of my head what I did, but I will look if I still have the packages stored somewhere and get back to you.

---

<div class="post-metadata">

**Author:** ![certik](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/certik/32/4_2.png) [@certik](https://fortran-lang.discourse.group/u/certik)\
**Post date:** [August 30, 2024, 9:31pm UTC](https://fortran-lang.discourse.group/t/optional-dependencies-with-fpm/8538/3 "2024-08-30T21:31:54Z")

</div>

I think this is just this old issue: [Optional dependencies · Issue #84 · fortran-lang/fpm · GitHub](https://github.com/fortran-lang/fpm/issues/84), nobody has implemented it yet. PRs welcome. 🙂

---

<div class="post-metadata">

**Author:** ![milancurcic](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/milancurcic/32/2_2.png) [@milancurcic](https://fortran-lang.discourse.group/u/milancurcic)\
**Post date:** [August 31, 2024, 3:39am UTC](https://fortran-lang.discourse.group/t/optional-dependencies-with-fpm/8538/4 "2024-08-31T03:39:43Z")

</div>

As a workaround I ended up pulling out the code that depends on HDF5 and other dependencies and putting in its own standalone package: [GitHub - neural-fortran/nf-keras-hdf5: Keras HDF5 adapter for neural-fortran](https://github.com/neural-fortran/nf-keras-hdf5), which now uses neural-fortran as a required dependency.

On the Fortran end, this was only possible thanks to the use of submodules, which allowed separating the implementation (in nf-keras-hdf5) from the interface (in neural-fortran). Thanks to @rouson who convinced me to start using submodules more than 2 years ago, much to my resistance.

---

<div class="post-metadata">

**Author:** ![FedericoPerini](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/federicoperini/32/1750_2.png) [@FedericoPerini](https://fortran-lang.discourse.group/u/FedericoPerini)\
**Post date:** [August 31, 2024, 7:09am UTC](https://fortran-lang.discourse.group/t/optional-dependencies-with-fpm/8538/5 "2024-08-31T07:09:50Z")

</div>

I think it would be great to have optional dependencies in fpm and if we find consensus on the syntax, it’d be relatively easy to implement. In my view, any “optional” feature should be bound to the definition of a boolean macro, for the reason discussed here above (calls to modules/functions will have to be conditional, etc.). I like the way it was proposed on the wake of [Cargo](https://github.com/fortran-lang/fpm/issues/609). Here, one would have an optional package with a boolean

```toml
[dependencies]
mpi = { version="*", optional=true }

```

Being `optional` would automatically define a `features` table with the same name as the dependency, where the optional features can be set:

```toml
[features]
mpi.preprocess.cpp = ["WITH_MPI"]
mpi.fortran.implicit_typing = true

```

Because currently we already support [dependency based cpp macros](https://github.com/fortran-lang/fpm/issues/950) _without_ a feature table:

```toml
[dependencies]
a = { git = "https://github.com/b/c", preprocess.cpp.macros=["MY_MACRO"]}

```

I would also support a “simplified” syntax that, instead of grouped “features”, allows the definition of these flags directly in the `dependency` field:

```toml
[dependencies]
a = { git = "https://github.com/a/b", optional=true, fortran.implicit_typing=true, preprocess.cpp.macros=["WITH_A"]}

```

These options would of course not be enforced when the dependency is not present.

---

<div class="post-metadata">

**Author:** ![FedericoPerini](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/federicoperini/32/1750_2.png) [@FedericoPerini](https://fortran-lang.discourse.group/u/FedericoPerini)\
**Post date:** [August 31, 2024, 7:11am UTC](https://fortran-lang.discourse.group/t/optional-dependencies-with-fpm/8538/6 "2024-08-31T07:11:54Z")

</div>

> [@milancurcic](#):
>
> I want to make the HDF5 dependency

PS: on trunk, the HDF5 dependency is now a metapackage and you might want to give it a try:

```toml
[dependencies]
hdf5 = "*"

```

---

<div class="post-metadata">

**Author:** ![HugoMVale](https://avatars.discourse-cdn.com/v4/letter/h/e19adc/32.png) [@HugoMVale](https://fortran-lang.discourse.group/u/HugoMVale)\
**Post date:** [August 31, 2024, 10:31am UTC](https://fortran-lang.discourse.group/t/optional-dependencies-with-fpm/8538/7 "2024-08-31T10:31:49Z")

</div>

Regarding syntax for optional dependencies, `poetry` might be a good source of inspiration, especially the concept of (optional) groups.

[Managing dependencies | Documentation | Poetry - Python dependency management and packaging made easy (python-poetry.org)](https://python-poetry.org/docs/managing-dependencies/)

You end up with something like so:

```toml
...
[tool.poetry.dependencies]
python = ">=3.9,<4.0"
numpy = "^1.23.5"
...

[tool.poetry.group.docs]
optional = true
[tool.poetry.group.docs.dependencies]
mkdocs = "^1.4.2"
mkdocs-material = "^9.5.3"
...

[tool.poetry.group.dev]
optional = true
[tool.poetry.group.dev.dependencies]
pytest = "^8.1.1"
pytest-cov = "^5.0.0"
...

```

You activate optional groups with `--with`:

```sh
poetry install --with dev,docs

```

---

<div class="post-metadata">

**Author:** ![milancurcic](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/milancurcic/32/2_2.png) [@milancurcic](https://fortran-lang.discourse.group/u/milancurcic)\
**Post date:** [August 31, 2024, 11:40am UTC](https://fortran-lang.discourse.group/t/optional-dependencies-with-fpm/8538/8 "2024-08-31T11:40:26Z")

</div>

> [@FedericoPerini](#):
>
> PS: on trunk, the HDF5 dependency is now a metapackage and you might want to give it a try:

Great! I’ll try it once it’s in a tagged release.

---

<div class="post-metadata">

**Author:** ![vmagnin](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/vmagnin/32/28_2.png) [@vmagnin](https://fortran-lang.discourse.group/u/vmagnin)\
**Post date:** [March 14, 2025, 4:02pm UTC](https://fortran-lang.discourse.group/t/optional-dependencies-with-fpm/8538/9 "2025-03-14T16:02:58Z")

</div>

> [@milancurcic](#):
>
> A possible workaround could be to have two separate fpm.toml files, e.g. fpm.toml and fpm-with-hdf5.toml.

I have the same kind of problem and idea to convert a project to fpm. I have a computing project that can be built with GTK or be used on CLI. For the moment, I use two scripts `with_GUI.sh` and `without_GUI.sh` to compile and run it.

I have just made a quick test on a toy project where I have created two manifests `fpm1.toml` and `fpm2.toml` with different `src` directories (`src1` and `src2`). The manifest `fpm.toml` used by fpm is a symbolic link:

```bash
$ ln -sf fpm1.toml fpm.toml
$ fpm build
 Hello, essai!

```

It works, but when you switch you are obliged to first clean the build directory:

```bash
$ ln -sf fpm2.toml fpm.toml && fpm clean --skip 
$ fpm build
 Hello, essai2!

```

else fpm will not detect that the manifest has changed and will not rebuild the project.

Well, it seems a decent workaround, the commands being recorded in the terminal history. I will try to adapt my project with this solution.

---

<div class="post-metadata">

**Author:** ![RJaBi](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/rjabi/32/5161_2.png) [@RJaBi](https://fortran-lang.discourse.group/u/RJaBi)\
**Post date:** [May 13, 2025, 5:15pm UTC](https://fortran-lang.discourse.group/t/optional-dependencies-with-fpm/8538/10 "2025-05-13T17:15:50Z")

</div>

I’ve been hit by this question today too.

My problem is a touch different however, I want to disable any external dependencies. (Some systems do not have git or external internet on compute nodes which could be tricky to handle).

I can easily turn on/off the dependency using the cpp preprocessor, i.e.

```auto
#ifdef EXTDEPS                               
  use stdlib_hash_64bit, only: fnv_1a_hash   
#endif

```

but fpm still looks for that dependency. None of this is truly end of world stuff (it is easy enough for me to get a git exectuable manually, and point fpm at a local copy of stdlib), but it would be nice for others to have a way to avoid it.

---

<div class="post-metadata">

**Author:** ![hkvzjal](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/hkvzjal/32/3055_2.png) [@hkvzjal](https://fortran-lang.discourse.group/u/hkvzjal)\
**Post date:** [May 13, 2025, 5:28pm UTC](https://fortran-lang.discourse.group/t/optional-dependencies-with-fpm/8538/11 "2025-05-13T17:28:49Z")

</div>

Isn’t what you want to achieve easier to handle by coping the dependencies and using a path identifier to the location of your dependencies?

```toml
[dependencies]
stdlib = { path = "../stdlib" }

```

(Path relative to the root of current project, no need for git)

---

<div class="post-metadata">

**Author:** ![davidpfister](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/davidpfister/32/3949_2.png) [@davidpfister](https://fortran-lang.discourse.group/u/davidpfister)\
**Post date:** [May 13, 2025, 8:57pm UTC](https://fortran-lang.discourse.group/t/optional-dependencies-with-fpm/8538/12 "2025-05-13T20:57:30Z")

</div>

You may want to have a look at the open issue [773](https://github.com/fortran-lang/fpm/issues/773) on GitHub. It presents different ways to deal with the problem you are facing.

If you want to keep the preprocessing mechanism you can also do as follows:

```auto
#ifdef EXTDEPS                               
#include <stdlib.inc>
#endif

```

and in the file `stdlib.inc`

```auto
use stdlib_hash_64bit, only: fnv_1a_hash   

```

It’s a bit hacky but it does the job.

---

<div class="post-metadata">

**Author:** ![RJaBi](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/rjabi/32/5161_2.png) [@RJaBi](https://fortran-lang.discourse.group/u/RJaBi)\
**Post date:** [May 14, 2025, 8:09am UTC](https://fortran-lang.discourse.group/t/optional-dependencies-with-fpm/8538/13 "2025-05-14T08:09:19Z")

</div>

Thanks both!

I want to keep it simple for others to use, hence the disabling entirely. When we are running this code in full production mode, I don’t envision any issues with having dependencies (we would just compile once on the head node), but we are doing some profiling at the moment which is compiling on the compute nodes which are restricted somewhat.

I will update my notes to reflect the path version of dependencies, and also do the #include method.
