

fabricate: The better "make". Finds dependencies automatically for any language. - benhoyt
http://code.google.com/p/fabricate/

======
st3fan
"""For a start, fabricate won't say " __* missing separator" if you use spaces
instead of tabs.""" - No, but it will say "IndentationError: unindent does not
match any outer indentation level" if you mess up Python's indentation :-)

------
tsally
You don't need to enter in dependencies with 'make' either (suffix rules or
makedepend). Don't get me wrong, fabricate looks great, but let's not
misrepresent the power of make in the right hands. From the docs:

    
    
       files.o : files.c defs.h buffer.h command.h
             cc -c files.c
    

I don't know a programmer beyond the introductory level that still writes this
in their make file. :-p

~~~
silentbicycle
Right. Make already _knows_ how to convert .c to .o, all you need to say is

    
    
        files.c: defs.h buffer.h command.h
    

and there are tools such as makedepend (for C and OCaml, off the top of my
head) that _generate those listings automatically_ , so you just add this to
the Makefile:

    
    
        include (autogenerated dependency listing file)
    

While the mandatory tab in Make syntax is a genuine wart, make has been around
long enough that there are several other tools that know how to work with it.

(Now, having the scan for access time changes added as a warning to Make might
not be a bad idea. "WARNING: You forgot this dependency")

~~~
garnet7
> make has been around long enough that there are several other tools that
> know how to work with it.

I'd prefer an improved from-scratch 2nd-generation tool instead of using one
that simply wraps around a complicated 1st-gen one that I'd rather not touch.

Make has more warts than just the tab characters. Lots of obscurely-named
variables, for starters.

~~~
Bluem00
You might want to check out tup. It uses the dependency tree in a
fundamentally different way from make, in order to improve build times.
<http://gittup.org/tup/>

------
silentbicycle
It looks like they hardcoded gcc as the compiler in the example. What about
trying to port a program to a platform without it (or that calls it
differently), that needs extra compilation flags, etc.?

A lot of the seemingly esoteric stuff in Makefiles is there to make porting
feasible (and the rest is autogenerated by autoconf, automake, etc.). Not just
which files an operation depends on, but e.g. the options used for building
shared libraries correctly on this platform, paths for libraries, etc. While
the build system will remember what it found as dependencies, _it still needs
to know what to find the first time_. (It will note header files as
dependencies, though.)

------
sorbits
I have a machine with two quad-core CPUs, I want to run 8 parallel jobs at a
time!

Most of these make replacements start with design decisions (like using
Python) that pretty much rule out ever reaching what make does best, and which
is essential to get my build times improved by at least a factor of 6.

Using a tool (like CMake) to generate your Makefiles is an excellent solution,
heck, even a Python script that generated a Makefile and then ran make would
be to prefer over this tool.

