When should I use (non-header) source files in modern C++? - 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.

Related

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.

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.

Building "Monolithic" Libraries

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.

What's the relationship between header files and library files in c++?

Why do we need to add both includes and libs to the compilation?
Why doesn't the libs wrap everything in it?
Header files define interfaces; libraries provide implementations.
The header for a library is going to tell your compiler the names and signatures of functions provided by the library, the names of variables provided by the library, and the layout of classes provided by the library.
The library itself is compiled code which is executed at run time. Using the header during compilation allows your compiler to generate compiled code which knows how to invoke and communicate with the existing library code.
A header file (usually) only contains declarations for classes and functions. The actual implementations are built from CPP files. You can then link against those implementations with only the header declarations available.
I'm guessing this is your way of handling the question you asked at How to make #include <mysql.h> work?
Unfortunately, I think the better solution is to either learn more about C++, or learn more about Google, before posting absolutely everything to this site.

Tool to create an amalgamation/combine all source files of a library into one for C/C++?

SQLite and googletest come with a very easy-to-use, single-file version which makes it a breeze to use it in other projects, as you just need to add a single source file. Both of them use home-brew tools to create the combined source file, so I wonder if there is a more generic tool for this? It should take a list of implementation/header files and spit out a combined header/source, and fix up the local includes. I'm fine if it doesn't handle conditional includes/includes with different #defines before them like Boost.Tuple/MPL uses them. A typical target library would be something like ICU.
try this
https://github.com/vinniefalco/Amalgamate/
may be it can help...
If your includes are correctly defined (that is, there are guards in all header files, and each header/code unit contains all includes that it requires) then you can do it 'half-manually'. Locate system header includes and comment them out, then create a header that just includes everything in any random order and preprocess the header (in gcc that would be gcc -E) and then operate similarly with the code units.
This manual approach can be cumbersome, but if you only need to do it once it will be fine. Then again, even if merging the header files might make sense I prefer not to do it. I would actually leave the files separate, and if you feel like you need to simplify access to it, provide bundling headers that just include the others. This is the approach that some boost libraries take, where you can include the details of what you want or a single header that includes everything else. The code can be compiled/linked into an static lib and used as if it was a single element.
This might be sort of interesting in ICU, which has, in some cases, incompatible defines/includes and mixtures of C and C++ and a number of generated files. Maybe let us know how it goes?
(disclosure: icu developer)