Building "Monolithic" Libraries - c++

I have a series of small library "modules" designed to handle very specific tasks. A single module usually consists of just a .h and a .cpp, and possibly another set to provide relevant non-friend, non-member functions that the user might find useful.
For example, Foo.h might declare a class called Foo, that Foo.cpp defines, and FooUtilities.h might declare a function that uses Foo which is defined by FooUtilities.cpp.
Normally to use these modules in my programs, I add the .h and .cpp to my project and #include the .h in whatever files need it. However, for larger programs that use more potentially-interdependent modules, this is growing to be a big inconvenience. Therefore, I'd like to compile it all as a single monolithic static or dynamic library so I can just add the library file to my project, set the header search directories to folders that contain the aforementioned .h files, and compile.
Seems pretty simple, right? All I'd have to do is start a new project with a static/dynamic library as its build target and then add all the appropriate files. The .cpp files, which #include the .h files anyway, will be compiled and added to the final product.
However, some of the modules use templates and therefore have to use .tpp instead of .cpp. The .tpp files are only meant for organization and are #included by their respective header files, which is the opposite of how the normal modules are handled. Because of this, just adding them to my library project won't compile anything.
How can I work around this? Should I have a CompileThis.cpp file that includes all the modules that use templates? If so, should this file also include the non-template modules? It seems like this could rapidly become an organizational mess.

Many compilers cannot "precompile" templates into libraries. My best suggestion is to treat them like header files; header files are not compiled into libraries, they are just included.
I compile code into a library when the amount of changes is minimal. This often speeds up the build process since those files don't need to be compiled again (and again...).

Should I have a CompileThis.cpp file that includes all the modules that use templates?
Yes - you'll still need an object to link. It's also nice because it will perform the syntax/instantiation checks (assuming your depends are properly ordered).
If so, should this file also include the non-template modules?
that depends on the structure.
at minimum, it should include/define what it must export (and their dependencies).
it should often include the headers represented by the module, in order to easily detect errors issues at the package level.
ideally, you'll add all necessary concepts and some instantiations (in some cases).
this makes it easier to maintain, and will not require major restructuring when you realize you have moved from needing 0 exported symbols to needing one or more.

Related

When should I use (non-header) source files in modern C++?

The typical way of writing C++ code is to seperate it in header and (non-header) source files.
I saw a lot of modern C++ libraries that are header-only (e.g. some Boost libraries). Typically these libraries make a lot of use of templates.
Instead of seperating their files into header and source files, they seperate their files into header declarations and header implementations.
So my questions are:
Is it just the old fashion way to use source files?
When does it make sense to use source files at all?
What are the pros and cons for creating a header-only library?
They do it because templates cannot be defined in a source file without making life difficult. It also means you don't need to worry about linking anything (so, convenience). That's it.
In general, we use the header/source model to promote re-usability, partial rebuilds, and better code organisation.

Common Practice For Library File Structure

Is there some kind of generally agreed-upon standard for how C++ libraries should be structured, file-wise? I'm thinking my library would be static. It's fairly expansive, so right now, I have classes split into different files. Each source file has a header file to go with it.
I don't want the end user to have to #include every one of my header files, obviously. I thought about having a single header file named "libraryname.h" that just #includes all the header files for the user, but I've never seen any other libraries do that, and I fear that's for a reason.
I've seen libraries use a single header file and multiple source files, which seems simple but also a bit cluttered. I've also seen libraries completely nix the idea of separating source and header files and just have one file with #define guards that has all the code. That seems like a pretty good way to dramatically increase compile time, which I'd like to avoid, but if there's a really compelling reason to do libraries that way, I'd love to know it. Any advice on what style to use would be appreciated!
Having a single header file really slows down your build (i.e. a single change in one of your class declarations requires a full library build).
Also, you'll find that most source files will not need all the headers. You can also use forward declarations too which helps.
If your compiler supports precompiled headers, then that is the place to put all standard C++ library includes. But, don't put your headers in there or you'll force a whole library rebuild on a single change.

How do I create a library?

