Compilation failing - no #include - boost - c++

I'm trying to compile a third-party library, but g++ is complaining about the following line:
typedef boost::shared_ptr<MessageConsumer> MessageConsumerPtr;
The strange thing is, there is no #include directive in the file - and it is clearly supposed to be this way; there are about 60 files with the same (or very similar) issues. Clearly if there was an #include directive referencing the relevant boost header this would compile cleanly.
My question is: how can I get g++ to somehow automagically find the relevant symbol (in all instances of this issue, it is a namespace that can't be found - usually std:: or boost::) by either automatically processing the relevant header (or some other mechanism).
Thanks.
Edit
My current g++ call looks like:
g++ -fPIC -O3 -DUSING_PCH -D_REENTRANT -I/usr/include/boost -I./ -c MessageInterpreter.cpp -o MessageInterpreter.o

You can use the -include command line option:
g++ -include boost/shared_ptr.hpp ...
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.

Create your own wrapper .h file that includes the boost .h and then the broken .h .
Or (very fragile) ensure that you precede every use of the broken .h with boost .h .

Perhaps the third-party library is designed in such a way that you should always include a certain "main" header file in order to get the dependencies right.
Otherwise, you can add #include <boost/shared_ptr.hpp> before including the third-party header file that is giving the error message.

Related

Building a C++ template library with make

I am having difficulties with re-writting my C++ library into template form; main problem concerns re-designing the Makefile.
In the previous state, when it was non-template I had:
a header file lib.h in which (protected by include guards) we have the declarations of classes and overloaded operators. This file does not include any other libraries at all.
an implementation file lib.cpp in which, on top of the file, I include many headers from the standard library (cmath, iostream, etc) as well as I include the header file for this custom library: #include "lib.h"
a Makefile with commands for build/install the library:
CC = g++
CFLAGS = -O2
SRC = lib.cpp
HDR = $(SRC:.cpp=.h)
OBJ = $(SRC:.cpp=.o)
LIB = $(OBJ:.o=.a)
.PHONY: all install clean uninstall
# =========================================================
# Build
# =========================================================
all: $(LIB)
# Create an object file
$(OBJ):
$(CC) $(CFLAGS) -c -o $# $(SRC)
# Create a static library file
$(LIB): $(OBJ)
ar rcs $# $<
# =========================================================
# Install
# =========================================================
install: ~/lib/lib/$(LIB) ~/lib/include/$(HDR)
# Create top-level directory for the libraries
~/lib:
mkdir -p $#;
# Create top-level directory for the static library files
~/lib/lib:
mkdir -p $#;
# Create top-level directory for the headers
~/lib/include:
mkdir -p $#;
# Copy the library file into the right directory
~/lib/lib/$(LIB): $(LIB) ~/lib/lib
cp $< $#
# Copy the header file into the right directory
~/lib/include/$(HDR): $(HDR) ~/lib/include
cp $< $#
following the installation my CI (GH Actions) would compile a small test program, which includes my library header (#include <lib.h>) with the following command:
g++ -O0 -Wall --std=c++14 test.cpp -I ~/lib/include/ ~/lib/lib/lib.a -o test
This setup worked fine.
Problems emerge now, when I want to re-write my class to be template.
Following the information in this post I have added an #include "lib.cpp" at the end of the header file for my library (inside the include guard, ofc). With that change I needed to adjust the compilation process and do not provide my implementation file in the command line (as it is already included in the header and I have to avoid re-definition errors). That works fine. The core of the problem is now in the Makefile, in the command to build an object file. As I try to compile the implementation file of my library, it includes the header and the header includes the implementation again... I red about the problem in this port and they suggest to remove the header inclusion from the implementation file. So I did that, I commented the #include "lib.h" and tried to run:
g++ -O2 -c -o lib.o lib.cpp
And I end up with a lot of error: use of undeclared identifier errors...
How can I build the library properly with make? My constraint is that the library stays in two separate files: header and implementation. What I want in the end is to be able to #include <lib.h> in my further programs.
Is it even possible to create an archived object file? What about shared object library (.so)
I have added an #include "lib.cpp" at the end of the header file for my library (inside the include guard, ofc).
I can't say I think much of the advice you followed there. Code that is intended to be used as or in a header should be named appropriately (.h, .hpp, or whatever convention your project follows), and code that is suitable for direct compilation pretty much never belongs in a header. Perhaps your conversion involves changing everything of the latter kind into to former kind, so maybe you want to rename lib.cpp to lib_impl.h, or something similar, and skip trying to compile it at all. Maybe.
Note well, however, that if you name and structure the implementation code as a header, then it needs its own include guards. Note also that it must not, then, contain any external, non-template functions. If it did, then no two separate translation units contributing to the same program could both include the header, as that would result in duplicate function definitions, include guards notwithstanding. And if there are no external, non-template functions (and no external object definitions) then it is pointless to try to compile to an object file, as there would be no accessible entry point to any function within.
How can I build the library properly with make?
This isn't really about make in particular. That just provides automation. The issue is with the structure of the library itself and your expectations.
My constraint is
that the library stays in two separate files: header and
implementation.
This constraint makes sense only if the implementation contains any instantiated templates for external objects or functions, or any external non-template functions or objects. These are the things that would contribute to a buildable object file that you could directly or indirectly link to applications. If converting to a template library means that there are no longer any such entities in your library then the constraint is arbitrary, as the converted result is a header-only library. Nevertheless, you can split up your headers any way you like, as long as each resulting one is structured as a header, with only contents appropriate for a header, and with its own inclusion guards.
On the other hand, if your converted implementation code does contain any of those things then they must not be #included into any header, as discussed above.
What I want in the end is to be able to #include <lib.h> in my further programs.
If the converted implementation code is suitable for use as or in a header, then you are already there, but it would be much better style to rename your lib.cpp as a header. If you want to be able to include that header directly into code other than the main library header then it needs its own inclusion guards -- that will take care of the duplicate declarations. Do note, however, that those errors arise from the fact that you have a circular dependency, and that's a strong sign that you ought to refactor. Such a refactoring would involve moving enough code from lib.cpp to lib.h that the circular dependency can be removed (one of the files would no longer #include the other).
Whatever implementation code is not suitable for use in a header obviously must not be included into the header. If any such code remains in the converted library then perhaps you keep that in lib.cpp, and move the rest into lib.h
Is it even possible to create an archived object file? What about shared object library (.so)
Templates cannot be compiled. They are templates for code that can be compiled: their instantiations. If your conversion leaves nothing else then no, you cannot usefully create an object file or a shared library. And you don't need to do, for this is a header-only library.

linker input file unused because linking not done, I can't get .o

I have a template class of a binary tree, tree.tpp and tree.h. I have done a test with the class but I can't compile it
#include <cstdlib>
#include <iostream>
#include "arbolbinario.h"
using namespace std;
int main(int argc, char** argv) {
ArbolBinario<int> pila(45);
return 0;
}
And I'm having the following error when I do: g++ -c -o ./tree.o ./tree.tpp -I ./tree.h
g++: warning: ./tree.tpp: linker input file unused because linking not done
(I'm working with netbeans)
.tpp is not one of the file endings recognized by g++, see its documentation.
Therefore g++ assumes that you want the file to be passed to the linker directly. But since you used the -c flag, which indicates that you want g++ to only compile, but not invoke the linker, you get that error message.
The solution is to tell g++ what kind of file it is that you are passing it explicitly:
g++ -c -o ./tree.o -x c++ ./tree.tpp -I ./tree.h
or, better, rename your C++ source file use one of the common file endings for C++ source files, e.g. .cpp, .cc, .cxx, etc. That would result in less trouble with build tools and less confusion for others looking at your project.
As noted in the question comments -I ./tree.h also is clearly wrong, but not the cause of this particular error (and probably it just doesn't belong there at all).
However:
If your .tpp contains the implementation of methods of a class template, then you should not rename it (.tpp is appropriate in that case), but you also should not compile it as translation unit at all. That means it should not appear in any g++ command.
.tpp files implementing a template classes methods need to be included in the .h file with the class template definition, instead. Otherwise you will get linker errors later when you try to link your files, see Why can templates only be implemented in the header file?.
The -c flag tells GCC to only compile the input source files, not to do any linking.
If you want the compiler to link the object files into an executable binary, you need to remove the -c flag.

g++ compilation using 'include' statement with non-relative paths (C++)

I am trying to compile a c++ code with a third party library using g++ as a compiler.
My main.cpp needs to include the header file core.hpp while the core.hpp needs to include cvdef.h whereas cvdef.h need to include interface.h.
The paths for these three headers in the include statements are as follows:
#include "opencv2/core.hpp"
#include "opencv2/core/cvdef.h"
#include "opencv2/core/hal/interface.h"
See file structure in image below.
When I compile my main.cpp it finds the core.hpp. The core.hpp, however, cannot seems to find cvdef.h as it is looking within the 'core'-folder for the 'opencv2'-folder (which is a level below).
Without changing the paths in the include statement, how would I go about this?
My current compile statement using g++ under Windows is:
g++ main.cpp -o main
It seems that OpenCV2 wants to look for the header files in standard locations.
You can add to the list of standard locations by using the -I (upper-case i) option, specifying the path to add.
In your case you should be able to do it with
g++ main.cpp -o main -Iopencv2/core

G++ Add include and linking path

My Problem
I read somewhere that to add include paths to g++ you need to use the -I option:
g++ -I /some/directory and_then_my_files.cpp
However, I'm not sure if this is actually what I need. It's currently not working for me, and I couldn't find anything else close to what I have.
My Setup
I've got a directory with all my current project code, and in it a subdirectory classes, that contains various .h and .cpp files containing classes that may or may not be used when compiling my main files.
Since g++ ./classes/*.cpp main.cpp takes a long time (large number of files in classes directory), I'm looking for an alternative that only compiles and links the files that are included in the main file.
Main file:
#include "classes/a.h"
#include "classes/b.h"
// ... my code
And as you can imagine, g++ complains about undefined references to classes A and B, unless I add ./classes/*.cpp to the build command.
What I want to achieve
So -I and -L did not work, and adding the whole directory to the build command results in a ridiculously long build time - I'm talking 3-5 minutes, which really slows down my development speed.
Is there any way to only build/link the included classes from my classes directory, such as only classes A and B from the example I gave above?
Small Recap of what I've already tried
g++ -I ./classes main.cpp -o main
g++ -L ./classes main.cpp -o main (probably stupid but I tried it anyway)
g++ ./classes/*.cpp main.cpp -o main (what I currently have to resort to)
Thanks in advance :)
A temporary workaround
export CPLUS_INCLUDE_PATH=/usr/local/include

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.

Categories