How to minimize compilation time in C++ - c++

I've coded an script that generates a header file with constants like version, svn tag, build number. Then, I have a class that creates a string with this information.
My problem is the following: As the file is created in every compilation, the compiler detects that the header has changed, and forces the recompilation of a large number of files. I guess that the problem is in the situation of the header file. My project is a library and header has to be in the "interface to the world" header file (it must to be public).
I need some advice to minimize this compilation time or to reduce the files forced to recompile.

In the header write something like:
extern const char *VERSION;
extern const char *TAG;
extern const char *BUILD_DATE;
and create a .c (or .cpp) file that will contain
const char *VERSION = "0.13";
const char *TAG = "v_0_13";
const char *BUILD_DATE = "2011-02-02 11:19 UTC+0100";
If your script updates the .c file, only that file will have to be recompiled, but the files that include your header won't.

Generate the constants in the implementation file.
Make sure the header doesn't get changed by your script.

The easiest way to solve this is to not make those constants in a header file. Instead, make functions in the header file which get these values. Then place the values themselves in a small cpp file which implements those functions. (Or place them in a header ONLY included in that cpp file). When you recompile, only that one file will need to be recompiled.
Also, you could look in to distcc to speed up compilation if you have a few machines to spare.

If you're using gcc, you can try using ccache. it caches object files based on a hash of the preprocessed output, so will not recompile unless an actual change occured

Another way is to declare the constant values like extern const double PI; in your a header like "my_constants.h" and add one cpp file to the project with contents like:
#include "my_constants.h"
const double PI = 3.1415926535;
Then the actual values will only be compiled once, and changing a value only requires compiling that single file and linking the project again.

If you want to keep it as a single public header, you could add a pre-build step that takes your public header file and
filters out the version details, either removing them or replacing them with a fixed string, to a temp copy of the file
moves this to an internal version of your header only if it has changed, i.e. don't copy the file (+ update the timestamp) unless something other than the version has changed
then build your precompiled headers from this internal header file. You can still use the public header with the version details for the source files that need the version.
There's a moveifchanged script in the GCC sources you can borrow for this if you're on unix, or you can rig something up using fc in a batch file on Windows.

Object oriented solution:
Generally, you should put those often refreshed cnstants to cpp file, not h. Put them for example into a class. If you already have a class which creates a string of them and publish this by a method, I'd put all those constants to the same cpp and added some public methods to access them from other source files.

Related

How to extract all the required definitions from header files in C++

I would like to know how can one produce (either using gcc or an external tool) a single .h file that contains only the definitions of the types and functions used in the .cpp file.
For example: let's say I have multiple header files that contain a lot of functions (including their implementations) and I have a .cpp file that includes a single header file which in turns include all the other header files.
Inside the single .cpp file I call a function abc(some_argument); and I want to somehow grab only all the parts of code that I need for abc(some_argument) to work. Kind of producing a single header file that contains only the definitions required for abc(some_argument).
I know this idea might sound crazy, probable ugly, but I really need something like that.
Thank you!!

C/C++ huge header/source

In my C project, I am reading data from an obj file and an image file for opengl. All the data is combined into 1 header file.
Example (psuedo code):
vertices = {
0 , 2, 4,
....
};
normals = {
0, 0, 0,
....
};
texture_pixels = {
0, 0, 0
...
}
The thing is that all this data adds up to a 15mb header. Is it a bad idea to have this massive header? Will this cause any issues in my program?
Whether having a big header file vs. other approaches depends on the application.
The header file is processed at compile time. If the file is infrequently compiled, or its compilation time is quick enough to be acceptable, there is no problem.
If the header file is frequently updated (say like more than once per day) even in its deployed configuration, perhaps the program could be rearchitected to read the equivalent data from a data file from the network, SD card, disk, or what-have-you.
Data files have their own weaknesses:
They are a separate piece apart from the program executable which may need to be kept in sync.
The file format is subject to big vs. little endian issues, unless it is coded in some character format (like XML).
How should the program find the data? Command line parameter, hard coded path, etc.
If the file cannot be found, what to do?
Usually you declare types and function prototypes in headers. and the only function bodies should be inline functions or static functions.
Header files are combined in the source during pre-processing. it is means the large header file will be combined to any source file who is including it.
it is not the right thing to declare variables in a header files. if you declare variable in the headers and include it from several source file, you'll get the "already defined" link error, exactly as if you declare 2 global variables with the same name.
if the header file is included only once than it is exactly like to put it in the source file.
but in any other case the large data should be located in a source file, and the header should contain only the extern declaration of the variables.
The compilation time for a source file depends it size after pre-processing. therefore if you reduce the file size by exporting parts to headers you won't improve the compilation time. if you divide it to several source files any part will be compiled separately, it slow down the compilation by a bit, but when you change one part, other parts won't be needed to recompile so sometimes it is better.

