This question already has answers here:
Why does the order in which libraries are linked sometimes cause errors in GCC?
(9 answers)
Compiling Fortran netCDF programs on Ubuntu
(2 answers)
Closed 4 years ago.
I want to compile some of my often-used Fortran code into a static library (assuming I would have access to both *.mod and *.a files).
This worked.
However, I have encountered the problem with linking.
Here is an example. Let's say I have mylib.f90 file:
MODULE MYLIB
IMPLICIT NONE
CONTAINS
INTEGER FUNCTION FOO(N)
INTEGER, INTENT(IN) :: N
FOO = N + 2
END FUNCTION FOO
END MODULE MYLIB
Which is compiled as
gfortran -c mylib.f90
ar rcs libmylib.a mylib.o
Now, I have a program that uses FOO function:
PROGRAM MYPROG
USE MYLIB
IMPLICIT NONE
INTEGER M
M = FOO(3)
WRITE (*,*) M
END PROGRAM MYPROG
For simplicity I put it in the same directory as mylib.mod and libmylib.a. Compilation:
gfortran -c myprog.f90
no issues. Linking, however results in error:
gfortran -L./ -lmylib myprog.o
myprog.o: In function `MAIN__': myprog.f90:(.text+0x11): undefined
reference to `__mylib_MOD_foo' collect2: error: ld returned 1 exit
status
However, symbol __mylib_MOD_foo is in libmylib.a:
nm libmylib.a
mylib.o:
0000000000000000 T __mylib_MOD_foo
and it compiles without a problem if I give it mylib.o. What am I doing wrong?
PS. I've seen somewhere, but can't find where now the way to link as follows:
gfortran -Wl,--whole-archive libmylib.a -Wl,--no-whole-archive myprog.o
It works. But it should solve the problem with weak symbols, whereas the output of nm didn't mark __mylib_MOD_foo as weak.
Related
I'm compiling a Fortran code to obtain shared library .so. In the code it uses a module. The compiling has no problem while it reports undefined symbol error when opening the .so library.
Code mesh_map.F are as follows:
#include "cfx5ext.h"
dllexport(mesh_map)
SUBROUTINE mesh_map (CZ, DZ, IZ, LZ, RZ)
USE EXTRA_FLUID2
USE ISO_C_BINDING
USE IFPORT
IMPLICIT NONE
CHARACTER*(1) CZ(*)
DOUBLE PRECISION DZ(*)
INTEGER IZ(*)
LOGICAL LZ(*)
REAL RZ(*)
MAP_STATUS = 1
END
extra_fluid2.f90:
Module EXTRA_FLUID2
INTEGER :: map_status = 0
end module EXTRA_FLUID2
Compiling command:
ifort -c extra_fluid2.f90
/home/xxx/intel/oneapi/compiler/2021.4.0/linux/bin/intel64/ifort -fpic -assume 2underscore -check uninit -warn declarations -diag-error 6717 -ftz -O2 -fp-speculation=safe -fp-model=precise -fp-model=source -fimf-arch-consistency=true -qno-opt-dynamic-align -fpe0 -fomit-frame-pointer -real-size 32 -integer-size 32 -I/usr/ansys_inc/v192/CFX/include -o linux-amd64/ifort/mesh_map.o -c mesh_map.F
-lrt/xxx/intel/oneapi/compiler/2021.4.0/linux/bin/intel64/ifort -shared -o ./linux-amd64/ifort/libmesh_map.so linux-amd64/ifort/mesh_map.o extra_fluid2.o
When I check the .so library using:
ldd -r libmesh_map.so
The result shows as:
undefined symbol: extra_fluid2_mp_map_status__ (./libmesh_map.so)
How can I fix this? Thanks.
You must use -assume 2underscore in both compilations, using/not using the option cannot be mixed.
Also extra_fluid2.f90 should be compiled with option -fpic. It's generally a bad idea to use different sets of flags for files that are supposed to go into the same executable or shared object.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
I am compiling my .so library code and came across a weird problem.
In one the the header file i have decleared a variable extern that is included in other .c file and not defined any where.
Code compiles fine and while runtime it gives error.
Why no error or warning at compile time ?
I am using gcc 9.
Use -Wl,--no-undefined and specify the libraries where your functions come from on the command line. For example, if library x uses functions defined in library y:
gcc -shared -o libx.so x.c # OK
gcc -shared -o libx.so x.c -Wl,--no-undefined # undefined symbols from lib y
gcc -shared -o libx.so x.c -ly -Wl,--no-undefined # OK again
This question already has answers here:
What is an undefined reference/unresolved external symbol error and how do I fix it?
(39 answers)
Closed 4 years ago.
I am trying to compile a Fortran 90 code that uses HDF5. For that purpose, I am using the following Makefile:
# Location of HDF5 binaries (with include/ and lib/ underneath)
HDF5 = /fs/posgrado16/other0/guido/libraries/hdf5/serial
# Compiler
FC = gfortran
# ------ No machine-specific paths/variables after this -----
FORTRANLIB=-I$(HDF5)/include $(HDF5)/lib/libhdf5_fortran.a
FSOURCE = h5_crtgrpar.f90
OBJECTS = $(FSOURCE:.f90=.o)
EXECUTABLE = $(FSOURCE:.f90=.exe)
LIBSHDF = $(FORTRANLIB) $(HDF5)/lib/libhdf5.a
all:$(EXECUTABLE)
$(EXECUTABLE):$(OBJECTS)
$(FC) -o $# $^ $(LIBSHDF)
$(OBJECTS):$(FSOURCE)
$(FC) -c $# $< $(LIBSHDF)
.PHONY : clean
clean:
rm -f $(FSOURCE) $(OBJECTS) *.h5
But, I get the following error:
$ make -f Makefilef
gfortran -o h5_crtgrpar.exe h5_crtgrpar.o -I/fs/posgrado16/other0/guido /libraries/hdf5/serial/include /fs/posgrado16/other0/guido/libraries/hdf5/serial/lib/libhdf5_fortran.a /fs/posgrado16/other0/guido/libraries /hdf5/serial/lib/libhdf5.a
/fs/posgrado16/other0/guido/libraries/hdf5/serial/lib/libhdf5.a(H5PL.o): In function `H5PL_term_interface':
H5PL.c:(.text+0x205): undefined reference to `dlclose'
/fs/posgrado16/other0/guido/libraries/hdf5/serial/lib/libhdf5.a(H5PL.o): In function `H5PL_load':
H5PL.c:(.text+0x477): undefined reference to `dlsym'
H5PL.c:(.text+0x5be): undefined reference to `dlopen'
H5PL.c:(.text+0x5d7): undefined reference to `dlsym'
H5PL.c:(.text+0x704): undefined reference to `dlclose'
H5PL.c:(.text+0x789): undefined reference to `dlerror'
H5PL.c:(.text+0x960): undefined reference to `dlclose'
collect2: error: ld returned 1 exit status
make: *** [h5_crtgrpar.exe] Error 1
I have no idea what the error is. Probably, there is something wrong with my Makefile.
To compile Fortran code with HDF5 enabled, you can replace
FC = gfortran
by
FC = h5fc
and skip all the hdf5 flags, as the h5fc wrapper will take care of those.
If you have some specific reason of calling the compiler by its name, you can learn about what flags are needed by calling
h5fc -show
that will show you what flags are added to the compiler.
On my computer (linux with gfortran), the result is:
gfortran -g -O2 -fstack-protector-strong -I/usr/include/hdf5/serial -L/usr/lib/x86_64-linux-gnu/hdf5/serial /usr/lib/x86_64-linux-gnu/hdf5/serial/libhdf5hl_fortran.a /usr/lib/x86_64-linux-gnu/hdf5/serial/libhdf5_hl.a /usr/lib/x86_64-linux-gnu/hdf5/serial/libhdf5_fortran.a /usr/lib/x86_64-linux-gnu/hdf5/serial/libhdf5.a -Wl,-z,relro -lpthread -lz -ldl -lm -Wl,-rpath -Wl,/usr/lib/x86_64-linux-gnu/hdf5/serial
Often you can get by with less flags than that, which you can find with some experimentation.
Given the error message you report, you lack the -ldl flags that enables linking of the dynamic linking library, see for isntance this other SO question.
I'm a newby in cppuTest and actually I'm trying to build the ./examples within the CppuTest root directory. Source and Test files are compiled without problems but I'm stucking on the final linking stage where I get this error:
C:\CppUTest\cpputest-3.7.1\examples>make
compiling AllTests.cpp
compiling CircularBufferTest.cpp
compiling EventDispatcherTest.cpp
compiling HelloTest.cpp
compiling MockDocumentationTest.cpp
compiling PrinterTest.cpp
compiling CircularBuffer.cpp
compiling EventDispatcher.cpp
compiling Printer.cpp
compiling hello.c
Building archive lib/libCppUTestExamples.a
a - objs/ApplicationLib/CircularBuffer.o
a - objs/ApplicationLib/EventDispatcher.o
a - objs/ApplicationLib/Printer.o
a - objs/ApplicationLib/hello.o
Linking CppUTestExamples_tests
../lib/libCppUTest.a(UtestPlatform.cpp.obj): In function `PThreadMutexCreate':
c:/CppUTest/cpputest-3.7.1/src/Platforms/Gcc/UtestPlatform.cpp:248: undefined reference to `_imp__pthread_mutex_init'
../lib/libCppUTest.a(UtestPlatform.cpp.obj): In function `PThreadMutexLock':
c:/CppUTest/cpputest-3.7.1/src/Platforms/Gcc/UtestPlatform.cpp:255: undefined reference to `_imp__pthread_mutex_lock'
../lib/libCppUTest.a(UtestPlatform.cpp.obj): In function `PThreadMutexUnlock':
c:/CppUTest/cpputest-3.7.1/src/Platforms/Gcc/UtestPlatform.cpp:260: undefined reference to `_imp__pthread_mutex_unlock'
../lib/libCppUTest.a(UtestPlatform.cpp.obj): In function `PThreadMutexDestroy':
c:/CppUTest/cpputest-3.7.1/src/Platforms/Gcc/UtestPlatform.cpp:266: undefined reference to `_imp__pthread_mutex_destroy'
collect2.exe: error: ld returned 1 exit status
make: *** [CppUTestExamples_tests] Error 1
I'm using MinGW on Windows 7. The MinGW contains also the pthread.a library. My makefil look as follows:
#---------
#
# CppUTest Examples Makefile
#
#----------
#Set this to # to keep the makefile quiet
ifndef SILENCE
SILENCE = #
endif
#--- Inputs ----#
COMPONENT_NAME = CppUTestExamples
CPPUTEST_HOME = ..
CPPUTEST_USE_EXTENSIONS = Y
CPP_PLATFORM = Gcc
CFLAGS = -Dmalloc=cpputest_malloc -Dfree=cpputest_free
CPPFLAGS =
GCOVFLAGS = -fprofile-arcs -ftest-coverage
LDFLAGS = -lpthread
#USER_LIBS = -lpthread
# This line is overriding the default new macros. This is helpful
# when using std library includes like <list> and other containers
# so that memory leak detection does not conflict with stl.
CPPUTEST_MEMLEAK_DETECTOR_NEW_MACRO_FILE = -include ApplicationLib/ExamplesNewOverrides.h
SRC_DIRS = \
ApplicationLib
TEST_SRC_DIRS = \
AllTests
INCLUDE_DIRS =\
.\
ApplicationLib\
$(CPPUTEST_HOME)/include\
include $(CPPUTEST_HOME)/build/MakefileWorker.mk
As you can see the pthread lib is given to the linker with the LDFLAGS....
somebody similar experience? or maybe knows where the problem is?
Will be thankful for any tips!
thx to #Keith Marshall and #MadScientist,
so instead of
LDFLAGS = -lpthread
I used:
LD_LIBRARIES += -lpthread
and placed this line directly before:
include $(CPPUTEST_HOME)/build/MakefileWorker.mk
Now it works.
As can be seen in the Catalogue of Built-In Rules:
Linking a single object file
n is made automatically from n.o by running the linker (usually called
ld) via the C compiler. The precise recipe used is:
$(CC) $(LDFLAGS) n.o $(LOADLIBES) $(LDLIBS)
and Variables Used by Implicit Rules:
LDFLAGS
Extra flags to give to compilers when they are supposed to invoke the linker,
ld, such as -L. Libraries (-lfoo) should be added to the LDLIBS variable
instead.
So in this case -lpthread should be set or added to LDLIBS, not LDFLAGS.
I'm using gcc 4.3.4 and ld 2.20.51 in Cygwin under Windows 7. Here's a simplified version of my problem:
foo.o contains function foo_bar() which calls bar() in bar.o
bar.o contains function bar()
main.c calls functions in foo.o, but foo_bar() is not in the call chain
If I try to compile main.c and link it to foo.o, I get an undefined reference to _foo_bar error from ld. As you can see from my Makefile except below, I've tried using flags for putting each function in its own section and having the linker discard unused sections.
COMPILE_CYGWIN = gcc -iquote$(INCDIR)
COMPILE = $(COMPILE_CYGWIN) -g -MMD -MP -Wall -ffunction-sections -Wl,-gc-sections $(DEFINE)
main_OBJECTS = main.o foo.o
main.exe : $(main_OBJECTS)
$(COMPILE) -o main.exe $(main_OBJECTS)
The function foo_bar() is a short function that provides a connection between two networking layers in a protocol stack. Some programs don't need it, so they won't link in the other object files related to the upper layer of the stack. It's a small function, and seems inappropriate to put it into its own .o file.
I don't understand why ld throws the error -- nothing is calling foo_bar(), so there's no need to include bar() in the final executable. A coworker has just told me that ld is not a "smart linker", so maybe what I'm trying to do isn't possible?
Unless the linker is from Cyberdyne Systems it has no way to know exactly which functions will actually be called. It only knows which ones are referenced. Even Skynet's linker can't predict what run-time decisions will be made or what will happen if you load a module dynamically at run-time and it starts calling various global functions1.
So, if you link in module m and it references function f, you will need to link with whatever module has f.
1. This problem is related to the Halting Problem and has been proven undecidable.
I hit the similar issue and I find this page:
http://lists.gnu.org/archive/html/bug-gnu-utils/2004-09/msg00098.html
Highligt:
The GNU linker still works at .o file granularity.
Gcc pulls in foo.o and then find bar() was undefined.
You'd better put foo_bar() into another .o file.