~~~
vr
Using Python does not prevent parallel execution of tasks. It's just the build
tasks graph that gets created by a single process, but then the build system
can use all the available CPUs to actually execute it. See e.g. -j flag to
SCons [http://www.scons.org/doc/production/HTML/scons-
user.html#AEN...](http://www.scons.org/doc/production/HTML/scons-
user.html#AEN2099).

~~~
sorbits
As I said, generating a Makefile (i.e. the dependency graph) from Python would
be fine, which conceptually sounds like what SCons do (from your comment).

But look at the build file example on the fabricate page, it is a user
supplied build file with a build function which calls a compile function which
loops over sources. Having the fabricate system take input like that and do
parallel execution is as hard as solving the halting problem.

------
benhoyt
We've been using memoize to build stuff for a while now, but we needed
something that worked under Windows too. So here's our "fabricate" build tool.
It's BSD licensed -- enjoy!

~~~
kragen
Does it scan your entire filesystem for atimes so as not to miss the .h files
over in /usr/include, and if not, how does it know which directories need
scanning?

~~~
benhoyt
No, it defaults to recursively scanning the current directory, but you can
easily override this if you want, eg:

    
    
        setup(dirs=['.', '../lib'])

~~~
kragen
Is there a way to override it to just use strace?

~~~
benhoyt
Sure is. This will do it:

    
    
        setup(runner='strace_runner')

~~~
kragen
Neat! Thanks!

------
thingie
Do I miss something? That example is like three times longer than an
equivalent Makefile would needed to be, and I need to know Python, obviously.
For a trivial project, I guess that Make would be easier to use, and for
something more complex, I think I would have to do quite a lot of programming,
with Fabricate…

~~~
st3fan
What misses in my opinion is 'build by convention'. Most things that you want
to build have recipes that are mostly the same. You have some sources that you
want to compile and then link against some libraries. Using some platform
specific compiler and linker flags.

So, instead of writing a program to do the build I would rather see a simple
DSL that allows me to specify just the minimal amount of configuration to get
things going.

For example building the example on the fabricate wiki page, should not be
more complicated than:

    
    
      :program programname : program.c utils.c
    

(This is actually an a-a-p recipe that will do the same. Throw this in a
main.aap file and you get everything that fabricate does, build, dependency
checks, clean, etc.)

I don't mind to script the build when things get more complex. But only then
and only when there really is no simple built-in alternative.

Fabricate seems to be more like ant in the Java world. Where you specify in
detail what your build should do. Most people have agreed by now that it is a
waste of time and instead use Maven, which completely works on simple
conventions and standard rules.

~~~
jimbokun
What's a-a-p?

~~~
st3fan
See <http://a-a-p.sf.net>

------
growt
I haven't tried fabricate yet, but I think the number of build-tools out there
is a sure sign that something fundamental is broken.

~~~
tvon
I think it's just the nature of the beast, and an example of a complex problem
with a lot of different solutions.

------
st3fan
I wish someone would pick up <http://a-a-p.sourceforge.net/> again. It is a
great build tool written by the Vim author. I've used it to build complex
projects in the past with a minimal amount of aap configuration. It is much
less verbose than fabricate.

------
herge
Not to be confused with Fabric (<http://www.nongnu.org/fab/>), also a very
cool python tool.

------
pmorici
looks a lot like SCube only way more verbose for the simple case.
<http://code.google.com/p/scube/wiki/Example1>

The problem with this and other Python build tools is They are a _huge_ pain
to use on older systems that either don't have a recent enough version of
Python installed or don't have Python installed at all. It's just not as
portable as Make is in that respect.

------
gchpaco
The central problem with these sorts of "make replacements" is they miss out
on the whole thing that makes make useful. I care not a whit about implicit
rules, and I would welcome a real language over GNU make's function apparatus
(filenames with spaces in them tend to get split in the functions, due to the
fundamentally macro style), but without pattern matching rules and a real
dependency engine I won't even think once about it. I use both far, far too
often, in almost every makefile I've ever written.

~~~
bryhoyt
gchpaco, could you give an example of a situation where you'd use a _real_
dependency engine, which could not be solved (at least not easily) by using
fabricate.py? I know such cases exist in theory, but have never run across a
need, so I'm interested.

~~~
gchpaco
Since fabricate makes Python, a full language available, it's not that there's
things that cannot be expressed, it's really about ease. So I'll tell you
about something I did when I was a grad student.

I was using an up to date TeX install. My advisor wasn't. To placate him, I
had to copy all of my packages, and all the packages they referred to, and so
on down the line so that he could compile my papers. I did this entirely
within make + some small shell scripts. The fact that I could write scanners
for %.tex and %.sty and %.cls and have GNU make (obviously) automagically use
them to build the dependency scripts I instructed it to include was immensely
convenient. This is not impossible to do procedurally, but it was
inconvenient, and the all-make solution had the attractive side that whenever
there were bugfixes to the packages they got automatically included in what I
was doing.

A better example, come to think of it, is the typical LaTeX woe; you can't
build the final .dvi until you have accurate page numbers, references, tables
of contents, indexes. You get all of those by--building the .dvi. So there's a
strange circular dependency here. Make doesn't deal with this especially well,
although it can be done. Ant and SCons don't even try.

------
dinther
Spot on. A must have for every developer.

