Check what files is 'make' including - c

I'm compiling a kernel module and I'm including <asm/unistd.h>, but I'm not sure if the compiler is using the unistd.h from /usr/includes/ (wrong) or the one from /usr/src/kernel-3.x.x/arch/x86/includes/ (right).
My question is: How can I check which one of those two is the compiler using?
And also, is there a way to force the file from the kernel headers instead of the one from /usr/include?

cpp code.c | grep unistd.h
or
gcc -E code.c | grep unistd.h

To answer the second part of your question:
And also, is there a way to force the file from the kernel headers instead of the one from /usr/include?
You can pass the -nostdinc option to gcc:
"Do not search the standard system directories for header files. Only the directories you have specified with -I options (and the directory of the current file, if appropriate) are searched."
GCC: Options Controlling the Preprocessor

Related

How do I use an external library with gcc?

I am attempting to compile this code:
#include <GLFW/glfw3.h>
int main() {
glfwInit();
glfwTerminate();
return 0;
}
Using this command in MSYS2 on Windows 10:
gcc -Wall runVulkan.c -o runVulkan
as well as this:
gcc -Wall -Llibs/glfw runVulkan.c -o runVulkan
libs/glfw is where I downloaded the library to.
For some reason I keep getting this:
runVulkan.c:1:10: fatal error: GLFW/glfw3.h: No such file or directory
1 | #include <GLFW/glfw3.h>
| ^~~~~~~~~~~~~~
compilation terminated.
It seems like I'm getting something very basic wrong.
I'm just getting started with C, I'm trying to import Vulkan libraries.
Run pacman -S mingw-w64-x86_64-glfw to install GLFW.
Then build using gcc -Wall runVulkan.c -o runVulkan runVulkan.c `pkg-config --cflags --libs glfw3`.
The pkg-config command prints the flags necessary to use GLFW, and the ` backticks pass its output to GCC as flags. You can run it separately and manually pass any printed flags to GCC.
Note that any -l... flags (those are included in pkg-config output) must be specified after .c or .o files, otherwise they'll have no effect.
For me pkg-config prints -I/mingw64/include -L/mingw64/lib -lglfw3.
-I fixes No such file or directory. It specifies a directory where the compiler will look for #included headers. Though it's unnecessrary when installing GLFW via pacman, since /mingw64/include is always searched by default.
-l fixes undefined reference errors, which you'd get after fixing the previous error. -lglfw3 needs a file called libglfw3.a or libglfw3.dll.a (or some other variants).
-L specifies a directory where -l should search for the .a files, though it's unnecessrary when installing GLFW via pacman, since /mingw64/lib is always searched by default.
#include are just headers, for declarations. gcc, as any compilers, needs to know where those .h should be searched.
You can specify that with -I option (or C_INCLUDE_PATH environment variable).
You'll also need -L option, this times to provide the library itself (.h does not contain the library. Just declarations that the compiler needs to know how to compile codes that use the library function's and types).
-L option tells the compiler where to search for libraries.
But here, you haven't specify any libraries (just headers. And I know that it seems logical that they go together. But strictly speaking, there is no way to guess from #include <GLFW/glfw3.h> which library that file contain headers for (that is not just theory. In practice, for example, the well known libc declarations are in many different headers)
So, you will also have to specify a -l option. In your case -lglfw.
This seems over complicated, because in your case you compile and like in a single command (goes from .c to executable directly). But that are two different operations done in one command.
Creation of an executable from .c code source is done in two stage.
Compilation itself. Creating .o from .c (many .c for big codes), so many compilation commands. Using command such as
gcc -I /path/where/to/find/headers -c mycode.c -o mycode.o
Those are not related to the library. So no -l (and therefore no -L) for that. What is compiled is your code, so just your code is needed at this stage. Plus the header files, because your code refers to unknown function and types, and the compiler needs to know, not their code, but at least declarations that they really exist, and what are the types expected and returned by the functions is the headers files.
Then, once all the .o are compiled, you need to put together all compiled code, yours (the .o) and the libraries (which are somehow a sort of .zip of .o) to create an executable. That is called linking. And is done with commands like
gcc -o myexec mycode1.o mycode2.o -L /path/where/to/search/for/libraries -lrary
(-lbla is a compact way to include /path/where/to/search/for/libraries/libbla.so or /path/where/to/search/for/libraries/libbla.a)
At this stage, you no longer need -I or anything related to headers. The code is already compiled, headers has no role left. But you need everything needed to find the compile code of the libraries.
So, tl;dr
At compilation stage (the stage that raises the error you have for now), you need -I option so that the compiler knows where to find GLFW/glfw3.h
But that alone wont avoid you the next error that will occur at linking stage. At this stage, you need -lglfw to specify that you want to use that library, and a -L option so that the compiler knows where to find a libglfw.so

Files accessed by GCC while compiling a given code

I came across the topic of the precompiled headers in C, so I started reading about it, in brief, the article(s) I read said that gcc will use precompiled header (h.gch) if there is one, otherwise normal header file(.h) will be used.
I just wanted to try it out and see if that actually happens with my code. So, I wanna know if there is any command in Linux(Ubuntu) to see what all files are being used by the GCC compiler while it is compiling your code. What I am thinking is, if the .h.gch file is used instead of .h files then it works how it should be and I get the concept of precompiled header files.
For example,
if I do something like
gcc myCode.c
then gcc will definitely go to that file (myCode.c) and if myCode.c file includes a header file then that header file will also be touched/opened by gcc.
https://gcc.gnu.org/onlinedocs/gcc-5.1.0/gcc/Precompiled-Headers.html
This is from where I read about precompiled headers.
If you simply want to see what files are opened by gcc or any other process on Linux then you can use Strace.
strace -f -e open gcc myCode.c

Alias or command to compile and link all C files

I recently started compiling/linking my C files by hand using the gcc command. However it requires all of the source files to be typed at the end of the command. When there are many files to compile/link it can be boring.
That's why I had the idea of making a bash alias for the command which would directly type all *.h and *.c files of the folder.
My line in .bashrc is this:
alias compile='ls *.c *.h | gcc -o main'
I found it to work some times but most of the time compile will return this :
gcc: fatal error: no input files
compilation terminated.
I thought that pipe would give the results of ls *.c *.h as arguments to gcc but it doesn't seem to work that way. What am I doing wrong? Is there a better way to achieve the same thing?
Thanks for helping
A pipe does not create command line arguments. A pipe feeds standard input.
You need xargs to convert standard input to command line arguments.
But you don't need (or want) xargs or ls or standard input here at all.
If you just want to compile every .c file into your executable then just use:
gcc -o main *.c
(You don't generally need .h files on gcc command lines.)
As Kay points out in the comments the pedantically correct and safer version of the above command is (and I don't intend this in a pejorative fashion):
gcc -o main ./*.c
See Filenames and Pathnames in Shell: How to do it Correctly for an extensive discussion of the various issues here.
That being said you can use any of a number of tools to save you from needing to do this and from needing to rebuild everything when only some things change.
Tools like make or its many clones, "front-ends" (e.g. the autotools, cmake) or replacements (tup, scons, cons, and about a million other tools).
Have you tried using a makefile? It sounds like that might be more efficient for what you're trying to do.
If you really want to do it with BASH aliases, you have to use xargs to get standard input to command line arguments.
There are several misconceptions here:
the pipe redirects the standard output of the first command to the standard input of the second command; however, gcc doesn't accept the files to compile on stdin, but on the command line;
the wildcard syntax is not something that is magical just to ls, it's the shell that performs their expansion on the command line;
header files are not to be compiled - you compile .c files, which in turn may include headers.
Armed with this knowledge, you'll understand that the correct command something like
gcc -o main *.c
Actually we can do better: first of all, you'll want to change the *.c to ./*.c; this prevents files whose name start with a - from being interpreted as command line options.
Most importantly, you should really enable the compiler warnings, they can be life saver. You'll want to add -Wall and -Wextra.
gcc -Wall -Wextra -o main ./*.c
Finally, it's worth saying that by default you are compiling with optimizations disabled. If you are debugging that's OK, but you want also to add -g to have an executable usable in debugging; otherwise, if the target is speed you should at least add -O2.

gcc switches - what do these do?

I am new with using gcc and so I have a couple of questions.
What do the following switches accomplish:
gcc -v -lm -lfftw3 code.c
I know that lfftw3 is an .h file used with code.c but why is it part of the command?
I couldn't find out what -lm does in my search. What does it do?
I think I found out -v causes gcc to display programs invoked by it.
-l specifies a library to include. In this case, you're including the math library (-lm) and the fftw3 library (-lffw3). The library will be somewhere in your library path, possibly /usr/lib, and will be named something like libffw3.so
From GCC's man page:
-v Print (on standard error output) the commands executed to run the
stages of compilation. Also print the version number of the
compiler driver program and of the preprocessor and the compiler
proper.
-l library
Search the library named library when linking. (The second
alternative with the library as a separate argument is only for
POSIX compliance and is not recommended.)
It makes a difference where in the command you write this option;
the linker searches and processes libraries and object files in the
order they are specified. Thus, foo.o -lz bar.o searches library z
after file foo.o but before bar.o. If bar.o refers to functions in
z, those functions may not be loaded.
The linker searches a standard list of directories for the library,
which is actually a file named liblibrary.a. The linker then uses
this file as if it had been specified precisely by name.
The directories searched include several standard system
directories plus any that you specify with -L.
Normally the files found this way are library files---archive files
whose members are object files. The linker handles an archive file
by scanning through it for members which define symbols that have
so far been referenced but not defined. But if the file that is
found is an ordinary object file, it is linked in the usual
fashion. The only difference between using an -l option and
specifying a file name is that -l surrounds library with lib and .a
and searches several directories.
libm is the library that math.h uses, so -lm includes that library. You might want to get a better grasp of the concept of linking. Basically, that switch adds a bunch of compiled code to your program.
-lm links your program with the math library.
-v is the verbose (extra ouput) flag for the compiler.
-lfftw3 links your program with fftw3 library.
You just include headers by using #include "fftw3.h". If you want to actually include the code associated to it, you need to link it. -l is for that. Linking with libraries.
arguments starting with -l specify a library which is linked into the program. Like Pablo Santa Cruz said, -lm is the standard math library, -lfftw3 is a library for fourier transformation.
Try man when you're trying to learn about a command.
From man gcc
-v Print (on standard error output) the commands executed to run the
stages of compilation. Also print the version number of the
com-
piler driver program and of the preprocessor and the compiler
proper.
As Pablo stated, -lm links your math library.
-lfftw3 links in a library used for Fourier transforms. The project page, with more info can be found here:
http://www.fftw.org/
The net gist of all these statements is that they compile your code file into a program, which will be named the default (a.out) and is dependent on function calls from the math and fourier transform libs. The -v statement just helps you keep track of the compilation process and diagnose errors should occur.
In addition to man gcc which should be the first stop for questions about any command, you can also try the almost standard --help option. Even for commands that don't support it, an unsupported option usually causes it to print an error containing usage information that should hint at a similar option. In this case, gcc will display a terse (for gcc, its only about 50 lines long) help summary listing the small number of options that are understood by the gcc program itself rather than passed on to its component programs. After the description of the --help option itself, it lists --target-help and -v --help as ways to get more information about the target architecture and the component programs.
My MinGW GCC 3.4.5 installation generates more than 1200 lines of output from gcc -v --help on Windows XP. I'm pretty sure that doesn't get much smaller in other installations.
It would also be a good idea to read the official manual for GCC. It is also helpful to read the documentation for the linker (ld) and assembler (often gas or just as, but it may be some platform specific assembler as well); aside from a platform-specific assembler, these are documented as part of the binutils collection.
General familiarity with the command line style of Unix tools is also helpful. The idea that a single-character option's value might not be delimited from the option name is a convention that goes back essentially as far as Unix does. The modern convention (promulgated by GNU) that multiple-character option names are introduced by -- instead of just - implies that -lm might be a synonym for -l m (or the pair of options -l -m in some conventions but that happens not to be the case for gcc) but it is probably not a single option named -lm. You will see a similar pattern with the -f options that control specific optimizations or the -W options that control warnings, for example.

-I dir vs. -isystem dir

If I want to include directories to be searched for header files, which is the preferred way and why?
One way to view this is to use headers that you control with -I and the ones you don't (system, 3rd party libs) with -isystem. The practical difference comes when warnings are enabled in that warnings which come from -isystem headers will be suppressed.
From the gcc documentation for -I:
Add the directory dir to the head of the list of directories to be searched for header files. This can be used to override a system header file, substituting your own version, since these directories are searched before the system header file directories. However, you should not use this option to add directories that contain vendor-supplied system header files (use -isystem for that). If you use more than one -I option, the directories are scanned in left-to-right order; the standard system directories come after.
If a standard system include directory, or a directory specified with -isystem, is also specified with -I, the -I option will be ignored. The directory will still be searched but as a system directory at its normal position in the system include chain. This is to ensure that GCC's procedure to fix buggy system headers and the ordering for the include_next directive are not inadvertently changed. If you really need to change the search order for system directories, use the -nostdinc and/or -isystem options.
So -I is probably the preferred option to specify the location of your header files, except for special cases such as vendor-supplied system headers.
You should use -I to specify the location of your headers.
The files you specify with -isystem are searched after -I is processed and receive a special treatment by gcc (the same as standard system headers).
So here's the difference I've found by running some experiments. Imagine the following setup:
my_std_lib/stdio.h
#ifndef _CUSTOM_STDIO_H
void test() {}
#endif
#include_next <stdio.h>
#include_next <custom.h>
my_user_lib/custom.h
#ifndef _CUSTOM_HEADER_H
void custom_func() {}
#endif
main.cpp
#include "stdio.h"
int main() {
test();
custom_func();
printf("Hello world!");
return 0;
}
If you compile using
g++ -isystem my_std_lib -isystem my_user_lib main.cpp everything will work fine.
However, g++ -isystem my_std_lib -I my_user_lib main.cpp will result into an error
In file included from main.cpp:1:
my_std_lib/stdio.h:10:15: fatal error: 'custom.h' file not found
#include_next <custom.h>
^~~~~~~~~~
1 error generated.
So what is going on?
To my understanding, when I write #include "stdio.h", GCC will start traversing the list of available header files until it finds my_std_lib/stdio.h. Directive #include_next <custom.h> at the end of this file tells the compiler to search for a custom.h by traversing include directories from its current position onwards.
When I add my_user_lib to the list of directories using -I flag, it appears before all the system directories in the directory list. Therefore, it appears in the list before my_std_lib directory and the #include_next fails.
The same would happen if I were to compile using g++ -isystem my_user_lib -isystem my_std_lib main.cpp. Apparently, directories are added to the list in the same order the flags are specified, so, again, my_user_lib will come before my_std_lib.
So in a nutshell, -I and -isystem differ in a way they add their target to the list of include directories.
When you include a header "Myheader.h" using -I, the compiler generates search order: "Myheader.h" , "system/headers". So if something can't be found in "MyHeader.h" you fallback on "system/headers". However when you use -isystem, you are basically saying that replace "system/headers" with whatever I give you. So there is no more falling back on "system/headers".

Resources