Gcc - Undefined reference but library contains matching symbol - c++

i have tried to link a programm of mine with the libmodbus opensource lib. After some trouble with automake, i finally managed to compile it.
But now I get a undefined reference error from gcc, when I use one of the functions the library provides in my own programm:
main.cpp:(.text+0x21): undefined reference to `modbus_udp_init(char*, int, __modbus_udp_handle*)'
collect2: Fehler: ld gab 1 als Ende-Status zurück
From my point of view, the arguments of gcc to compile my project are correct:
g++ -v -I ../libmodbus/modbus -o main main.cpp -L../libmodbus/modbus/.libs/ -lmodbus
I checked with nm if the function is really in that library, but everything looks fine for me (I have deleted some parts from the output, to prevent the output from getting too big):
$ nm ../libmodbus/modbus/.libs/libmodbus.a
modbus.o:
0000000000000590 T crc16
U free
U malloc
U memcpy
0000000000000b40 T modbus_diagnostics
0000000000000d90 T modbus_error_get_exception_code
0000000000000100 C modbus_error_str
0000000000000cf0 T modbus_exception
[...]
modbus-udp.o:
U bcopy
U close
U __errno_location
U gethostbyname
U modbus_error_str
U modbus_tcp_frame_pack
U modbus_tcp_frame_parse
0000000000000000 T modbus_udp_close
0000000000000030 T modbus_udp_init
0000000000000220 T modbus_udp_recv
0000000000000190 T modbus_udp_send
0000000000000010 r __PRETTY_FUNCTION__.4582
0000000000000000 r __PRETTY_FUNCTION__.4592
U recvfrom
U sendto
U setsockopt
U snprintf
U socket
U strerror
modbus-tcp.o:
[...]
modbus-serial.o:
[...]
Does someone have an idea why gcc can't resolve the symbol?

As noloader suggested, i missed adding extern "C" as libmodbus is a C-library. I edited my source:
extern "C" {
#include <modbus.h>
#include <modbus-udp.h>
}
Now it compiles fine. Thank you!

Related

libgcc linker error: hidden symbol __aarch64_swp1_acq_rel in libgcc.a is referenced by DSO

I am trying to link a shared library I have no control on. This library has an undefined symbol (nm output):
U __aarch64_swp1_acq_rel
Which seems to be defined in libgcc.a:
[user#fedora ~]$ nm -a /usr/lib/gcc/aarch64-redhat-linux/12/libgcc.a | grep swp1_acq_rel
0000000000000000 T __aarch64_swp1_acq_rel
[user#fedora ~]$ objdump -t /usr/lib/gcc/aarch64-redhat-linux/12/libgcc.a | grep swp1_acq_rel
0000000000000000 g F .text 000000000000002c .hidden __aarch64_swp1_acq_rel
But whenever I try to link, I get the error in the title of this question. I understand that this symbol is hidden for dynamic linking (please confirm if I am wrong). So my question is what is the right approach to link against this libgcc symbol when the shared library I am using (and linking against) does not define it.
I expected that it would be possible to resolve this symbol with the libgcc.a in my system. Why is it hidden?
Compile it with cflags "-mno-outline-atomics" can solve my problem.
GCC 10.0 enables calls to out-of-line helpers to implement atomic operations.
You can view the compile code to see the differences:
https://godbolt.org/z/z8W7z1cqx

How to read nm commands : What does nm options -T and -U (undefined) mean?

I have linking errors that I suspected from 'libsimint.a'.
Linker messages (if any) follow...
/home/.../simint/lib/libsimint.a(shell.c.o): In function `simint_copy_shell':
shell.c:(.text+0x126): undefined reference to `__intel_ssse3_rep_memcpy'
/home/.../simint/lib/libsimint.a(shell.c.o): In function`simint_normalize_shells':
shell.c:(.text+0x4e3): undefined reference to `__svml_pow4'
I tried nm commands to figure it out:
>> nm libsimint.a |grep __intel_ssse3_rep_memcpy
U __intel_ssse3_rep_memcpy
>> nm libsimint.a |grep simint_copy_shell
0000000000000090 T simint_copy_shell
From what I understand by the above (with help of nm man), simint_copy_shell function is mentioned in code but __intel_ssse3_rep_memcpy is not defined in some other libray our libsimint is compiled with. Can anybody verify this or add any clarification? Thanks
(I'm compiling and linking a large code using gcc, that was compiled with icpc but instead.)
U means "undefined" -- the object has a reference to the symbol but no definition
T means globally defined in the text segment -- the object defines and exports the symbol
The manual page (man nm) lists all these type codes.

Static Library Linking Issue "Undefined symbols" for symbols that are defined

I am using Apple LLVM version 8.0.0 (clang-800.0.42.1) to compile. It's about 1200 files, but I have used them before. I go and compile them all, no problems. Then I make my static library (ar rcs libblib.a *.o), no problems. So when I try to use my brand new library, I have my problem.
gcc main.c -L. -lblib
Undefined symbols for architecture x86_64:
"_N_method", referenced from:
_main in main-7fc584.o
ld: symbol(s) not found for architecture x86_64
But, I know this is defined. I check to see that the file is included (ar -t libblib.a | grep N_METHOD.o) and it is in there. Check the source file, and there is the method, exactly named as it is in the header file. What is the problem I am having here? I am at a complete loss and I am hoping I am missing something simple.
I did nm -g N_METHOD.o and got back:
0000000000000000 T __Z8N_methodP6stacks
Transferring comments into an answer.
Based on the question content, I asked:
Have you checked that N_METHOD.o is a 64-bit object file (or a fat object file with both 32-bit and 64-bit code in it)? If it is a 32-bit object file, then it is no use for a 64-bit program. However, that's a little unlikely; you have to go out of your way to create a 32-bit object file on Mac.
Have you run nm -g N_METHOD.o to see whether _N_method is defined in the object file?
I did nm -g N_METHOD.o and got back:
0000000000000000 T __Z8N_methodP6stacks
Don't compile C code with a C++ compiler. Or don't try to compile C++ code with a C compiler. The mangled name (__Z8N_methodP6stacks) is for C++. Maybe you simply need to link with g++ instead of gcc? They are different languages — this is the property of 'type-safe linkage' that is characteristic of C++ and completely unknown to C.
First step — compile and link with:
g++ main.c -L. -lblib
Assuming that the source is in the C++ subset of C (or C subset of C++), then the chances are that should work. At least, if the code contains N_Method(&xyz) where xyz is a variable of type stacks, then there's a chance it will call __Z8N_methodP6stacks.
The following code:
typedef struct stacks stacks;
extern int N_method(stacks*);
extern int relay(stacks *r);
int relay(stacks *r) { return N_method(r); }
compiles with a C++ compiler to produce the nm -g output:
0000000000000000 T __Z5relayP6stacks
U __Z8N_methodP6stacks
It also compiles with a C compiler to produce the nm -g output:
0000000000000038 s EH_frame1
U _N_method
0000000000000000 T _relay

compiling Suitesparse 4.4.4 with Openblas on linux

I downloaded and compiled Openblas, and now I am trying to compile and link openblas to Suitesparse 4.4.4. After compiling all lib files, I get the following error when the compiler tries to compile umfpack_di_demo.c:
../Lib/libumfpack.a(umf_di_local_search.o): In function `umfdi_local_search':
umf_local_search.c:(.text+0x4c0): undefined reference to `dtrsv_'
umf_local_search.c:(.text+0x634): undefined reference to `dgemv_'
../Lib/libumfpack.a(umf_di_blas3_update.o): In function `umfdi_blas3_update':
umf_blas3_update.c:(.text+0x11d): undefined reference to `dtrsm_'
umf_blas3_update.c:(.text+0x1de): undefined reference to `dgemm_'
umf_blas3_update.c:(.text+0x2ae): undefined reference to `dger_'
which I took to mean that the linking is not proper. But, as directed in SuiteSparse_config.mk, I gave the absolute location of libopenblas.a on my system. Also, I also gcc-nm to see if the symbol dtrsv_ is defined in libopenblas.a, and I got the following output which shows that the symbol is defined in the library:
0000000000000000 T dtrsv_
U dtrsv_NLN
U dtrsv_NLU
U dtrsv_NUN
U dtrsv_NUU
U dtrsv_TLN
U dtrsv_TLU
U dtrsv_TUN
U dtrsv_TUU
U dtrsv_NLN
U dtrsv_NLU
U dtrsv_NUN
U dtrsv_NUU
U dtrsv_TLN
U dtrsv_TLU
U dtrsv_TUN
U dtrsv_TUU
dtrsv_NUU.o:
0000000000000000 T dtrsv_NUU
dtrsv_NUN.o:
0000000000000000 T dtrsv_NUN
dtrsv_NLU.o:
0000000000000000 T dtrsv_NLU
dtrsv_NLN.o:
0000000000000000 T dtrsv_NLN
dtrsv_TUU.o:
0000000000000000 T dtrsv_TUU
dtrsv_TUN.o:
0000000000000000 T dtrsv_TUN
dtrsv_TLU.o:
0000000000000000 T dtrsv_TLU
dtrsv_TLN.o:
0000000000000000 T dtrsv_TLN
U dtrsv_NLU
U dtrsv_NUN
U dtrsv_TLU
U dtrsv_TUN
U dtrsv_NLU
U dtrsv_NUN
U dtrsv_TLU
U dtrsv_TUN
U dtrsv_
U dtrsv_
U dtrsv_
I am not sure whats going wrong here. Should I include lapack with openblas in the suitesparse_config.mk file? Any help is appreciated. Thanks.
Note: if it helps, I used gcc 4.4.7 for all compilation and my system details are:
Linux 3.2.0-4-amd64 #1 SMP Debian 3.2.60-1+deb7u3 x86_64 GNU/Linux
== EDIT 1: the steps i followed ==
For Openblas:
Downloaded openblas from
http://github.com/xianyi/OpenBLAS/zipball/v0.2.14.
Unzipped and compiled it on my system using gcc-4.4.7 and the following command
make FC=/usr/bin/lgfortran-4.4
I had to provide 'FC' as my system is not having libgfortran.* present in /usr/lib/.
After compilation is done, I type
make install
to install to a custom directory in my home folder.
For suitesparse:
Downloaded suitesparse from http://faculty.cse.tamu.edu/davis/SuiteSparse/SuiteSparse-4.4.4.tar.gz
Unzipped it, and edited the suitsparse_config.mk file to do the following modifications: A) enabled GPU configuration for CHOLMOD and SPQR, B) Not using metis, so commented "METIS_PATH = ../../metis-4.0" and "METIS = ../../metis-4.0/libmetis.a". Also, uncommitted "CHOLMOD_CONFIG = -DNPARTITION". C) gave path to custom installation of openblas: BLAS = -L//OpenBLAS/local/lib/libopenblas.a -lpthread -L/usr/lib/gcc/x86_64-linux-gnu/4.4.7/libgfortran.so
type make in srcdir.

How to avoid standard include files during compilation

I am trying to use my own printf function so i don't want to include standard include files... so I am compiling my code with -nostdinc
I have created my program something like this:
extern int printf(const char*,...);
printf("Value:%d",1234);
//printf("\n");
It is working fine for this code, but when I use printf("\n") then it is showing undefined reference to 'putchar'.
If i comment printf("\n"); then nm command is showing
$ nm test1.o
U exit
00000000 T main
U printf
00000030 T _start
but if I use printf("\n"); then nm command is showing
$nm test1.o
U exit
00000000 T main
U printf
U putchar
0000003c T _start
I am not getting how and from where putchar is getting included
gcc version 4.8.2 (GCC)
gcc optimizes printf in certain situations. You can look at the function fold_builtin_printf here for the complete details. IIRC, it optimizes calls with one argument followed by a newline to puts/putchar. You can turn it off by specifying -fno-builtin(gcc docs).