GCC Linux C - Compile object header not found - c

I've been working on a module in C (under Linux) that requires another module (headers are in other directories).
My problem is that when I compile the code with my Makefile, the gcc compiler tells me that some headers aren't found.
gcc -c render.c
So I include the directories to find the header but here, gcc tries to find the "main" function which does not exist: it is a module...
gcc /opt/vc/include -c render.c
So I would like to know how is it possible to compile a module (output in module.o) that requires other modules?
Here are my files:
render.c:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "render.h"
int width,height;
int loop,counter;
int initRender(void(*setup)(void),void(*draw)(void),void(*end)(void))
{
init(&width, &height);
loop = -1;
counter = 0;
setup();
while(loop==-1)
{
Start(width, height);
draw();
End();
counter++;
}
end();
finish();
exit(0);
return 0;
}
render.h:
#include "VG/openvg.h"
#include "VG/vgu.h"
#include "fontinfo.h"
#include "shapes.h"
#ifndef RENDER_H_
#define RENDER_H_
extern int width,height;
extern int loop,counter;
int initRender(void(*setup)(void),void(*draw)(void),void(*end)(void));
#endif
Makefile:
INCLUDEFLAGS=-I/opt/vc/include -I/opt/vc/include/interface/vmcs_host/linux -I/opt/vc/include/interface/vcos/pthreads -IopenVG
LIBFLAGS=-L/opt/vc/lib -lGLESv2 -lEGL -lbcm_host -lpthread -ljpeg -LopenVG
NEEDED= openVG/libshapes.o openVG/oglinit.o
all: render
render.o: render.c
gcc -Wall -g $(INCLUDEFLAGS) -c render.c

You probably want
gcc -Wall -g -I/opt/vc/include -c render.c
this will produce a render.o object file.
Please take time to read the documentation about invoking GCC. In particular, check what every option -Wall, -g, -I and -c means. IMHO the first two are very important.
Later, you probably want to link all your object files into an executable, with some external libraries. Perhaps you want something like
gcc -g -Wall -L/opt/vc/lib render.o main.o -lvc -o myprogram
(you really want the -Wall and -g options; IMHO you need to be an expert to dare avoiding them; once you have debugged your program and want to benchmark it, add -O2 for optimizations)
But surely, you want other options.
Notice that order of arguments to gcc matters a lot
Of course, you should learn about GNU make and you need to use it. See this and that examples. You might use make --trace (with recent make) or remake to debug your Makefile (which is not good). You should also run once make -p to understand more the builtin rules of make.
Perhaps you want a library, then read the Program Library HowTo.

Related

Undefined reference to functions included by a lib

