makefile error with 2 Dirs, 3 header Files - c++

I have 2 Dirs and 3 header files stored in them, as follows:
Dir A : contains Header files A and C
Dir B : contains Header file B
Dirs A and B are sub-directories of a dir named Apps (which is a subdir of some other dirs).
Basically, the problem occurred in a similar situation, from which I have isolated the problem. Hence, the C++ source files shown below are trivial:
Header file A.h:
#ifndef A_H
#define A_H
class A
{
};
#endif /// A_H
Header file C.h:
#ifndef C_H
#define C_H
#include "B.h"
class C
{
};
Tester for A.h, viz. TestA.cpp:
/** TestA.cpp */
#include "A.h"
/// ...
int main()
{
}
Tester for C.h, viz. TestC.cpp:
/** TestC.cpp */
#include "C.h"
/// ...
int main()
{
}
Dir B contains 1 C++ header file B.h and its tester TestB.cpp, both trivial:
Header file B.h:
#ifndef B_H
#define B_H
#include "A.h"
class B
{
};
#endif /// B_H
Tester for B.h, viz. TestB.cpp:
/** TestB.cpp */
#include "B.h"
/// ...
int main()
{
}
The 3 testers TestA.cpp, TestB.cpp and TestC.cpp have 3 makefiles: MakeA, MakeB and MakeC respectively. MakeA and MakeC are in dir A and MakeB is in dir B, as expected.
I am not showing MakeA and MakeB, since they work correctly.
The error occurs in MakeC:
CPP = g++
OFLAG = -o
CFLAG = -std=c++11 -c
PROG1 = TestC
HC = C
HB = B
HA = A
HBDIR = ../B/
HADIR = ./
IHBDIR = -I$(HBDIR)
IHADIR = -I$(HADIR)
all : $(PROG1).o $(PROG1).exe run1
$(PROG1).o : $(PROG1).cpp $(HADIR)$(HC).h $(HBDIR)$(HB).h $(HADIR)$(HA).h
$(CPP) $(CFLAG) $(IHADIR) $(IHBDIR) $<
$(PROG1).exe : $(PROG1).o
$(CPP) $(OFLAG) $# $^
run1:
$(PROG1)
This make file is unable to locate header file A (which is #included by header file B) and gives the following error:
In file ...
../B/B.h fatal error: A.h : no such file or directory
#include "A.h"
compilation terminated
Evidently, make is searching for A.h in B.h's dir (since B.h #includes A.h). However, I have defined the symbol HADIR (as ./), which should have caused make to search in the default dir, which is Dir A.
Please note:
1) The header file references are simple and linear : A.h is #included by B.h which is #included by C.h.
2) I don't wish to hard-code dir paths in the source files. They must be stored only in the makefiles, since that's one of the purposes of makefiles.
3) There are 2 solutions to the problem that I know of:
a) Relocate C.h, its tester and makefile to a dir C. However, I don't want to do this, since A.h and C.h are semantically related.
b) In MakeC, define HADIR as ../A, rather than ./ But I don't understand why I should do that.
The BAT file that invokes the make utility with MakeC as input makefile, is as follows:
cd /f/Files/C/SW/Applications/Samples/C++Samples/Introductory/
Classes/Apps/A/
make -f MakeC
Thanks.

