Trying to use sleep() to pause my program briefly.
Except when I "make" I get an undefined reference to sleep, even though I #include <unistd.h> at the top.
In function `main':
[...]/source/ball.c:232: undefined reference to `sleep'
[...]/source/ball.c:240: undefined reference to `sleep'
collect2: error: ld returned 1 exit status
I'm using linux.
Any suggestions?
Thanks
EDIT: This Is not a duplicate question because every other time this question has been asked, the user was running it on Windows. The solution. for me, is not simply to include the windows header.
EDIT(2): The link to that other question does not help me. That's why I made a new post. I'm not on windows!!
This is a linker error, not a compiler error (you can see that from the "ld returned 1 exit status" part - ld is the linker). So sleep is declared in the header, which compiles fine, but you need to ensure you include the correct library/binary file for the linking stage.
I can roughly replicate the reported behavior with the following program:
#include <unistd.h>
int main (void) {
sleep(1);
return 0;
}
void _start (void) {
asm("call main;"
"mov %eax,%ebx;"
"movl $1,%eax;"
"int $0x80;");
}
But, it must be compiled with -nostdlib. From this TIO example, I get:
/tmp/ccfjKQV4.o: In function `main':
.code.tio.c:(.text+0xa): undefined reference to `sleep'
collect2: error: ld returned 1 exit status
Which pretty closely matches the output you are reporting. To fix this, you need to provide libc when linking the program. This can be accomplished by adding -lc, as demonstrated at this TIO example. But, if you are using -nostdlib, this solution may not be viable (more on that later).
_start
The sample program I provided is an example of how to create an x86 linux program that will call main and then call exit without needing to use the C runtime. Without the standard C runtime, linux will attempt to jump to a routine called _start. Since there is no C library, exit is called via assembly.
-nostdlib
The -nostdlib option is telling the compiler to not include the standard C runtime and C libraries when building the executable. This is sometimes used in embedded software development where the embedded platform has its own runtime. If this software is intended to run on an embedded platform, it may be erroneous to include -lc to the link line, since it may cause interference with embedded system's library. In that case, you may need to implement your own version of sleep or find a different way to pause your program.
Related
I am a C beginner so I tried to hack around the stuff.
I read stdio.h and I found this line:
extern int printf (const char *__restrict __format, ...);
So I wrote this code and i have no idea why it works.
code:
extern int printf (const char *__restrict __format, ...);
main()
{
printf("Hello, World!\n");
}
output:
sh-5.1$ ./a.out
Hello, World!
sh-5.1$
Where did GCC find the function printf? It also works with other compilers.
I am a beginner in C and I find this very strange.
gcc will link your program, by default, with the c library libc which implements printf:
$ ldd ./a.out
linux-vdso.so.1 (0x00007ffd5d7d3000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fdf2d307000)
/lib64/ld-linux-x86-64.so.2 (0x00007fdf2d4f0000)
$ nm -D /lib/x86_64-linux-gnu/libc.so.6 | grep ' printf' | head -1
0000000000056cf0 T printf##GLIBC_2.2.5
If you build your program with -nolibc you have to satisfy a few symbols on your own (see
Compiling without libc):
$ gcc -nolibc ./1.c
/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/10/../../../x86_64-linux-gnu/Scrt1.o: in function `_start':
(.text+0x12): undefined reference to `__libc_csu_fini'
/usr/bin/ld: (.text+0x19): undefined reference to `__libc_csu_init'
/usr/bin/ld: (.text+0x26): undefined reference to `__libc_start_main'
/usr/bin/ld: /tmp/user/1000/ccCFGFhf.o: in function `main':
1.c:(.text+0xc): undefined reference to `puts'
collect2: error: ld returned 1 exit status
You need to understand the difference between the compile and link phases of program compilation.
In the compilation phase you describe to the compiler the various things you intend to call that may be in this file, in other files or in libraries. This is done using function declarations.
int woodle(char*);
for example. This is what header files are full of.
If the function is in the same file then the compiler will work out how to call it while it compiles that file. But for other functions it leaves a note in the generated code that says
please wire up the woodle function here so I can call it.
Usually called an import and there are tools you can use to look at the imports in an object file - name depends on platform and toolset
The linkers job is to find those imports and resolve them. It will look at objects files passed on the command line, at libraries included on the command line and also standard libraries that the c standard says should be available to all programs.
In your printf case the linker found printf in the c standard library that the linker includes automatically.
BTW - the linker looks for 'exports' from objects and libraries, there are tools to look at those too. The linkers job is to match each 'import' to an 'export'
First, realize what the gcc program is. Technically, it is not a compiler, but a compiler driver. A compiler driver is responsible for driving the various other tools which perform compilation-related tasks. Some of the tools are found in PATH, whereas others are in internal compiler directories.
There are various ways to check what the driver is doing. I won't go into much detail about how I made the rest of this post, but briefly:
strace -f -e %process gcc is a Linux-specific way of showing all the programs executed (elsewhere in this answer, I assume Linux when specifying details but it doesn't matter)
gcc -v will dump out various information, but you have to learn what parts actually matter for whatever you are doing.
there exists a "specs" file that controls some of the argument-related stuff the driver does
Now for the actual data:
Here's the tree of processes that gcc might execute:
gcc, the "driver" (input various, output various. Some arguments are handled by the driver itself, but most are passed to the various subprocesses)
(these are repeated for every input file. If -pipe is passed, temporary files are omitted and processes are run in parallel; if --save-temps is passed, intermediate files are preserved):
cc1 -E -lang-asm, the "preprocessor" for assembly code (input .S, output .s - yes, case matters. Only relevant if you're trying to compile separate ASM files that need preprocessing)
cc1 -E, the "preprocessor" for C code (input .c; output .i. Only a separate process if -fno-integrated-cpp is passed, which is rare. Note that the cpp program in PATH is never called, even though it is provided by GCC - rather, it calls this. If -E is passed, the driver stops after this)
cc1, the "compiler" proper (input (usually) .c or (rarely) .i; output .s. If -S is passed, the driver stops after this; if -fsyntax-only is passed, this stage doesn't even complete)
(For other languages, replace cc1 with cc1plus, cc1d, cc1obj, f951, gnat1, etc. Note that the different drivers like g++, gdc, etc. only affect what extra libraries are linked by default)
as, the "assembler" (input .s; output .o. This is looked up in PATH; it is shipped as part of Binutils, not GCC. If -c is passed, the driver stops here)
collect2, the "linker" wrapper (supposedly this has something to do with constructors, and potentially calls ld twice, but in practice I've never seen it. Just think of it as forwarding all its arguments to ld, even if you have constructors normally)
ld, the "linker" proper (input .o or others (assumed to be libraries); output executable or shared library. Like as, this is actually part of Binutils, not GCC, so it is looked up in PATH)
The driver has a lot of logic, so it is important that you use it. Notably, you should never call as or ld yourself, since that will omit arguments that rely on the driver's sense of "exact current platform".
Now, getting to your specific question:
Ignoring irrevelant arguments and simplifying paths, the ld call ends up looking like:
ld -o foo Scrt1.o crti.o crtbeginS.o foo.o -lgcc -lgcc_s -lc -lgcc -lgcc_s crtendS.o crtn.o
The various "crt" loose object files are a mixture of parts of GLIBC and GCC, needed to support the C runtime (note that there are others as well; which are linked depends on arguments). The gcc and gcc_s libraries are needed to run code on the platform at all; they are repeated because they rely on the c library which also relies on them.
Since -lc is passed by default (regardless of language), the printf symbol can be resolved. Notably, -lm, -lrt, -lpthread and others are not passed by default, so other symbols from differents parts of the C library will not be resolved unless you pass them manually.
All of this is completely independent of what headers are included.
That your program compiles without a header present means that the compiler settings were lenient. You should still get a warning though. The reason that your program links is that the C standard library, which contains the code of the function printf, is linked automatically. Almost every C program needs it because input and output, or generally interaction with peripherals, which that library handles, are the general means of generating a "side effect", an effect outside the program. The opposite is so uncommon that one must make the wish to not link with it explicit.
So why does your compiler accept a call to a function which has not been declared?
C emerged at a time when programs were much smaller and software development as an engineering discipline didn't formally exist:
Four years later [i.e., in 1978], as a still-junior faculty member, I tried to get my colleagues [...] to create an undergraduate computer-science degree. A senior mechanical engineer of forbidding mien snorted surely not: Harvard had never offered a degree in automotive science, why would we create one in computer science? I waited until I had tenure before trying again (and succeeding) in 1982. -Harry R. Lewis
That was about 10 years after Denis Ritchie had started to develop this versatile new programming language, the successor to B. The problems involved in creating and maintaining large programs back then were simply not as pressing and not as well-understood as they are, perhaps, today.
Among the many things that help us today, at least in most compiled languages, is strong typing. Every identifier we use is declared with a static type. But the importance and benefits of that were not that obvious in the 1970s, and early C permitted mixing and matching integers and pointers at will. It's all numbers, right? And a function is just a name for a jump address, right? The user will know what to put on the stack, and the function will read it off the stack — I really don't see a problem here ;-). This attitude brought us functions like printf().
After this stage-setting we are slowly getting to the point. Because a function is just a jump address, no function declaration needed to be present in order to to call one. The assumed parameters were what you presented, and the presumed return type defaulted to int, which was often correct or at least didn't hurt. And for a long time C kept this backward compatibility. I think the C99 standard forbid the use of undeclared identifiers, and the standard drafts for C11 and C21 both say:
An identifier is a primary expression, provided it has been declared as designating an object (in which case it is an lvalue) or a function (in which case it is a function designator)91
Footnote 91 says "Thus, an undeclared identifier is a violation of the syntax." (All emphasis by me.)
All compilers I tried compile it anyway (with a warning), perhaps because some ancient code that still gets compiled frequently depends on it.
Whenever I include math.h to my c code I can't compile without the -lm option. I get this error message:
d.o: In function `refresh_position':
d.c:(.text+0x4df): undefined reference to `sqrt'
d.c:(.text+0x524): undefined reference to `sqrt'
collect2: error: ld returned 1 exit status
I can compile it with just typing -lm but my teacher says that if code doesn't work i will get 0 point from that homework. I want to know is this error occurs because of my code or because of my computer or c library. I have to be sure about it will run without any error on my teachers computer.
Some implementations such as gcc do not link the math library (called libm.a on most *nix implementations) by default, which is why you need to include the -lm when building the code.
Your teacher should be aware of issues like this, and as long as your code is using sqrt and other math routines correctly (using the right type for the inputs and output), he or she should be able to build your code such that it will run.
When a C program is compiled it under goes in the order of pre-processor,compiler,assembler,linker.
One of the main tasks for linker is to make code of library functions available to your program.
Linker can link them in two ways static or dynamically..
stdio.h contains only declarations,no definitions are present in it.
we only include stdio.h in program to say compiler about the return type and name of functions eg(printf(),scanf(),getc(),putc()...)..
Then how printf() and scanf() are linked in the example program below?
If it is linking dynamically which "DLL" is responsible in linking??
Is total "C" Library is linked dynamically to program??
#include "stdio.h"
int main()
{
int n;
printf("Enter an integer\n");
scanf("%d", &n);
if (n%2 == 0)
printf("Even\n");
else
printf("Odd\n");
return 0;
}
I think the question you are trying to ask is: “I know that functions like printf and scanf are implemented by the C runtime library. But I can use them without telling my compiler and/or IDE to link my program with the C runtime library. Why don’t I need to do that?”
The answer to that question is: “Programs that don’t need to be linked with the C runtime library are very, very rare. Even if you don’t explicitly use any library functions, you will still need the startup code, and the compiler might issue calls to memcpy, floating-point emulation functions, and so on ‘under the hood.’ Therefore, as a convenience, the compiler automatically links your program with the C runtime library, unless you tell it to not do that.”
You will have to consult the documentation for your compiler to learn how to tell it not to link in the C runtime library. GCC uses the -nostdlib command-line option. Below, I demonstrate the hoops you have to jump through to make that work...
$ cat > test.c
#include <stdio.h>
int main(void) { puts("hello world"); return 0; }
^D
$ gcc -nostdlib test.c && { ./a.out; echo $?; }
/usr/bin/ld: warning: cannot find entry symbol _start
/tmp/cc8svIx5.o: In function ‘main’:
test.c:(.text+0xa): undefined reference to ‘puts’
collect2: error: ld returned 1 exit status
puts is obviously in the C library, but so is this mysterious "entry symbol _start". Turn off the C library and you have to provide that yourself, too...
$ cat > test.c
int _start(void) { return 0; }
^D
$ gcc -nostdlib test.c && { ./a.out; echo $?; }
Segmentation fault
139
It links now, but we get a segmentation fault, because _start has nowhere to return to! The operating system expects it to call _exit. OK, let's do that...
$ cat > test.c
extern void _exit(int);
void _start(void) { _exit(0); }
^D
$ gcc -nostdlib test.c && { ./a.out; echo $?; }
/tmp/ccuDrMQ9.o: In function `_start':
test.c:(.text+0xa): undefined reference to `_exit'
collect2: error: ld returned 1 exit status
... nuts, _exit is a function in the C runtime library, too! Raw system call time...
$ cat > test.c
#include <unistd.h>
#include <sys/syscall.h>
void _start(void) { syscall(SYS_exit, 0); }
^D
$ gcc -nostdlib test.c && { ./a.out; echo $?; }
/tmp/cchtZnbP.o: In function `_start':
test.c:(.text+0x14): undefined reference to `syscall'
collect2: error: ld returned 1 exit status
... nope, syscall is also a function in the C runtime. I guess we just have to use assembly!
$ cat > test.S
#include <sys/syscall.h>
.text
.globl _start
.type _start, #function
_start:
movq $SYS_exit, %rax
movq $0, %rdi
syscall
$ gcc -nostdlib test.S && { ./a.out; echo $?; }
0
And that, finally, works. On my computer. It wouldn't work on a different operating system, with a different assembly-level convention for system calls.
You might now be wondering what the heck -nostdlib is even good for, if you have to drop down to assembly language just to make system calls. It's intended to be used when compiling completely self-contained, low-level system programs like the bootloader, the kernel, and (parts of) the C runtime itself — things that were going to have to implement their own everything anyway.
If we had it to do all over again from scratch, it might well make sense to separate out a low-level language-independent runtime, with just the syscall wrappers, language-independent process startup code, and the functions that any language's compiler might need to call "under the hood" (memcpy, _Unwind_RaiseException, __muldi3, that sort of thing). The problem with that idea is it rapidly suffers mission creep — do you include errno? Generic threading primitives? (Which ones, with which semantics?) The dynamic linker? An implementation of malloc, which several of the above things need? Windows's ntdll.dll began as this concept, and it's 1.8MB on disk in Windows 10, which is (slightly) bigger than libc.so + ld.so on my Linux partition. And it's rare and difficult to write a program that only uses ntdll.dll, even if you're Microsoft (the only example I'm sure of is csrss.exe, which might as well be a kernel component).
Generally, standard C libraries are linked dynamically. This is mainly because of the reasons that once a program has been statically linked, the code in it is fixed forever. If someone finds and fixes a bug in printf or scanf, then every program has to be linked again in order to pick up the fixed code.
In case of dynamic linking, none of the executable files (created after linking) contains a copy of the code for printf or scanf. If a new, fixed, version of printf is available, then it is picked up at run time.
-static-libstdc++
When the g++ program is used to link a C++ program, it normally
automatically links against libstdc++. If libstdc++ is available as a
shared library, and the -static option is not used, then this links
against the shared version of libstdc++. That is normally fine.
However, it is sometimes useful to freeze the version of libstdc++
used by the program without going all the way to a fully static link.
The -static-libstdc++ option directs the g++ driver to link libstdc++
statically, without necessarily linking other libraries statically.
For more details, please check this thread.
How can i statically link standard library to my c++ program?
They are linked statically, that way your program will be able to determine if there are any compilation errors before preceding to run the program.
I am trying to compile a hello world program in C on a Linux 64-bit machine. I am using an ARM cross compiler to load my application onto an ARM processor. However, when compiling the code using arm-none-eabi-gcc -o hello hello.c I get a series of errors:
/home/dico/gcc-arm-none-eabi-4_7-2013q3/bin/../lib/gcc/arm-none-eabi/4.7.4/../../../../arm-none-eabi/lib/libc.a(lib_a-exit.o): In function exit':
exit.c:(.text.exit+0x2c): undefined reference to_exit'
/home/dico/gcc-arm-none-eabi-4_7-2013q3/bin/../lib/gcc/arm-none-eabi/4.7.4/../../../../arm-none-eabi/lib/libc.a(lib_a-sbrkr.o): In function _sbrk_r':
sbrkr.c:(.text._sbrk_r+0x18): undefined reference to_sbrk'
/home/dico/gcc-arm-none-eabi-4_7-2013q3/bin/../lib/gcc/arm-none-eabi/4.7.4/../../../../arm-none-eabi/lib/libc.a(lib_a-writer.o): In function _write_r':
writer.c:(.text._write_r+0x20): undefined reference to_write'
/home/dico/gcc-arm-none-eabi-4_7-2013q3/bin/../lib/gcc/arm-none-eabi/4.7.4/../../../../arm-none-eabi/lib/libc.a(lib_a-closer.o): In function _close_r':
closer.c:(.text._close_r+0x18): undefined reference to_close'
/home/dico/gcc-arm-none-eabi-4_7-2013q3/bin/../lib/gcc/arm-none-eabi/4.7.4/../../../../arm-none-eabi/lib/libc.a(lib_a-fstatr.o): In function _fstat_r':
fstatr.c:(.text._fstat_r+0x1c): undefined reference to_fstat'
/home/dico/gcc-arm-none-eabi-4_7-2013q3/bin/../lib/gcc/arm-none-eabi/4.7.4/../../../../arm-none-eabi/lib/libc.a(lib_a-isattyr.o): In function _isatty_r':
isattyr.c:(.text._isatty_r+0x18): undefined reference to_isatty'
/home/dico/gcc-arm-none-eabi-4_7-2013q3/bin/../lib/gcc/arm-none-eabi/4.7.4/../../../../arm-none-eabi/lib/libc.a(lib_a-lseekr.o): In function _lseek_r':
lseekr.c:(.text._lseek_r+0x20): undefined reference to_lseek'
/home/dico/gcc-arm-none-eabi-4_7-2013q3/bin/../lib/gcc/arm-none-eabi/4.7.4/../../../../arm-none-eabi/lib/libc.a(lib_a-readr.o): In function _read_r':
readr.c:(.text._read_r+0x20): undefined reference to_read'
collect2: error: ld returned 1 exit status
When I try compiling by doing: arm-none-eabi-gcc -c hello.c, it creates an object code hello.o which tells me that the compiler runs fine.
Could someone perhaps tell me why my compilation is return such errors please?
UPDATE
I realize now that the C runtime library isn't included in the compilation. Does anyone know of any options I need to include in the compilation or how to link the library to be able to use standard functions such as printf for example?
What should the MCU chip do with a printf string since there is no console? That's what is happening. libc needs low level functions that is platform dependent and shall not be included in the libc.
You need a retarget.c or a syscalls.c file that defines all these missing symbols and properly retarget the printf output to a serial line that you have access from the outside of the chip.
I strongly recommend you to use the yagarto toolkit, they provide a syscall.c file with what's necessary to build a project when linking against libc, as you are doing.
If you want to try the short path, include the syscall.c file to your project and reprogram its functions internals to suit your needs.
Linking bare gcc toolchain against libc in the microcontroller world is not for beginners. My recommendation is always to follow step by step yagarto's tutorials.
So, I have TVZLib.h, TVZlib.dll, and TVZlib.lib, and I am using gcc to compile the following program (it's a simple test case). The complier gives me the error:
"undefined reference to '_imp__TVZGetNavigationMatrix'"
Yet. when I comple the program with a different type of parameter for the function's call, it complains that it's not the correct parameter (requires *float). To me, that means that it at least has found the function, as it knows what it wants.
From my research, I can tell that people think it's to do with the linking of the library, or the order in which I link, but I've tried all of the gcc commands in all combinations, and all give me the same error, so I'm desperate for some help.
#include <stdlib.h>
#include <stdio.h>
#include "TVZLib.h"
int main() {
float floatie = 2;
float *ptr = &floatie;
TVZGetNavigationMatrix(ptr);
getchar();
return 0;
}
Thanks a lot in advance!
My compiler command:
gcc dlltest.c -L. TVZLib.lib
The header file (TVZLib.h).
And the direct output:
C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\ccuDpoiE.o:dlltest.c:(.text+0x2c): undefined reference to `_imp__TVZGetNavigationMatrix'
collect2: ld returned 1 exit status
It's been a while since I've been compiling natively on Windows...
Did you intend to link statically against TVZlib.lib? That's not happening.
By default, gcc will pick the dynamic version of a library if it finds both a static and a dynamic lib. If you want to force gcc to link statically, you can use the -static option.
If memory serves me right the _imp__ prefix is a sign that a DLL was loaded (_imp__ symbol prefix is used for the trampoline function that calls into the DLL).