I have one lib which contains a file (called Util.c down here), and i'm trying to use some funtions defined in this file to compile a little prog. I'm already using others functions from the lib, but the ones of this particular file always give me back an "Undefined Reference". What's really weird is: the others functions from the lib does use functions from Util.c, and that's working well. It's just that...i can't use them directly.
I'll try to give you a clear view of the things here:
Util.c
void foo (void *var){
print ("in Foo!");
}
void *bar (int var){
print ("in bar!");
}
Util.h:
#ifndef UTIL_DEFINED
#define UTIL_DEFINED
void foo(void *var)
void *bar(int var)
#endif
libobj.c:
#include "Util.c"
// #include "a lot of other files.c"
MyFile.c:
#include "Util.h"
// #include "others headers from the lib which functions are working well"
int main(){
//here i use the lib's function without a prob, except for the ones coming from Util.c, namely foo and bar. For example:
int *var;
//Say that LibFunc is another function from the lib, but not from Util.c.
//Libfunc make a call to foo, and it's working well.
Libfunc(var);
//However, here i try to use foo or bar, and i get the undefined reference!
foo(var);
bar(var);
}
The Makefile is a big thing, but if i search only for the parts related to the lib, it looks like it:
Lib Makefile
default: $(LIB)
$(LIB): $(LIBOBJ)
-$(RM) "$#"
$(DLLD) -o "$#" $(DLLDFLAGS) "$(LIBOBJ)"
$(LIBOBJ): libobj.c $(LIBSRC) $(LIBINC)
$(CC) -c $(LOTOFFLAGS) libobj.c -o "$#"
LIBSRC: libobj.c\
aBunchOfOtherFiles.c
LIBINC: Util.h\
ABunchOfHeadersFiles.h
LIBOBJ=$(LIBNAME)dll.o
LIB=$(LIBNAME).dll
CC= gcc
DLLD = gcc -shared -fprofile-arcs -ftest-coverage -fprofile-generate
DLLDFLAGS = -fPIC
LOTOFFLAGS = -Wall -pedantic -Wno-long-long -Wno-unused-function -g -g3 -ggdb -std=c99 --coverage -fprofile-arcs -ftests-coverage -fprofile-generate -Wl,--allow-multiple-definition -fPIC $(IFLAGS)
#IFLAGS include all headers files, as well as some info concerning Lib version, OS, PROC, etc... not so important here.
IFLAGS = -I$(FOLDERS) -DWINDOWS
FOLDERS= MyFolders
LIBNAME = MyLibName
RM= del
And finally, my makefile looks like it:
My Makefile
default: $(PROG_EXE)
$(PROG_EXE) : $(LIB) $(PROG_OBJ)
$(CC) $(SOMEFLAGS) $(PROG_OBJ) "$(LIB)" -o "$#"
$(PROG_OBJ) : MyFile.c $(LIBINC)
$(CC) -c $(SOMEFLAGS) -$(IFLAGS) MyFile.c -o "$#"
LIB = $(LIBNAME).dll
LIBINC = Util.h\
ABunchOfHeadersFiles.h
PROG_EXE= MyProg
PROG_OBJ = MyProg.o
CC= gcc
SOMFLAGS = -Wall -std=c99 -pedantic -g -g3 - ggb -fprofile-arcs -ftests-coverage
#IFLAGS basically include all folders containing source code and headers. Also gives some D, such as OS, PROC or the lib version. Not really important for my prob.
IFLAGS = -I$(FOLDERS) -DWINDOWS
FOLDERS = MyFolders
LIBNAME = MyLibName
Note that i didn't made any of that. I'm just supposed to make it works...
I've tried to get all the flags (think i got them all). Some of them are only for the use of gcov, others just to include the good folders and files. I've already checked: Util.c and Util.h are correctly included in thoses. BTW, when i compil MyProg, i don't have the "file not found" error on Util.h, so it is found.
Also, i've seen that foo is supposed to get a void* and is actually given a int*. But i don't think it's the problem here, since when i compile MyProg using directly Util.c, without trying to get it from the lib, it works well.
So i really think that, somehow, my prog can't find the functions in the lib. But it does found the header well, and it does found others functions from the lib well, and those functions use the ones froms Util.c, so i just don't get it :'(
Plus, i've tried to compile the lib WITHOUT Util.c, just to be sure that the lib really uses it. Then i got the same "undefined reference", so it seems that the lib correctly includes Util.c
PS: i'm on windows 32bits, if that is of any use...
I think the mistake comes from libobj.c file:
#include Util.c
The quotation marks are missing:
#include "Util.c"
In General we #include the .h and not the .c.
I've found a way to make it works, even if i still can't understand the problem.
It seems that, in Windows using Mingw, you have to add __declspec( dllexport ) in front of each function you wanna use from outside of the dll.
So, if i change my Util.c this way:
`__declspec( dllexport ) void foo (void *var){
print ("in Foo!");
}
`__declspec( dllexport ) void *bar (int var){
print ("in bar!");
}
I think this lib is somehow set so that it has "publics" and "privates" functions; until now i was just using the public ones, and the ones inside Util.c are private. It's the only explanation i see, even if i had no idea how to makes function privates or public.

GCC link against .so file without souce code