See this link for information on which paths include searches. Assuming you used the form include "file" (with quotes, not #include <file>, which is slightly different):
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.
...
There are a number of command-line options you can use to add
additional directories to the search path. The most commonly-used
option is -Idir, which causes dir to be searched after the current
directory (for the quote form of the directive) and ahead of the
standard system directories. You can specify multiple -I options on
the command line, in which case the directories are searched in
left-to-right order.
notice that
directory of the current file
refers to the directory that gcc was invoked from, as opposed to the directory of the source file (not the best wording). So, if you invoke gcc from the directory of your .c file, you would want to add a -IA -IB flag to your compiler options, and then do not include paths in your #include directives (assuming gcc is being called from the directory of the .c file).
If you do want to include paths, they must be relative to the directory from which gcc was invoked, or one of the other include paths specified by a -I option.
---- EDIT -----
OK, I just read your updates, and it seems that TestC.c is in directory A, which I didn't get from your original post This means you're compiling from directory A. In this case I cannot reproduce your problem (at least not on my linux system):
[157]~/tmp/tmp9/A> find .. -type f -exec echo "------ " {} " ------" \; -exec more {} \;
------ ../A/A.h ------
#pragma message "A.h"
// blank
------ ../A/C.h ------
#pragma message "C.h"
#include "B.h"
------ ../A/testC.c ------
#pragma "message file.c"
#include "C.h"
int main() {}
------ ../B/B.h ------
#pragma message B.H
#include "A.h"
[157]~/tmp/tmp9/A> gcc -I. -I../B testC.c
In file included from testC.c:2:
C.h:1: note: #pragma message: C.h
In file included from C.h:2,
from testC.c:2:
../B/B.h:1: warning: expected a string after ‘#pragma message’
In file included from ../B/B.h:2,
from C.h:2,
from testC.c:2:
./A.h:1: note: #pragma message: A.h
[157]~/tmp/tmp9/A>
Your make command should echo the command used to build your test program -- attach that output to the question.

Per https://gcc.gnu.org/onlinedocs/gcc-3.0.2/cpp_2.html#SEC6:
Section 2.1: Include Syntax
[#include with quotation marks] is used for header files of your own program. It searches for a file named file first in the directory containing the current file, then in the same directories used for <file>
Since we're discussing an include-with-quotes from another header, we must figure out what is considered the "current file". Our options are:
the source file that included the original header
the original header itself (that now includes the subject header)
Section 2.2: Include Operation
The `#include' directive works by directing the C preprocessor to scan the specified file as input before continuing with the rest of the current file
To me, this wording implies that #include acts as an interruption to the processing of "current file", during which the included file becomes "current". (Consider how this would have been written if the #include were interpreted as expanding into or as a part of the #including file.) Also, if the quotation-mark version of #include were interpreted in the context of the #including file, it would break all the time and be mostly useless.
So the #include "A.h" within B.h looks for A.h relative to the location of B.h. But $HADIR is not equal to $HBDIR so this lookup fails.
Note however that -I adds to the list of places that should be searched by #include-with-angle-brackets...which should also be searched after "directory of the current file" for #include-with-quotation-marks...so your compiler is doing something weird with it's search.
I also confirm that gcc 4.8.5 does not repro your issue. Here's my test setup relative to the directory Prog
[Prog]$ find ..
../Prog
../Prog/A.h
../Prog/MakeC
../Prog/TestA.cpp
../Prog/TestC.cpp
../Prog/C.h
../B
../B/B.h
../B/TestB.cpp
Then building yields:
[Prog]$ make -f MakeC
g++ -std=c++11 -c -I./ -I../B/ TestC.cpp
g++ -o TestC.exe TestC.o
TestC
What compiler are you using? (I'd bet a fair sum it's either old (circa gcc 2.9.6) or is customized by a vendor to target an embedded plaform) I've seen interesting include path checks with some of these.
Here's a small contrived demo to show the proper behavior of #include-with-quotes:
inc/a.h
#pragma once
#include "b.h"
inc/b.h
#pragma once
extern int garbage;
test.c
#include "inc/a.h"
Then
$ gcc -E test.c
# 1 "test.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "test.c"
# 1 "inc/a.h" 1
# 1 "inc/b.h" 1
extern int garbage;
# 4 "inc/a.h" 2
# 1 "test.c" 2
Note the main .c file includes "inc/a.h" directly, and there is no search path given on the compiler commandline, yet it still finds "b.h".

OK, I've finally solved the problem as follows:
1) Make the BAT file set the default dir to 1 dir above the A and B dirs, ie, to the Apps dir, and invoke the make utility from there:
cd /f/Files/C/SW/Applications/Samples/C++Samples/Introductory/Classes/Apps/
make -f A/MakeC
2) Modify the makefile to access each header explicitly from the dir in which it is stored, create the obj and exe file in a specified dir and invoke the exe file in the specified dir:
CPP = g++
OFLAG = -o
CFLAG = -std=c++11 -c
# BAT file invoking MakeC sets default to ... Classes/Apps/
HADIR = ./A/
HBDIR = ./B/
# HADIR contains HA and HC
# HBDIR contains HB
HA = A
HC = C
HB = B
PROG1 = TestC
IHADIR = -I$(HADIR)
IHBDIR = -I$(HBDIR)
all : $(PROG1).o $(PROG1).exe run1
$(PROG1).o : $(HADIR)$(PROG1).cpp $(HADIR)$(HC).h $(HBDIR)$(HB).h $(HADIR)$(HA).h
# Create obj file in HADIR explicitly
$(CPP) $(OFLAG) $(HADIR)$# $(CFLAG) $(IHADIR) $(IHBDIR) $<
$(PROG1).exe : $(HADIR)$(PROG1).o
# Create exe file in HADIR explicitly
$(CPP) $(OFLAG) $(HADIR)$# $^
clean:
# Specify dir explicitly
rm $(HADIR)*.exe $(HADIR)*.o
run1:
# Specify dir explicitly
$(HADIR)$(PROG1)
As I've stated, I'm using g++ 4.8.1.
What worked for me, was to have the invoking BAT file set the default dir to one level above the dirs that contain the source files and in the makefile, specify the dirs explicitly.
---- EDIT ----
I'd like to suggest a possible reason for why this works.
First, notice that originally, the HADIR variable was set to ./ (the default dir).
As #lockcmpxchg8b said, the "default dir" could be interpreted as (a) wrt the original file or (b) the #included header file. These are the only 2 possibilities. Since the compiler can't find the #included header, it means it has selected the wrong possibility. This is obviously a version-specific gcc problem, since others can't repro the problem on later gcc versions.
Then, the solution is to avoid using ./ as a value for a dir symbol such as HADIR. Instead set the default dir outside make to another dir. In this case, it was done to the dir one level above A and B (viz. Apps). Then, the makefile's dir symbols can be made all wrt to that dir and would obviously not be ./
With values other than ./ (interpreted as the default dir by the compiler), the compiler interprets the value for the dir symbol as desired.

I think in your "B.h", you should do: #include "(Adir)/A.h"
It seems like "A.h" is in a adjacent directory of the "B.h" directory. so when "B.h" tries to look for it in its current directory, it can't find it.
I'm guessing #include "../A/A.h"

Related

How to specify location of angle-bracket headers in gcc/g++?

Is there a way to tell gcc/g++/clang where to look for headers that are included via angle brackets ("<", ">")?
I don't use the angle bracket convention for non-system files, but the problem is that when I try using the headers from some packages I download, I get errors for all of the included files.
For example, say I want to include headers from a module called Foo that I download:
/foo-v1.0/include/DependencyA.hpp:
#ifndef DEP_A_HPP
#define DEP_A_HPP
class DependencyA
{
...
};
#endif
/foo-v1.0/include/Api.hpp:
#ifndef FOO_HPP
#define FOO_HPP
#include <Foo/DependencyA.hpp>
void doSomething(DependencyA* da);
#endif
Then, in my own code:
/mycode.cpp:
#include "/foo-v1.0/include/Api.hpp"
DependencyA* da = new DependencyA();
doSomething(da);
I get a compile error:
fatal error: 'Foo/DependencyA.hpp' file not found
I've tried building with:
clang -c mycode.cpp -isystem./foo-v1.0/include -o mycode.o
clang -c mycode.cpp -isystem./foo-v1.0/include/ -o mycode.o
clang -c mycode.cpp -I./foo-v1.0/include -o mycode.o
clang -c mycode.cpp -I./foo-v1.0/include/ -o mycode.o
and so on, to no avail.
How do I tell the compiler to resolve <Foo/**/*> to a particular root directory for every included file?
The answer is already in the comments.
To check include dirs one can use the method described here: What are the GCC default include directories? , preferably with - replaced with /dev/null:
clang -xc -E -v /dev/null
On my machine for clang it gives
ignoring nonexistent directory "/include"
#include "..." search starts here:
#include <...> search starts here:
/usr/local/include
/usr/lib/clang/11.0.0/include
/usr/include
End of search list.
To discover how to manipulate this list, it suffices to read the gcc (or clang) manual (man clang or find it in the Internet, for example, https://man7.org/linux/man-pages/man1/gcc.1.html ). For gcc this reads:
Options for Directory Search
These options specify directories to search for header files, for
libraries and for parts of the compiler:
-I dir
-iquote dir
-isystem dir
-idirafter dir
Add the directory dir to the list of directories to be searched
for header files during preprocessing. If dir begins with = or
$SYSROOT, then the = or $SYSROOT is replaced by the sysroot
prefix; see --sysroot and -isysroot.
Directories specified with -iquote apply only to the quote form
of the directive, "#include "file"". Directories specified with
-I, -isystem, or -idirafter apply to lookup for both the
"#include "file"" and "#include <file>" directives.
This description is followed by a detailed description of the order in which header files are searched and by some recommendations as to which option to use for which purpose. You'll find it in the manual. Search for "Options for Directory Search".
What I really don't like in your code is this line:
#include "/foo-v1.0/include/Api.hpp"
It seems to contain the absolute path to the header and I've never seen anything like this. I would change it to
#include "Api.hpp"
with /foo-v1.0/include being added to the search list via the usual compiler -I command-line option.

Generate binaries using macros inside a source file

I am trying to generate output file by the use of macro in source file.
Whatever a macro name is, generate the final .exe file by using the macro name.
#include <iostream>
#define Apple
//#define Banana
//#define Mango
int main()
{
...
}
How could i generate an output file name like Apple.exe ?
compiler: g++
OS: windows
You cannot steer the name of the final linker artifacts (executable in your case) from within the source code.
This needs to be done using the -o <filename> linker flag, thus in your case
> g++ -o Banana.exe main.cpp -DNAME=Banana
To control this more easily you can define these as variables in a makefile, e.g. like
# Comment the current, and uncomment a different definiton to change the executables
# name and the macro definition for NAME
FINAL_NAME = Banana
# FINAL_NAME = Apple
# FINAL_NAME = Mango
$(FINAL_NAME).exe : main.cpp
g++ -o $(FINAL_NAME).exe main.cpp -DNAME=$(FINAL_NAME)

compilation error when including directory containing headers

I have a directory maths which is a library that is comprised solely of header files.
I am trying to compile my program by running the following command in my home directory:
g++ -I ../maths prog1.cpp prog2.cpp test.cpp -o et -lboost_date_time -lgsl -lgslcblas
but I get the following compilation error:
prog1.cpp:4:23: fatal error: maths/Dense: No such file or directory
compilation terminated.
prog2.cpp:6:23: fatal error: maths/Dense: No such file or directory
compilation terminated.
maths is located in the same directory(i.e. my home directory) as the .cpp files and I am running the compilation line from my home as well.
prog1.cpp and prog2.cpp have the following headers
#include<maths/Dense> on lines 4 and 6 respectively, hence I am getting the error.
how do I fix it.
You can either change your include path to -I.. or your includes to #include <Dense>
Wait, if maths is in the same directory as your source files and that is your current directory, you can either change your include path to -I. or your includes to #include "Dense"
maths is located in the same directory(i.e. my home directory) as the .cpp files
Your include path is given as -I ../maths. You need -I ./maths – or simpler, -I maths since maths is a subdirectory of the current directory, not of the parent directory. Right?
Then in your C++ file, use #include <Dense>. If you want to use #include <maths/Dense> you need to adapt the include path. However, using -I. may lead to massive problems1, I strongly advise against this.
Instead, it’s common practice to have an include subdirectory that is included. So your folder structure should preferably look as follows:
./
+ include/
| + maths/
| + Dense
|
+ your_file.cpp
Then use -I include, and in your C++ file, #include <maths/Dense>.
1) Consider what happens if you’ve got a file ./map.cpp from which you generate an executable called ./map. As soon as you use #include <map> anywhere in your code, this will try to include ./map instead of the map standard header.

Include one header file in each source file

Say you have 100s of source files (.c or .cpp) files, and you want to include some definitions, function/variable declarations in each of them. Normally in C/C++, you use header files for that purpose. But in this case you need to put #include "header.h" in each source file.
Now my question is, is there a way to include one header for all the files without putting #include "header.h" in each of the file, because it will be very tiresome to write #include "header.h" for 100s of source files.
You can use the -include flag for clang or GCC. From the man page:
-include file
Process file as if "#include "file"" appeared as the first line of the primary source file. However, the first directory searched for file is the preprocessor's working directory instead of the directory containing the main source file. If not found there, it is searched for in the remainder of the "#include "..."" search chain as normal.
If multiple -include options are given, the files are included in the order they appear on the command line.
Example:
clang -include header.h -c file1.c
clang -include header.h -c file2.c
clang -include header.h -c file3.c
clang -o app file1.o file2.o file3.o
MSVC has the /FI flag, which is similar.
You could solve this problem using a unix pipe
find ./ -name "*.c" -or -name "*.cpp" | xargs -n 1 sed -i '1 i #include <my_header.h>'
You can't do that, although you could write a script for you to do it. A script that takes each files, and writes #include "header.h" at top. Edit: -include in gcc does this.
However, what you need is achievable in a different way through the compiler options. In gcc, with -D.
Let's say, you want the define DEBUG_LEVEL to 2 in all your source files. You can simply do this by invoking gcc like this:
gcc -DDEBUG_LEVEL=2
Note that in this case, you would need to rebuild all your project (which would have been done anyway if you had changed this definition in 1 header file to which ALL the source files depend on)
Header files are not definitions - they are declarations.
You put as few in as possible - saves the compiler work and also inter-dependencies.
You can even reduce the number further by using forward declarations in those header files.
If you are clever you can get you IDE to help you out with filling in the gaps instead of hurting your fingers.

BOOST_PP_ITERATE() result in "no such file or directory"

I'm learning the boost preprocessor library (because i need to use it), and I wanted to try the file iteration mechanism. I've set up a minimal project with a.cpp and b.hpp. What I'm trying to do is including many time b.hpp via the boost pp :
#include <boost/preprocessor/iteration/iterate.hpp>
#define BOOST_PP_ITERATION_LIMITS (0, 5)
#define BOOST_PP_FILENAME_1 "b.hpp"
#include BOOST_PP_ITERATE()
When I try to compile (with -E to see the preprocessor result) :
g++ -E a.cpp > pp_result
I got this error :
In file included from a.cpp:
/usr/local/include/boost/preprocessor/iteration/detail/iter/forward1.hpp:47:37: error: b.hpp: No such file or directory
b.hpp is in the same directory, I can't see what I'm dooing wrong. It seems the g++ searches b.hpp in the same directory as forward1.hpp, but following the boost documentation my code should work (my boost version is 1.44).
Does anybody experienced the same problem ?
Yep, you need to add -I. to the command line in order to make it work. This adds the directory you started gcc in to the include search path, allowing the compiler to find the file b.hpp.