Linked by Jussi Pakkanen on Tue 17th Apr 2007 18:20 UTC
Editorial Let me begin by telling you a little story. Some time ago I needed to run a script at work once a day. We had tons of machines ranging from big Unix servers to Linux desktops. Due to various reasons the script could only be run on a desktop machine. However using cron was disabled on desktops. All other machines allowed cron.
Thread beginning with comment 231670
To read all comments associated with this story, please click here.
Invincible Cow
Member since:
2006-06-24

On Linux/Unix, makefiles are used to specify which files depends on which files. This is considered like "state-of-the-art" because you don't have to type in a HUGE command line with all your program's files every time you want to compile something. And also only the modified files are recompiled. Really a good idea.

Of course, writing makefiles turned out to be almost as bad as tucking the compilation commands into a shell script. So someone invented a makefile generator. And this makefile generator needed a configuration file for each project... (I bet you see where this is heading.)

As programmers used the makefile generator instead of writing the makefiles themselves, they became less comfortable with editing the makefiles, and as more and more non-programmers needed to compile programs on different systems, editing makefiles didn't look like a good idea any more. Especially with all the different configurations in different Linux distros and on different desktops and servers, which made makefile editing necessary more often. The solution? Make the makefile generator generate a shell script that generated the makefile.

So, instead of writing a makefile ("config file for make"), we now write a config file for the makefile generator generator. Nice improvement.

So why are makefiles needed at all? Partially because of another hack: header files, partially I don't know why. Pascal does not need makefiles at all. A pascal compiler can automatically find out which files need recompilation and links the object files together automatically.

One command and the library path in the global configuration file is all that is needed to build an entire project. Why does C have to make it so hard?

mjones Member since:
2006-06-14

Check out Ant and Jam -- they are next generation Makes

Reply Parent Bookmark Score: 2

Invincible Cow Member since:
2006-06-24

