how #Include works when I compile a linux kernel - c

I need to compile a 2.6.28 linux kernel with arm-linux-gcc as an embeded system.I'm running Ubuntu 12.10 x86.
I viewed the 2.6 kernel source code and found this:
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/input.h>
#include <asm/io.h>
#include <asm/irq.h>
...
Will gcc compiler include these files from /usr/include /usr/local/include or from Linux_2.6.28 source folder?

The Kernel is self-contained. This means that it is not allowed to have any external dependency. In other words, your Kernel source tree contains all the material needed to build your Kernel. There is no point to look for code anywhere else.
As I suggested in my comments, just take a glance at the main Makefile. You'll find it under the root of your source tree. A little ctrl+f with "include" and here's interesting quotes I can feed back to you :
# Look for make include files relative to root of kernel src
MAKEFLAGS += --include-dir=$(srctree)
# .... Other stuff
# Use USERINCLUDE when you must reference the UAPI directories only.
USERINCLUDE := \
-I$(srctree)/arch/$(hdr-arch)/include/uapi \
-Iarch/$(hdr-arch)/include/generated/uapi \
-I$(srctree)/include/uapi \
-Iinclude/generated/uapi \
-include $(srctree)/include/linux/kconfig.h
# Use LINUXINCLUDE when you must reference the include/ directory.
# Needed to be compatible with the O= option
LINUXINCLUDE := \
-I$(srctree)/arch/$(hdr-arch)/include \
-Iarch/$(hdr-arch)/include/generated \
$(if $(KBUILD_SRC), -I$(srctree)/include) \
-Iinclude \
$(USERINCLUDE)

These files should not be directly accessible in the /usr/local etc. If they are, it's a problem, because your kernel will not build correctly unless it uses the ones that belong to that kernel. Some of these files change on a regular basis, as the kernel is being updated and improved.
The files used by the kernel are found in the linux/include/... directory. The compiler options use -nostdinc to avoid the standard include locations from being searched, and then add the appropriate locations from within the kernel source directory.

To find out what files are included for some given compilation, pass -H to gcc.
To add a directory for searching included files, pass -I somedir to gcc, e.g. -I /usr/local/include/; there are preprocessor options to remove directories or to clear the include path.

Related

C Project - How to manage a feature list?

I have multiple features that can be enabled or disabled at the build time in a project.
The current implementation uses declarations such as #define FEATURE_FOO. Whenever I need to do something related to a particular feature, I use a pre-processor directive such as #ifdef.
The features definitions are stored inside a global header file.
This approach have two drawbacks:
It requires to #include this global header in every file, before any other header.
I cannot easily disable a C file:
This is not very good:
// file: foo.c
#include <stdio.h>
#include "main_header.h"
#ifdef FEATURE_FOO
...
#endif
Because I prefer this:
// file: foo.c
#ifdef FEATURE_FOO
#include <stdio.h>
...
#endif
So, another approach to this problem is to declare all my features at the build time:
gcc -DFEATURE_FOO -c %< -o %#
What I don't like here is that I manually need to pass each feature to my compiler.
An acceptable workaround would be to read a features.list file that contains all the features. In my Makefile I will have:
DEFINES=$(shell perl -ne 'print "-DFEATURE_$1 " if /(\w+)/' features.list)
%o: %c
gcc $(DEFINES) -c %< -o $#
What better alternative can I find?
You can use gcc's option -include myheader.h.
It adds the content of myheader.h to the very beginning of the current translation unit's source.
I am using a GNU make based build process for most of my projects and although it wasn't about features so far, I used techniques that could help you here, too.
First, the idea to have a configuration file is very good, but why not just have it in make syntax and include it?
I use something like this
# default configuration
CC := gcc
DEBUG := 0
GCC32 := 0
USELTO := 1
# read local configuration
-include defaults.mk
You could use this for having a list of features, e.g. in your defaults.mk
FEATURES := foo bar baz
and then do something like
FEATUREDEFINES := $(addprefix -DFEATURE_, $(FEATURES))
There's a lot more black magic possible with GNU make when you use the $(eval ...) function -- this might be a good alternative for completely excluding a source file from compilation depending on your settings. I use this for platform-specific implementations. For example I have this included Makefile for building a binary:
P:= src
T:= csnake
csnake_SOURCES:= csnake.c utils.c game.c board.c snake.c food.c screen.c
csnake_PLATFORMSOURCES:= ticker.c
csnake_LDFLAGS:= -lm
csnake_posix_LDFLAGS:= -lcurses
csnake_dos_LDFLAGS:= -Wl,-Bstatic -lpdcurses
csnake_win32_LDFLAGS:= -static-libgcc -Wl,-Bstatic -lpdcurses \
-Wl,-Bdynamic -lwinmm
csnake_win32_RES:= res$(PSEP)csnake.rc
$(eval $(BINRULES))
My P is the current relative path in the source tree, T is the target to build and PSEP is just a helper variable containing / or \ in order to be compatible with windows. The rest should be quite self-explanatory -- for $(T)_PLATFORMSOURCES, $(BINRULES) looks in the relative path platform/$(PLATFORM)/. It works like this:
define BINRULES
BINARIES += $$(BINDIR)$$(PSEP)$(T)$$(EXE)
$(T)_SOURCES_FULL := $$(addprefix $(P)$$(PSEP),$$($(T)_SOURCES))
ifneq ($$(strip $$($(T)_PLATFORMSOURCES)),)
$(T)_SOURCES_FULL += $$(addprefix \
$(P)$$(PSEP)platform$$(PSEP)$$(PLATFORM)$$(PSEP), \
$$($(T)_PLATFORMSOURCES))
endif
[...] (... further rules ... )
endef
All these double dollars are there because $(eval ...) will expand variables -- that's desired for $(T) and $(P) but not for all the other ones, so they are protected with an extra dollar. I'm just quoting the part doing the magic for deciding which files to compile here. If you consider doing something like this, see the full example

