fortdepend
==========

[![Build Status](https://travis-ci.org/ZedThree/fort_depend.py.svg?branch=master)](https://travis-ci.org/ZedThree/fort_depend.py)
[![codecov](https://codecov.io/gh/ZedThree/fort_depend.py/branch/master/graph/badge.svg)](https://codecov.io/gh/ZedThree/fort_depend.py)

A python script to automatically generate Fortran dependencies.

Given a set of files, `fortdepend` automatically constructs the
dependency graph for the programs and files and can write a dependency
file suitable for Makefiles. `fortdepend` now uses [`pcpp`][pcpp], a
preprocessor written in Python, so it can determine which modules will
actually be used when you compile.

You can even use `fortdepend` to draw the graph of the module
dependencies (requires [`graphviz`][graphviz])!

Complete documentation is available [on ReadTheDocs][docs].

Original script by D. Dickinson

Installation
============

You can install fortdepend with pip:

    pip3 install --user fortdepend

Limitations
===========

`fortdepend` requires Python 3.

`fortdepend` works by looking for matching pairs of `program
<name>/end program <name>` and `module <name>/end module <name>`, and
so will not work on Fortran 77-style files that just use `end` without
the appropriate label.

Usage
=====

Basic usage:
------------

    fortdepend -o Makefile.dep

This will look for all files ending in `.f90` or `.F90` in the current
directory and write the output to `Makefile.dep`. The output will
something like this:

    test :  \
            moduleA.o \
            moduleB.o \
            moduleC.o \
            moduleD.o \
            programTest.o

    moduleA.o :

    moduleB.o :  \
            moduleA.o

    moduleC.o :  \
            moduleA.o \
            moduleB.o

    moduleD.o :  \
            moduleC.o

You could then get a basic makefile working by putting the following
in `Makefile`:

    .f90.o:
        gfortran -c $<

    test:
        gfortran $^ -o $@

    include Makefile.dep

And `make test` will magically build everything in the correct order!

Move advanced use
-----------------

You can specify preprocessor macros with `-D` and search paths with `-I`:

    fortdepend -DMACRO=42 -Isome/include/dir -o Makefile.dep

will replace instances of `MACRO` with `42` according to the usual C99
preprocessor rules. This can be used to conditionally `use` some
modules or change which module is `use`d at compile time.

Full command line arguments:

    $ fortdepend --help
    usage: fortdepend [-h] [-f FILES [FILES ...]] [-D NAME[=DESCRIPTION]
                      [NAME[=DESCRIPTION] ...]] [-b BUILD] [-o OUTPUT] [-g] [-v]
                      [-w] [-c] [-e EXCLUDE_FILES [EXCLUDE_FILES ...]]
                      [-i IGNORE_MODULES [IGNORE_MODULES ...]]

    Generate Fortran dependencies

    optional arguments:
      -h, --help            show this help message and exit
      -f FILES [FILES ...], --files FILES [FILES ...]
                            Files to process
      -D NAME[=DESCRIPTION] [NAME[=DESCRIPTION] ...]
                            Preprocessor define statements
      -I dir                Add dir to the preprocessor search path
      -b BUILD, --build BUILD
                            Build Directory (prepended to all files in output)
      -o OUTPUT, --output OUTPUT
                            Output file
      -g, --graph           Make a graph of the project
      -v, --verbose         explain what is done
      -w, --overwrite       Overwrite output file without warning
      -c, --colour          Print in colour
      -e EXCLUDE_FILES [EXCLUDE_FILES ...], --exclude-files EXCLUDE_FILES [EXCLUDE_FILES ...]
                            Files to exclude
      -i IGNORE_MODULES [IGNORE_MODULES ...], --ignore-modules IGNORE_MODULES [IGNORE_MODULES ...]
                            Modules to ignore
      --skip-programs       Don't include programs in the output file
      -n, --no-preprocessor
                            Don't use the preprocessor

Here's a slightly more advanced example of how to use `fortdepend` in
your makefiles:

    # Script to generate the dependencies
    MAKEDEPEND=/path/to/fortdepend

    # $(DEP_FILE) is a .dep file generated by fortdepend
    DEP_FILE = my_project.dep

    # Source files to compile
    OBJECTS = mod_file1.f90 \
              mod_file2.f90

    # Make sure everything depends on the .dep file
    all: $(actual_executable) $(DEP_FILE)

    # Make dependencies
    .PHONY: depend
    depend: $(DEP_FILE)

    # The .dep file depends on the source files, so it automatically gets updated
    # when you change your source
    $(DEP_FILE): $(OBJECTS)
        @echo "Making dependencies!"
        cd $(SRCPATH) && $(MAKEDEPEND) -w -o /path/to/$(DEP_FILE) -f $(OBJECTS)

    include $(DEP_FILE)

This will automatically rebuild the dependency file if any of the
source files change. You might not like to do this if you have a lot
of files and need to preprocess them!

[pcpp]: https://github.com/ned14/pcpp
[graphviz]: https://github.com/xflr6/graphviz
[docs]: https://fortdepend.readthedocs.io/en/latest/
