Gatto Nou
Gatto Nou

Reputation: 99

gfortran makefile problems

I have program writing on fortran which uses library. For compiling I use my simple shell script and everything is fine:

gfortran -c mod_input.f90 mod_cpp.f90 mod_data.f90 main.f90 b_coils.f

gfortran -o main mod_input.o mod_cpp.o mod_data.o main.o b_coils.o libspline.a -lstdc++

(libspline.a - library writing on c++)

Now I want to use makefile instead of shell script, but don't know how to write it properly.

Makefile:

target = main
srcdir = src/
objdir = obj/
targetdir = run/

FORT = gfortran
mflag = module
FORTFLAGS =
LDFLAGS = -lstdc++  

MKLPATH =/home/gatto/Desktop/ray_u3/src
LIBDIR  =-L$(MKLPATH)
LIBS = -lspline                                                             
MODDIR = obj/                                                           

# Ray sources
sources = mod_input.f90 mod_cpp.f90 mod_data.f90  main.f90 b_coils.f


# objects
objects  = $(patsubst %.for,%.o,$(filter %for,$(sources)) )
objects += $(patsubst %.f90,%.o,$(filter %f90,$(sources)) )

# main target
build:$(targetdir)$(target)

# build rules
$(targetdir)$(target):$(addprefix $(objdir),$(objects))
    @echo === build $@ ===
    $(FORT) $(FORTFLAGS) $(LDFLAGS) $(LIBDIR) -o $@ $(LIBS) $^

#compilation target
compile :$(addprefix $(objdir),$(objects))

# compilation rules
$(objdir)%.o : $(srcdir)%.f90
    @echo === compile $< ===
    $(FORT) -c $(objdir) $(FORTFLAGS) -o $@ $<

$(objdir)%.o : $(srcdir)%.f
    @echo === compile $< ===
    $(FORT) -c $(objdir) $(FORTFLAGS) -o $@ $<


# cleaning rules
cleanobj:
    -rm $(objdir)*.o $(objdir)*.mod
cleantarget:
    -rm $(targetdir)$(target)

cleanall:cleanobj cleantarget

.PHONY: compile build cleanall cleanobj cleantarget

Output:

gfortran  -lstdc++   -L/home/gatto/Desktop/ray_u3/src -o run/main -lspline obj/mod_input.o obj/mod_cpp.o obj/mod_data.o obj/main.o
obj/mod_data.o: In function `__global_data_MOD_modbfield':
mod_data.f90:(.text+0x3e2): undefined reference to `gbcoil_'
obj/mod_data.o: In function `__global_data_MOD_moddensity':
mod_data.f90:(.text+0x5d4): undefined reference to `GetSplineValue'
mod_data.f90:(.text+0x64f): undefined reference to `GetSplineValue'
mod_data.f90:(.text+0x6ca): undefined reference to `GetSplineValue'
mod_data.f90:(.text+0x745): undefined reference to `GetSplineValue'
obj/mod_data.o: In function `__global_data_MOD_inpfile':
mod_data.f90:(.text+0xa66): undefined reference to `Approx_input'
mod_data.f90:(.text+0xa75): undefined reference to `SetSpline'
collect2: error: ld returned 1 exit status
make: *** [run/main] Error 1

Upvotes: 0

Views: 394

Answers (1)

BaRud
BaRud

Reputation: 3218

I would suggest you to use automake (and autoconf). It do have a large number of metatags, but for simple programs, its faster to write, and in most of the cases, you may find yourself get going with minimal changes (like filename).

Here is my autoconf and automake's input for a similar project, which just uses lapack, instead of mkl.

configure.ac

#AC_PREREQ(2.69)
AC_INIT([src], [0.1],
    [],
    [mftc],
    [])
AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_MACRO_DIR([m4])

AM_INIT_AUTOMAKE([1.9.6 dist-bzip2 subdir-objects foreign])

AC_SEARCH_LIBS([dsyev_], [lapack], ,AC_MSG_ERROR([No LAPACK library]))
AC_OPENMP
FCFLAGS="$OPENMP_FFLAGS "
AC_PROG_FC([gfortran, ifort])
AC_CHECK_PROG([DEPF90_CHECK],[makedepf90],[yes],[no])
AM_CONDITIONAL([FOUND_MAKEDEPF90], [test "x$DEPF90_CHECK" = xyes])
AC_CONFIG_FILES([
         Makefile
         ])
AC_OUTPUT

Makefile.am

bin_PROGRAMS =  mftc
mftc_SOURCES = src/mftc.f90  src/parse.f90 src/sort.f90
depend depend.mk:
    makedepf90 $(mftc_SOURCES) >depend.mk
@am__include@ @[email protected]@am__quote@
mftc_LDADD = 
EXTRA_DIST=depend.mk autogen.sh Makefile.am
CLEANFILES =*.mod  *.log

The depend depend.mk depends on makedepf90 program, which is available on most linux platform. This program take care of the dependencies (that is modules are compiled first before the program).

Usage If you are ok with LAPACK, I don't see anything for you to change in the configure.ac. Change _SOURCES line for proper filename. Now, its 3 command in terminal:

 $autoconf 
 $./configure 
 $make

Off course, you also need to have automake and autoconf installed.

Hope, this helps

Upvotes: 1

Related Questions