makefilefortranprofilinggprof

How to use a makefile with gprof to recompile dependencies?


I have a makefile which compiles and links together objects to create an executable. In order to profile, I need to use an additional flag -pg before compiling. Here is my current makefile:

# objects required
OBJS = obj1.o obj2.o

# flags
FC = gfortran
FLAGS = -O3
PROFILEFLAG = -pg

# executable
EXE = program.exe
PROFEXE = program_prof.exe

# suffixes
.SUFFIXES: .o .f90

# rules
%.o: %.f90
    $(FC) $(FLAGS) -c $<

default: $(OBJS)
    $(FC) $(FLAGS) $(OBJS) -o $(EXE)

profile: $(OBJS) 
    $(FC) $(FLAGS) $(OBJS) -o $(PROFEXE) $(PROFILEFLAG)

clean: 
    rm *.o *.mod

Running make profile runs the rule associated with profile, which creates the executable program_prof.exe which can be profiled. However, since the individual dependencies obj1 and obj2 are not compiled with the -pg flag, I cannot profile the code running in those files.

Is there a way I can add a rule such that the individual objects are also recompiled with the -pg flag when I need to profile?

Currently I am editing the individual object dependencies manually to:

%.o: %.f90
    $(FC) $(FLAGS) -c $< -pg

which works as expected, but is time consuming (my actual makefile has multiple dependencies in subfolders, all of which need to be edited). Ideally, I am looking for a rule which should recompile individual objects with the `-pg' flag.


Solution

  • You can do exactly what you want, with target-specific variables:

    PROFILE :=
    
    %.o : %.f90
            $(FC) $(FLAGS) $(PROFILE) -c -o $@ $<
    
    default: $(OBJS)
        ....
    
    profile: PROFILE := -pg
    profile: $(OBJS)
        ....
    

    However, this is not usually the preferred way. Unless you're really diligent about always doing a full clean when switching back and forth between profile and non-profile builds it's very easy to get confused and have some objects compiled with profiling and others compiled without.

    As mentioned in the comments, it's better to build them into separate directories:

    $(PDIR)/%.o : %.f90
            @mkdir -p $(@D)
            $(FC) $(FLAGS) -pg -c -o $@ $<
    
    $(ODIR)/%.o : %.f90
            @mkdir -p $(@D)
            $(FC) $(FLAGS) -c -o $@ $<
    
    default: $(addprefix $(ODIR)/,$(OBJS))
            $(FC) $(FLAGS) $^ -o $@
    
    profile: $(addprefix $(PDIR)/,$(OBJS))
            $(FC) $(FLAGS) -pg $^ -o $@