Undefined reference to a function, linker error - c

This is a rookie question and I might be doing something stupid, but I wrote a C program that includes two non default libraries: curl and libxml2. I am trying to go through the compilation process in detail to learn the process and statically link the libraries. These are the steps I took:
Downloaded libxml2 and curl and compiled it with the included makefile and did the following:
ar rcs libcurl.a /home/${USER}/Desktop/Curl/curl-7.73.0/lib/*.o
ar rcs libxml2.a /home/${USER}/Desktop/xml2/libxml2-2.7.2/*.o
Even though I only use a few functions from those libraries I packed all together in case they needed each other, or at least I think that's how it works. I copied the generated arhive library to a separate location and lastly I did:
cp ~/Desktop/libxml2-2.7.2/libxml2.a ~/Desktop/libs/
cp ~/Desktop/Curl/curl-7.73.0/lib/libxml2.a ~/Desktop/libs/
gcc WolframParser.c -I/home/${USER}/Desktop/Curl/curl-7.73.0/include/ -I/home/${USER}/Desktop/libxml2-2.7.2/include/ -L/home/${USER}/Desktop/libs/ -lcurl -lxml2 -lm
The linker reports a bunch of errors of undefined references, the likes of:
/usr/bin/ld: /home/${USER}/Desktop/libs//libcurl.a(libcurl_la-multi.o): in function `multi_getsock':
multi.c:(.text+0x18e): undefined reference to `Curl_ssl_getsock'
/usr/bin/ld: /home/${USER}/Desktop/libs//libcurl.a(libcurl_la-easy.o): in function `curl_global_init':
easy.c:(.text+0x172): undefined reference to `Curl_ssl_init'
/usr/bin/ld: /home/${USER}/Desktop/libs//libcurl.a(libcurl_la-easy.o): in function `curl_global_init_mem':
easy.c:(.text+0x22e): undefined reference to `Curl_ssl_init'
/usr/bin/ld: /home/${USER}/Desktop/libs//libcurl.a(libcurl_la-easy.o): in function `curl_global_cleanup':
easy.c:(.text+0x295): undefined reference to `Curl_ssl_cleanup'
. . .
Can someone please point out what I did wrong, and can this be done like this at all?

Related

How can I cross-compile for Solaris with cgo?

I am trying to compile some cgo code for Solaris. I get these errors when I try to build:
$ CGO_LDFLAGS="-L$(pwd)/solaris-11.4-amd64-libs" CGO_CFLAGS='-I/home/shane/src/ioctl-experimentation/solaris-11.4-headers -Wno-unknown-pragmas' CGO_ENABLED=1 GOOS=solaris GOARCH=amd64 go build
# runtime/cgo
/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o: in function `_start':
(.text+0x16): undefined reference to `__libc_csu_fini'
/usr/bin/ld: (.text+0x1d): undefined reference to `__libc_csu_init'
/usr/bin/ld: (.text+0x2a): undefined reference to `__libc_start_main'
/usr/bin/ld: $WORK/b003/_x003.o: in function `_cgo_release_context':
gcc_context.c:(.text+0x5c): undefined reference to `__stack_chk_fail'
/usr/bin/ld: $WORK/b003/_x004.o: in function `x_cgo_sys_thread_create':
gcc_libinit.c:(.text+0x87): undefined reference to `__stack_chk_fail'
/usr/bin/ld: $WORK/b003/_x004.o: in function `_cgo_wait_runtime_init_done':
gcc_libinit.c:(.text+0x121): undefined reference to `__stack_chk_fail'
/usr/bin/ld: $WORK/b003/_x004.o: in function `_cgo_try_pthread_create':
gcc_libinit.c:(.text+0x291): undefined reference to `__stack_chk_fail'
/usr/bin/ld: $WORK/b003/_x006.o: in function `x_cgo_init':
gcc_solaris_amd64.c:(.text+0xb6): undefined reference to `__stack_chk_fail'
/usr/bin/ld: $WORK/b003/_x006.o:gcc_solaris_amd64.c:(.text+0x214): more undefined references to `__stack_chk_fail' follow
collect2: error: ld returned 1 exit status
I am cross-compiling on Linux. Here is my Go version:
$ go version
go version go1.18.3 linux/amd64
The solaris-11.4-amd64-libs directory contains a copy of all files under /lib/amd64 from a Solaris 11.4 AMD64 machine. The solaris-11.4-headers directory contains a copy of all files under /usr/include from a Solaris 11.4 AMD64 machine.
Here is my Go code in main.go:
//go:build solaris
// +build solaris
package main
import "C"
func main() {
}
I know cgo is fully supported for Solaris as of Go 1.5, and I am using Go 1.18.
I'm looking for help understanding why these linker errors are happening, even when I copied across all libs from the /lib/amd64 directory. Is it possible there are more libs I also need to copy over from somewhere else?
Edit
At the suggestion of Liam Kelly, I looked at this question about how to link against a different libc. I tried passing -Xlinker -rpath=$(pwd)/solaris-11.4-amd64-libs as part of CGO_LDFLAGS, but I got the same errors as before. I tried using -nodefaultlibs and -nostdlib both separately and together along with -Xlinker -rpath=$(pwd)/solaris-11.4-amd64-libs, but using either of these two flags either separately or together just increased the number of linker errors.
I am going to assume that libxnet is needed for Solaris and that is why is is being automatically added.
First confirm that the libxnet library is where is should be with sudo find /lib libxnet*. I expect you will see one line of the output show:
lib/64/libxnet.so
Assuming you see the above output, I believe you just need to tell the linker to look in that location with CGO_LDFLAGS="-L/lib/64" CGO_ENABLED=1 GOOS=solaris GOARCH=amd64 go build. If that works then you should be able to embedded that LDFlag in your main.go file with:
// #cgo LDFLAGS: -L/lib/64
import "C"
Once embedded you will not need to explicitly set CGO_LDFLAGS

understanding compilation commands C and configuring CodeBlocks

I'm learning C in college. And I wanted to try new things, so I decided to use the allegro Game library to create some stuff. I followed the tutorial, and everything went fine. I wrote a piece of code in the text editor and executed the commands provided by the tutorial and it compiled and run. (I'm on linux btw).
These are the commands:
gcc hello.c -o hello $(pkg-config allegro-5 allegro_font-5 --libs --cflags)
./hello
So, I understand that gcc is calling the gcc compiler and hello.c is the name of the source code file and -o hello specifies the name of the compiled file. but the next part is ambiguous and beyond my knowledge:
$(pkg-config allegro-5 allegro_font-5 --libs --cflags)
So can anyone explain what it means (it has something to do with linking). and if I remove that part the compiler returns these error codes:
/usr/bin/ld: /tmp/ccIQsEis.o: in function `main':
hello.c:(.text+0x2f): undefined reference to `al_install_system'
/usr/bin/ld: hello.c:(.text+0x34): undefined reference to `al_install_keyboard'
/usr/bin/ld: hello.c:(.text+0x45): undefined reference to `al_create_timer'
/usr/bin/ld: hello.c:(.text+0x4e): undefined reference to `al_create_event_queue'
/usr/bin/ld: hello.c:(.text+0x61): undefined reference to `al_create_display'
/usr/bin/ld: hello.c:(.text+0x6a): undefined reference to `al_create_builtin_font'
/usr/bin/ld: hello.c:(.text+0x73): undefined reference to `al_get_keyboard_event_source'
/usr/bin/ld: hello.c:(.text+0x85): undefined reference to `al_register_event_source'
/usr/bin/ld: hello.c:(.text+0x91): undefined reference to `al_get_display_event_source'
/usr/bin/ld: hello.c:(.text+0xa3): undefined reference to `al_register_event_source'
/usr/bin/ld: hello.c:(.text+0xaf): undefined reference to `al_get_timer_event_source'
/usr/bin/ld: hello.c:(.text+0xc1): undefined reference to `al_register_event_source'
/usr/bin/ld: hello.c:(.text+0xd4): undefined reference to `al_start_timer'
/usr/bin/ld: hello.c:(.text+0xe7): undefined reference to `al_wait_for_event'
/usr/bin/ld: hello.c:(.text+0x125): undefined reference to `al_is_event_queue_empty'
/usr/bin/ld: hello.c:(.text+0x13d): undefined reference to `al_map_rgb'
/usr/bin/ld: hello.c:(.text+0x16a): undefined reference to `al_clear_to_color'
/usr/bin/ld: hello.c:(.text+0x17e): undefined reference to `al_map_rgb'
/usr/bin/ld: hello.c:(.text+0x1ca): undefined reference to `al_draw_text'
/usr/bin/ld: hello.c:(.text+0x1cf): undefined reference to `al_flip_display'
/usr/bin/ld: hello.c:(.text+0x1e7): undefined reference to `al_destroy_font'
/usr/bin/ld: hello.c:(.text+0x1f3): undefined reference to `al_destroy_display'
/usr/bin/ld: hello.c:(.text+0x1ff): undefined reference to `al_destroy_timer'
/usr/bin/ld: hello.c:(.text+0x20b): undefined reference to `al_destroy_event_queue'
collect2: error: ld returned 1 exit status
And for the second part of the question, I tried to compile this code in code:blocks but it returns the same errors given by the compiler without the term: $(pkg-config allegro-5 allegro_font-5 --libs --cflags)
So, what configuration should I change in codeblocks so that it compiles well code using allegro libraries.
PS. I didn't include the source code intentionally as it adds no useful information to the question, only clutters it.
This is a Bash command-syntax feature which executes another command and then provides its output as a string. This idiom is being used here to programmatically provide command-line parameters to the gcc command. The pkg-config command is being executed, and it returns a string which becomes part of – is textually included in – the command-string for invoking gcc. (Which of course neither knows nor cares where its command-line parameters "come from.")
(Clever, huh?)
For example, try this:
echo $(ls)
You will be rewarded with a list of all the files in the current directory, concatenated as a string.
To elaborate on the answer by #Mike Robinson,
$(pkg-config allegro-5 allegro_font-5 --libs --cflags) will execute the command pkg-config and substitute the result. pkg-config is build utility that helps when compiling C programs. It's not specific to allegro, it is used by many C libraries.
In this particular case, pkg-config is called with the parameters allegro-5 allegro_font-5 --libs --cflags, which asks pkg-config "what are the compiler options (--cflags) and libraries (--libs) I need when compiling and linking with allegro?" Allegro consists of several modules, in this case you chose the main module 'allegro' and the font module 'allegro_font'. In both cases you're referring to major version 5 of allegro.
On your system, the result of the command is -I/usr/include/x86_64-linux-gnu -lallegro_font -lallegro. The meaning of these options is as follows:
-I/usr/include/x86_64-linux-gnu tells the compiler to add the path /usr/include/x86_64-linux-gnu to the header search path (because the allegro headers are located there)
-lallegro_font and '-lallegro` tells the linker to add the allegro_font and allegro libraries respectively. That also explains why you get all those undefined reference errors when you remove this - you are no longer telling the linker to add the allegro library, so it can't find all those functions anymore.

Undefined reference to `__gmpz and makefile

I can’t figure out why I’m getting these compilation errors:
gcc -o Compil obj/MillerRabin.o obj/main.o -L. -L/usr/lib/ -Wl,-rpath=/home/---------/Documents/AC20_Cyrpto -lgmp -lCommon -ltest -lprimeGen
./libtest.so: undefined reference to `__gmpz_set_str'
./libtest.so: undefined reference to `__gmpz_set_ui'
./libtest.so: undefined reference to `__gmpz_add_ui'
./libtest.so: undefined reference to `__gmpz_clear'
./libtest.so: undefined reference to `__gmpz_init'
./libtest.so: undefined reference to `mpzPrint'
collect2: error: ld returned 1 exit status
Makefile:61: recipe for target 'Compil' failed
make: *** [Compil] Error 1
These errors are coming from libs/test/test.c, I’m using a make file that a friend of mine made, and I haven’t really looked into how they work yet.
So what’s weird is that in my libs folder I have another .c file that’s using gmp (libs/Common/common.h and mpzfunctions.c), and that one doesn’t give me any errors. If I move my test function to the main the compilation works.
If anyone knows how to fix this, it would be great! Thanks.
Symbols from libraries are applied in order. So when you write:
-lgmp -ltest
It means that symbols used in libgmp will be looked up in libtest but not vice versa.
Apparently, your libtest requires functions from libgmp, so you need to apply them in the opposite order.
As a rule of thumb, external libraries should always go last because they do not generally require symbols from your libraries.
So without knowing too much, I 'd guess that the order should be:
-lCommon -lprimeGen -ltest -lgmp
It looks to me like you will want to remove -lgmp from LINK_FLAGS and add it somehow to the end of the link command.

Issue with linking libraries built with gnat

When trying to build some test cases (just programs written in Ada), I get the following error:
gcc -c -shared decimaltests.adb
gnatbind -x decimaltests.ali
gnatlink decimaltests.ali -lGenerics -lNumerics -lTesting
/usr/bin/ld: decimaltests: hidden symbol `_Unwind_Resume' in
/usr/lib/gcc/x86_64-pc-linux-gnu/7.2.1/libgcc_eh.a(unwind-dw2.o) is referenced by DSO
/usr/bin/ld: final link failed: Bad value
collect2: error: ld returned 1 exit status
gnatlink: error when calling /usr/bin/gcc
gnatmake: *** link failed.
I'm building them with gnatmake -shared *.ad{b,s} -largs -lGenerics -lNumerics -lTesting Clearly this isn't a problem with building the sources, but just to further confirm that, I copied the sources into this directory and built using gnatmake -shared *.ad{b,s} which built the tests just fine.
The dependent libraries are built and installed into a path gnat searches through. It doesn't seem to be an issue of not finding those. Not sure what's going on here.
All the libraries are built with gnatmake -O2 -fPIC -shared *.ad{b,s} as well as any relevant library dependencies. All libraries that depend on these can still be built. It's only even programs that depend on the libraries that throw this error, and always the same error.
Update: Building the libraries using gprbuild and then installing them with gprinstall seems to work similarly, except now the error is as follows:
decimaltests.o: In function `_ada_decimaltests':
decimaltests.adb:(.text+0x43): undefined reference to `testing__start'
decimaltests.adb:(.text+0x4a): undefined reference to
`generics__testing__default_tolerance'
decimaltests.adb:(.text+0x9e): undefined reference to
`generics__testing__default_tolerance'
decimaltests.adb:(.text+0x108): undefined reference to
`generics__testing__default_tolerance'
decimaltests.adb:(.text+0x172): undefined reference to
`generics__testing__default_tolerance'
decimaltests.adb:(.text+0x1dc): undefined reference to
`generics__testing__default_tolerance'
decimaltests.o:decimaltests.adb:(.text+0x23f): more undefined references to
`generics__testing__default_tolerance' follow
decimaltests.o: In function `_ada_decimaltests':
decimaltests.adb:(.text+0x14f5): undefined reference to `testing__stop'
/usr/lib/numerics//libNumerics.so: undefined reference to
`generics__testing__not_started#SYMS'
/usr/lib/numerics//libNumerics.so: undefined reference to
`generics__testing__pass#SYMS'
/usr/lib/numerics//libNumerics.so: undefined reference to
`generics__testing__fail#SYMS'
collect2: error: ld returned 1 exit status
gprbuild: link of decimaltests.adb failed
So I looked through the symbols table for both build methods and noticed, in both cases, the symbol most definitely exists, but the reference to it seems to be the wrong location. I'll try building on different platforms/compilers and update again if anything relevant comes up.
Both processes correctly build the libraries and test programs, and the test programs run properly, on different platforms. To further confirm that this is a bug, I've installed a different GCC toolchain and repeated the builds under the original platform, and this problem did not arise. I'll be filing a bug report.

Compiling using arm-none-eabi-gcc and linking library liba.a error

I am compiling a hello world program in C on a 64-bit Linux machine. I am using a GCC ARM embedded toolchain to cross compile my program on a FOX G20 V board with an ATMEL AT91SAM9G20 processor.
On the first take, I had a few errors when compiling because the program didn't recognize the printf, return etc. functions (the standard C functions). So I decided to make the link between the functions, which I believe are defined in the libc.a library (correct me if I'm wrong), by doing arm-none-eabi-gcc -o hello hello.c libc.a but the outcome still results in errors:
libc.a(lib_a-exit.o): In function `exit':
exit.c:(.text.exit+0x16): undefined reference to `_exit'
libc.a(lib_a-sbrkr.o): In function `_sbrk_r':
sbrkr.c:(.text._sbrk_r+0xc): undefined reference to `_sbrk'
libc.a(lib_a-writer.o): In function `_write_r':
writer.c:(.text._write_r+0x10): undefined reference to `_write'
libc.a(lib_a-closer.o): In function `_close_r':
closer.c:(.text._close_r+0xc): undefined reference to `_close'
libc.a(lib_a-fstatr.o): In function `_fstat_r':
fstatr.c:(.text._fstat_r+0xe): undefined reference to `_fstat'
libc.a(lib_a-isattyr.o): In function `_isatty_r':
isattyr.c:(.text._isatty_r+0xc): undefined reference to `_isatty'
libc.a(lib_a-lseekr.o): In function `_lseek_r':
lseekr.c:(.text._lseek_r+0x10): undefined reference to `_lseek'
libc.a(lib_a-readr.o): In function `_read_r':
readr.c:(.text._read_r+0x10): undefined reference to `_read'
collect2: error: ld returned 1 exit status
I'm really unsure as to why the program still does not recognize the standard functions even though I've linked the library to the application. If anyone has a reason as to why, or a solution as to how I can fix this problem, I would be very grateful.
UPDATE
I've downloaded the glibc library from here. I've compiled and created a static library from the syscalls.c library that I found in newlib-2.1.0/libgloss/arm and when I link the library to my application code, I still get the same error.
Try executing this:
arm-none-eabi-gcc --specs=rdimon.specs -lgcc -lc -lm -lrdimon -o hello hello.c
Your toolkit seems to provide the librdimon.a, a library which provides the basic standard C functions.
I got this error because my binary cannot fit the ROM.
My first error was:
address 0x34000 of arm_flash.elf section `.mmu_tbl' is not within region `ps7_ram_0`
Then I've got the same list of undefined reference errors.
I need to reduce the binary size, by removing new keywords, and all dynamic memory allocation from my C++ code.

Resources