[RFC] Flang Dependency Scanning for CMake

RFC: Flang — Fortran Dependency Scanning for CMake

Summary and Motivation

This RFC proposes adding a dependency scanning mode to Flang. When invoked with new -fdeps- flags, Flang will preprocess and parse a Fortran translation unit without generating object code or .mod files, then emit a P1689R5-format JSON file listing the Fortran modules the file immediately provides and requires. CMake makes use of these P1689R5 format files to construct an accurate transitive module-dependency graph and determine correct build order. This will allow CMake to replace its current approximate Fortran parser for Flang and other derived compilers that use the Flang frontend with this new dependency scanning methodology.

CMake already supports compiler-driven dependency scanning for C++ (via clang-scan-deps, GCC’s -fdeps-, MSVC’s /scanDependencies flags and the P1689R5 format). Because no Fortran compiler currently supports this interface, CMake’s existing Fortran support relies on an approximate parser which relies on implementations to expand and serialize their preprocessing and might not handle all extensions a compiler allows. This can lead to incorrect build ordering in non-trivial projects. Having Flang emit authoritative dependency information will enable correct incremental builds for Fortran module hierarchies in CMake project involving Flang and also skip the offline preprocessing step as Flang will provide this functionality while scanning the file for dependencies.


Interface

Three new compiler flags activate the scan-only compiler action:

Flag Description
-fdeps-format=<format> Output format; defaults to p1689r5 (only supported value for now)
-fdeps-file=<file> Path for the .ddi dependency file; defaults to stdout (-)
-fdeps-target=<file> Path to the primary output (passed through to the JSON primary-output field)

When any of these flags are present, flang enters scan-only mode. This interface matches the g++ interface, and is isomorphic to the interface of the MSVC compiler.

Note: Clang has taken a different approach with it’s scan-deps command and redoes much of the work that CMake’s architecture will handle automatically. We may eventually want to make a matching interface for consistency, but the proposed interface will give us the same functionality with much less engineering.


Implementation

The implementation is structured as a reusable pipeline so both the Flang compiler and any program using the frontend as a library can reuse the implementation.

  1. CLI — Add three new options to both the flang and flang -fc1.

  2. ScanDependenciesAction — A new FrontendAction created when the scan flags are detected. It extracts ScanDependenciesOptions, ParserOptions, and LangOptions from CompilerInvocation and calls ScanDependencies. Abstracting the mode of operation allows other frontends using Flang as a library to invoke this behavior.

  3. ScanDependencies function — Takes ScanDependenciesOptions, ParserOptions, and LangOptions. Runs the following pipeline:

    • Preprocess and parse the translation unit into a parse tree (via the existing Parsing API).
    • Walk the parse tree with a ParseTreeVisitor to collect provides (MODULE/SUBMODULE definitions) and requires (USE statements minus locally-defined modules), producing a TranslationUnitImmediateDependencies object.
    • Serialize this object to a P1689R5 JSON object using llvm::json and write to the output specified by -fdep-file.
  4. The updated more accurate module scanning will be available once Flang-Fortran.cmake has been updated to make it similar to the corresponding lines in GCC-CXX.cmake.

Testing: Unit tests derived from CMake’s own Tests/FortranModules test suite, covering provided/required module detection, preprocessing, and error conditions. Tests will be added to Flang’s lit suite and kept in sync with the scanner output.

1 Like

With [Flang] Move builtin .mod generation into runtimes (Reapply #137828) by Meinersbur · Pull Request #171515 · llvm/llvm-project · GitHub, Flang-RT will rely on CMake’s dependency scanner for building Flang’s own intrinsic modules. Currently it contains some workaround because Fortran_BUILDING_IN(S)TRINSIC_MODULES is broken in CMake. If you implement this, please do not forget this use case.

2 Likes