I am trying to compile compile a simple "hello world" program for an Axis A210 (cris architecture). I managed to get download GCC from the vendor, but it came with glibc, and the camera is running uClibc-0.9.27. I pulled the file /lib/libuClibc-0.9.27.so from the device.
I managed to compile this program that segfaults:
#include <unistd.h>
int main(int argc, char** argv)
{
*((unsigned int*)0) = 0xDEAD;
}
and this program that just hangs:
#include <unistd.h>
int main(int argc, char** argv)
{
int a = 0;
}
with cris-gcc -g -static -nostdlib -o compiled main.c.
Now I'd like to use the functions in libuClibc, but I can't seem to get the linking to work: I've tried
cris-gcc -g -static -nostdlib -o compiled main.c -luClibc-0.9.27 -L.
but that just gives:
./libuClibc-0.9.27.so: could not read symbols: Invalid operation
collect2: ld returned 1 exit status
Is there a way to link to this .so file or to otherwise get some standard functions like exit working?
regarding:
cris-gcc -g -static -nostdlib -o compiled main.c -luClibc-0.9.27 -L.
The linker works with libraries in the order they are encountered. So they must be listed in the order needed.
The linker needs to know where the library is located before knowing which library to examine. Suggest:
cris-gcc -g -static -nostdlib -o compiled main.c -L. -luClibc-0.9.27
However, a *.so library is NOT a static library. It is a dynamic library, so the option: -static should be removed However, that requires that the dynamic library be available at 'run time' if the related *.a (a static library) is available then it should be used in the compile/link statement.
Note: the function: exit() has its' prototype exposed via the stdlib.h header file, not the unistd.h header file.
regarding:
#include <unistd.h>
int main(int argc, char** argv)
{
*((unsigned int*)0) = 0xDEAD;
}
the parameters: argc and argv are not used, so the compiler will output two warning statements about 'unused parameters'. Suggest using the function signature: int main( void )
this code is trying to write to address 0. However, the application does not 'own' address 0, (an usually, such an address will be 'marked' as 'readonly' so the application will exit with a 'seg fault event')
it is poor programming practice to include header files those contents are not used. Suggest removing the statement: #include <unistd.h>
this statement: int a = 0; will result in the compiler outputting a warning message about a variable that is 'set' but never 'used'
regarding:
cris-gcc -g -static -nostdlib -o compiled main.c -L. -luClibc-0.9.27
When compiling, should always enable the warnings, then fix those warnings. Suggest:
cris-gcc -Wall -Wextra -Wconversion -pedantic -std=c99 -g -static -nostdlib -o compiled main.c -luClibc-0.9.27 -L.
Apart of all the problems noticed by #user3629249 in his answer (all of them are to be followed), the message:
./libuClibc-0.9.27.so: could not read symbols: Invalid operation
collect2: ld returned 1 exit status
means that the libuClibc-0.9.27.so binary has been stripped its symbols or you have not privileges to read the file, and so, the symbol table. The linker is unable to use that binary and it can only be loaded into memory. Anyway, you need a nonstripped shared object, and as suggested by #user3629249, don't use -static (by the reason stated in his answer), put the parameters in order (library dir before the library to be linked, also stated by him). Even you can link the shared by specifying it as:
cris-gcc -nostdlib -o compiled main.c libluClibc-0.9.27.so
and another thing: You need not only the standard C library to link an executable... you normally use a crt0.o at the beginning of your program with the C runtime and the start code for your program. You have not included that, and probably the compiler is getting it from another place.
One question: If you got the compiler, why do you intend to supply your own version of the standard library? isn't provided by the compiler? If you change the libc, then you must change also the crt0.o file. It defaults to some compiler provided, and you haven't received the message no definition for start.
Try to compile with just a main function, as you did, but don't specify shared libraries or directories... just the main code:
cris-gcc -o compiled main.c
and see what happens.... this will be very illustrative of what you lack in your system.

Shared library and rpath

