Skip to content

Unix Makefiles: do not use recursive calls to build *.provides.build targets

Makefiles generated by cmake use a series of recursive calls to build *.provides.build targets that are used when the "requires step" is needed. It seems that currently only Fortran targets use "requires step", thus the example provided is Fortran-specific, but the described issue would affect any language that needs "requires step".

In case of Fortran project and Unix Makefile generator, cmake generates the following structure of targets to be built during the "requires step":

build.make:

foo.F90.o.provides: foo.F90.o.requires
        $(MAKE) -f build.make foo.F90.o.provides.build

foo.F90.o.provides.build: foo.F90.o

depend.make:

foo.F90.o.provides.build:
        $(CMAKE_COMMAND) -E cmake_copy_f90_mod moda_foo moda_foo.mod.stamp GNU
        $(CMAKE_COMMAND) -E cmake_copy_f90_mod modb_foo modb_foo.mod.stamp GNU
        $(CMAKE_COMMAND) -E cmake_copy_f90_mod modc_foo modc_foo.mod.stamp GNU
        $(CMAKE_COMMAND) -E touch foo.F90.o.provides.build

That leads to significant degradation of the build time for incremental builds, especially for medium and large-size projects, because for each source file a new instance of make would be invoked and start from parsing of the build.make file, that is quite large, again and again. As result, for a medium-size project with approx 1500 Fortran modules a simple call to the make command requires more than 5 minutes to tell that all sources are up-to-date.

To speed-up these builds recursive make calls for *.provides.build targets could be eliminated by re-arranging target dependencies in the following way:

build.make:

foo.F90.o.provides: foo.F90.o.requires
foo.F90.o.provides: foo.F90.o.provides.build

foo.F90.o.provides.build: foo.F90.o

depend.make:

foo.F90.o.provides.build: moda_foo.mod.stamp
moda_foo.mod.stamp: foo.F90.o
        $(CMAKE_COMMAND) -E cmake_copy_f90_mod moda_foo moda_foo.mod.stamp GNU
foo.F90.o.provides.build: modb_foo.mod.stamp
modb_foo.mod.stamp: foo.F90.o
        $(CMAKE_COMMAND) -E cmake_copy_f90_mod modb_foo modb_foo.mod.stamp GNU
foo.F90.o.provides.build: modc_foo.mod.stamp
modc_foo.mod.stamp: foo.F90.o
        $(CMAKE_COMMAND) -E cmake_copy_f90_mod modc_foo modc_foo.mod.stamp GNU

foo.F90.o.provides.build:
        $(CMAKE_COMMAND) -E touch foo.F90.o.provides.build

That results in a significant speed-up of incremental builds for the Fortran projects. In our case, time required for make to tell that all sources are up-to-date went from 5 minutes to 2 seconds.

This merge request eliminates recursive calls and re-arranges dependencies of *.provides.build targets for the Fortran projects to speed-up incremental builds.

Topic-rename: makefile-simplify-fortran

Edited by Brad King

Merge request reports