# Fortran: Importing \`.mod\` with fallback to \`.f90\`

**URL:** <https://discourse.cmake.org/t/fortran-importing-mod-with-fallback-to-f90/9978>\
**Category:** Code\
**Created:** [January 31, 2024, 6:12pm UTC](https://discourse.cmake.org/t/fortran-importing-mod-with-fallback-to-f90/9978 "2024-01-31T18:12:39Z")\
**Posts on this page:** 13\
**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:** [January 31, 2024, 6:12pm UTC](https://discourse.cmake.org/t/fortran-importing-mod-with-fallback-to-f90/9978/1 "2024-01-31T18:12:39Z")

</div>

I am thinking of a workaround compatibility until the CXX modules logic can be ported to Fortran as well. My idea is the following:

1. Pacakge both the `.mod` files and the `.f90` files with the `install(TARGETS)` all of which are installed at `PUBLIC_HEADER` (Maybe `FILE_SET` would be better, but how to do that?)
2. Inside the `<Package>Config.cmake` run `try_compile` consuming a `.mod` file
3. If it fails, then `target_sources(INTERFACE)` that imported target

My only concern here is, how to hide the packaged `.mod` file from being used. My hope is that `CMAKE_Fortran_MODULE_DIRECTORY` will take precedence over `-I` include search. What do you guys think?

---

<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:** [February 4, 2024, 7:44pm UTC](https://discourse.cmake.org/t/fortran-importing-mod-with-fallback-to-f90/9978/2 "2024-02-04T19:44:15Z")

</div>

I don’t think Fortran compilers support `.mod`-only compilation modes. Also, `.mod` files are searched for via `-I` flags, so precedence is a difficult thing to untangle there.

`FILE_SET` would definitely be a better way of doing this, but as long as module searches are implicit searches rather than “find module X in _this_ file”, I don’t think there’s a lot to gain in practice.

---

<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:** [February 5, 2024, 2:25pm UTC](https://discourse.cmake.org/t/fortran-importing-mod-with-fallback-to-f90/9978/3 "2024-02-05T14:25:14Z")

</div>

@ben.boeckel I have found quite a neat way to support it in the meantime:

```cmake
	# TODO: CMake 3.25 use the modern try_compile signature. Remove the explicit CMakeScratch
	try_compile(spglib_fortran_try_compile ${CMAKE_BINARY_DIR}/CMakeFiles/CMakeScratch/spglib_fortran
			SOURCES ${CMAKE_CURRENT_LIST_DIR}/try_compile.f90
			LINK_LIBRARIES Spglib::fortran_mod
	)
	if (spglib_fortran_try_compile)
		# If the compilation was successful, use the module version of the library
		add_library(Spglib::fortran ALIAS Spglib::fortran_mod)
	else ()
		# Otherwise, assume it was because of incompatible compiler
		# Add the bundled `.f90` files as sources instead
		add_library(Spglib::fortran ALIAS Spglib::fortran_include)
	endif ()

```

Where I basically have defined 2 targets, one with `target_sources(INTERFACE)`, the other with the normal link library.

I think it would be good to document this design, what do you think?

---

<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:** [February 8, 2024, 5:06am UTC](https://discourse.cmake.org/t/fortran-importing-mod-with-fallback-to-f90/9978/4 "2024-02-08T05:06:31Z")

</div>

That feels like it’s going to end up with duplicated symbols because the `.f90` files will be compiled and linked in the linking target as well. Not that Fortran has an ODR that I’m aware of, but linkers still do.

---

<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:** [February 8, 2024, 7:44am UTC](https://discourse.cmake.org/t/fortran-importing-mod-with-fallback-to-f90/9978/5 "2024-02-08T07:44:08Z")

</div>

The key part is that `fortran_include` target contains only `target_sources` (and link libraries to dependencies) so it does not link to the compiled library in `fortran_mod`. In other words the former is `add_library(INTERFACE)`, and the latter `add_library(SHARED)` \[1\]. There will be duplicated fortran symbols as each consuming project will compile the f90 files themselves, but that should be fine if it’s not re-exposed isn’t it?

* * *

1. [spglib/fortran/CMakeLists.txt at develop · spglib/spglib · GitHub](https://github.com/spglib/spglib/blob/develop/fortran/CMakeLists.txt)

---

<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:** [February 8, 2024, 1:08pm UTC](https://discourse.cmake.org/t/fortran-importing-mod-with-fallback-to-f90/9978/6 "2024-02-08T13:08:57Z")

</div>

If you have:

```cmake
add_library(uses_fortran_sources)
target_link_libraries(uses_fortran_sources PUBLIC Spglib::fortran_include) # sources added here

add_library(transitive)
target_link_libraries(transitive uses_fortran_sources) # sources also added here

```

---

<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:** [February 8, 2024, 1:23pm UTC](https://discourse.cmake.org/t/fortran-importing-mod-with-fallback-to-f90/9978/7 "2024-02-08T13:23:16Z")

</div>

Oh, fair point. Users should be using `target_link_libraries(PRIVATE)` whenever possible. Would making an `OBJECT` layer between that help, assuming that `uses_fortran_sources` and `transitive` do not re-export the interface of `Spglib`?

I.e.:

```auto
	# TODO: CMake 3.25 use the modern try_compile signature. Remove the explicit CMakeScratch
	try_compile(spglib_fortran_try_compile ${CMAKE_BINARY_DIR}/CMakeFiles/CMakeScratch/spglib_fortran
			SOURCES ${CMAKE_CURRENT_LIST_DIR}/try_compile.f90
			LINK_LIBRARIES Spglib::fortran_mod
	)
	if (spglib_fortran_try_compile)
		# If the compilation was successful, use the module version of the library
		add_library(Spglib::fortran ALIAS Spglib::fortran_mod)
	else ()
		# Otherwise, assume it was because of incompatible compiler
		# Add the bundled `.f90` files as sources instead
		add_library(Spglib_fortran_obj OBJECT)
		add_library(Spglib_fortran_interface INTERFACE)
		target_link_libraries(Spglib_fortran_obj PRIVATE Spglib::fortran_include PUBLIC Spglib::symspg)
		target_link_libraries(Spglib_fortran_interface INTERFACE Spglib_fortran_obj $<TARGET_OBJECTS:Spglib_fortran_obj>)
		add_library(Spglib::fortran ALIAS Spglib_fortran_interface)
	endif ()

```

Should also confirm a few things about this:

- Is the restriction on `namespace::target` convention only for shared/static/executable or does it apply for object/interface as well?
- Is it possible to export object libraries such that it include the source and not the compiled objects there?

---

<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:** [February 16, 2024, 2:15pm UTC](https://discourse.cmake.org/t/fortran-importing-mod-with-fallback-to-f90/9978/8 "2024-02-16T14:15:21Z")

</div>

> [@Lecris](#):
>
> Is the restriction on `namespace::target` convention only for shared/static/executable or does it apply for object/interface as well?

This syntax is for exported targets (which become `IMPORTED` targets on the other side) and `ALIAS` targets (which you can add in your build to match consumers). When CMake sees a `::` in a linked library name, it knows it expects a target (rather than falling back to “try `-lstring`”).

> [@Lecris](#):
>
> Is it possible to export object libraries such that it include the source and not the compiled objects there?

Probably; still feels like an ODR violation waiting to happen to me, but I don’t see why this wouldn’t work.

---

<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:** [February 16, 2024, 2:44pm UTC](https://discourse.cmake.org/t/fortran-importing-mod-with-fallback-to-f90/9978/9 "2024-02-16T14:44:44Z")

</div>

Ok I did some simple tests. On the project side, we cannot export and object library to be an object library on the import side. It will still be an `INTERFACE IMPORTED`. At least it would not install object files.

> [@ben.boeckel](#):
>
> This syntax is for exported targets (which become `IMPORTED` targets on the other side) and `ALIAS` targets (which you can add in your build to match consumers).

Ok, so if we were to make an object target for that it would have to non-namespaced, and given the previous experiment, it would have to live in the `Config.cmake` file.

> [@ben.boeckel](#):
>
> Probably; still feels like an ODR violation waiting to happen to me, but I don’t see why this wouldn’t work.

It should solve the ODR w.r.t. object/modules for the build, but yeah it is prone to duplication as it is consumed across multiple libraries. But I don’t think there would be a design around that without injecting a shared library in one of the consuming projects.

The one downside that I could see in this approach is that the object libraries does not know when it should be PIC and not. Is there a downside for making it always PIC? Are there other irregularities around shared vs static?

---

<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:** [February 16, 2024, 2:55pm UTC](https://discourse.cmake.org/t/fortran-importing-mod-with-fallback-to-f90/9978/10 "2024-02-16T14:55:54Z")

</div>

> [@Lecris](#):
>
> we cannot export and object library to be an object library on the import side. It will still be an `INTERFACE IMPORTED`. At least it would not install object files.

I think you need to explicitly install the objects with `install(OBJECTS DESTINATION)` to get an `OBJECT` library on the other side.

> [@Lecris](#):
>
> Is there a downside for making it always PIC?

AFAIK, no. It allows your binaries to be ASLR-located.

---

<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:** [February 16, 2024, 4:08pm UTC](https://discourse.cmake.org/t/fortran-importing-mod-with-fallback-to-f90/9978/11 "2024-02-16T16:08:59Z")

</div>

Oh interesting. I’ve tried it out a bit, but the `OBJECT IMPORTED` does not get any private sources link-libraries, etc. that it can use to re-build itself, and we cannot attach anything other than `INTERFACE` on them, so we would still need to define it in `Config.cmake`

---

<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:** [February 16, 2024, 4:32pm UTC](https://discourse.cmake.org/t/fortran-importing-mod-with-fallback-to-f90/9978/12 "2024-02-16T16:32:54Z")

</div>

Ok, then we likely need some more thought into how this goes. Note that `$<COMPILE_ONLY>` allows for hiding this kind of stuff from linking usages. But we’ll probably want a `FILE_SET` for Fortran modules like we do for C++ to separate things out. It’ll definitely need a policy.

---

<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:** [February 17, 2024, 5:39am UTC](https://discourse.cmake.org/t/fortran-importing-mod-with-fallback-to-f90/9978/13 "2024-02-17T05:39:46Z")

</div>

While formalizing this as a feature request issue might be warranted, I really don’t know if/when any time to make it a priority would happen.
