GNU gcc compiler cannot handle partial include statements - c

Imagine that I have a C-project in the following folder:
C:\microcontroller\stm32\myProject
I have two important folders inside myProject:
- source => here are all my .c and .h files
- build => gcc will write all the object files in here
Note: as you can see, the backward slashes indicate that this is happening on a Windows pc.
The figure below gives an overview:
I will not display my complete makefile here, because that would lead us too far. The rules inside the makefile for all .c => .o files are similar. Let us just focus on the compilation of one specific file: fileA2.c:
--------------------- COMPILATION OF FILE fileA2.c -------------------
Building ./build/folderA/fileA2.o
arm-none-eabi-gcc C:\\microcontroller\\stm32\\myProject\\source\\folderA\\fileA2.c
-o C:\\microcontroller\\stm32\\myProject\\build\\folderA\\fileA2.o
-c
-MMD
-mcpu=cortex-m7
-...
-IC:/microcontroller/stm32/myProject/source/folderA
-IC:/microcontroller/stm32/myProject/source/folderB
Notice that the gcc call ends with two include flags: one for folderA and one for folderB. This enables gcc to use any of the header files from these folders (fileA1.h, fileA2.h or fileB1.h) if fileA2.c has an import statement.
Let us now consider the source code in fileA2.c. We assume that this file needs to include fileA2.h and also fileB1.h.
/*******************************/
/* SOURCE CODE fileA2.c */
/*******************************/
// Some include statements
#include "fileA2.h"
#include "fileB1.h"
// Code
...
These include statements work perfectly. The gcc compiler retrieves the files fileA2.h and fileB1.h in the given folders. But I noticed that the following does not work:
/*******************************/
/* SOURCE CODE fileA2.c */
/*******************************/
// Some include statements
#include "fileA2.h"
#include "folderB/fileB1.h"
// Code
...
The last include statement is a 'partial path' to the file. I get the error when compiling:
fatal error: folderB/fileB1.h: No such file or directory
How can I get gcc to handle this?
PS: It is not my own habit to use 'partial paths'. But they appear a lot in the libraries from the silicon vendor of my chip, so I have to live with it.

You specify two paths to look for includes other than the current directory for the source file:
-IC:/microcontroller/stm32/myProject/source/folderA
-IC:/microcontroller/stm32/myProject/source/folderB
You get the error because neither
C:/microcontroller/stm32/myProject/source/folderA/folderB/fileB1.h nor
C:/microcontroller/stm32/myProject/source/folderB/folderB/fileB1.h exists.
To address the error, you can add the following path:
-IC:/microcontroller/stm32/myProject/source

When using double-quotes to include a header file the compiler first looks in the same directory as the current file. If the header file is not found then it continues with the standard include search paths.
So when the compiler compiles the file source/folderA/fileA2.c the first directory the compiler will look for include files is the source/folderA directory. In the first example the fileB1.h will not be found there, but since you added source/folderB to the standard search path it will be found there as source/folderB/fileB2.h.
In the second example there is no folderB/fileB1.h file on source/folderA so the compiler will search the standard search path. When it comes to source/folderB it will again try folderB/fileB2.h (i.e. source/folderB/folderB/fileB2.h) and it will still not be found, nor will it be found anywhere else.
You need to add -IC:/microcontroller/stm32/myProject/source to be able to find folderB/fileB1.h.

