Fpm issue with preprocessor-defined use statements

Hi all.

I am trying to set up something like the following (which works fine in cmake makefiles) using fpm. Depending on the preprocessor flag/macro, I want different modules to be imported in the Fortran code.

My main.F90 is:

program main
#ifdef AAA
  use aaa
#endif
  use fpm_test, only: say_hello
  implicit none

  call say_hello()
end program main

My fpm.toml is:

name = "fpm-test"
version = "0.1.0"
license = "license"
author = "nedanator"
maintainer = "aaa@bbb.ccc"
copyright = "Copyright 2024, nedanator"
[build]
auto-executables = true
auto-tests = true
auto-examples = true
module-naming = false
[install]
library = false
[fortran]
implicit-typing = false
implicit-external = false
source-form = "free"
[preprocess]
[preprocess.cpp]

When I use

fpm build

I get the following error:

<ERROR> *cmd_build* Target error: Unable to find source for module dependency: "aaa" used by "app/main.F90"
STOP 1

I feel like I’m missing something obvious, but I haven’t been able to get it to work after a bit of playing around. Adding and removing the following line from the fpm.toml seems to do nothing.

macros = ["AAA=Off"]

Is this something with fpm needing to look at the files and dependencies before it even runs through the preprocessor, so it looks at all use statements (and, hence, the preprocessor can’t doesn’t get a chance to turn it off)?

Thanks in advance for any help.
Ned

This is exactly it. fpm doesn’t run the preprocessor before looking for use statements to determine the file dependencies. I don’t really know how cmake manages to accomplish this.

Thanks @everythingfunctional. This means I can stop looking at this idea. :slight_smile:

From what I understand, cmake does no work itself in terms of the compilation of the actual Fortran files. So it just calls the compiler with the preprocessor flags and, at which point, the file will have that section removed (if the option is off) before it is passed to the Fortran compiler properly.

I guess, with fpm’s easy dependency installation capabilities, I probably don’t actually need this option here, and can just always have it install the dependency aaa, regardless of whether or not the code will actually use it (and then I just need to find a way to pass that option flag through fpm to get to the compiler preprocessor). That way, it’ll always be able to find that library for the use statement, regardless of whether it’ll use it later on.

That’s what I would suggest, at least for now.

But then how does it know which order to compile the files? You cannot compile a file that uses a module before the file that contains the module. Surely it does something to respect that dependency, but maybe I’m assuming too much.

CMake has its own module dependency scanner. You can find more information in a previous post: CMake FortranCInterface - #8 by ivanpribec

2 Likes

The use statement was for importing an external library. So it would be using linking flags in the compiler command to link to something already built that didn’t have dependencies the other way.

Oh, that’s cool. Thanks @ivanpribec, I didn’t know that! :smiley:

See also:

Can you make fpm ignore a USE statement inside a preprocessor #ifdef #endif block · Issue #773 · fortran-lang/fpm · GitHub

until resolved in a more robust way, perhaps a note on how to work around this should be added to the documentation.

1 Like