Michael A
Michael A

Reputation: 4615

Why does make not recompile these object files when the source files are changed?

I have two sources files, library.f90 and toolbox.f90 in a separate directory. These are compiled into object files, which are linked when compiling the main file, aptly called main. Initially, I had this Makefile:

TARGET  = main
SRC     = ${TARGET}.f95

FC      = /usr/bin/gfortran
CFLAGS  = -O2 -std=gnu -Wfatal-errors -I${INCLUDE}

INCLUDE = /home/ma/include
OBJ     = library.o toolbox.o
OBJ_SRC = $(subst .o,.f90,${OBJ})


all: ${TARGET}

${TARGET}: ${SRC} ${OBJ}
    @${FC} ${CFLAGS} -pedantic -Wall ${OBJ} ${SRC} -o ${TARGET}

${OBJ}:
    @echo "Compiling $(subst .o,,$@)"
    @${FC} ${CFLAGS} -c ${INCLUDE}/$(subst .o,.f90,$@) -o $@

clean:
    @rm -vf ${TARGET} ${OBJ}

but this doesn't recompile library.o (or toolbox.o, respectively) when the source file library.f90 or toolbox.f90 is edited. I figured this was because the dependency was missing, so I tweaked the Makefile to look like this:

TARGET  = main
SRC     = ${TARGET}.f95

FC      = /usr/bin/gfortran
CFLAGS  = -O2 -std=gnu -Wfatal-errors -I${INCLUDE}

INCLUDE = /home/ma/include
OBJ     = library.o toolbox.o

all: ${TARGET}

${TARGET}: ${SRC} ${OBJ}
    @${FC} ${CFLAGS} -pedantic -Wall ${OBJ} ${SRC} -o ${TARGET}

${OBJ}: ${OBJ_SRC}
    @echo "Compiling $(subst .o,,$@)"
    @${FC} ${CFLAGS} -c ${INCLUDE}/$(subst .o,.f90,$@) -o $@

clean:
    @rm -vf ${TARGET} ${OBJ}

This, however, throws the error

make: *** No rule to make target 'library.f90', needed by 'library.o'.  Stop.

I don't understand this, because there isn't a rule to build ${SRC} either, but make recognizes the dependency there and compiles the source file as expected.

Upvotes: 0

Views: 827

Answers (1)

chw21
chw21

Reputation: 8140

In your first version, the object files' rule did not specify any prerequisite. That's why make did not check whether library.f90 had changed, and therefore did not recreate it.

Your second version is slightly better, but it now means that both library.o and toolbox.o depend on both library.f90 and toolbox.f90, meaning that if either one is changed, both are rebuild, and if either one is missing, both builds will fail.

As for why your rule failed: It was looking for library.f90 in your current directory, but from the rule I deduce that the sources are in the subdirectory /home/ma/include.

A better solution would be this:

${OBJ} : %.o : ${INCLUDE}/%.f90
        ${FC} ${CFLAGS} -c $^ -o $@

(I also removed the leading @, as I find it very useful to see the actual command it's trying to run.)

Upvotes: 2

Related Questions