Making library name part of include path in make? - c++

Say I'm working on a library, foo. Within my libraries source files, I'd like to include headers the same way a user of my library would:
#include <foo/bar.hpp>
// code defining bar methods here
In boost for example, includes of other headers within boost are done that way, e.g. <boost/shared_ptr.hpp>, rather than the relative quoted "../shared_ptr.hpp" style. I looked at how some other libraries accomplish this and it appears they add a redundant directory to their file layout in order to do it, e.g. the boost code lives in "boost_1_4_1/boost" rather than just "boost_1_4_1/".
Switching to that scheme is annoying if you already have source control using an existing layout. What's the best way with GNU make to layer it on? My only thought is to add a target that all build targets depend on that makes a hidden folder with a symlink inside to my source tree, and add that hidden folder to the include path. Perhaps there's a less obfuscated way?

Couldn't you use -I gcc key of INC option for your Makefile?
gcc:
gcc -c -I/home/joseph/dev/foo/headers
Makefile:
INC=-I/home/joseph/dev/foo/headers
In this case you would have only one place to make this change, Makefile.

Related

CMake/make apply -D flags on header files

I'm (cross-)compiling a shared C library with support for many different platforms which is handled by an hierarchy of CMakeLists files. In those files, several platform specific compiler flags are conditionally produced (with add_definitions()). I can successfully compile and link the source code leading to an appropriate .so file.
But to use the library in any project, I need to provide the right header files, too. The following install command of CMake selects the right header files to copy but does not apply the replacement of preprocessor defines/includes:
install(FILES ${headers} DESTINATION include/mylibrary)
So how can I generate/install the "post-compiled" header files?
What I thought of so far:
As add_definitions() should stack my -D's in the COMPILE_DEFINITIONS variable, maybe running a foreach loop on the copied raw headers and replace the define/include placeholders?
Using add_custom_command() to apply some logic before copying?
Edit: As pointed out by Tsyvarev, there is an answer quite near to my needs here, but unfortunately not quite it. In summary, the answer gives 2 options:
Include a special 'config' header in all of the library's headers and leverage the cmakedefine command to call configure_file() on this header. I can't use this approach because I don't want to alter the library headers.
Create a target-specific .cmake file which helps external projects in including the right headers together with all necessary -D defines. I can't use this approach either, because my external projects do not use cmake for building. Plus, I wish to create a library that is as easy to include as possible.
Any other thoughts?
Edit 2: I may have to elaborate on my statement, that the install command of CMake is not replacing defines. Take the following example:
//sampleheader.hpp
#ifndef SAMPLEHEADER_HPP_
#define SAMPLEHEADER_HPP_
#include OS_SPECIFIC_HEADER
//...
Now I have a CMakeLists.txt file that does something like this:
# ...
if (${OS} MATCHES "arm-emblinux")
add_definitions(-DOS_SPECIFIC_HEADER="emblinuxHeader.hpp")
elseif (${OS} MATCHES "linux")
add_definitions(-DOS_SPECIFIC_HEADER="linuxHeader.hpp")
endif()
# ...
Everything compiles fine, but when the install command above gets called, I have a header file in my ../include/ directory still with OS_SPECIFIC_HEADER placeholder in it. And of course, this cannot be properly included in any development project.

How to namespace C++ header files?

