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.
-
CLI — Add three new options to both the
flangandflang -fc1. -
ScanDependenciesAction— A newFrontendActioncreated when the scan flags are detected. It extractsScanDependenciesOptions,ParserOptions, andLangOptionsfromCompilerInvocationand callsScanDependencies. Abstracting the mode of operation allows other frontends using Flang as a library to invoke this behavior. -
ScanDependenciesfunction — TakesScanDependenciesOptions,ParserOptions, andLangOptions. Runs the following pipeline:- Preprocess and parse the translation unit into a parse tree (via the existing
ParsingAPI). - Walk the parse tree with a
ParseTreeVisitorto collectprovides(MODULE/SUBMODULE definitions) andrequires(USE statements minus locally-defined modules), producing aTranslationUnitImmediateDependenciesobject. - Serialize this object to a P1689R5 JSON object using
llvm::jsonand write to the output specified by-fdep-file.
- Preprocess and parse the translation unit into a parse tree (via the existing
-
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.