Let's say I have 10 *.hpp and *.cpp files that I need to compile a code. I know that I will need those same files for many different codes. Can I create a "package" with those files that would allow me to simply write:
#include <mypackage>
instead of:
#include "file1.hpp"
#include "file2.hpp"
...
#include "file10.hpp"
I wouldn't then need to write a makefile every time I need this "package".
To be more precise, I use Linux.
A collection of CPP sources (H files and CPP files) can be compiled together in to a "library," which can then be used in other programs and libraries. The specifics of how to do this are platform- and toolchain-specific, so I leave it to you to discover the details. However, I'll provide a couple links that you can have a read of:
Creating a shared and static library with the gnu compiler [gcc]
Walkthrough: Creating and Using a Dynamic Link Library (C++)
Libraries can be seperated in to two types: source code libraries, and binary libraries. There can also be hybrids of these two types -- a library can be both a source and binary library. Source code libraries are simply that: a collection of code distributed as just source code; typically header files. Most of the Boost libraries are of this type. Binary libraries are compiled in to a package that is runtime-loadable by a client program.
Even in the case of binary libraries (and obviously in the case of source libraries), a header file (or multiple header files) must be provided to the user of the library. This tells the compiler of the client program what functions etc to look for in the library. What is often done by library writers is a single, master header file is composed with declarations of everything that is exported by the library, and the client will #include that header. Later, in the case of binary libraries, the client program will "link" to the library, and this resolves all the names mentioned in the header to executable addresses.
When composing the client-side header file, keep complexity in mind. There may be many cases where some of your clients only want to use some few parts of your library. If you compose one master header file that includes everything from your library, your clients compilation times will be needlessly increased.
A common way of dealing with this problem is to provide individual header files for correlated parts of your library. If you think of all of Boost a single library, then Boost is an example of this. Boost is an enormous library, but if all you want is the regex functionality, you can only #include the regex-related header(s) to get that functionality. You don't have to include all of Boost if all you want is the regex stuff.
Under both Windows and Linux, binary libraries can be further subdivided in to two types: dynamic and static. In the case of static libraries, the code of the library is actually "imported" (for lack of a better term) in to the executable of the client program. A static library is distributed by you, but this is only needed by the client during the compilation step. This is handy when you do not want to force your client to have to distribute additional files with their program. It also helps to avoid Dependancy Hell. A Dynamic library, on the other hand, is not "imported" in to the client program directly, buy dynamically loaded by the client program when it executes. This both reduces the size of the client program and potentially the disc footprint in cases where multiple programs use the same dynamic library, but the library binary must be distributed & installed with the client program.
On Linux:
g++ FLAGS -shared -Wl,-soname,libLIBNAME.so.1 -o libLIBNAME.VERSION OBJECT_FILES
where
FLAGS: typical flags (e.g., -g, -Wall, -Wextra, etc.)
LIBNAME: name of your library
OBJECT_FILES: objects files resulting from compiling cpp files
VERSION: version of your library
Assuming your "file1.hpp" and "file2.hpp" etc are closely related and (nearly) always used together, then making one "mypacakge.h" that contains the includes of the other components is a good idea (it doesn't in and of itself make it into a library - that is a different process altogether).
If they are NOT closely related and/or used together, then you shouldn't have such a "mega include", because it just drags in a bunch of things that aren't needed.
To make a library involves building your code once, and either generating a .lib file or a shared librar (.dll or .so file). The exact steps to do this depends on what system you are using, and it's a little too complicated for me to explain here.
Edit: To explain further: All of the C++ library is actually one library file or shared library file [along with a number of header files that contain some of the code and the declarations needed to use the code in the library]. But you include <iostream> and <vector> separately - it would become pretty awful to include EVERYTHING from all the different C++ library headers in one <allcpplibrary>, even if it was a lot less typing involved. It is split into sections that do one thing per headerfile. So you get a "complete" set from one header file, but not a too much other things you don't actually need.
Yes and no.
You can write an include-all header so that #include "myLib.h" is sufficient, because you include all those headers through the single header. However, that does not mean that the single include is enough to have the content of the 10 '.cpp' files linked to your project automagically. You will have to compile them into a library and link that single library (instead of all the object files) to the projects that use "myLib.h". Library binaries come as static and dynamic libraries, the files are typically named .lib and .dll (windows) and .a and .so (linux) for static and dynamic libraries, respectively.
How to build and link such libraries depends on your build system, you might want to loke those terms up on the net.
One alternative is to get rid of the .cpp files by defininig all the functions in the headers. That way you won't have to link the additional library, but it comes at the cost of increased build times, because the compiler will have to process all those functions every time you include the header directly or indirectly into one of your translation units.
If a client needs all ten headers to actually make use of your "package" (library), that's pretty bad interface design.
If a client needs only some headers, depending on which parts of your library are being used, let the client include the appropriate headers, so only a minimal set of identifiers are introduced. This helps scope, modularization, and compilation times.
If all else fails, you can make an "interface header" for external use, which is different from the ones you use internally for actually compiling your library. This would be the one that gets installed, and consists of the necessary contents from the other headers. (I still don't think you would need everything from every header in your lib.)
I would discourage Salgar's solution. You either have individual headers, or a monolithic one. Providing individual headers plus a central one that simply includes the others strikes me as pretty poor layout.
What I do not understand is inhowfar Makefiles play into this. Header dependencies should be resolved automatically by your Makefile / build system, i.e. it shouldn't matter here how your header files are layed out.
simply all you'd have to do is create a .h or .hpp file that has
#ifndef MAIN_LIB_H
#define MAIN_LIB_H
#include "file1.hpp"
#include "file2.hpp"
#include "file3.hpp"
...
#include "file10.hpp"
#endif
make the file called whatever I would choose main_lib.h because of the ifndef, and just
#include "DIRECTORY PATH IF THERE IS ONE/main_lib.h"
in the main file. No need for anything else if you were using visual studios. Just build then press CTRL + F5.

C++ How to include class headers without having to compile their cpp files?

We can include < iostream > and we do not care about its cpp file, but why can't we do the same for our own classes ?
So if my project uses 50 custom classes, not only do I have to have 50 includes, but also have to compile/link 50 cpp files along with them (and clutter the project tree).
Q: Is there any way to use custom headers the same way we use standard libraries ?
In other words is there a kosher way so that we do not have to add all those cpp files in the project. I want to only include ClassSnake.hpp which in turn knows where to find ClassSnake.cpp which links to ClassVector.hpp which knows how to find ClassVector.cpp ... all in an automatic daisy chain without me having to explicitly add those cpp files in my project tree.
Edit: I am not worried so much about the cpp files recompiling. My issue is with having to remember which class internally links to which other class, so that I can properly include all those hidden cpp files in the project tree ... and clutter the tree.
Not really.
What you're missing is that your compiler toolchain has already compiled the bits <iostream> needs that aren't in the header.
Your compiler (linker really) just implicitly links this code in without you having to specify it.
If you want to clean up your project tree a bit, you could create other projects that are libraries of code for one main project to use.
Headers do not (normally) provide implementations of things (functions, classes), they must be implemented somewhere if you are going to use them.
When you include your own header, you include your own sources in order to provide the implementation. Straight forward enough there.
When you include a standard header (such as iostream), the implementation is in the libraries you include (either implicitly because the compiler just does it, or explicitly through compiler/linker options).
As an extention to Collin's answer, you could always offload "shared" code to a shared library, and then reference the header files and lib files in your other projects. The lib files will only come in to play at the linker stage, as all those other pesky .cpp files have already been compiled.
If this is is just a self-enclosed project with no other commonality, you're just going to have to suck up the fact you have to provide an implementation :)
First of all if you use a system such as make then it will identify that the .cpp file has not changed and therefore the compiler does not have to reconstruct the object file.
You can also create your own static/shared library. The method to do this depends on the platform. If you go down this avenue then all you need is the header file along with the library.
Please Google on how to construct how to make a library for you particular platform.
Actually, if you have a decent build process cpp files that have not changed will not be compiled again. They only have to be linked. If you don't want that either you need to create your own libraries. It can be done, is just a bit more involved.
Edit: This question might help you if you want to create your own library.
So answer to edited question: Yes, you can avoid having all those cpp files in the project but only if you don't want to change them. In this case you can just create a static or dynamic library and you will only need the symbols for linking. In that case you would create another project to compile everything into such a library.
STL code like "iostream" is made of templates no code is actually generated until instances of the templates are created.

linking vs including a file

When working with a large codebase, I've seen when certain object is being used, that object's header file is included. At other times that object's library is linked in the make file.
What is the reason for doing one or the other. If they have access to the source code, why not include all files whose object you are using instead of linking into their lib *.a files?
edit: made it clear based on first comment. It was a confusing statement
Normally, you need to do both. Header files tell the compiler what
functions are available, and what they look like. They have to be
present when you compile. Libraries contain the implementation, and
must be linked with the application in order for the compiler generated
calls to work.
In a few rare cases, the "library" may consist of just header files; C++
still requires the implementation of a template to be present in the
header, and not in a library, so a library which consists of nothing but
templates may be header-only. In such cases, it is sufficient to
include the headers; there's nothing more to link. (Of course, such
libraries drive compile times through the roof.)
There isn't necessarily a one-to-one relationship between header files and binaries. In fact, there quite commonly isn't. For example, just because you see foo.h being included doesn't necessarily mean there's going to be a foo.obj or foo.lib. The reverse is also true; ie, you might see foo.lib being linked but there is no foo.h.
Using Windows as an example, you need quite a few header files to use anything found in kernel32.lib, but there is no kernel32.h.
One good argument for use of libraries it's that can be used more easily: to compile large codebases, all the right dependencies must be available, and there could be specific steps required, not relevant for the task at hand. And of course, the compile time it's cut away.