Two issues in make file, g++, gfortran

Question 1:

I have a c++ project that I am trying to re-organize. I am trying to subdivide the src directory to move some src files that seldom are changed to a more out of the way location. The project is a c++ application with a fortran function called from the c.

The reorganization went fine, until I got to the fortran src file. I have two fortran complie rules for the src directory.

# compile src fortran objects with c preprocessor
$(BDIR)/%.o: $(SOURCELOC)/%.FPP  \
             ${SOURCELOC}/COMMON.BLK \
             $(SOURCELOC)/PARAM.DAT \
             $(SOURCELOC)/ATSYMB.DAT
    $(FCOMP) $(FCFLAGS) $(VFLAGS) -c -o $@ $<

# compile src fortran objects with fortran preprocessor
$(BDIR)/%.o: ${SOURCELOC}/%.FOR \
             ${SOURCELOC}/COMMON.BLK \
             ${SOURCELOC}/PARAM.DAT \
             ${SOURCELOC}/ATSYMB.DAT
    $(FCOMP) $(FCFLAGS) $(VFLAGS) -c -o $@ $<

What I tried to do was to add a driectory to ./src, ./src/src_main/ and move some or the fortran src files into that directory. I added a compile rule for the new subdirectory,

 $(BDIR)/%.o: ${SOURCELOC}/src_main/%.FOR \
             ${SOURCELOC}/src_main/COMMON.BLK \
             ${SOURCELOC}/src_main/PARAM.DAT \
             ${SOURCELOC}/src_main/ATSYMB.DAT
    $(FCOMP) $(FCFLAGS) $(VFLAGS) -c -o $@ $<

I am getting an error that there is no rule to make the fortran objects. This same method worked fine to move some cpp src files to a different sub directory. I am guessing this is an issue with the fortran includes (COMMON etc), but I would have expected the fortran to fail with a compiler error, not the linker to fail because the object never go compiled. Is there some off the wall syntax to this or something?

Question 2:

I have a little logic that tries to determine which fortran is installed.

HAVEgfortran := $(shell which gfortran)

ifeq "$(HAVEgfortran)" "/usr/bin/gfortran"
  FCOMP = gfortran
endif
ifeq "$(HAVEgfortran)" "/usr/local/bin/gfortran"
  FCOMP = gfortran
else
  FCOMP = g77
endif

Which gfortran returns /usr/bin/gfortran, but I am getting g77 as FCOMP. I must have made an error in the above, but I can't see it.

Suggestions would be greatly appreciated.

LMHmedchem

Hi.

Question 2:

You are testing HAVEgfortran in the second if sequence which will then (re)set FCOMP. I suggest making the first endif an else, and add another endif, say on a file "m2":

# Thu Mar 17 09:37:00 CDT 2011

HAVEgfortran := $(shell which gfortran)

ifeq "$(HAVEgfortran)" "/usr/bin/gfortran"
  FCOMP = gfortran
else
  ifeq "$(HAVEgfortran)" "/usr/local/bin/gfortran"
    FCOMP = gfortran
  else
    FCOMP = g77
  endif
endif

.PHONY: all

all:
	@echo " FCOMP is " $(FCOMP)

Then:

% make -f m2
 FCOMP is  gfortran
1 Like

Thanks, that fixes the second question. I was sure it was something obvious, but I find limited value in staring at code forever when I can't see what's wrong.

Any ideas as to why my Fortran won't compile?

LMHmedchem

What exactly does it do? Are there any errors?

Hi.

There are no TABS in the rules you posted ... cheers, drl

It just says that there is no rule to make the required object.

I checked, and there is definitely a tab there to start the second line. I am not counting the lines with the continue characters. The src file compiles fine when it is in src/, with the same rule, but when I move the src file to src/src_Main/ and add a rule for src/src_Main/, the object doesn't get created.

The cpp files in that folder get compiled, it is just the Fortran that are being skipped.

LMHmedchem

Hi.

Let us step back a minute.

If make thinks there is no rule, then the compiler would not get called, and so there could not be an error in compilation. If there is no compilation, then I would expect the linker to complain.

Could you explain more about "same method worked fine to move some cpp src files" -- are you saying that the makefile causes files to be moved? Or that you moved them and that a makefile for cpp worked correctly?

Do you have cpp and fortran source in the same directory, and have a single makefile for both the cpp and fortran codes?

Please post the exact error message that you get -- copy and paste so you get all the characters.

The version of make you are using would also be useful.

cheers, drl

What I have done is to try to clean up my src location by moving some files into sub-folders. The files I moved don't get changed very often, and when I port to linux, it helps some to only have to deal with files that have been changed.

I took my src directory, and added some sub directories,

src/
src/src_server/
src/src_main/

I moved some cpp files from src/ to src/src_server/ and then added the compile rule,

# compile src c++ server objects
$(BDIR)/%.o: $(SOURCELOC)/src_server/%.cpp
    $(CC++) $(CFLAGS) $(VFLAGS) -c -o $@ $<

This is what "worked fine". The src files in src/src_server/ got compiled and the objects placed in BDIR.

I tried the same thing with some fortran files, moving them to src/src_main/ and adding the compile rule,

# compile src gfortran main function objects
# compile src g77 objects
$(BDIR)/%.o: $(SOURCELOC)/src_main/%.FOR \
                      $(SOURCELOC)/src_main/COMMON.BLK \
                      $(SOURCELOC)/src_main/PARAM.DAT \
                      $(SOURCELOC)/src_main/ATSYMB.DAT
    $(FCOMP) $(FCFLAGS) -c -o $@ $<

When I run the make, I get a message that there is no rule to compile the object for the first src file and it quits. I need to reproduce the message and then I will post the output. Under cygwin, I am using make 3.81. I am also doing this in ubuntu, so I will have to boot into that to get the version that is installed there.

At first, I thought the issue may have been with COMMON.BLK, PARAM.DAT, etc, but I thought that would generate a compiler error, not a message about a missing rule. I am not sure why these files need to be included in the compile rule like they are, since they are included in the src, but I don't remember where I got the syntax for this and it's harder to find good information about Fortran make files than other languages.

LMHmedchem

---------- Post updated at 07:44 PM ---------- Previous update was at 07:23 PM ----------

I made the changes in my cygwin make file, and everything worked fine. I need to go back over to linux and see if the problem persists there or not. I'm not sure if I did anything differently this time or not.

Hi.

My brief experiments suggest that targets in the first rule with syntax "%.o" will get compiled and the subsequent targets will be ignored. If this is true, then I assume your cpp rule comes before the fortran rule.

If this is the case with your makefile, you should be able to edit the makefile to place the fortran rule before the cpp rule and run make. I'm guessing that with that, the fortran will be compiled and the cpp ignored.

If my theory is true, then we can talk about how to solve the problem ... cheers, drl

( Edit 1: fixed typo )

Thank you so much for your help. I was able to get it to compile, but there are all kinds of problems in the output. I think this has nothing to do with the changes in the make, but rather with some size limits I have exceeded. These limits are not in a part of the code that I wrote, so I will have to dig in and try to locate the issue. I am going to temporarily go back to a previous version just in case any of my recent changes are part of the problem. Hopefully I can get it working properly with my old make and then I can look at restructuring the build directory again. I hope that will be tomorrow sometime, but I will post back when I get it working again.

LMHmedchem