What is the difference between including a .c file and a .h file

Lot of the times when I watch other people's code I see some are including a .h file and some are including a .c/.cpp file. What is the difference?
It depends on what is in the file(s).
The #include preprocessor directive simply inserts the referenced file at that point in the original file.
So what the actual compiler stage (which runs after the preprocessor) sees is the result of all that inserting.
Header files are generally designed and intended to be used via #include. Source files are not, but it sometimes makes sense. For instance when you have a C file containing just a definition and an initializer:
const uint8_t image[] = { 128, 128, 0, 0, 0, 0, ... lots more ... };
Then it makes sense to make this available to some piece of code by using #include. It's a C file since it actually defines (not just declares) a variable. Perhaps it's kept in its own file since the image is converted into C source from some other (image) format used for editing.
.h files are called header files, they should not contain any code (unless it happens to contain information about a C++ templated object). They typically contain function prototypes, typedefs, #define statements that are used by the source files that include them. .c files are the source files. They typically contain the source code implementation of the functions that were prototyped in the appropriate header file.
Source- http://cboard.cprogramming.com/c-programming/60805-difference-between-h-c-files.html
you can look at gcc website (https://gcc.gnu.org/onlinedocs/gcc/Invoking-G_002b_002b.html) that reports a good summary of all the extensions that you can use in C/C++:
C++ source files conventionally use one of the suffixes ‘.C’, ‘.cc’, ‘.cpp’, ‘.CPP’, ‘.c++’, ‘.cp’, or ‘.cxx’; C++ header files often use ‘.hh’, ‘.hpp’, ‘.H’, or (for shared template code) ‘.tcc’; and preprocessed C++ files use the suffix ‘.ii’. GCC recognizes files with these names and compiles them as C++ programs even if you call the compiler the same way as for compiling C programs (usually with the name gcc).
Including header file with declarations is the main, recommended and used almost anywhere, method for making consistent declarations among a project. Including another source file is another (very rare) kind of beast, and it's useful and possible under specific conditions:
There is a reason to split code to separate source files despite it shall be compiled as a single module. For example, there are different versions of some functions which shan't be visible from another modules. So, they are declared static but which version is included is regulated by compile options. Another variant is size and/or maintanenance credentials issues.
The included file isn't compiled by itself as a project module. So, its exported definitions aren't in conflict with the module that file is included to.
Here, I used terms definition and declaration in the manner that the following are declarations:
extern int qq;
void f(int);
#define MYDATATYPE double
and the following are definitions:
int qq; // here, the variable is allocated and exported
void f(int x) { printf("%d\n", x); } // the same for function
(Also, declarations include C++ methods with bodies declared inside their class definition.)
Anyway, the case another .c/.cxx/etc. file is included into source file are very confusing and shall be avoided until a very real need. Sometimes a specific suffix (e.g. .tpl) is used for such files, to avoid reader's confusion.

How does includes work in C++?

In my folder I have a small version.cpp file with the following structure:
#include "thelibr/version.h"
const int major = MAJOR;
const int minor = MINOR;
I cannot understand what this code does and how is it used by the remaining part of the code (stored in other files of the same directory).
First, I understand that the code sets values of two variables (major and minor) but what is not clear to me is where the values of MAJOR and MINOR are set. Are they set in thelibr/version.h.
Second, it is also not clear to me when the above given lines of the code are executed. They are not put in any method that could potentially be called from other methods coded in other files. So, how these lines can be called?
Third, I see that string version is not present in any other file from the same directory. Does it mean that none of these file uses the code stored in the version.cpp. Shouldn't we include version.h file somewhere in other file to be able to use the code from the version.cpp?
Fourth, if we set the values of major and minor variables in the version.cpp, will these variables be visible somewhere else? It wonders me since we do not use any words like global or external.
C++ doesn't have a module system like Python where pure symbols may be exported and their values used in another source file. Instead it has header files: The contents of thelibr/version.h are essentially copy-pasted in place of the #include line. Anything inside that file is processed as if it were written out in the version.cpp file.
To export from one file to another (or to create libraries which can be interpreted by the linker or dynamic loader), use extern storage, which is the default for many things.
Deciding what is visible from one .cpp file to the next is rather complicated, but as a rule you cannot share compile-time values such as the version number; you can only share access to runtime objects such as the ints which store the version number.
To use major and minor from another .cpp file, you could declare in version.h:
extern const int major;
extern const int minor;
And then #include "thelibr/version.h" from the other file.

How can I speed up compile time when using many extern type declarations

The Project:
C++ Programming in xcode. I have over 3,000+ type definitions spread over 2,000+ .c/.h files. Each myType type contains a string description. I used a script to define a map<std::string, myType> of 3,000+ elements in a .cpp file to use for looking up a myType type to pass to a function that processes data based on which myType is passed to it. Because the myType definitions are spread over 2,000+ files, I used a script to write each extern myType TYPENAME; in a header file.
Overview:
(2,000+ .c files with myTypedefinitions)
myTypes.h (contains all the extern myType statements for each myType in the above files)
myTypes.cpp (contains the map<std::string, myType> of 3,000+ elements in the above files)
typeProcessor.cpp (includes myTypes.h. Uses the map defined in myTypes.cpp to match a string to a myType. Passes the myType to a function from the file below)
dataProcessor.cpp (processes data based on the myType passed to it)
The Problem:
Since I've added myTypes.h with 3,000+ extern statements and myTypes.cpp with a map of 3,000+ elements my project compile time has lengthened from 20 seconds to 1-1.5 hours.
My Question:
Without touching the 2,000+ files or the dataProcessor.cpp that receives the myType, what can I do to reduce the compile time?
Some thoughts I've had:
use a script to put all the myType definitions into one big myTypes.cpp file and remove the extern statements. or
use a script to #include each of the 2,000+ files containing the myType definitions
I don't know much about compilers, the main factors on compile time, and how to write code to minimize compile time. Any help is appreciated. Thank you.
Regardless of many things you could do/have done to structure your code better, why don't you
create a public static registration function e.g. (typemap.h)
.
std::map<std::string, myTypeBase>& getGlobalTypeMap();
# define getGlobalTypeMap _once_ in typemap.cpp !
template <class myType>
registerTypeMapping(std::string name, const myType& instance)
{
getGlobalTypeMap().insert(name, instance);
}
In every .cpp for a type definition, call the registration function. That way a type registers itself, and there is no need for the type map to 'know all the types'. This is inversion of dependency, in a simple form
The crux is, that no file needs to include all the type headers for the registration process. You'll still need to include (selected) type headers if you need interfaces specific to the subtype (e.g. when using dynamic_cast<subtype> on a map element)
PS. I'm assuming some kind of common base type for myType (because there is no way you could get the std::map<std::string, myType> to compile otherwise)
Update
Edit
Yes, you can make registerTypeMapping an extern "C" function (just edit the prototype to be C-conforming)
For each type_xx.h/type_xx.c combi you can always generate an extra source file type_xx_register.c that includes just that type and registers it.
Note that this will lead to more sources but will likely reduce compile times. Especially, if you have a makefile and only compile the type_xx_register.o object file when it's dependencies truly changed.
That way, only a change in typemap.h would cause a recompilation of all these files.
It is also not impossible that a simple
$CC type*_register.cpp -o
_would be faster than the compilation of a single source including all type_xx.h at once_
As all these files don't change much (I'm assuming), it's either parsing the 3000+ line header or linking that kills the compile time. If it's parsing, a precompiled header should solve that, if it's linking, something like Visual Studio's incremental linking should help out, but I don't think any compiler except MSVC has this capability (correct me if I'm wrong).
it might be a matter of preventing a save on those 3,000 files
do the opposite of the xcode autosave method
this autosave off option is (very foolish) missing in newer versions of xcode (3.1 is a solid xcode) thus all files get a new timestamp and then the equivalent of a clean all rebuild.
try make on the commandline that doesn't save files as a speed comparison.