Avoid compilation overhead

428 views Asked by At

I'm working on SpiderMonkey project, which is a large scale project with a lot of .h and .cpp files. Despite of I know I changed only file or two files, each time I make a change on the project, I have to run the make command and compile the whole project again to get the executable ./js file.

So, my question is that is there any solution to avoid compiling all files and compile only specific files to get the new executable ./js file?

4

There are 4 answers

0
nyrl On

make utility has a meaning of target and dependency. Target is only rebuilt if any dependency is changed, otherwise it is considered up to date (a bit simplified explanation). The following Makefile will cause target to be rebuilt only if any object file is changed, and object file will be rebuilt only if source/header is changed:

all: target

target: obj1.o obj2.o
    $(CC) -o $@ $^

obj1.o: obj1.c obj1.h
    $(CC) -o $@ -c $<

obj2.o: obj2.c obj2.h
    $(CC) -o $@ -c $<

Having said that, you should probably review project's Makefile and check if dependencies are properly defined. Complicated build systems (e.g. autotools/automake) use $(CC) -M or -MM to build list of dependencies for sources.

P.S. Check that your source/header files dates are correct and not in the future - make usually issues warning on that case since it cannot correctly determine dependency changes. This might be especially important for NFS files, which are edited on one computer and compiled on another.

1
Yaroslav Rybalka On

You can try to change only cpp files, not h, because cpp files includes one time in projects. Also you can use #pragma once directive, some compilers have acceleration of compilation. And yet you can use IncrediBuild tool in your company. It distributes compilation on all computers where there is IncrediBuild.

0
DevSolar On

The whole idea of make is to re-built only those parts of the project that need rebuilding, judged by file modification dates and the dependency information available to make.

If your project takes long to recompile, there are three things that might be to blame:

  1. The dependency information available to make is not optimal, i.e. make recompiles files that don't need recompiling because it thinks there are dependencies where there are none. This would be a defect of the Makefile in question, i.e. poor Makefile design.

  2. There are lots of dependencies. Implementation files including lots of headers, headers including each other etc. etc. -- you end up with one little modification requiring lots of translation units to be recompiled (usually when editing a header file). This would be an architectural deficiency of the project in question, and can only be fixed with a major refactoring.

  3. The project assumes the usage of precompiled headers. This usually results in a single, very big header file (or a header including lots of others), which is then stored in pre-processed form. Including this pre-processed header is a very cheap operation, but if your setup does not actually do this kind of pre-processing (but includes the monolithic header as-is), compilation times can skyrocket. This would be a deficiency of your setup; check the available documentation and your setup.

Which one is responsible for your specific problem? I cannot tell, really. (I don't know the first thing about Spidermonkey.)

0
Tony Delroy On

Given SpiderMonkey's an established project that's presumably got some good developers working on it, it's likely the makefile is basically sound, with relatively few bogus dependencies. If that doesn't ring true, you may want to query the SpiderMonkey community asking why modifications to a particular file trigger rebuilds of some other, or work through at a code level to see what the dependent file's using (perhaps by selectively removing #includes to see what breaks).

Still, it may well be that you're modifying files that have a lot of genuine dependencies, such as header files included (directly or indirectly) by a lot of different translation units. If that's the case, then there's relatively little you can do without restructuring the code. Techniques that may help include out-of-line function definitions, forward-declaration headers (ala the Standard's <iosfwd>), pImpl idiom, using virtual interfaces, and not going completely template-happy (as the definitions need to be included by client code to work).