# How to prevent CMake usage of an outdated fortran module

**URL:** https://discourse.cmake.org/t/how-to-prevent-cmake-usage-of-an-outdated-fortran-module/8710
**Category:** Code
**Tags:** os:linux, gen:makefiles, gen:ninja, lang:fortran
**Created:** [August 10, 2023, 8:05am UTC](https://discourse.cmake.org/t/how-to-prevent-cmake-usage-of-an-outdated-fortran-module/8710 "2023-08-10T08:05:14Z")
**Posts on this page:** 7
**Page:** 1

<div class="post-metadata">

### Author: ![uranix](https://discourse.cmake.org/user_avatar/discourse.cmake.org/uranix/32/3704_2.png) [@uranix](https://discourse.cmake.org/u/uranix)
#### Post date: [August 10, 2023, 8:05am UTC](https://discourse.cmake.org/t/how-to-prevent-cmake-usage-of-an-outdated-fortran-module/8710/1 "2023-08-10T08:05:14Z")

</div>

I’m using CMake to build a moderate-sized Fortran project. I noticed that sometimes when I refactor modules I ran into weird compilation errors that are gone after clean rebuild in a fresh build directory.

I’ve managed to reproduce the problem in the following minimal example. Consider a project with two libraries and a single executable

```sh
├── build
├── CMakeLists.txt
├── liba
│ ├── CMakeLists.txt
│ ├── first.f90
│ └── second.f90
├── libb
│ ├── CMakeLists.txt
│ └── third.f90
└── main.f90

```

The `main.f90` is simply

```fortran
program test
  use first, only: x
  use second, only: y
  use third, only: z
  implicit none
  print *, x, y, z
end program

```

and the root `CMakeLists.txt` is

```cmake
project(test)
enable_language(Fortran)

add_subdirectory(liba)
add_subdirectory(libb)

add_executable(main main.f90)
target_link_libraries(main a b)

```

Each module just exports a single parameter value

```f90
! first.f90
module first
  integer, parameter :: x = 1
end module first
! second.f90
module second
  integer, parameter :: y = 2
end module second
! third.f90
module third
  integer, parameter :: z = 3
end module third

```

The libraries are described similarly as

```cmake
# liba/CMakeLists.txt
add_library(a
    first.f90
    second.f90
)
target_include_directories(a PUBLIC ${CMAKE_CURRENT_BINARY_DIR})
# libb/CMakeLists.txt
add_library(b
    third.f90
)

target_include_directories(b PUBLIC ${CMAKE_CURRENT_BINARY_DIR})

```

Building and running I get `1 2 3`, as expected.

**Now the problem**. If I move the `second.f90` to `libb` and change `y = 2` to `y = 42` I **still** have `1 2 3` as the output, even if I do full rebuild using `make -C build clean all`. This is because `liba` output directory contains `second.mod` with outdated parameter value `y = 2` and it is used instead of the correct module in the `libb` build directory. The Ninja generator behaves just the same.

I greatly appreciate any suggestions how to fix my build scripts to avoid this kind of errors.

Just in case you want to try it yourself, here is the example on GitHub:

```bash
$ git clone https://github.com/uranix/cmake-fortran-modules
$ cd cmake-fortran-modules
$ git checkout a90ddfc
$ cmake -B build
$ make -C build
$ ./build/main 
           1 2 3
$ git checkout 736b738
$ make -C build
$ ./build/main 
           1 2 3
$ make -C build clean all
$ ./build/main 
           1 2 3
$ cmake -B build2
$ make -C build2
$ ./build2/main 
           1 42 3

```

---

<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: [August 10, 2023, 12:05pm UTC](https://discourse.cmake.org/t/how-to-prevent-cmake-usage-of-an-outdated-fortran-module/8710/2 "2023-08-10T12:05:14Z")

</div>

Can you please try 3.27.1? I recently fixed some dependency bits for the Fortran module logic.

---

<div class="post-metadata">

### Author: ![uranix](https://discourse.cmake.org/user_avatar/discourse.cmake.org/uranix/32/3704_2.png) [@uranix](https://discourse.cmake.org/u/uranix)
#### Post date: [August 10, 2023, 12:31pm UTC](https://discourse.cmake.org/t/how-to-prevent-cmake-usage-of-an-outdated-fortran-module/8710/3 "2023-08-10T12:31:41Z")

</div>

Tried `3.27.20230809-e525f856`, the issue persists. Directory `build/liba` still contains an outdated version for `second.mod`.

---

<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: [August 10, 2023, 12:37pm UTC](https://discourse.cmake.org/t/how-to-prevent-cmake-usage-of-an-outdated-fortran-module/8710/4 "2023-08-10T12:37:08Z")

</div>

Oh, right. So the issue here is that Fortran searches for modules using `-I` and searching instead of getting more direct “this is module `a`’s file” information. I don’t know exactly what we can do to clean up modules that we don’t know about anymore 😕 . We’d have to store the information in a “previous” file, diff it, then remove things no longer expected to be generated.

I am, in general, wary about build systems deleting files that are (no longer) mentioned in the build graph because we don’t actually know what its purpose is or how to get it back.

---

<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: [August 10, 2023, 12:38pm UTC](https://discourse.cmake.org/t/how-to-prevent-cmake-usage-of-an-outdated-fortran-module/8710/5 "2023-08-10T12:38:16Z")

</div>

> [@ben.boeckel](#):
>
> We’d have to store the information in a “previous” file, diff it, then remove things no longer expected to be generated.

And if Fortran is completely removed from a target, we wouldn’t generate the command for module collation in the first place, so the cleanup bridge would be lost as well.

---

<div class="post-metadata">

### Author: ![uranix](https://discourse.cmake.org/user_avatar/discourse.cmake.org/uranix/32/3704_2.png) [@uranix](https://discourse.cmake.org/u/uranix)
#### Post date: [August 10, 2023, 5:30pm UTC](https://discourse.cmake.org/t/how-to-prevent-cmake-usage-of-an-outdated-fortran-module/8710/6 "2023-08-10T17:30:18Z")

</div>

I think it is possible to maintain a separate module directory with symlinks or copies of .mod files. And keep it up to date by removing outdated links / copies

---

<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: [August 10, 2023, 6:18pm UTC](https://discourse.cmake.org/t/how-to-prevent-cmake-usage-of-an-outdated-fortran-module/8710/7 "2023-08-10T18:18:01Z")

</div>

I suppose the collator could:

- prepare a dedicated directory for `.mod` files
- upon finding out what modules will be created, delete all other module files

Issues:

- users can currently control this directory (via [`Fortran_MODULE_DIRECTORY`](https://cmake.org/cmake/help/latest/prop_tgt/Fortran_MODULE_DIRECTORY.html) and if these overlap, we don’t know what else is supposed to be here
- users need to know where they exist at configure time to write `install()` rules (or we go with C++'s solution which generates install script snippets in the collator)
