fpm icon indicating copy to clipboard operation
fpm copied to clipboard

use fpm to fill the gap between gcc macros and gfortran to enable seamless cpp preprocessing

Open jalvesz opened this issue 1 year ago • 5 comments

Description

Hi, I would like to propose that fpm fills in the gap left between gcc and gfortran where all defined macros are not available from gfortran without using CMake.

While there are many discussions about preprocessors, most of the defacto preprocessing is being done using cpp/fpp. Simple tasks such as determining on which OS a program is running (which can be set at compile time) either rely on C preprocessing or having to use get_environment_variable at runtime.

Possible Solution

One idea would be to make it such that fpm catches the list of macros from gcc by running (if using gfortran) the commands: Linux

gcc -dM -E - < /dev/null

Windows

gcc -dM -E - <NUL:

And pass them through the preprocess.cpp mechanism by default.

Additional Information

No response

jalvesz avatar Oct 02 '24 18:10 jalvesz

You are referring to the issue also documented here, https://cyber.dabamos.de/programming/modernfortran/preprocessor.html,

As CPP, the preprocessor of GNU Fortran, is not indicating the current operating system, we have to pass the macro through argument -D, in this particular case, -D__FreeBSD__

Concerning the behaviour of CMake, some material can be found in the discussion https://github.com/fortran-lang/fpm/discussions/730. If I understood you correctly, you are saying the CMake somehow merges the preprocessor environment of gcc and gfortran, and then invokes gfortran on the preprocessed file?

ivan-pi avatar Oct 18 '24 21:10 ivan-pi

Well, I had done some tests in which CMake managed to preprocess for instance the WIN32 definition... I'm testing a single file test anew and I'm not getting the behavior, so I might need to go again through it ...

Now, CMake does have OS definitions which can be used. For instance, one can add the following to a CMakeLists.txt:

# Convert CMAKE_SYSTEM_NAME to uppercase
string(TOUPPER "${CMAKE_SYSTEM_NAME}" SYSTEM_NAME_UPPER)

# Pass the uppercase system name as a macro
add_compile_options(-D${SYSTEM_NAME_UPPER})

So any of the system names provided here https://cmake.org/cmake/help/latest/variable/CMAKE_SYSTEM_NAME.html can be used as a definition.

It seems that it would also be necessary to find way to recover gcc definitions with CMake.

jalvesz avatar Oct 18 '24 22:10 jalvesz

One way to identify the OS and save it as a parameter would be to use the compiler_version and compiler_options intrinsic functions. It will certainly need quite some testing and experimenting, but I believe that at least for the major compilers it would be relatively easy to come up with a parameter boolean flag that stores whether the local system is Windows/unix/etc.:

use iso_fortran_env
character(1024), parameter :: opts= compiler_options()
character(1024), parameter :: vers =compiler_version()
logical :: is_windows = index(opts,"C:\")>0 .or. &
                        index(opts,":\")>0 .or. &
                        index(vers,'Windows')>0 .or. &
                        index(vers,'MSYS')>0
print *, opts
print *, vers
print *, 'is_windows = ',is_windows 
end

note that this would not work if we're cross-compiling (i.e. a Windows .exe from a unix machine).

perazz avatar Oct 19 '24 09:10 perazz

For cross compilation I guess it would be necessary to distinguish between the current build OS and the "target" OS. If the target is different from the build OS then one should pass this as an optional parameter. I'm not familiar with this though, I usually build directly for the target OS and use a virtual machine to build for a different one, which in any case implies that the build system sees it as "native".

I was imagining to maybe print the defined macros from the compiler to a temp file which can be retrieved to pass the macros as definitions, at least for gnu as it seems that intel fortran does the job. But for cross compilation this would not be enough indeed.

jalvesz avatar Oct 20 '24 11:10 jalvesz

Most macro definitions in GCC are rarely used by GFortran users. The commonly used ones are __GFORTRAN__ and _WIN32. In at least some scenarios, perhaps fpm can, like CMake, define a macro definition similar to CMAKE_SYSTEM_NAME to compile fpm projects and address the issue of operating system judgment first?

For example, fpm defines -DOS_WINDOWS and -D_WIN32 under Windows, defines -DOS_Linux under Linux, and defines -DOS_MACOS under macOS.

zoziha avatar Oct 23 '24 03:10 zoziha