For the past several days I haven't been able to get some Fortran code to compile (note that I am not the author of this code, I downloaded it from the author's web page. It's open source). The main program is called multitaper.f95, and it uses modules called plot and spectra, as well as libraries called mwlib.a and gplot.a. I have multitaper.f95, mwlib.a, gplot.a, plot.mod, and spectra.mod all in the same directory for simplicity. The plot and spectra moduels are made from gplot.f90 and mtspec.f95, respectively, which are also in the same directory as everything else. However, the following command produces an error message:
gfortran multitaper.f95 mtspec.f95 gplot.f90 -o multitaper -L gplot.a mwlib.a
/tmp/ccBJzwYI.o: In function `MAIN__':
multitaper.f95:(.text+0x1111): undefined reference to `gplot_'
multitaper.f95:(.text+0x11af): undefined reference to `gplot_'
multitaper.f95:(.text+0x1246): undefined reference to `gplot_'
collect2: error: ld returned 1 exit status
The contents of gplot.f90 are
module plot
!
! Interface to allow for x or y to be a matrix, and plot each vector
! of y against x. The matrix is given by horizontal vectors, y(:,1) is
! the first vector.
! April 22 2005
! Allowing to also use real(4) and real(8) units.
!
!
! Interface
! dvv vector vs vector
! dvm vector vs matrix
! dmm matrix vs matrix
! rvv real(4) vector vs vector
! rvm real(4) vector vs matrix
! rmm real(4) matrix vs matrix
!
interface gnuplot
module procedure gnuplot_dvv, gnuplot_dvm, gnuplot_dmm, &
gnuplot_rvv, gnuplot_rvm, gnuplot_rmm, &
gnuplot_rv, gnuplot_rm
end interface gnuplot
! The subroutines
contains
!The NEW GNUPlot subroutines
include 'gnuplot.f90'
end module plot
!======================================================================
Gnuplot.f90 has 3700 lines of code, so I won't post it in here. I'm new to Fortran, so I apologize in advance if I'm simply doing something stupid. But, I've been combing the internet for days looking for a solution, but I didn't turn up much. I found this (Fortran compilation error - undefined reference), but multitaper.f95 has a use statement for both spectra and plot, and gplot and the subroutines of gnuplot.f90 are not private. According to https://gcc.gnu.org/wiki/GFortranGettingStarted and http://www.oceanographers.net/forums/showthread.php?378-How-to-make-a-FORTRAN-library my terminal incantation should work, to the best of my knowledge. Just to be sure, I went ahead and tried compiling gplot.f90 and mtspec.f95 separately and giving the object files to the gfortran command instead, but this changed nothing. I also tried changing the file extension of gplot.f90 and gnuplot.f90 to f95, since there shouldn't be anything in there that would result in a version conflict, but once again this produced the same error message. I also tried including the full path to the directory after the -L command, just in case, and got the same error message.
The Makefile doesn't work any better, and I admittedly don't know much about them and how they work. When I run the make command, I get the following error as when I try to compile it manually. The contents of the Makefile are as follows:
# Location of files
DIR = /N/u/rccaton/Quarry/EarthHum/mtspec/program
LIB = /N/u/rccaton/Quarry/EarthHum/mtspec/program
#LIB2 =
# Objects and Libraries
OBJS = $(LIB)/mwlib.a \
$(LIB)/gplot.a \
# /Applications/Absoft/lib/libU77.a
# Module locations
MODS = $(LIB)
MODS2 = $(LIB)
# Compiler
#FC = g95
#FC = f95
FC = gfortran
# Compiler flags
# none
FLAGS =
# debug
#FFLAGS = -g
# Module flag
# Sun Compiler
#MFLAG = -M
# Nag Compiler
#MFLAG = -i
MFLAG = -I
# Absoft Compiler
#MFLAG = -p
# g95 compiler
#MFLAG = -I
MODULE = $(MFLAG)$(MODS) # $(MFLAG)$(MODS2)
# Compile
all : multitaper
%: %.f95 $(OBJS)
$(FC) $(FFLAGS) $(MODULE) $< $(OBJS) -o $#
# Clean
clean :
rm multitaper
At the end of the day it makes to difference to me whether I end up compiling it with the makefile or with manual commands, I just need it to run. Sorry if this was verbose, I just want to provide as much relevant info as possible. Thank you for any assistance you can give.
I would suggest to find which symbol is exported from gplot.a
nm gplot.a | grep -i "gplot"
and change compilers flags accordingly, search for gfortran flags:
-fno-underscoring
-fsecond-underscore
-fcase-*
In case it does not help, ask the author to give you correct MakeFile.
Related
I am using the Intel Fortran compiler in WSL, with its installation directory /opt/intel. I want to use the sparse BLAS functions. link to intel's documentation of the libaray.
Here is part of the related code.
double complex, allocatable :: H(:,:),Hvert(:,:),Hstar(:,:)
allocate(H(dimH,dimH),Hvert(dimH,dimH),Hstar(dimH,dimH))
! initialization of Hstar
info = mkl_sparse_z_create_coo(Hstar, SPARSE_INDEX_BASE_ONE, m**L, m**L, 2**L, ind(1,:), ind(2,:), Hele)
! initialization of empty matrix
ind = 0
info = mkl_sparse_z_create_coo(Hvert, SPARSE_INDEX_BASE_ONE, m**L, m**L, 0, ind(1,1), ind(2,1), H)
! add A and B to form the final matrix
info = mkl_sparse_z_add(SPARSE_OPERATION_NON_TRANSPOSE, Hstar, 1d0, Hvert, H)
When I compile it with the following command
ifort -xHost -parallel full.f90 -o output -lmkl_intel_lp64 -lmkl_intel_thread -lmkl_spblas -lmkl_core -liomp5 -lpthread -lm -qopenmp && ./output
it gave me the following error, even if I have sourced the libraries
source /opt/intel/bin/ifortvars.sh -arch intel64 -platform linux
source /opt/intel/bin/compilervars.sh -arch intel64 -platform linux
full.f90(146): error #6404: This name does not have a type, and must have an explicit type. [MKL_SPARSE_Z_CREATE_COO]
info = mkl_sparse_z_create_coo(Hvert, SPARSE_INDEX_BASE_ONE, m**L, m**L, 2**L, ind(1,:), ind(2,:), Hele)
------------^
full.f90(226): error #6404: This name does not have a type, and must have an explicit type. [MKL_SPARSE_Z_ADD]
info = mkl_sparse_z_add(SPARSE_OPERATION_NON_TRANSPOSE, Hstar, 1d0, Hvert, H)
------------^
full.f90(240): error #6404: This name does not have a type, and must have an explicit type. [MKL_SPARSE_Z_MV]
info = mkl_sparse_z_mv(SPARSE_OPERATION_NON_TRANSPOSE, 1d0, H, SPARSE_MATRIX_TYPE_HERMITIAN, psi(a,:), 0d0, dummy)
--------------^
compilation aborted for full.f90 (code 1)
I think it is caused by my incorrect linking to the related library as well as initializing the matrices as plain allocatable arrays.
What should I do to use these functions?
also, I have no idea what the uppercase variablesSPARSE_INDEX_BASE_ONE mean. Should I use it that way?
the linking path is correct. You don't need to link -mkl_spblas. Please refer always to the MKL Linker Adviser ( https://software.intel.com/en-us/articles/intel-mkl-link-line-advisor).
I would recommend looking at the existing sparse_z_csrmv.f90 example which shows how to make the call of the similar Sparse BLAS functions. This example has been call CSR but not COO formats but it doesn't matter in such cases.
I'm trying to understand how BLAS and LAPACK in Fortran work and so on, so I made a code that generates a matrix and inverts it.
Here's the code
program test
Implicit none
external ZGETRF
external ZGETRI
integer ::M
complex*16,allocatable,dimension(:,:)::A
complex*16,allocatable,dimension(:)::WORK
integer,allocatable,dimension(:)::IPIV
integer i,j,info,error
Print*, 'Enter size of the matrix'
Read*, M
Print*, 'Enter file of the matrix'
READ(*,*), A
OPEN(UNIT=10,FILE = '(/A/)' ,STATUS='OLD',ACTION='READ')
allocate(A(M,M),WORK(M),IPIV(M),stat=error)
if (error.ne.0)then
print *,"error:not enough memory"
stop
end if
!definition of the test matrix A
do i=1,M
do j=1,M
if(j.eq.i)then
A(i,j)=(1,0)
else
A(i,j)=0
end if
end do
end do
call ZGETRF(M,M,A,M,IPIV,info)
if(info .eq. 0) then
write(*,*)"succeded"
else
write(*,*)"failed"
end if
call ZGETRI(M,A,M,IPIV,WORK,M,info)
if(info .eq. 0) then
write(*,*)"succeded"
else
write(*,*)"failed"
end if
deallocate(A,IPIV,WORK,stat=error)
if (error.ne.0)then
print *,"error:fail to release"
stop
end if
close (10)
end program test
The matrix A is in a file, which I'm calling, and also I say the size of the matrix (M ). When I copile them with gfortran I get these message
/tmp/ccVkb1zY.o: In function MAIN__':
test.f03:(.text+0x751): undefined reference tozgetrf_'
test.f03:(.text+0x85d): undefined reference to `zgetri_'
collect2: error: ld returned 1 exit status
I have installed BLAS and LAPACK installed so I don't know if I'm calling in a right way the library.
Any suggestion?
It looks like you might not have linked to the libraries. Try:
gfortran -o test test.f03 -llapack -lblas
This causes the linker (the program which joins all the program parts together; usually called "ld" on UNIX) to include the library code for the LAPACK call (or a dynamic link to it) in your program.
If the result of the above line is "cannot find -llapack" or similar, there are two common problems:
Libraries can be "shared" (names ending ".so") or "static" (names ending ".a"); the linker will look for the shared one, so if you only have the static one you should add "-static" before the library link:
gfortran -o test test.f03 -static -llapack -lblas
This will also make it look for the static version of BLAS; if you need the shared version, add "-shared" in front of the "-lblas":
gfortran -o test test.f03 -static -llapack -shared -lblas
You might find this page helpful.
The linker isn't looking in the right directory for the libraries. You need to locate the actual library (called something like "liblapack.so" or "liblapack.a") and make sure the directory it's in is included in the directories the linker looks in, e.g. to get it to look in "/mylibs/maths" as well:
gfortran -o test test.f03 -L/mylibs/maths -llapack -lblas
I have two sources files:
! main.f90
program main
use foo
write(*,*) x
end program main
! foo.f90
module foo
real, parameter :: x = 3.14
end module foo
First build is successful. If I now set x = 5 it again builds without errors but the program still prints 3.14. Adding
%.o %.mod: %.f90
$(FC) -c $<
main.o: foo.mod
to my Makefile.am makes the problem disappear but this is probably not the correct way to do it.
Some googling reveals that the correct Fortran dependency tracking has been a known problem with Autotools, although I'm not sure if some solution has been found by now. Is there a simple way to fix the above problem?
I am not a Fortran programmer (just a short experience), but I need to compile a program partly written in F77. Someone has compiled it with Absoft compiler before me, but now I need to repeat the procedure on another machine with g77. For Absoft, the makefile has
f77 -f -w -O -B100 -B108 -c *.f
mv *.f flib && mv *.o olib
f77 -B100 -o runme olib/*.o clib/*.o -L/usr/X11R6/lib64 -L/usr/X11R6/lib -lX11 -L$PVM_ROOT/lib/$PVM_ARCH -lfpvm3 -lpvm3 -L$ABSOFT/lib -lU77
I have modified these lines to be
g77 -w -O -B100 -B108 -c *.f
mv *.f flib && mv *.o olib
g77 -B100 -o runme olib/*.o clib/*.o -L/usr/X11R6/lib64 -L/usr/X11R6/lib -lX11 -L$PVM_ROOT/lib/$PVM_ARCH -lfpvm3 -lpvm3 -lgfortran -lgfortranbegin
But I get the following error messages
somefile.f:(.text+0x93): undefined reference to `for_open'
somefile.f:(.text+0xf4): undefined reference to `for_write_seq_fmt'
somefile.f:(.text+0x128): undefined reference to `for_write_seq_fmt_xmit'
somefile.f:(.text+0x454): undefined reference to `for_read_seq'
How can I fix this?
UPDATE1
If I add -libifcore to the end of the last line (linker), then I get
/usr/bin/ld: cannot find -libifcore
I have located the library
$ find /opt/intel/* -name 'libifcore*'
/opt/intel/fce/9.1.036/lib/libifcore.a
/opt/intel/fce/9.1.036/lib/libifcore.so
/opt/intel/fce/9.1.036/lib/libifcore.so.5
/opt/intel/fce/9.1.036/lib/libifcore_pic.a
/opt/intel/fce/9.1.036/lib/libifcoremt.a
/opt/intel/fce/9.1.036/lib/libifcoremt.so
/opt/intel/fce/9.1.036/lib/libifcoremt.so.5
/opt/intel/fce/9.1.036/lib/libifcoremt_pic.a
But even if I do the following in the source directory
$ export PATH=$PATH:/opt/intel/fce/9.1.036/lib/
$ ln -s /opt/intel/fce/9.1.036/lib/libifcore.so
it is not found.
Moreover, it is the same machine where I get another problem How to pass -libm to MPICC? libimf.so: warning: feupdateenv is not implemented and will always fail
It seems that the compiler should find the library, if needed
$ echo $LD_LIBRARY_PATH
/opt/intel/fce/9.1.036/lib:/opt/intel/cce/9.1.042/lib:/usr/local/lib/openmpi:/usr/local/lib:/usr/lib:
Absoft accepted an extended version of Fortran 77 that is not completely compatible with the extended version of Fortran 77 accepted by g77.
So there is no guarantee that you can do this without editing the code. I seem to recall that the Absoft compiler accepted a handy initialization syntax that can not be replicated with g77.
If you want to compile & link using g77, the easiest way is to use the command "g77". (What compiler does f77 invoke on your computer? Try "f77 -v" or similar to find out...) It should automatically find the g77 Fortran-specific libraries. You should not need to explicitly link to Fortran libraries, and especially not to the libraries of gfortran, which is a different compiler. You could also compile & link with gfortran -- it will probably recognize that the source code is Fortran 77 and compile appropriately if the files have the correct file type, otherwise you will have to use options -- for this compiler, use the command "gfortran".
With g77 and gfortran it should not need Intel libraries -- maybe f77 is connected to ifort, the Intel compiler, on your computer?
Edited later:
I suggest trying something simpler first to test your setup.
Try this FORTRAN 77 program as file "junk.f"
C234567
write (6, *) "Hello World"
stop
end
Try this command:
g77 junk.f -o junk.exe
Run it via:
./junk.exe
This will test whether g77 is working.
it looks like you are trying to link with libifcore.
Edit:
You can include this library by adding
'-lifcore' to your compiler options. To quote the gcc tutorial
In general, the compiler option -lNAME will attempt to link object files with a library file ‘libNAME.a’ in the standard library directories.
why do you use g77 and not gfortran?
what do you mean with multiprocessing? openmp or vectorized?
you can use openmp with the gfortran compiler and when you want to use vector mode like the ifort compiler does, you have to specify sse explicitly in the compiler options.
It seems that the problem was in an error in one of the source files, which wasn't a big deal for Absoft compiler. g77 was giving a warning about it, but compiling this file and producing the original errors (mentioned in the question) without a binary.
When I tried ifort, compilation of that file was aborted, but other files were compiled and a binary was created.
fortcom: Error: somefile.f, line 703: An extra comma appears in the format list. [)]
& (1p5e12.3,5h ...,))
-------------------------^
compilation aborted for somefile.f (code 1)
When I removed the extra comma, then both compilers have compiled everything and created binaries, although ifort produced a number of warnings.
Then, when I tried to run both binaries, the one made by Intel comiler was working fine, but the one by g77 was behaving very strange and didn't really do what I wanted.
So now the original problem is resolved, however the code doesn't run in multiprocessing mode, so the binary is unfortunately useless for me.
While compiling Linux kernel modules that depend on each other, linker gives undefined symbol warnings like
Building modules, stage 2.
MODPOST
*** Warning: "function_name1" [module_name] undefined!
*** Warning: "function_name2" [module_name] undefined!
*** Warning: "function_name3" [module_name] undefined!
The unresolved symbols are resolved as soon as module is inserted into kernel using insmod or modprobe. Is there any way to get rid of the linker warning, though?
I have read through 3 Google SERP's on this issue - it seems nobody knows the answer. Are these linker warnings supposed to be this way when you build a kernel module?
Use KBUILD_EXTRA_SYMBOLS as below:
KBUILD_EXTRA_SYMBOLS='your module path'/Module.symvers
Finally, I got it. Thanks to shodanex for putting me on the right track.
Update: Be very careful when applying this fix to builds for older versions of kernel, as there is a bug in Makefile.modpost file in older versions of the kernel which makes your build misbehave and build wrong targets when you specify KBUILD_EXTMOD option.
You have to specify the paths to the source of the modules you depend on in KBUILD_EXTMOD make parameter.
Say, you have a module foo that depends on symbols from module bar.
Source files for foo are in foo/module/ and source files for bar are in bar/module/
The make command in Makefile for foo probably looks like
make ARCH=$$ARCH CROSS_COMPILE=$$CROSS_COMPILE -C $$LINUX_DIR \
M=`pwd`/module \
modules
(the exact line may differ in your project).
Change it to
make ARCH=$$ARCH CROSS_COMPILE=$$CROSS_COMPILE -C $$LINUX_DIR \
M=`pwd`/module \
KBUILD_EXTMOD=`pwd`/../bar/module \
modules
(we added the KBUILD_EXTMOD=pwd/../bar/module \ line, where pwd/../bar/module is a path to sources of kernel module we depend on.
One would expect KBUILD_EXTRA_SYMBOLS parameter to work this way, however it's KBUILD_EXTMOD.
No they are not. Wheter you build your code in-tree or out of tree, this message should not be displayed.I think you should fix your Makefile. Here is an example makefile. Not perfect, but used to work (until 2.6.26, did not try it since) :
ifneq ($(KERNELRELEASE),)
# We were called by kbuild
obj-m += mymodule.o
mymodule-objs := mymodule_usb.o a.o b.o c.o
else # We were called from command line
KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
#echo ' Building FOO drivers for 2.6 kernel.'
#echo ' PLEASE IGNORE THE "Overriding SUBDIRS" WARNING'
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
install:
./do_install.sh *.ko
endif # End kbuild check
clean:
rm -f -r *.o *.ko .*cmd .tmp* core *.i
For further documentation, you can check the kernel tree, the kbuild process is documented
Related to the above technique of using KBUILD_EXTMOD, and the question of which kernel versions it works under:
andycjw indicated it didn't work for him in 2.6.12
It didn't work for me in 2.6.15 (broke my module build)
Looking through the kernel commits, I see a number of changes to Makefile.modpost that seem related in 2.6.26 and 2.6.28, so I expect one of those is the limit.
My need to be tailored to your tree.
In our source we created a SYMBOLSDIR that is a path to all the modules
SYMBOLSDIR = 'some path'
make (same as above example) $(KERNELDIR) MODVERDIR=$(SYMBOLSDIR) modules