Here's an example that should work:
.compile_flags: Makefile
[ "`cat $@`" = '$(FLAGS)' ] || echo '$(FLAGS)' > $@
$(FORTRAN_OBJECTS) $(CPP_OBJECTS) $(EXECUTABLE): .compile_flags
An alternative is to generate the object files and executable into a separate subdirectory for each different base target. Then they won't overlap. This has the added benefit that you don't have to recompile the world for each type of build (only since the last time you did that build). But it uses more disk space and may cause other issues if you have other parts of the system expecting things to live where they do now.
To put things in other directories can't be done with target-specific variables. The simplest way to do it is to use one instance of recursive make instead, like this:
EXECUTABLE=ecis
#debug build
.PHONY: debug
debug: FLAGS=-g
#No optimization
.PHONY: opt0
opt0: FLAGS=
#level 1 optimization
.PHONY: opt1
opt1: FLAGS=-O1
#level 2 optimization
.PHONY: opt2
opt2: FLAGS=-O2
debug opt0 opt1 opt2:
$(MAKE) OUTDIR=obj_$@ FLAGS=$(FLAGS) obj_$@/$(EXECUTABLE)
...
FORTRAN_OBJECTS := $(addprefix $(OUTDIR)/,$(FORTRAN_OBJECTS))
CPP_OBJECTS := $(addprefix $(OUTDIR)/,$(CPP_OBJECTS))
$(OUTDIR)/$(EXECUTABLE):$(FORTRAN_OBJECTS) $(CPP_OBJECTS)
$(CPP) $(FLAGS) $(FORTRAN_OBJECTS) $(CPP_OBJECTS) -lgfortran -o $@
...
And, you'll have to create pattern rules for your object files like:
$(OUTDIR)/%.o : %.cpp
...
and ditto for FORTRAN.