Using library gives unknown reference error - c

I am currently creating a C library to accept input(similar to scanf), but after moving all the necessary files to the relevant places, this error is seen when I type this command (gcc main.c -o main.exe -linput)
undefined reference to `getInput
collect2.exe: error: ld returned 1 exit status
I have moved the C file and the header file to the GCC include folder, and I have moved libinput.a to the lib folder.
I have also done the same thing with another library I made, but that works fine.
After some further digging I found out that when I right-click on the function "getinput" and click "go to definition", it goes to the input.c file instead of the input.h. In the other libraries, it redirects me to the library.h file and not the library.c file. This might be the problem but I have no idea of how to fix it.
Note- running gcc main.c libinput.a works while having libinput.a in the same directory, but I
would prefer gcc main.c -o main.exe -linput(without having it in the same directory,
similar to how other libraries work). Having input.c and input.h in the same directory
and then linking it also works.
Environment - VS code on windows 10
Here is my code so far:
input.h
#ifndef INPUT_H
#define INPUT_H
void getInput(char *str, ...);
#endif
main.c(an example code where I am using the library)
#include <stdio.h>
#include <input.h>
int main()
{
char *s = NULL;
getInput("{s}", &s);
printf("%s\n", s);
}
Edit - I fixed it by moving the files to the following places
libinput.a = D:\mingw64\lib\gcc\x86_64-w64-mingw32\8.1.0
input.c and input.h = D:\mingw64\x86_64-w64-mingw32\include

You tell the linker to search other directories with -L searchdir. gcc will pass that option through to the linker.

Related

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"?

Using a function from another C file placed in another directory?

Say I have a parent directory A with two subdirectories B and C.
Sub-directory C has a helper.c and helper.h as shown:
//helper.c
void print(){
printf("Hello, World!\n");
}
//helper.h
void print();
Now, in sub directory B, I have a main.c which just calls the print function:
//main.c
#include<stdio.h>
#include"../C/helper.h"
void main(){
print();
}
I tried the following commands for compiling main.c:
Command 1: gcc main.c //Gives undefined reference to 'print' error
Command 2: gcc main.c ../C/helper.c //Compiles successfully
Now I removed the #include"../C/helper.h" from main .c and tried the Command 2 again. It still works.
So I have the following questions:
i) What difference does it make whether the helper.h file is included or
helper.c?
ii) Why command 1 fails?
iii) Is there a way to compile my C program without having to specify
helper.c everytime?
What happens when you execute:
Command 1: gcc main.c //Gives undefined reference to 'print' error
When execute gcc main.c
Compiler compiles main.c and creates objective file. This file will contain unresolved link to function print(). Because there is no implementation of function print() in main.c file.
After compilation gcc tries to make full executable file. To do this gcc combines all objective files and tries to resolve all unresolved links. As you remember there is unresolved link for function print(), gcc can't find implementation and raise the error.
When you execute
Command 2: gcc main.c ../C/helper.c //Compiles successfully
gcc compiles both files. Second file ../C/helper.c contains implementation of function print(), so linker can find it and resolve reference to it in function main().
i) What difference does it make whether the helper.h file is included or helper.c?
In your case helper.h contains forward declaration of function print(). This gives information to compiler how to make call of function print().
ii) Why command 1 fails?
See above.
iii) Is there a way to compile my C program without having to specify helper.c everytime?
Use make utility. Compile helper.c in separate objective file helper.o and use it in linkage command.
helper.o: ../C/helper.c ../C/helper.h
gcc -c ../C/helper.c
main.o: main.c main.h
gcc -c main.c
testprog: main.o helper.o
g++ main.o helper.o -o testprog
See make utility manual for details.
Commands should be indented by TAB.
First you need to understand that #include simply adds whatever text is in the #include parameter to the position in the file the statement is in, for example:
//file1.h
void foo();
//main.c
#include "file1.txt"
int main(int argc, char **argv)
{
foo();
return 0;
}
Will cause the pre-compilation to generate this unified file for compilation:
//main.c.tmp
void foo();
int main(int argc, char **argv)
{
foo();
return 0;
}
So to answer your first and second questions:
When you include a header file (or any file) that only contains declarations (i.e function signatures) without definitions (i.e function implementations), as in the example above, the linker will fail in finding the definitions and you will get the 'undefined reference' error.
When you include a c code file (or any file) that contains definitions, these definitions will be merged to your code and the linker will have them, that's why it works.
and as for your third question
It is bad practice to include c files directly in other c files, the common approach is to keep separate c files with headers exposing the functionality they provide, include the header files and link against the compiled c files, for example in your case:
gcc main.c helper.c -o out
Will allow you to include helper.c in main.c and still work because you instructed the compiler to compile both files instead of just main.c so when linking occurs the definitions from the compilation will be found and you will not get the undefined behavior error
This is, in a nutshell. I abstracted a lot of what's going on to pass on the general idea. this is a nice article describing the compilation process in fair detail and this is a nice overview of the entire process.
I'll try to answer:
i) What difference does it make whether the helper.h file is included or helper.c?
When you include a file, you don't want to expose your implementation, hence its better to include h files, that contains only the "signatures" - api of your implementation.
ii) Why command 1 fails?
When you compile you must add all your resources to the executable, otherwise he won't compile.
iii) Is there a way to compile my C program without having to specify
helper.c everytime?
You can use Makefile to compile your program. Maybe this tutorial can help you.
i) What difference does it make whether the helper.h file is included
or helper.c?
Including helper.c means that helper.c gets compiled each time as if it were part of main.c
Including helper.h lets the compiler know what argument types the function print() takes and returns so the compiler can give an error or warning if you call print() incorrectly
ii) Why command 1 fails?
The compiler is not being told where to find the actual code for the print function. As explained, including the .h file only helps the compiler with type checking.
iii) Is there a way to compile my C program without having to specify
helper.c everytime?
You can compile it once into an object file and optionally you can add that obj to a static or dynamically loaded library. You still need to help the compiler find that obj or library. For example,
gcc -c helper.c
gcc main.c helper.o
The correct way to avoid compiling modules that don't need compiling is to use a Makefile. A Makefile compares when a module was last compiled compared to when it was last modified and that way it knows what needs to be compiled and what doesn't.

How to organize Header files

Using header files in this way gives me the error "undefined reference to somefunc". What is the proper way to make sure somefunc.c is seen so this error doesn't occur? It seems simply including somefile.h in main.c isn't enough to see the definitions in somefile.c
main.c
#include "somefile.h"
int main() {
somefunc();
return 0;
}
somefile.h
#ifndef SOMEFILE_H
#define SOMEFILE_H
void somefunc();
#endif
somefile.c
#include <stdio.h>
#include "somefile.h"
void somefunc() {
printf("hello\n");
}
I don't understand why I am getting errors because this is the same manner in which they are used in tutorials and videos i've been viewing while looking for an answer. The code above is an answer given earlier but it is still has the same error.
Undefined reference to somefunc is a linker error, not a compiler error.
This means that, although when compiling main.c the header somefile.h is found, you are not compiling the file somefile.c together with main.c. So when linking occurs the linker is not able to find the implementation of somefunc in any object file to resolve the call from main().
If you are using GCC or Clang just compile both source files to your command, eg
gcc somefunc.c main.c -o output
If you are using an IDE instead, make sure that somefile.c is compiled together with main.c when building the application.
This doesn't appear to be a problem with the header file.
This appears to be a problem in linking, which depends on how you build the project. If you use an IDE, it means that somefile.c is not included in the project. If you're using make and a makefile, it means that somefile.c is not listed in the makefile, or at least not included for the linker. If you're building at the command line (not using make or some build tool, but using gcc), then you're not including somefile.c in the command.
The undefined reference error means the linker couldn't find the code in somefile.c, because the linker didn't know to include it.

C include error multiple definition error

I'm encountering a classic error but still don't get why it occurs...
Below is the simplified explanation
Apparently I have two C files main.c and support.c
in support.c i have one function void bla(int input);
in main.c i have several functions using bla from support.c, and i included
#include<support.c>
at the top of main.c
However I cannot compile the project because of the error multiple definition of bla, first defined here (eclipse points to the definition of bla in support.c)
I know that optimally I would have to create header file support.h and gives prototype extern void bla(int input) there, but for this I have to include the .c file.
Thanks in advance.
The preprocessor will copy the contents of support.c, and paste it to main.c to replace the line #include<support.c>. So there are two definition of the function bla, one in support.c, the other in main.c.
The solution is, don't include an source file. Put the declarations of functions that you want to export in a header file support.h, and include the header file in main.c:
#include "support.h"
You don't include source files into other source files. Instead you make a header file (with the extension .h) that contains declarations of functions, i.e. function prototypes. Then you build both source files separately, and link them together to form the final executable.
So a header file support.h like
#ifndef SUPPORT_H
#define SUPPORT_H
void blah(void);
#endif
(The preprocessor #ifdef/#define/#endif things are for include guards, to protect from multiple inclusion in the same source file.)
Then the support.c source file
#include "support.h"
void blah(void)
{
/* Some code here... */
}
And finally the main.c source file
#include "support.h"
int main(void)
{
blah();
return 0;
}
If you have an IDE (like Visual Studio) if you add these files to your project the IDE will make sure everything is built and linked properly. If you're compiling on the command line, compile each source file into an object file (usually using an option like -c (used for GCC and clang)) and then link the two object files together to create the executable.
Command line example with GCC:
$ gcc -Wall -c main.c -o main.o
$ gcc -Wall -c support.c -o support.o
$ gcc main.o support.o -o my_program
The above three commands will first compile the source files into object files, and then link them together.
What compiler are you using?
When compiling, make sure you do this:
gcc main.c support.c -o yourProgram

Undefined reference to functions C

I downloaded a library from here. I added the header file in my program but when I try to access the functions of this header file, I get error:
undefined reference to the function for u_open() and u_accept(). I tried to compile the .c files of this header file but I get this error:
undefined reference to main.
I tried everything in my knowledge to solve this issue, but couldn't solve it. Here is the program.
#include "uici.h"
int main()
{
char client[50];
char buf[1024];
u_port_t portnumber;
portnumber=48625;
int fd = u_open(portnumber);
int communFd = u_accept(fd,client,50);
perror("Opened");
fprintf(stderr,"\nComun fd is %d\n\n\n",communFd);
read(communFd,buf,1024);
write(STDOUT_FILENO,buf,1024);
fprintf(stderr,"\n\nReading complete\n");
return 0;
}
What can I do to solve this problem?
Regards
Your header file uici.h declares the functions you're calling in main() (u_open() and u_accept()), but not their implementations, which are in the source files. When the linker tries to create the entire program, it then complains that the implementations can't be found.
The solution is to link all the files together when creating the actual program binary. When using the g++ frontend, you can do this by specifying all the source files together on the command line. For example:
g++ -o main main.c uici.c
will create the main program called "main", assuming that the implementations you need are in uici.c.
edit: In the case you're linking against a prebuilt library for uici, you'll need to specify to the frontend that the library is needed for linking, e.g. with:
g++ -o main main.c -luici
You need to link the library when using gcc like :
gcc nameofprgram.c -l<library>
Use any of these flags while compiling with gcc
-I <searchpath to include files>
-L <searchpath to the lib file>
-l<thelibname>
Ex:
gcc -o myprogram -lfoo -L/home/me/foo/lib myprogram.c
This will link myprogram with the static library libfoo.a in the folder /home/me/foo/lib

Resources