I use a code with different libraries, which use names like defines.h. This does not only cause conflicts for identical filenames, but also creates confusion. From which library is the defines.h include?
Including as #include <library/defines.h> would be a clean solution, but then the include path would need to be the parent directory of the library, which is rather unclean again.
Is there some way to alias the include path, so that -I/path/to/library makes the headers available under library/headername.h?
Is there some way to alias the include path, so that -I/path/to/library makes the headers available under library/headername.h?
There seems to be no need to in this case. You can simply use -I/path/to which makes /path/to/library/headername.h available under library/headername.h.
That said, while there is no such compilation option (that I know of), you can create such "aliases" to file paths in most file systems. These aliases are called symbolic links. In this case, you could make a link /path/to/library/mylibrary that points to . which would make /path/to/library/headername.h available under mylibrary/headername.h assuming you've used -I/path/to/library.
At least on unixy systems, when you compile and install a library, headers are installed for example to
/usr/lib/libraryname/*.h
Or maybe something like
/opt/libraryname-1.2/include/libraryname/*.h
And then if necesssry (not installing to compiler's default include search path), right dir is added with compiler option, for gcc for example option
-I/opt/libraryname-1.2/include
Then just always do this in source code, trusting build system to have included the right search paths:
#include <libraryname/includefile.h>

MACRO depending on its folder location

In the following files:
app/main.cpp
app/config.hpp
app/show.hpp
app/file.hpp
lib/append.hpp
lib/clear.hpp
lib/reopen.hpp
lib/crypt.hpp
I have a problem. Imagine a few of my files use lib/crypt.hpp. For example in app/file.hpp I should write:
#include "../lib/crypt.hpp"
If I take this file to lib folder it does not work anymore. So I need a something like:
#include "LIB/crypt.hpp"
So, this LIB/ has meaning of (empty) in lib directory while it has meaning of "../lib/" in app directory.
Then I will have no worry about moving file.hpp from app to lib. I just need to fix the callers of it. But not what it calls.
Similar to concept of web programming frameworks. Is it possible in C/C++?
According to what you wrote you're searching for a way to move your sources around without worrying for hard-coded paths to your headers.
You didn't specify the compiler you're using so I'm not focusing on a specific one, anyway most C++ compilers have an option to specify one or more header search paths (on gcc you would just use something like -Ilib_parent_dir).
Once you've included your lib's parent path to the search list, you can move your sources around (as long as you don't move lib's headers) and have them include the right headers with something like #include <lib/crypt.hpp> (and keep include paths priority in mind)
This should be a cleaner and simpler way to achieve what you asked rather than using a macro.

Using project directory in include filename

I am developing C++ headers only library, lets call it PROJ. When a library header is including another, it uses:
#include <proj/foo.h>
And compiler (gcc and clang) have -I path-to-proj-parent. Users of the library should also have parent of PROJ in their include search path.
My rationally for using this scheme is that after installing this library into proj subdirectory of default-seachable parent (/usr/include/proj or /usr/local/include/proj), library user do not need to specify -I option.
Is there cons to this scheme? Is using <foo.h> without proj/ prefix is more conventional and recommended way?
Question is not about if installing in subdir or not (there will be proj subdir), but rather how to refer to include-files.
If you look at boost, you will note that they use a similar scheme:
#include <boost/shared_ptr.hpp>
It has the advantage of preventing clashes with another similarly named file from another dependency.
However, in the case of boost, they take it one step further. If you include <x/y/z.hpp>, then you are likely to be dealing with an entity named ::x::y::z (be it function or class). That is, the way the directories in the project are laid out mimic the namespace organization. It's quite neat really to orient oneself.
Normally, most projects are stashed in subdirectories (and subnamespaces), but the most used ones are pulled into the boost namespace for convenience, and thus they have headers living directly in the boost folder. There are also some convenience headers (whose job is just to gather a smattering of other headers to pull them in all at once).
You may finally note, if you open a header file, than the include guards they use follow the exact same hierarchy:
#ifndef BOOST_SHARED_PTR_HPP_INCLUDED
once again because it helps avoiding clashes since it's named after the very file it's in and there can be only one at that place in the whole Boost project (on case sensitive filesystems).
It is ok to have proj in the path if you create the proj directory when you install. In fact its a good way to prevent name collisions with other include files.
The name should not be something generic like "proj' though. It should be specific to the project.

Using a class from another project in C++

I have access to a large C++ project, full of files and with a very complicated makefile courtesy of automake & friends
Here is an idea of the directory structure.
otherproject/
folder1/
some_headers.h
some_files.cpp
...
folderN/
more_headers.h
more_files.cpp
build/
lots_of things here
objs/
lots_of_stuff.o
an_executable_I_dont_need.exe
my_stuff/
my_program.cpp
I want to use a class from the big project, declared in say, "some_header.h"
/* my_program.cpp */
#include "some_header.h"
int main()
{
ThatClass x;
x.frobnicate();
}
I managed to compile my file by painstakingly passing lots of "-I" options to gcc so that it could find all the header files
g++ my_program.cpp -c -o myprog.o -I../other/folder1 ... -I../other/folderN
When it comes to compiling I have to manually include all his ".o"s, which is probably overkill
g++ -o my_executable myprog.o ../other/build/objs/*.o
However, not only do I have to do things like manually removing his "main.o" from the list, but this isn't even enough since I forgot to also link against all the libraries that he happened to use.
otherproject/build/objs/StreamBuffer.h:50: undefined reference to `gzread'
At this point I am starting to feel I am probably doing something very wrong. How should I proceed? What is the usual and what is the best approach this kind of issue?
I need this to work on Linux in case something platform-specific needs to be done.
Generally the project's .o files should come grouped together into a library (on Linux, .a file if it's a static library, or .so if it's a dynamic library), and you link to the library using the -L option to specify the location and the -l option to specify the library name.
For example, if the library file is at /path/to/big_project/libbig_project.a, you would add the options -L /path/to/big_project -l big_project to your gcc command line.
If the project doesn't have a library file that you can link to (e.g. it's not a library but an executable program and you just want some of the code used by the executable program), you might want to try asking the project's author to create such a library file (if he/she is familiar with "automake and friends" it shouldn't be too much trouble for him), or try doing so yourself.
EDIT Another suggestion: you said the project comes with a makefile. Try makeing it with the makefile, and see what its compiler command line looks like. Does it have many includes and individual object files as well?
Treating an application which was not developed as a library as if it was a library isn't likely to work. As an offhand example, omitting the main might wind up cutting out initialization code that the class you want depends upon.
The responsible thing to do here is to read the code, understand it, and turn the functionality you want into a proper library. Build the "exe you don't need" with debug symbols and set breakpoints in the constructors and methods of the class. Step into them so you get a grasp on the functionality and what parts of the program are relevant and irrelevant to your needs.
Hopefully the code is under some kind of version control system that supports branching (such as Git). If not, make your own repository that does. Edit the files until you've organized them into a library and code that uses the library. Make sure it works properly within the context of the original program. Then turn around and use this library in your own program.
If you've done a good job, you might be able to convince the original authors to accept the separation back into their original codebase. If not, at least version control has your back so you can manage integration of future changes.