They will still just do what should not be necessary. (I don't doubt that they are slightly better at doing it, though.)

Reply Parent Bookmark Score: 2

siebharinn Member since:
2005-07-06

So, instead of writing a makefile ("config file for make"), we now write a config file for the makefile generator generator. Nice improvement.

This is not limited to C/C++:
http://discuss.joelonsoftware.com/default.asp?joel.3.219431.12

This is part of the reason why people are migrating en mass to languages like Ruby and Python.

Reply Parent Bookmark Score: 3

sanctus Member since:
2005-08-31

yeah python, (same thing goes for ruby) to make your script work you have to write at the beginning : #!/usr/bin/python
but wait, what if python is not located there.
solution : #!/usr/bin/env python
but wait, what if env is not there either !!

what a hack

so just remove that line and type python before the script

Reply Parent Bookmark Score: 1

MORB Member since:
2005-07-06

This is part of the reason why people are migrating en mass to languages like Ruby and Python.

Most python apps come with configure scripts/makefile to make sure that all required optional 3rd party modules are available and to precompile everything to .pyc anyway.

Reply Parent Bookmark Score: 1

ma_d Member since:
2005-06-29

I don't think it's caused by header files, I'd say it's actually caused by linking issues; and I wouldn't call this a hack.

Some of the complexity of making a working makefile is finding header files; but it's not an issue of header files: It still exists in Java for example with $CLASSPATH.

In my opinion the trouble is a lack of separation of concern. The makefile is definitely well suited to building code: Most of us could probably make a makefile to build a medium complexity project for one system. The trouble comes into effect that there's no effective separation between makefile commands and the shell and so you end up dependent on the OS.
One place you get stuck is installing, and another is the joy of filling in the -I and -L's.
I think that what we need is a smarter makefile that encapsulate's our -I and -L's. Some kind of make + pkg-config (note that what we have is _ok_ but it's a hack since you need both, and then you need your packages to install .pc files). The beauty is that programs installed with this system would automatically contribute their .pc because it would be automatically generated by the install section!

I don't think syntax actually needs to change much. But I would prefer to separate make from the shell in typical sequences with some extra keyword to get shell integration (and a big warning about how you're going to break compatibility in books).

all: target

target { needs gtk+-2.0 }: file1.object file2.object
->link file1.object file2.object as target

file1.object { needs gtk+-2.0 }: file1.source [c]
->compile file1.source to file1.object

file2.object: file2.source [c++]
->compile file2.source to file2.object


Maybe not so many keywords, but I think you get the idea.

Edit: And of course osnews doesn't help me out and it's all flat, just pretend it's indented if you see "->".

Edited 2007-04-17 20:41 UTC

Reply Parent Bookmark Score: 5

Doc Pain Member since:
2006-10-08

"I don't think it's caused by header files, I'd say it's actually caused by linking issues; and I wouldn't call this a hack."

That's correct. Makefile controls dependencies (questions if everything or just a part of a project needs recompile), proper linking (here, header files affect) and conditions at compile time (compiling for different architectures, with debug enabled, with optimization, with certain features turned off or on etc.).

"Some of the complexity of making a working makefile is finding header files; but it's not an issue of header files: It still exists in Java for example with $CLASSPATH."

The access to header files belonging to the system is usually done via the include/ directories with their default settings, making them available using the #include <...> macro, or calling them absolutely with #include "...", which should be avoided.

Makefile automates parameter calls for cc and ld, such as -I <include path>, -L <library path> or -l<library name>.

"In my opinion the trouble is a lack of separation of concern. The makefile is definitely well suited to building code: Most of us could probably make a makefile to build a medium complexity project for one system. The trouble comes into effect that there's no effective separation between makefile commands and the shell and so you end up dependent on the OS."

Usually, /bin/sh (default Bourne shell) is invoked for every command in Makefile. If you want to place them into more than one line (starting with tab), you need to end the line with a backslash, otherwise you're running into trouble. Access to shell variables is a bit complicated; while you can access make variables via $(NAME), you need $$NAME for a shell variable which is only active for the current line (representing a shell command call).

I use Makefiles for more than programming, such as for LaTeX or HTML builds of larger document projects. Surely make is not inteded for this kind of work, but it's quite nice for such kind of work, as long as you know what you're doing.

"One place you get stuck is installing, and another is the joy of filling in the -I and -L's."

This is a problem in fact. You mentioned some suggestions. Today, the Makefiles for the FreeBSD ports collections serve this purpose. They do not only compile programs, they also:

# make update
# make fetch
# make extract
# make patch
# make uninstall
# make reinstall
# make install
# make package
# make clean

You surely know what this does in reality. It works fine with the ports, but applications not included in the ports usually do not have this functionality.

"I don't think syntax actually needs to change much."

I'd like to get rid of the tab character, instead, having some kind of grouping mechanism as in C, just as an example:

foo.pdf: foo.tex bar.tex blah.eps {
... commands here...
}

"But I would prefer to separate make from the shell in typical sequences with some extra keyword to get shell integration (and a big warning about how you're going to break compatibility in books)."

So make must be able to realize the command content independent from the actual shell (default shell?), but calling a shell to run a command is the usual way of doing things here. On the other hand, explicitely calling a shell (or entering "shell mode") would be good to have access to shell environment and variables. It would allow to write commands according to the shell languace (such as csh or zsh commands).

"Edit: And of course osnews doesn't help me out and it's all flat, just pretend it's indented if you see "->"."

As I mentioned - or complained :-) - before, it would be great to have the <pre></pre> HTML tags enabled in order to post source code or shell fragments in an appealing way.

Edited 2007-04-17 22:24

Reply Parent Bookmark Score: 3

MORB Member since:
2005-07-06

makefiles are not specific to C and C++, and conversely you don't have to use makefiles to write C/C++ programs.

However, automatically rebuilding things based on dependencies is a problem common to many languages.

There are some nice build systems nowadays. Check out jam, ant, cmake, scons, qmake for instance.

I'm using cmake in my current personal project and I'm very happy with it (although unlike some other recent build systems, on unix platforms it doesn't replace make and generate makefiles instead - but as I don't have to modify or even to look at them, I don't care)

cmake files are pretty straightforward and easy to write, and even complicated dependencies (like having an interface description language to C++ compilation program being built as part of the project and subsequently used to build the rest) are easy to describe.

Reply Parent Bookmark Score: 1