Apart of the two correct responses you have received before this, you have the third chance to specify the path to the file in the #include directive from the curren directory, as with
`#include "../folderB/fileB1.h"

Related

gcc 5.3.0 for unix reports included c file not found despite it existing

I created a very simple hello world program in C and I'm trying to call a function from an included file. The problem is the gcc program is strange in how it recognizes files.
Suppose the main file is named a.c and the file I want to include is b.c
So in my headers, I add:
#include <./b.c>
and when I run gcc 5.3.0, I receive this error:
./a.c:xx:yy: fatal error: ./b.c: No such file or directory
compilation terminated.
(where xx is the line number of the include line and yy is where the > is located on that line.)
I also tried another idea. I executed gcc while including the library path as follows:
gcc -I./ a.c
and I still get the same error.
In all tests, the file b.c exists in the same folder as a.c is and that I execute gcc from.
Now If I change the include line in the source to the following:
#include </path/to/b.c>
(thereby replacing the relative path with an absolute path) and run gcc, the file is then read for processing.
Is there a way I can change my code so I don't have to constantly specify absolute paths if I need to include multiple custom C files that are all in the same folder as the code that references them?
Like... is there such thing as....
#setlibpath /path/to/my/c/files
#include <./item.c>
#include <./item2.c>
....
#include <./itemn.c>
or do I have to do this....
#include </path/to/my/c/files/item1.c>
#include </path/to/my/c/files/item2.c>
....
#include </path/to/my/c/files/itemn.c>
Converting my comments into an answer.
Use double quotes around the name and the header (source file) will be found. Use angle brackets around system headers. And generally, avoid using ./ (and ../ even more so) in header names. For GCC, see also Include Operation and the following sections.
Also see the POSIX specification for the c99 compiler for the -I option:
Change the algorithm for searching for headers whose names are not absolute pathnames to look in the directory named by the directory pathname before looking in the usual places. Thus, headers whose names are enclosed in double-quotes ("") shall be searched for first in the directory of the file with the #include line, then in directories named in -I options, and last in the usual places. For headers whose names are enclosed in angle brackets (<>), the header shall be searched for only in directories named in -I options and then in the usual places. Directories named in -I options shall be searched in the order specified. If the -I option is used to specify a directory that is one of the usual places searched by default, the results are unspecified.
Note that ./b.c is not an absolute pathname — so the name is appended to a set of directories, and the current directory is not used unless the #include line uses double quotes.

Makefile, better understanding rules

Reading the official documentation
A prerequisite is a file that is used as input to create the target. A
target often depends on several files.
If my source file already includes the header, should I list the header in the rule?
src.c
#include <stdio.h>
#include "myheader.h"
int main()
{
printMessage();
return 0;
}
myheader.h
void printMessage()
{
printf("a message to screen\n");
}
makefile
src : src.o
cc -o src src.o
src.o : src.c
cc -c src.c
If I add myheader.h in the prerequisite it changes nothing, the same message is printed to screen. If a header is explicitly included, should it appear in the prerequisite?
The header file should be included in the dependency list.
The first time you use make to build your program, it will compile just the same whether you include myheader.h as a dependency or not. The difference is what happens when one of the files changes.
If you run make again without changing anything, it will say that "src" is up to date and won't compile anything. However, if you were to modify myheader.h and you didn't include it as a dependency, then make will say that the target is up to date. It doesn't look at the source file to see what files it includes. The make utility doesn't know anything about C or C++ source code (or any other source code). It looks only at whether the given files have changes without looking at their content.
When you include myheader.h as a dependency, if you later modify that file then running make will rebuild the program.
If you want to know all the non-system header files that a given source file depends on, you can run gcc with the -MM option. This will output a make rule listing the header dependencies of a source file.
For example, if you run gcc -MM src.c, you'll get the following output:
src.o: src.c myheader.h
You can then include that in your makefile.
Yes, you should.
The make program uses the list of files to figure out if a dependency changed and the the target should be rebuilt as a result. It needs you to specify that dependency explicitly.
It does not see the inclusion, it only sees the rules you specified. So there is a theoretical possibility that you change the header in a way that may require a re-compilation of src.o, but make will not know you did that unless you tell it to watch out.

New .h file in /usr/include linux

I developed small c application in linux. For this application i placed .h file in
linux standard path (/usr/include). Again i am compiling the same program
Output:
FATA ERROR : xyz.h(my own header file) not found
Do i need to update any variable in gcc or way to solve this problem
Thank You
Place the header file in the same directory as your .c file and use -I. when compiling
gcc -I. main.c -o myprog
You shouldn't place your header files in /usr/include that is meant for the system headers.
Note: you don't actually need the -I. because the current directory is searched by default, nevertheless, it doesn't hurt to add it.
Files specified by include directives are meant to be located in one of the search paths of the complier which are specified with the -I option in many cases (at least for gcc, is it the same for other compilers?). The search paths are verified in the order of definition in the command line.
There are 2 kinds of include directives:
double quoted ones (#include "xyz.h")
angle bracket ones (#include <xyz.h>)
IIRC, the default and first search path for the former is the working directory. For the later, it's compiler dependant, but it's usually /usr/include/.
Depending of the include directive you used, you should pick the right location for your file. Or better, put your file in a good location (say the same place as the including file), and add a search path to your gcc command.
You should separate your header .h files, from system and repository built headers so you don't break anything.
I would recommend making a folder in your home directory called include and just adding it to your path, that way you never have to worry about it again and no need for the -I/flag

C/C++ How to access header files?

I have added some source (header files) in a common folder (..\shared\abc) and my code file from another folder (..\src\xyz) has #include <abc/../foo.hpp>. I get this error:
Cannot open Source file error
I can fix that by giving absolute path but that change needs to be done at many place. What should I see to fix this?
Using VC9 nmake to compile code. This is a Makefile based project.
If the included files are from some library your code is using, you'll want to specify the include path with a compiler option. For the Visual C++ compiler the command-line option to specify additional include directories is /I, e.g.:
cl /I ..\shared foo.cpp
You'll need to modify the compiler options in your Makefile accordingly.

How to link a non-standard header file into a C compiler

I'm trying to use a non-standard header file (http://ndevilla.free.fr/gnuplot). Its used in lots of codes in various different places on my computer. Currently I have to put the header file and the object file in every folder which its needed with the preprocessor directive:
#include "gnuplot_i.h"
In the file. Is there a way by which I can put the header file in one place so I can reference it like other standard header file. Cheers.
Compile with -I<directory>
E.g.
compile with -I/usr/local/gnuplot/inc.
Also it might be worth your reading up on include paths and the difference between:
#include <include_file.h>
and
#include "include_file.h"
Linking in an object file needs to be done explicitly the same way as a C file, which means (I believe) that you need a full path. However if you archive it into a proper library then you can use -l<library name> and -L<library path> instead. E.g.
gcc -I/usr/local/gnuplot/inc -L/usr/local/gnuplot/lib -lgnuplot -o my_prog my_prog.c
Most compilers have a flag -I that lets you add a directory of your choosing to the search path for include files.

Resources