arm-gcc unresolved reference 'sinf' - c

I'm getting this error when trying to compile:
error: undefined reference to `sinf'
I have included math.h, and verified that it is defined in there:
#include <math.h>
However, I get an error while trying to link to the math library:
arm-none-eabi-ld -L/usr/lib -lm --gc-sections -T ../standalone.ld -o "main.elf" ./main.o ./startup_gcc.o
error: cannot find -lm
However, the library is obviously there:
Kens-MacBook-Pro:lib Ken$ pwd
/usr/lib
Kens-MacBook-Pro:lib Ken$ ls | grep libm
libm.dylib
libmecab.1.0.0.dylib
libmecab.dylib
libmecabra.dylib
libmenu.5.4.dylib
libmenu.dylib
libmx.A.dylib
libmx.dylib
Kens-MacBook-Pro:lib Ken$
What am I doing wrong? I'm using Eclipse.

Judging by your arm-none-eabi-ld command, I'm assuming you're cross compiling. You need to install some sort of math library into the toolchain for whatever your platform is.
The ls output you posted contains a list of libraries available for your host, not your target. On my machine, the libraries for my ARM cross-compiler resides in /opt/local/arm-none-eabi/lib/ for example.
danieltang ~$ ls /opt/local/arm-none-eabi/lib/
crt0.o ldscripts libm.a libssp_nonshared.a libstdc++.a-gdb.py libsupc++.la
elf2flt.ld libc.a libssp.a libssp_nonshared.la libstdc++.la thumb
fpu libg.a libssp.la libstdc++.a libsupc++.a

Related

C compiler not finding gmp linked library

I'm trying to compile a simple C program on an M1 Mac that includes gmp.h. For whatever reason, however, it continuously says that it can't find the library. I checked to see if it exists via locate libgmp.a to which it says it is located in /opt/local/lib/libgmp.a. I also attempted to install it via brew to no avail. I really don't understand what I'm doing wrong here. I also checked the PATH environment variable to make sure this path was included, which it is.
The output of find /opt/local -type f -name "gmp.h" is /opt/local/include/gmp.h, and the output of find /opt/local -type f -name "libgmp*" is
/opt/local/libgmp.a
/opt/local/lib/libgmpxx.4.dylib
/opt/local/lib/libgmp.a
/opt/local/lib/libgmpxx.a
/opt/local/lib/libgmp.10.dylib
I compiled by linking via -L/opt/local/lib -lgmp does not fix the issue.
Command used: gcc main.c -o main.o -L/opt/local/lib -lgmp
To compile a program that relies on a header file:
#include <gmp.h>
located in a non-standard location /usr/local/include/gmp.h you need to tell the compiler where to find it by setting the directory where to find the header file:
gcc -c main.c -I/usr/local/include
Note: gpp -x c -v
To link the program, you need to tell the compiler which library to use (-l) and where to find that library (-L) which in this case /usr/local/lib/gmp.a:
gcc main.o -o main -L/usr/local/lib -lgmp
Note: gcc -print-search-dirs | grep ^libraries
If you are using a dynamic library (.so), you may also need to tell the linker where to find the library at run-time:
export LD_LIBRARY_PATH=/usr/local/lib
./main

why can my gcc command not have -static parameter

I usually use gcc to compile my C program, it works ok, but when I tried to compile static library with -static parameter it always failed.
Although I tried some solutions on google, but it still didn't get fixed.
My command is as follows:
gcc mycode.c -static -L . -lurl -lcap -o mycode
The error message is:
/usr/bin/ld: cannot find -lc
collect2: error: ld returned 1 exit status
but when I remove -static it works very well.
GCC's -static linkage option directs the linker to ignore shared libraries
during the linkage. So it must find static versions of all the libraries required
by the linkage, including those that are linked by default, such as libc.
You have not installed the static version of libc (which would be /usr/lib/???/libc.a), so:
/usr/bin/ld: cannot find -lc
collect2: error: ld returned 1 exit status
libc.a is installed by the libc development package. The name of the libc
development package and how to install it depends on your distro. E.g. On Debian
or Ubuntu, the package to install is libc6-dev; on Fedora it is glibc-develop.
But before you go to do that, hang on a tick. You said:
I tried to compile static library with -static parameter it always failed.
gcc mycode.c -static -L . -lurl -lcap -o mycode
That sounds rather as if you just wanted to link your program with one or both
static libraries liburl.a, libcap.a, located in ./, and thought you should
do it by passing -static to the linkage.
There is no need to pass -static to link your program with ./liburl.a and/or
./libcap.a. The options:
-L . -lurl -lcap
will direct the linker to search in ./ for either of the files liburl.so (shared library)
or liburl.a (static library) and if it finds one or other of them it will link your
program with that library. If it finds both of them in ./, then it will choose the
shared library liburl.so. So unless you have ./liburl.so as well as ./liburl.a
then:
-L . -lurl
by itself will link your program against ./liburl.a.
And likewise for -lcap. No need for -static. The default shared library libc.so
will be linked automatically. The linker has no problem at all linking your program
with some static libraries and some shared ones. That is what is already happening
with your successful linkage:
gcc mycode.c -L . -lurl -lcap -o mycode
assuming that liburl.a and libcap.a are the only candidates for resolving
-lurl and -lcap in ./.
And even if you do have both ./liburl.a and ./liburl.so - and/or ./libcap.a and ./libcap.so - there is still no
need for a solution as drastic as a fully static linkage. You can just explicitly
tell the linker to find a particular static library if that's what you want, like:
gcc mycode.c -L . -l:liburl.a -l:libcap.a -o mycode

How do I make the MinGW cross compiler use the same libraries as gcc?

My program uses the GNU Multiple Precision Arithmetic Library to deal with numbers of an arbitrary size. I successfully compile it using GCC with:
gcc main.c -o diff -g -lgmp
However, when I try to use the MinGW crosscompiler compiler, I get the following error:
i686-w64-mingw32-gcc main.c -o diff.exe -g -lgmp
main.c:3:46: fatal error: gmp.h: No such file or directory
#include <gmp.h>//For files of arbitrary size
I then tried to tell it exactly where the header file was:
i686-w64-mingw32-gcc main.c -o diff.exe -I/usr/include -g -lgmp
/usr/lib/gcc/i686-w64-mingw32/4.9.2/../../../../i686-w64-mingw32/bin/ld: cannot find -lgmp
collect2: error: ld returned 1 exit status
Ok, so I figure now it successfully found the header, but cant find the library. So I tried again:
i686-w64-mingw32-gcc main.c -o diff.exe -I/usr/include -g -L/usr/lib -lgmp
/usr/lib/gcc/i686-w64-mingw32/4.9.2/../../../../i686-w64-mingw32/bin/ld: cannot find -lgmp
collect2: error: ld returned 1 exit status
I guess I need to specify the exact files to use, so I tried this:
i686-w64-mingw32-gcc main.c -o diff.exe -I/usr/include -g /usr/lib/libgmp.so
/usr/lib/libgmp.so: file not recognized: File format not recognized
collect2: error: ld returned 1 exit status
So, I honestly don't know what to do and I'd really really appreciate your help.
First, a disclaimer: the cross-compiler you are using is neither distributed by, nor supported by MinGW.org, whom I represent; if you are looking for a pre-compiled solution, you should seek it from the distributor of the specific cross-compiler itself.
That said, I can offer the following insight, (which will apply, in general, to any cross-compiler): the headers you find in /usr/include, or in /usr/local/include, and the libgmp.so which you find in /usr/lib, or in /usr/local/lib, are intended for use with your native platform compiler. They are not suitable for, and cannot be used with your MinGW cross-compiler; attempting to do so will surely never work. Thus, you have two options:
Ask your cross-compiler distributor to provide a pre-compiled copy of gmp.dll, (or at the very least, a compatible import library, although you may need the gmp.dll to distribute with your own application anyway), and any associated header files, and/or equivalent statically linkable library, for use with your cross-compiler.
Use your cross-compiler to build gmp.dll yourself, then install it, its associated headers, and perhaps also its associated import library and/or equivalent statically linkable library, into the same prefix-path as the cross-compiler itself.

Error "undefined reference" while linking in MinGW

I have got the object-file from source code using MinGW.
But on linking:
ld -o test.exe test.o
I get errors, for example the following:
undefined reference to printf
First, why are you using ld directly?
The following is an excerpt from the "GCC and Make" tutorial found at http://www3.ntu.edu.sg/home/ehchua/programming/cpp/gcc_make.html.
Compile and Link Separately
The above command compile the source file into object file and link with other object files (system library) into executable in one step. You may separate compile and link in two steps as follows:
// Compile-only with -c option
> g++ -c -Wall -g Hello.cpp
// Link object file(s) into an executable
> g++ -g -o Hello.exe Hello.o
Note g++ (you can substitute gcc if you are using C and not C++) is used both for compiling and linking. ld is not used at all.
The benefit of using g++ or gcc to link is that it will link with default libraries, such as the one you need to link with for printf, automatically.
To link with other libraries, you specify the library name with the -l parameter, as in -lmylib.
We can view commands ran by compiler via command
c99 -v test.o
We'll get some text. All after string which contains "COLLECT_CGG_OPTIONS" will be arguments of ld.
But size of executable file is much more then size of file got by previous way.

Linking a C program directly with ld fails with undefined reference to `__libc_csu_fini`

I'm trying to compile a C program under Linux. However, out of curiosity, I'm trying to execute some steps by hand: I use:
the gcc frontend to produce assembler code
then run the GNU assembler to get an object file
and then link it with the C runtime to get a working executable.
Now I'm stuck with the linking part.
The program is a very basic "Hello world":
#include <stdio.h>
int main() {
printf("Hello\n");
return 0;
}
I use the following command to produce the assembly code:
gcc hello.c -S -masm=intel
I'm telling gcc to quit after compiling and dump the assembly code with Intel syntax.
Then I use th GNU assembler to produce the object file:
as -o hello.o hello.s
Then I try using ld to produce the final executable:
ld hello.o /usr/lib/libc.so /usr/lib/crt1.o -o hello
But I keep getting the following error message:
/usr/lib/crt1.o: In function `_start':
(.text+0xc): undefined reference to `__libc_csu_fini'
/usr/lib/crt1.o: In function `_start':
(.text+0x11): undefined reference to `__libc_csu_init'
The symbols __libc_csu_fini/init seem to be a part of glibc, but I can't find them anywhere! I tried linking against libc statically (against /usr/lib/libc.a) with the same result.
What could the problem be?
/usr/lib/libc.so is a linker script which tells the linker to pull in the shared library /lib/libc.so.6, and a non-shared portion, /usr/lib/libc_nonshared.a.
__libc_csu_init and __libc_csu_fini come from /usr/lib/libc_nonshared.a. They're not being found because references to symbols in non-shared libraries need to appear before the archive that defines them on the linker line. In your case, /usr/lib/crt1.o (which references them) appears after /usr/lib/libc.so (which pulls them in), so it doesn't work.
Fixing the order on the link line will get you a bit further, but then you'll probably get a new problem, where __libc_csu_init and __libc_csu_fini (which are now found) can't find _init and _fini. In order to call C library functions, you should also link /usr/lib/crti.o (after crt1.o but before the C library) and /usr/lib/crtn.o (after the C library), which contain initialisation and finalisation code.
Adding those should give you a successfully linked executable. It still won't work, because it uses the dynamically linked C library without specifying what the dynamic linker is. You'll need to tell the linker that as well, with something like -dynamic-linker /lib/ld-linux.so.2 (for 32-bit x86 at least; the name of the standard dynamic linker varies across platforms).
If you do all that (essentially as per Rob's answer), you'll get something that works in simple cases. But you may come across further problems with more complex code, as GCC provides some of its own library routines which may be needed if your code uses certain features. These will be buried somewhere deep inside the GCC installation directories...
You can see what gcc is doing by running it with either the -v option (which will show you the commands it invokes as it runs), or the -### option (which just prints the commands it would run, with all of the arguments quotes, but doesn't actually run anything). The output will be confusing unless you know that it usually invokes ld indirectly via one of its own components, collect2 (which is used to glue in C++ constructor calls at the right point).
I found another post which contained a clue: -dynamic-linker /lib/ld-linux.so.2.
Try this:
$ gcc hello.c -S -masm=intel
$ as -o hello.o hello.s
$ ld -o hello -dynamic-linker /lib/ld-linux.so.2 /usr/lib/crt1.o /usr/lib/crti.o hello.o -lc /usr/lib/crtn.o
$ ./hello
hello, world
$
Assuming that a normal invocation of gcc -o hello hello.c produces a working build, run this command:
gcc --verbose -o hello hello.c
and gcc will tell you how it's linking things. That should give you a good idea of everything that you might need to account for in your link step.
In Ubuntu 14.04 (GCC 4.8), the minimal linking command is:
ld -dynamic-linker /lib64/ld-linux-x86-64.so.2 \
/usr/lib/x86_64-linux-gnu/crt1.o \
/usr/lib/x86_64-linux-gnu/crti.o \
-L/usr/lib/gcc/x86_64-linux-gnu/4.8/ \
-lc -lgcc -lgcc_s \
hello.o \
/usr/lib/x86_64-linux-gnu/crtn.o
Although they may not be necessary, you should also link to -lgcc and -lgcc_s, since GCC may emit calls to functions present in those libraries for operations which your hardware does not implement natively, e.g. long long int operations on 32-bit. See also: Do I really need libgcc?
I had to add:
-L/usr/lib/gcc/x86_64-linux-gnu/4.8/ \
because the default linker script does not include that directory, and that is where libgcc.a was located.
As mentioned by Michael Burr, you can find the paths with gcc -v. More precisely, you need:
gcc -v hello_world.c |& grep 'collect2' | tr ' ' '\n'
This is how I fixed it on ubuntu 11.10:
apt-get remove libc-dev
Say yes to remove all the packages but copy the list to reinstall after.
apt-get install libc-dev
If you're running a 64-bit OS, your glibc(-devel) may be broken. By looking at this and this you can find these 3 possible solutions:
add lib64 to LD_LIBRARY_PATH
use lc_noshared
reinstall glibc-devel
Since you are doing the link process by hand, you are forgetting to link the C run time initializer, or whatever it is called.
To not get into the specifics of where and what you should link for you platform, after getting your intel asm file, use gcc to generate (compile and link) your executable.
simply doing gcc hello.c -o hello should work.
Take it:
$ echo 'main(){puts("ok");}' > hello.c
$ gcc -c hello.c -o hello.o
$ ld hello.o -o hello.exe /usr/lib/crt1.o /usr/lib/crti.o /usr/lib/crtn.o \
-dynamic-linker /lib/ld-linux.so.2 -lc
$ ./hello.exe
ok
Path to /usr/lib/crt*.o will when glibc configured with --prefix=/usr

Resources