Reputation: 99
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
Reputation: 3218
I would suggest you to use automake
(and autoconf
). It do have a large number of metatag
s, 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