I am new to Fortran. I am working on a research project where I am using an open source project that has several files distributed in multiple folders. i found the dependency of each programs but could not figure out how to compile them.
I have source code distributed in three folders. a)modules b)interfaces c)subroutines
I would like to run a program named as 'Main.f90' in subroutines folder, this program has dependency of source codes from modules and interfaces folders.
I am using eclipse for folder structure and makefile to compile.
Any help with this is appreciated.
UPDATE: I followed the answer posted by @MBR and @Stefan, for some reason VPATH did not able to find programs in source code so I explicitly gave path to those source folder in my Makefile. below is my make file script.
.PHONY: Mopac_exe clean
# Change this line if you are using a different Fortran compiler
FORTRAN_COMPILER = gfortran
SRC = src
#make main program
Mopac_exe: subroutines mopac.o
$(FORTRAN_COMPILER) mopac.o *.o -O2 -g -o bin/Mopac_exe -I Modules/
#compile all the subroutines
subroutines: interfaces
$(FORTRAN_COMPILER) -c $(SRC)/subroutines/*.F90 -J Modules/Subroutines/ -I Modules/
#compiles all the interfaces
interfaces: modules
$(FORTRAN_COMPILER) -c $(SRC)/interfaces/*.f90 -J Modules/
# build all the modules and generate .mod file in Modules directory
modules: build_vast_kind
$(FORTRAN_COMPILER) -c $(SRC)/modules/*.f90 -J Modules/
$(FORTRAN_COMPILER) -c $(SRC)/modules/*.F90 -J Modules/
# compile vastkind.f90 files and generates the .mod file in Modules directory.Every other Modules and interfaces are dependent on this.
build_vast_kind:clean
$(FORTRAN_COMPILER) -c $(SRC)/modules/vastkind.f90 -J Modules/
clean:
rm -f bin/Mopac_exe *.mod
rm -f Modules/*.mod
rm -f *.o
I compiled all the modules and placed in Modules directory of root Folder. All compilation goes well. I get error when I build the executable. I get following error.
gfortran mopac.o *.o -O2 -g -o bin/Mopac_exe -I Modules/
mopac.o: In function `main':
mopac.F90:(.text+0x27c1): multiple definition of `main'
mopac.o:mopac.F90:(.text+0x27c1): first defined here
getdat.o: In function `getdat_':
getdat.F90:(.text+0x22): undefined reference to `iargc_'
getdat.F90:(.text+0xf2): undefined reference to `getarg_'
symr.o: In function `symr_':
symr.F90:(.text+0xd3f): undefined reference to `symp_'
writmo.o: In function `writmo_':
writmo.F90:(.text+0x20c2): undefined reference to `volume_'
collect2: error: ld returned 1 exit status
make: *** [Mopac_exe] Error 1
`iargc_' is being used in 'getdat file and iargc is already compiled. why there is error while making the executable saying undefined reference? what am I missing?
You can do a Makefile which looks like that
F90=gfortran
FFLAGS = -O0
VPATH = modules:interfaces:subroutines:
MODOBJ = module1.o module2.o ...
your_executable: $(MODOBJ) main.o
$(F90) main.o -o your_executable
%.o:%.f90
$(F90) $(FFLAGS) -c $^ -o $@
VPATH
is the paths of the directories where your Makefile will look for source files, so if you compile your source in the root directory of modules/
, interfaces/
and subroutines/
, you just have to set up VPATH
like that.
If you have many objects and you don't want to write everything by hand, you can retrieve them using the following trick
F90 = gfortran
FFLAGS = -O0
VPATH = modules:interfaces:subroutines
SRCOBJ = $(wildcard modules/*f90)
MODOBJ = $(SRCOBJ:.f90=.o)
your_executable: $(MODOBJ) main.o
$(F90) main.o -o your_executable
%.o:%.f90
$(F90) $(FFLAGS) -c $^ -o $@
The wildcard
command in a Makefile allows you to use a joker *
; then you just have to say that in the strings you will retrieve in $(SRCOBJ)
, you want to substitute .f90
by .o
to get the filenames of your modules.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With