I cannot make rpath work properly and make my binary to search for the library in the specified folder:
I have 3 very simple files:
main.c
#include <stdio.h>
#include <func.h>
int main() {
testing();
return 1;
}
func.h
void testing();
func.c
#include "func.h"
void testing(){
printf(testing\n");
}
Then I proceed to create a shared library as it follows:
gcc -c -fpic func.c -o ../release/func.o
gcc -shared -o ../release/lib/lib_func.so ../release/func.o
And then compile the program:
gcc main.c ../release/lib/lib_time_mgmt.so -Wl,-rpath=/home/root/ -o ../release/main
I receive the next warning:
main.c:7:2: warning: implicit declaration of function ‘testing’ [-Wimplicit-function-declaration]
testing();
But besides it, the program works fine.
However, my problem is that if now I want to move the library to /home/root (as specified in rpath) it does not work and the library is still searched only in the path specified when I compiled the main.c file which is ../release/lib/lib_time_mgmt.so
What am I doing wrong?
EDIT: After accepting the answer, I leave here the exact line as I used it and made it work for whoever might find it useful:
gcc main.c -L/home/root -Wl,-rpath,'/home/root/' -l:libtime_mgmt -o ${OUT_FILE}
Note: the rpath was used with the path betwen simple '. Not sure if that was the reason why it was not working before, but it worked this way now.
rpath is not used at compile time, but rather at link/runtime... thus you probably need to use both of these:
-L /home/root - to link correctly at build time
-Wl,-rpath=/home/root - to link correctly at run-time
You should use the -l ${lib} flag to link with libraries, don't specify their path as an input.
In addition to this, convention states that the libraries are named libNAME.so - e.g:
-l func will try to link with libfunc.so
-l time_mgmt will try to link with libtime_mgmt.so
Once you've addressed the above points, try the following:
gcc main.c -L/home/root -Wl,-rpath=/home/root -lfunc -ltime_mgmt -o ${OUT_FILE}
As a final point, I'd advise that you try not to use rpath, and instead focus on installing libraries in the correct places.
Unrelated to your question, but worth noting. Your use of #include <...> vs #include "..." is questionable. See: What is the difference between #include <filename> and #include "filename"?

Can I re-compile a file with new code?

I have a question. I was wondering if you could re-compile code with another piece of code. For example (theoretical):
main.c:
#include <stdio.h>
void showme();
int main()
{
showme();
}
void showme()
{
fprintf(stderr, "errtest, show me");
}
Compile this file to main. (So the main is compiled)
After this I want to add a piece of code.
addthis.c:
void test()
{
test();
}
Now I want to use the (compiled) main and re-compile it with addthis.c.
When running it (./mainWithAddthis) should show the print 2 times.
I hope I explained it clear. Anybody an idea?
You need a forward declaration for your void test() like you have one for the void showme(). Compile each .c file with -c (compile only) option:
gcc -c addthis.c -o addthis.o
gcc -c main.c -o main.o
Then link the two object files with:
gcc main.o addthis.o -o main
Then enjoy ./main :-)
Your first code will not compile since there's not definition of test();.
As I understand, you want to take the compiled main and add it with the code generated on addthis.o to create a 2nd application named mainWithAddthis. This is not possible!
You are either confused or trying to do some hardcore trick.
Building an executable is a two step process.
For every source file you specify (in your project/makefile), your compiler will build an object file
For every object file you specify (in your project/makefile), your linker will link them together and make your executable
One way to re-compile would be simply to re-build your entire project. You'd get more or less the same result.
But it sounds like what you want to do is recompile only the source file, addthis.c, then re-link the old version of main.o (the object file compiled for main.c) with the new version of addthis.o. How to do this is completely dependent on the compiler and build system you use.
Also, that solution will only work if you have main.o, addthis.c, and have the exact same compiler binaries/install, and compiler flags used to generate main.o. If this is all on your box, then you're probably okay.
If you only have the files addthis.c and main.exe, then no there is no portable way to do what you want.
You can't do what you are talking about after the fact without some hardcore time with a hex editor.
However, if you plan ahead and build it into your software, you can use dynamic loading to achieve the same effect, which is how a lot of software provides plugin functionality. Check out glib modules for a common way to do this in C.
main.c
void f();
int main()
{
f();
return 0;
}
addon1.c
#include <stdio.h>
void f()
{
printf("I am the ONE.\n");
}
addon2.c
#include <stdio.h>
void f()
{
printf("I am the TWO.\n");
}
Compilation
gcc -c main.c -o main.o
gcc -c addon1.c -o addon1.o
gcc -c addon2.c -o addon2.o
gcc main.o addon1.o -o main1
gcc main.o addon2.o -o main2
You will have ./main1 and ./main2 programs which will print ...ONE. and ...TWO..

Is it a header file or library? in a makefile

I already know the differences between a header file and a library. However, when I'm writing my makefile, I have some difficulties on deciding if I should put something as a dependency of the file or just at the linking rule.
For example: I have 2 simple files:
main.c:
#include <stdio.h>
main(){
printf("this is the sine or 90");
sinus(90);
}
and func.c:
#include <math.h>
sinus(int num){
return sin(num);
}
and my makefile is:
main: main.o func.o
gcc main.o func.o -lm -o main
func.o: func.c
main.o: main.c
Well, my question is why this makefile works and this one doesn't:
main: main.o func.o
gcc main.o func.o -lm -o main
func.o: func.c math.h
main.o: main.c
You don't need to make func.o depend on math.h as that file is very unlikely to change.
Regarding the error you get if you do is because you don't explicitly specify how make should compile the file so it tries to deduce how to compile it and it only works in simple cases. I'm not sure exactly how make does it but I think it just does gcc -o target.o -c <your deps>.
Because make is looking for a file "math.h" in the current directory and trying to do cc func.c math.h to produce func.o
Problem is that you don't know exactly how Makefile is resolved after using implicit rules - definitely there's one which causes problems you have. (maybe try to compile math.h, or math.h is not found etc.. (you didn't posted errors you have so we can only speculate).
I would advice you to disable implicit rules by calling make with "-r" and do everything explicitly - this way you will learn more as you'll know how makefile works instead of knowing how to write makefiles which works under some circumstances.
More on implicit rules: Make documentation - Implicit rules
More on make Make documentation

Resources