I am using Eclipse on Ubuntu to write/compile/run C code.
I am trying to build my project.
Following is the output in the Eclipse console.
22:18:31 **** Build of configuration Debug for project Project1 ****
make all
Building file: ../project1.c
Invoking: GCC C Compiler
gcc -I/lib/i386-linux-gnu -O0 -g3 -Wall -c -fmessage-length=0 -pthread -lm -MMD -MP -MF"project1.d" -MT"project1.d" -o "project1.o" "../project1.c"
../project1.c: In function ‘main’:
../project1.c:146:6: warning: unused variable ‘this_thread_id’ [-Wunused-variable]
../project1.c: In function ‘_pre_init’:
../project1.c:126:1: warning: control reaches end of non-void function [-Wreturn-type]
Finished building: ../project1.c
Building file: ../scheduler.c
Invoking: GCC C Compiler
gcc -I/lib/i386-linux-gnu -O0 -g3 -Wall -c -fmessage-length=0 -pthread -lm -MMD -MP -MF"scheduler.d" -MT"scheduler.d" -o "scheduler.o" "../scheduler.c"
Finished building: ../scheduler.c
Building target: Project1
Invoking: GCC C Linker
gcc -L/lib/i386-linux-gnu -lm -pthread -o "Project1" ./project1.o ./scheduler.o
./project1.o: In function `advance_global_time':
/home/akshay/Cworkspace/Project1/Debug/../project1.c:50: undefined reference to `floor'
collect2: ld returned 1 exit status
make: *** [Project1] Error 1
Can anyone please help me figure out what the problem is and how to solve it?
You need to link libraries after the object files.
You have:
gcc -L/lib/i386-linux-gnu -lm -pthread -o "Project1" ./project1.o ./scheduler.o
You need:
gcc -L/lib/i386-linux-gnu -pthread -o "Project1" ./project1.o ./scheduler.o -lm
There seems to have been a change in the way the linkers work — at some time, it was possible to specify shared libraries (such as the maths library) before the object files, and all would work. However, nowadays, if the shared library doesn't satisfy any symbols when it is scanned, it is omitted from the link process. Ensuring that the object files are listed before the libraries fixes this.
See also Undefined reference to 'pthread_create'; same problem, same solution. And I doubt if that is the only such question in SO.
You need to link against the mathematical library, i.e., add -lm at the end of the link line. No idea how to do that in Eclipse, sorry.
Note, the linking flags in your output look out of order. Perhaps you attempted to add the -lm via the Linker Flags in Eclipse. This causes issues in Eclipse. I suggest you try...
Right click on your project -> properties -> C/C++ Build -> Settings
-> GCC Linker -> Libraies -> add "m" -> Apply -> build
OR, at the very list, make sure that the -L and -l parameters come after your .o files in the Linking process.
I just got hit by this today and it eluded me for a while.
Related
I am having issues linking a library (termbox) when compiling. I get the error:
make: *** No rule to make target `termbox.h', needed by `test.o'. Stop.
Makefile:
edit: test.o
gcc -Wall -o edit test.o
test.o: test.c termbox/src/termbox.h
gcc -Wall -c test.c -ltermbox/src
Include:
#include "termbox/src/termbox.h"
I have also tried using the compiled library but ran into similar issues. Do I have to use some sort of combination of specifying the header file and the location of the compiled library?
The directory of my termbox folder is in the same directory as test.c.
Thanks!
You have managed to compile and include the header file for the library, but you did not yet tell the compiler where the code (definitions) are - i.e. you did not tell it to link in the library yet.
You will need to do that next, this is done in a similar way to telling the linker what files to link, but with some extra syntax. It appears to be a static library (.a suffix) so you can link like this:
test.o: test.c termbox/src/termbox.h
gcc -Wall -c test.c -Itermbox/src -Lsrc -ltermbox
Where -L... specifies where libraries can be found and -l... specifies the library name to link to minus the lib prefix and the .a or .so suffix. Also note that order is important, so leave the library linkage at the end.
More on library linking order here
UPDATE
Sorry I added the linking to the wrong line! - here is the updated answer:
# The linker stage
edit: test.o
gcc -Wall -o edit test.o -Lsrc -ltermbox
# Compile stage
test.o: test.c termbox/src/termbox.h
gcc -Wall -c test.c -ltermbox/src
I do not know gcc and c well. In my /home/pi/Desktop/intern/adis16227_generic directory I have following 5 files.
ADIS16227.c
ADIS16227.h
Communication.c
Communication.h
main.c
main.c
#include<stdio.h>
#include "Communication.h" // Communication definitions.
int main() {
printf("hello!!\n");
unsigned char status = 0;
status = SPI_Init(0, 1000000, 1, 1);
printf("%u", status);
return 0;
}
Run command:
$ sudo gcc -L /home/pi/Desktop/intern/adis16227_generic main.c -lCommunication
Error:
/usr/bin/ld: cannot find -lCommunication
collect2: error: ld returned 1 exit status
Question:
What I am missing here?
What do I need to run the code?
-l is for libraries, and you never built a library from your Communication.c. The simplest solution is just add Communication.c to your compiler command line.
For larger projects, compile each translation unit separately with the -c switch like this:
gcc -c -Wall -Wextra -pedantic -omain.o main.c
gcc -c -Wall -Wextra -pedantic -oCommunication.o Communication.c
and so on ... (as a suggestion, I added some common warning options here, they help you spot errors)
The resulting .o files are object code. That's already compiled machine code, but with meta-information needed for a linker to link it with other object code into a complete executable.
Then link them all with one command:
gcc -oprogram main.o Communication.o
If you actually want a library from -- say -- Communication.c and ADIS16227.c, you could compile both to object code:
gcc -c -Wall -Wextra -pedantic -oCommunication.o Communication.c
gcc -c -Wall -Wextra -pedantic --oADIS16227.o ADIS16227.c
and then use ar to create a static library from them:
ar rcs libCommunication.a Communication.o ADIS16227.o
Then your initial compiler command would work (with the -lCommunication switch).
Final piece of advice: Never compile as root. This is completely unnecessary. So remove your sudo here.
those options:
-L /home/pi/Desktop/intern/adis16227_generic -lCommunication
suggest that the linker should find libCommunication.a (or .so) in the /home/pi/Desktop/intern/adis16227_generic directory.
But there are only sources in this directory. The linker won't build the sources of your "Communication" library for you.
So you could build the library and link with it:
gcc -c ADIS16227.c Communication.c
ar r libCommunication.a ADIS16227.o Communication.o
but maybe the fastest & quickest way to achieve a successful build would be:
sudo gcc -o main *.c
so it compiles all the files of the directory into the executable called main
Of course, it makes compilation times longer, but maybe it's not noticeable.
First move into the /home/pi/Desktop/intern/adis16227_generic directory:
cd /home/pi/Desktop/intern/adis16227_generic
Then, compile the source:
gcc ADIS16227.c Communication.c main.c -I .
You can now run your compiled program (called by default a.out):
./a.out
You have to compile separatedly files and then compile main with related obj file.
gcc -c Communication.c Communication.h
gcc main.c Communication.o -o main
I'm trying to compile and link some .c file. I have been using Eclipse IDE for C/C++ developers, and in my local machine i can compile without problems. However, when i try to compile and link the same file in a RedHat OS (gcc version is 4.9.2-6 in this OS) i'm having problems. I get some warnings at compile time, but those are fine, i think, i just ignored and the application still runs fine. Here are the commands i executed and the associated output:
gcc -O0 -g3 -Wall -c -fmessage-length=0 -std=c99 -MMD -MP -MF"example.d" -MT"example.d" -o "example.o" "example.c"
warning: suggest parentheses around assignment used as truth value [-Wparentheses]
warning: implicit declaration of function ‘wait’ [-Wimplicit-function-declaration]
This generates two files, example.d and example.o. Then, i try to link them, without luck, with the following command:
gcc -Xlinker -L/usr/lib -lrt -static -pthread example.o -o example
/usr/bin/ld: cannot find -lrt
/usr/bin/ld: cannot find -lpthread
/usr/bin/ld: cannot find -lc
collect2: error: ld returned 1 exit status
The commands are taken directly from the ones that Eclipse generates, and work just fine in my local computer (Ubuntu OS) but not in the RedHat environment. The last command didn't work, with and without the -L option. I suppose the directory in -L is fine, as i run, for example,
locate libpthread.so
And one of the locations i get is /usr/lib (also /usr/lib64, but neither work).
Any help will be greatly appreciated!! :)
If you try to link a static executable, it will look for the *.a versions of the libraries, not what you usually want. Remove the -static flag. Or you can install the static libraries if you really want to. It also should not be necessary to add -L/usr/lib explicitly.
I am trying to compile a C++ project (openFrameworks + CodeBlocks), using an external C library. I get "undefined reference" error, although I succesfully compile and use the library elsewhere.
The code consists of sources main.cpp, testApp.cpp and header files, including one for my library "myprocessing". When I make , the code is compiled and dies at linking with error
obj/i686Release/./src/testApp.o: In function `testApp::update()':
testApp.cpp:(.text+0x261): undefined reference to `gauss_5(datarect_t)'
collect2: ld returned 1 exit status
make: *** [bin/faceGrabber] Error 1
where gauss_5 is my library function, and it is called in testApp.cpp (header with declarations is included there).
Below I paste the make commands used to compile the code, generated by CodeBlocks (I strip it for clarity)
# compiling object for: ./src/testApp.cpp
g++ -c -g [some -I...] -DOF_USING_GTK -DOF_USING_MPG123 -Wall
-fexceptions -I. -Ilib/ -MMD -MP -MFobj/i686Debug/./src/testApp.d
-MTobj/i686Debug/./src/testApp.d -oobj/i686Debug/./src/testApp.o
-c ./src/testApp.cpp
# compiling object for: ./src/main.cpp
g++ -c -g -pthread [some -I...] -DOF_USING_GTK -DOF_USING_MPG123
-Wall -fexceptions -I. -Ilib/ -MMD -MP -MFobj/i686Debug/./src/main.d
-MTobj/i686Debug/./src/main.d -oobj/i686Debug/./src/main.o
-c ./src/main.cpp
# linking bin/faceGrabber_debug . ./src ./lib
g++ -o bin/faceGrabber_debug obj/i686Debug/./src/testApp.o
obj/i686Debug/./src/main.o -Wl,-rpath=./libs -Llib/ -lz
-lmyprocessing [some libs...]
Note that my library is referenced (-lmyprocessing) in the last, linking step. So, all the headers and libraries are found by the compiler, but somehow they are not compiled-in.
I tried both .a static and .so dynamic files for myprocessing, unsuccessfully. As I mentioned, I use the same library in other project (outside openFrameworks and CodeBlocks) and it works.
You say that the library is written in C. However, the fact that the linker is able to print out the type of the argument to gauss_5() suggests that it's working with the mangled, C++ name of the function.
I suspect you might be missing extern "C" { ... } guards around your C header.
I find a problem in the linking process of my application. I did not have the same with gcc 4.5. It tries to link math library with the following command.
gcc -Wall -Wno-unused -MD -o mems_seektest mems_seektest.o -lm -L. -g -DASSERTS -I../src// -I../ -I../src//src -DDEBUG -lmems_internals
and report following error massages:
undefined reference to `sqrt'
Any idea ?
recent gcc/ld uses the --as-needed linker flag as default. Practically, that means libraries have to be specified in the reverse order of dependencies on the command line. If the mems_internals library needs the sqrt function your -lm after -lmems_internals.
gcc -Wall -Wno-unused -MD -o mems_seektest mems_seektest.o -L. -g -DASSERTS -I../src// -I../ -I../src//src -DDEBUG -lmems_internals -lm
I've had the same problem with gcc 4.6.1, even with only one library. This doesn't work:
$ gcc -lm eg.o -o eg
eg.o: In function `foo':
/home/nick/tmp/eg.c:5: undefined reference to `sqrt'
collect2: ld returned 1 exit status
But this does:
$ gcc eg.o -o eg -lm
I hit this because I was using "LDFLAGS=-lm" in my Makefile. Works fine if you use "LDLIBS=-lm" instead.
You didn't tell us what -lmems_internals is, but maybe the unresolved symbol comes from there. The order of the -l options is generally important to the linker, you should always put system libraries last.
You can check where the unresolved symbol comes from by using something like
nm yourLibrary | grep sqrt
if there is a U in front of sqrt the symbol is undefined.
I'd say the linker is using the wrong libm.