TL;DR
In your SConstruct file, add the tools keyword argument to
Environment and DefaultEnvironment initialization to explicitly
specify the tools needed in your project. It saves a lot of time.
The Story
My resume was written in LaTeX and convert to PDF using a
handwritten Makefile, of which I always want to replace using a more
advanced automation tool.
So I'm looking at scons. It's written in Python which is a language
I like, and looks much simpler than CMake. But one thing I don't like
is the speed.
Here's the original SConstruct:
convert = Builder(action=[ "convert -alpha off -density 300 $SOURCE -append $TARGET"]) env = Environment(BUILDERS={"Convert": convert}) pdf = env.PDF("resume.tex") png = env.Convert('resume.png', pdf) Default(pdf)
So what this SConstruct file did is that it compiles the resume.tex
file into PDF, and then optionally convert the PDF into a PNG file.
And the time it takes? Here it is:
$ scons -f SConstruct.before --debug=time . |grep ^Total Total build time: 8.844431 seconds Total SConscript file execution time: 2.516214 seconds Total SCons execution time: 0.094147 seconds Total command execution time: 6.234070 seconds
In the total build time ~8 seconds, ~3 seconds was used in executing the
SConstruct file. Let's run a cleanup which make it more obvious:
$ scons -f SConstruct.before --debug=time -c . |grep ^Total Total build time: 2.669596 seconds Total SConscript file execution time: 2.579540 seconds Total SCons execution time: 0.090056 seconds Total command execution time: 0.000000 seconds
In a total build time ~2.6 seconds, ~2.5 seconds is wasted.
I know that there's a lot posts talking about how slow scons is
but I don't know it could be that slow. If this is a large project
managed by scons, 2.5 seconds seems insignificant but for a simple
task like compiling LaTeX file it's unacceptable.
After a simple profiling it become obvious that scons takes too much
time in initializing the Environment instance:
$ python2 -m cProfile -s cumtime `which scons` -f SConstruct.before -c . ... Ordered by: cumulative time ncalls tottime percall cumtime percall filename:lineno(function) ... 2 0.000 0.000 2.838 1.419 Environment.py:917(__init__)
Luckily there's a GoFastButton page on scons wiki that caught my
eyes: too many unnessesary tools in the Environment is a cause of
slow down.
It's straight forward after figuring out the cause. Here's an updated
SConstruct:
DefaultEnvironment(tools=[]) convert = Builder(action=[ "convert -alpha off -density 300 $SOURCE -append $TARGET"]) env = Environment(BUILDERS={"Convert": convert}, tools=['pdftex']) pdf = env.PDF("resume.tex") png = env.Convert('resume.png', pdf) Default(pdf)
Notice the tools keyword argument in initializing Environment, and
the tools keyword argument to DefaultEnvironment. The result is a
significantly reduced build time (for a small project):
$ scons -f SConstruct.after --debug time . |grep ^Total Total build time: 6.579649 seconds Total SConscript file execution time: 0.037326 seconds Total SCons execution time: 0.112706 seconds Total command execution time: 6.429617 seconds $ scons -f SConstruct.after --debug time . -c |grep ^Total Total build time: 0.122485 seconds Total SConscript file execution time: 0.030382 seconds Total SCons execution time: 0.092103 seconds Total command execution time: 0.000000 seconds
Conclusion?
If you know what you are going to build (you already know it would be a
C++ project, or in my case building PDF from LaTeX), you'd better
tell scons explicit what tools you want to be included in the
Environment. If your project is small, the saved time would be
significant.
P.S. I found it hard to decide what tools you want to be included in
Environment. The full list of available tools can be found in man 1
scons, but there's no description on what those tools do. For example,
in my case of compiling *.tex file into *.pdf file, there are three
relevant tools available: latex, pdftex, pdflatex. I have to test
among them to know pdflatex is the right one.
Comments !