C/C++ file before preprocessing

Is it possible to look at a c/c++ file before preprocessing? Or rather after just a half-hearted pre-processing? Basically there is a
#define <commonly_used_word> 0
in a third party library header and I want to figure out where it is. So basically, I just want the compiler to include all the headers but not the the preprocessor as such.
Your original source file is file before preprocessing.
It sounds like you want your #include directives processed, yet you want to keep macros non-substituted. Both actions are carried out by the preprocessor.
In general case it is impossible, since in C and C++ it is legal to use macros as include file names, as in
#define INCLUDE_FILE "stdio.h"
#include INCLUDE_FILE
Achieving what you want would require a preprocessor specifically designed to satisfy your request. I, for one, don't know of any such preprocessor implementation.
If you want to find where a specific macro is defined, you might try the following trick: define your own macro with the same name before including any headers, and start compilation. The compiler (the preprocessor) should complain about macro redefinition when it encounters the library definition of the same macro and point out its location to you.
There are GCC-specific -M and -MM options:
To list absolute paths of include files, use -M
Instead of outputting the result of preprocessing, output a rule
suitable for make describing the dependencies of the main source file.
The preprocessor outputs one make rule containing the object file name
for that source file, a colon, and the names of all the included
files, including those coming from -include or -imacros command line
options. gcc -M test.c
If you dont want the system includes like
#include <stdio.h>,
then use -MM Like -M but do not mention header files that are found in
system header directories, nor header files that are included,
directly or indirectly, from such a header. gcc -MM test.c
That could significantly narrow down the search area.
http://www.math-linux.com/spip.php?article263
You can tell cpp to generate the list of included files using -M option:
$ cpp -M a.c
a.o: a.c /usr/include/stdio.h /usr/include/features.h \
/usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
/usr/include/gnu/stubs.h /usr/include/gnu/stubs-64.h \
/usr/lib/gcc/x86_64-pc-linux-gnu/4.7.1/include/stddef.h \
/usr/include/bits/types.h /usr/include/bits/typesizes.h \
/usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
/usr/lib/gcc/x86_64-pc-linux-gnu/4.7.1/include/stdarg.h \
/usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h
It gives you a Makefile rule format but you could ignore that and use with any other command.
For example, you can grep for the symbol (here I'm ignoring stderr because of \ and a.o: not being a real file names -- laziness):
$ grep '#\s*define\s*BUFSIZ' $(cpp -M a.c) 2>/dev/null
/usr/include/stdio.h:# define BUFSIZ _IO_BUFSIZ
You can also use a program like ctags to find the symbol for you:
$ ctags $(cpp -M a.c)
...
$ grep BUFSIZ tags
BUFSIZ /usr/include/stdio.h 128;" d
If you know which header files contain the definition you're looking for, e.g by using find and grep as suggested, you may be able to pinpoint which one is affecting the current source file by getting gcc to print the header inclusion tree. As described in gcc's documentation, you can achieve this by using the -H option, possibly combined with -MG to eliminate normal processing.

How to compile .c file with OpenSSL includes?

I am trying to compile a small .c file that has the following includes:
#include <openssl/ssl.h>
#include <openssl/rsa.h>
#include <openssl/x509.h>
#include <openssl/evp.h>
In the same folder where I have the .c file I have a /openssl with all those files (and more), also in synaptic package manager I see OpenSSL installed, I am trying to compile with this:
gcc -o Opentest Opentest.c -lcrypto
but I always get the errors:
error: openssl/ssl.h: No such file or directory
error: openssl/rsa.h: No such file or directory
error: openssl/x509.h: No such file or directory
error: openssl/evp.h: No such file or directory
The file I want to compile is only a .c file, doesn't have Makefile or ./configure.
I already tried:
env CFLAGS=-I/path/to/openssl/
and tried to compile again but I get the same errors.
What should I do in order to compile with OpenSSL includes?
Your include paths indicate that you should be compiling against the system's OpenSSL installation. You shouldn't have the .h files in your package directory - it should be picking them up from /usr/include/openssl.
The plain OpenSSL package (libssl) doesn't include the .h files - you need to install the development package as well. This is named libssl-dev on Debian, Ubuntu and similar distributions, and openssl-devel on CentOS, Fedora, Red Hat and similar.
Use the -I flag to gcc properly.
gcc -I/path/to/openssl/ -o Opentest -lcrypto Opentest.c
The -I should point to the directory containing the openssl folder.
Use the snippet below as a solution for the cited challenge;
yum install openssl
yum install openssl-devel
Tested and proved effective on CentOS version 5.4 with keepalived version 1.2.7.
You need to include the library path (-L/usr/local/lib/)
gcc -o Opentest Opentest.c -L/usr/local/lib/ -lssl -lcrypto
It works for me.
If the OpenSSL headers are in the openssl sub-directory of the current directory, use:
gcc -I. -o Opentest Opentest.c -lcrypto
The pre-processor looks to create a name such as "./openssl/ssl.h" from the "." in the -I option and the name specified in angle brackets. If you had specified the names in double quotes (#include "openssl/ssl.h"), you might never have needed to ask the question; the compiler on Unix usually searches for headers enclosed in double quotes in the current directory automatically, but it does not do so for headers enclosed in angle brackets (#include <openssl/ssl.h>). It is implementation defined behaviour.
You don't say where the OpenSSL libraries are - you might need to add an appropriate option and argument to specify that, such as '-L /opt/openssl/lib'.
From the openssl.pc file
prefix=/usr
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include
Name: OpenSSL
Description: Secure Sockets Layer and cryptography libraries and tools
Version: 0.9.8g
Requires:
Libs: -L${libdir} -lssl -lcrypto
Libs.private: -ldl -Wl,-Bsymbolic-functions -lz
Cflags: -I${includedir}
You can note the Include directory path and the Libs path from this. Now your prefix for the include files is /home/username/Programming .
Hence your include file option should be -I//home/username/Programming.
(Yes i got it from the comments above)
This is just to remove logs regarding the headers. You may as well provide -L<Lib path> option for linking with the -lcrypto library.
For this gcc error, you should reference to to the gcc document about Search Path.
In short:
1) If you use angle brackets(<>) with #include, gcc will search header file firstly from system path such as /usr/local/include and /usr/include, etc.
2) The path specified by -Ldir command-line option, will be searched before the default directories.
3)If you use quotation("") with #include as #include "file", the directory containing the current file will be searched firstly.
so, the answer to your question is as following:
1) If you want to use header files in your source code folder, replace <> with "" in #include directive.
2) if you want to use -I command line option, add it to your compile command line.(if set CFLAGS in environment variables, It will not referenced automatically)
3) About package configuration(openssl.pc), I do not think it will be referenced without explicitly declared in build configuration.

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

Manipulating the search path for include files

My development environment is such that I have some_header.h in /usr/include and in /another/directory. /another/directory contains some header files I need to include in my program, but I want to use some_header.h from /usr/include. When I use
gcc ... -I/another/directory
gcc uses /another/directory/some_header.h. If I use
gcc ... -I/usr/include -I/another/directory
gcc does the same thing because it ignores /usr/include since it is part of the standard search path, but it gets searched after non standard directories included with -I.
Any ideas?
Use the -iquote switch:
Include the files that are in another/directory using quotes:
#include "another_file.h"
Then use
gcc -iquote /another/include ...
to add a search path for quoted include files. This switch will add a directory that is searched for quoted include files after the current directory and before -I and system include paths.
Include your other include files using brackets (i.e. #include <header.h>).
See here for more information:
Where are include files stored - Ubuntu Linux, GCC
Have you looked at -nostdinc ?
The manual says:
-nostdinc
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.
Of course that means that you will have to specify anything that normally goes on the standard search path that you do want...
Have you tried unsetting the system INCLUDE path environment variable?

Resources