I have these 3 files under /Users/koraytugay
checksum.h
enc.h
libsec.a
libsec.a is an archive file existing of checksum.o and enc.o
Korays-MacBook-Pro:~ koraytugay$ nm libsec.a
libsec.a(enc.o):
0000000000000090 s EH_frame0
0000000000000000 T _enc
00000000000000a8 S _enc.eh
U _strlen
libsec.a(checksum.o):
0000000000000078 s EH_frame0
0000000000000000 T _checkSumFor
0000000000000090 S _checkSumFor.eh
Korays-MacBook-Pro:~ koraytugay
This is how I try to compile my hello.c file:
Korays-MacBook-Pro:HelloWorld koraytugay$ gcc hello.c -L/Users/koraytugay -libsec -o koko.out
hello.c:4:10: fatal error: 'enc.h' file not found
#include <enc.h>
^
1 error generated.
What am I doing wrong?
Btw, hello.c:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <enc.h>
#include <checksum.h>
// code here..
You try to include enc.h, but it's not in your include path. You can add this to your gcc invocation to fix that:
-I/Users/koraytugay
In addition to the lack of -I. switch to bring the current directory into the include path, the link specification should read -lsec, not -libsec. The linker takes the string after the -l switch, prepends lib, and looks for that. In other words, -lfoo implies that there should be a libfoo.a (static) or libfoo.so (shared) file on the link path (which itself is specified with the -L switch).
There are two ways to #include a file: with "..." and with <...>.
Essentially both are implementation-defined:
<...> searches "a sequence of implementation-defined places", which is commonly referred as the include path.
"..." searches "in an implementation-defined manner", which is usually the directory of the parent file. If the file isn't found, the <...> way (include path) is used instead.
The first way should be used for system headers as well as headers of libraries not directly included in the project, while the second way is to be preferred for headers belonging directly to the project.
Related
An Introduction to GCC by Brian Gough says
Incidentally, the difference between the two forms of the include state-
ment #include "FILE.h" and #include <FILE.h> is that the former
searches for FILE.h in the current directory before looking in the system header file directories. The include statement #include <FILE.h>
searches the system header files, but does not look in the current directory by default.
But the following example seems to imply the directory containing the source file being compiled, instead of the current directory. What is correct?
$ mv src/hello.h .
$ gcc -c src/main.c
src/main.c:1:10: fatal error: hello.h: No such file or directory
#include "hello.h"
^~~~~~~~~
compilation terminated.
$ mv hello.h src/
$ gcc -c src/main.c
$
https://gcc.gnu.org/onlinedocs/cpp/Search-Path.html states that
By default, the preprocessor looks for header files included by the quote form of the directive #include "file" first relative to the directory of the current file, and then in a preconfigured list of standard system directories. For example, if /usr/include/sys/stat.h contains #include "types.h", GCC looks for types.h first in /usr/include/sys, then in its usual search path.
For the angle-bracket form #include <file>, the preprocessor’s default behavior is to look only in the standard system directories.
The document you are reading is therefore incorrect. Perhaps Mr. Gough has never attempted to write a nonrecursive Makefile, or separate his source and object directories, and has therefore never noticed that "the current directory" and "the directory containing the current file" are not necessarily the same thing.
GCC has a whole bunch of command line options that you can use to reconfigure how #include works. There is even an option that turns off looking in the directory of the current file (-I-), but it is not usable on many operating systems because it will break the C library's headers.
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"?
Is there a compiler or preprocessor flag that will force gcc to treat #include <x.h> like it would #include "x.h"? I have a bunch of generated code that uses #include <> for files in the current directory, and gcc reports No such file or directory for these files. I'm looking for a workaround that doesn't involve editing the code.
EDIT: -I. doesn't do it. Let's say I have the following files:
foo/foo.h:
#include <foo2.h>
foo/foo2.h:
#define FOO 12345
xyz/xyz.c
#include <stdio.h>
#include "foo/foo2.h"
int main(void)
{
printf("FOO is %d\n", FOO);
return 0;
}
If, inside the xyz directory, I compile with gcc -o xyz I.. xyz.c, the compile fails:
In file included from xyz.c:2:
../foo/foo.h:1:18: error: foo2.h: No such file or directory
xyz.c: In function ‘main’:
xyz.c:6: error: ‘FOO’ undeclared (first use in this function)
xyz.c:6: error: (Each undeclared identifier is reported only once
xyz.c:6: error: for each function it appears in.)
Adding -I. doesn't change anything.
But, if I change foo/foo.h to:
#include "foo2.h"
Then the compile works. I know I could add -I../foo to my command line, but I was looking for a more generic way to treat #include <> as #include "". Does one exist?
Yes, you can pass the switch -I . to the compiler to add the current directory to the include search path.
The -I- option might help you. From gcc's man page:
-I- Split the include path. Any directories specified with -I options
before -I- are searched only for headers requested with
"#include "file""; they are not searched for "#include <file>". If
additional directories are specified with -I options after the -I-,
those directories are searched for all #include directives.
I am trying to include a library file named libmathematica.a in gcc so it gets linked in the executable example.
I attempt to do this with gcc main.c libmathematica.a -o example
Note: I have to do this with gcc, as ld won't link it properly with the correct system libraries
But I get: fatal error: mathematica.h: No such file or directory ,which is odd because mathematica.h is in the library.
Can you help?
A header file cannot be in the library. It has to be present at a certain location and you have to specify that location with the -I compiler flag:
gcc -I/path/to/mathematica/include main.c libmathematica.a -o example
If the header file is in the directory where the main.c is or in a subdirectory, then be sure that you use quotes and not angle brackets in the #include directive.
The issue would be in your source file. If the mathematica.h is in the system includes directory then you would use #include <mathematica.h> and if it was in some local directory then you would use something like #include "libs/mathematica.h".
Try adding to the gcc call - an option like
-I/Full/Path/To/The/Directory/Where/the/desired/header/resides
For example:
gcc -I/usr/include/mathematica -lmathematica -o example main.c
I have a problem with Nvidia's OpenCl/Cuda framework, but I think it is a gcc linking issue.
The opencl_hello_world.c example file uses following header file:
#include "../OpenCL/common/inc/CL/opencl.h"
with opencl.h using these header files:
#include <../OpenCL/common/inc/CL/cl.h>
#include <../OpenCL/common/inc/CL/cl_gl.h>
#include <../OpenCL/common/inc/CL/cl_gl_ext.h>
#include <../OpenCL/common/inc/CL/cl_ext.h>
So all the header files are in the same folder.
When I then compile with gcc opencl_hello_world.c -std=c99 -lOpenCL I get following error messages:
error: ../OpenCL/common/inc/CL/cl.h: No such file or directory
error: ../OpenCL/common/inc/CL/cl_gl.h: No such file or directory
...
Even though cl.h and the other header files are located in this folder.
Having searched SO, I then changed the includes in the opencl.h to
#include "cl.h"
#include "cl_gl.h"
how I have read here: gcc Can't Find a Included Header.
But messing around with the frameworks header files does not seem like the way to go? What would be the proper way to handle this problem?
You're using both #include "" form and #include <>, which don't search in the same paths. "" is local to your project, and the -i command line specified to gcc, <> is the 'system' path specified by -I to gcc.
You probably need to set the include path with -Ipath/to/includes in gcc's command line.