Skip to content

scivision/fortran-filesystem

Repository files navigation

Ffilesystem: for Fortran using C++ filesystem or standalone C stdlib functions

DOI ci ci_windows oneapi-linux ci_fpm ci_meson

Platform independent (Linux, macOS, Windows, Cygwin, WSL, BSD, ...), object-oriented Fortran filesystem "Ffilesystem" path manipulation library. Ffilesystem header ffilesystem.h can be used from C and C++ project code--see example.

For C++ users, C++17 standard is required. For C users, C99 standard is required. Fortran uses Fortran 2003 standard and either the C or C++ Ffilesystem backend.

For full features, Ffilesystem uses C++ stdlib filesystem. If a compatible C++ compiler isn't available, Ffilesystem downloads and uses CWalk and C runtime library.

Inspired by (and benchmarked against) Python pathlib.

Important Ffilesystem functions are benchmarked to help improve performance.

Advanced / conceptual development takes place in ffilesystem-concepts repo.

Compiler support

Ffilesystem supports compilers including:

  • GCC ≥ 8 (gcc/g++, gfortran)
  • LLVM Clang ≥ 9 (clang/clang++, flang or gfortran)
  • Intel oneAPI (icx, icpx, ifx)
  • AMD AOCC (clang/clang++, flang)
  • NVidia HPC SDK (nvc++, nvfortran)
  • Visual Studio (C/C++)
  • Cray: using Cray compilers alone (cc, CC, ftn) or using GCC or Intel backend

C++ interface requires compiler to support <filesystem>. The older <experimental/filesystem> is NOT supported. To manually disable C++ support:

cmake -Bbuild -Dffilesystem_cpp=off

GCC 7.x and Clang 7.x, 8.x may work with option cmake -Dffilesystem_cpp=off.

libstdc++

Some systems have broken, obsolete, or incompatible libstdc++.

Intel: If Intel compiler linker errors use GCC >= 9.1. This can be done by setting environment variable CXXFLAGS to the top level GCC >= 9.1 directory. Set environment variable CXXFLAGS for Intel GCC toolchain like:

export CXXFLAGS=--gcc-toolchain=/opt/rh/gcc-toolset-10/root/usr/

which can be determined like:

scl enable gcc-toolset-10 "which g++"

Build

Ffilesystem can be built with CMake or Fortran Package Manager (FPM).

"libffilesystem.a" is the library binary built that contains the Fortran "filesystem" module--it is the only binary you need to use in your project.

Please see the API docs for extensive list of functions/subroutines.

Use any one of these methods to build Ffilesystem (CMake is recommended):

CMake:

cmake -B build
cmake --build build
# optional
ctest --test-dir build

Meson:

meson setup build
meson compile -C build
# optional
meson test -C build

Fortran Package Manager:

FPM_CXXFLAGS=-std=c++20 fpm build

GNU Make:

make

We provide Fortran REPL "filesystem_cli" and C++ REPL "fs_cli" for interactive testing of Ffilesystem routines.

Build options

Fortran "filesystem" module contains OPTIONAL (enabled by default) Fortran type "path_t" that contains properties and methods. The "path_t" type uses getter and setter procedure to access the path as a string character(:), allocatable.

use filesystem, only : path_t

type(path_t) :: p

p = path_t("my/path")  !< setter

print *, "path: ", p%path() !< getter

The CMake and Meson scripts detect if Fortran 2003 type is available and enable path_t by default. To manually enable / disable path_t with CMake set command option cmake -DHAVE_F03TYPE=1 or cmake -DHAVE_F03TYPE=0 respectively.

Usage from other projects

The example directory contains a use pattern from external projects. One can either cmake --install build ffilesystem or use CMake ExternalProject or FetchContent from the other project. To find ffilesystem in your CMake project:

find_package(ffilesystem CONFIG REQUIRED)

Note the CMake package variables ffilesystem_cpp and ffilesystem_fortran indicate whether ffilesystem was built with C++ and/or Fortran support.

ffilesystem.cmake would be included from the other project to find or build Ffilesystem automatically. It provides the appropriate imported targets for shared or static builds, including Windows DLL handling.

Notes

A few topics on unsupported features:

non-ASCII characters

Due to compiler limitations, currently Ffilesystem only officially supports ASCII characters.

The UCS selected_char_kind('ISO_10646'), is an optional feature of Fortran 2003 standard. Intel oneAPI does not support selected_char_kind('ISO_10646') as of this writing.

filesystem currently uses the default Fortran character kind, which is ASCII. This typically allows pass-through of UTF-8 characters, but this is not guaranteed.

C++ filesystem discussion

Security research led to TOCTOU-related patches to the C++ filesystem library in various C++ standard library implementations noted in that discussion. Ffilesystem does NOT use remove_all, which was the TOCTOU concern addressed above.

Since the underlying C++ filesystem is not thread-safe, race conditions can occur if multiple threads are accessing the same filesystem object regardless of the code language used in the Ffilesystem library.