I hate make

schwern on 2004-12-17T07:04:15

Particularly the concept of writing a cross-platform Makefile. Its like cross-platform GUI code, nearly impossible. Here's a little microcosm of my pain.

I want to run a make target in a subdirectory. On Unix that's easy.

cd dir && $(MAKE) target FOO=bar

And that even works on NT. But what about Win9x and nmake (ie. the "free as in beer" Windows native make that most people get)? It doesn't understand &&. Futhermore each line of the shell can effect another. So you have to do this.

cd dir $(MAKE) target FOO=bar cd ..

I'll be merciful and skip explaining what dmake brings to the party.

But then there's another make variant, MMS/K for VMS. And with completely alien shell conventions. There its...

set default [.dir] $(MAKE) target FOO=bar set default [-]

But that's not quite right. You can't just pass args to make on VMS, oh no. The need special macro magic.

set default [.dir] $(MAKE) target /macro=(FOO=bar) set default [-]

And $(MAKE) isn't set. Its $(MMS). Lovely.

MAKE = $(MMS)

set default [.dir] $(MAKE) target /macro=(FOO=bar) set default [-]

This difference alone accounts for a huge wad of duplication in MakeMaker. I'm whittling away at it with a cd() method.

my $make_command = $mm->cd($dir, @commands);

Then I can plunk that $make_command into a Makefile and be reasonably sure it'll be the right thing for the current platform. This alone knocked out most of MM_Win95.pm. MM_VMS is proving more tenacious, I haven't decided what to do yet about the /macro= wackiness and other MMS argument passing anomalies. Probably yet another method.

Now before you think "why do you bother with VMS?", let me say that I get more help and patches from vmsperl than I do from Windows users. And despite all its faults I can at least telnet to a VMS machine to test things out, DEC/Compaq/HP helpfully provides several for such purposes (http://www.testdrive.hp.com/). But rjbs is setting up a Windows machine for me to VNC into and I got an offer on Perlmonks for some sort of email-based Windows smoke acount. So hopefully that will make life a little easier.


abstract the abstract

jhi on 2004-12-17T14:50:57

Why not something like $mm->runcmd(%opt) where %opt:
cmd => argv[0]
args => [argv[1..]]
env => {...}
cwd => directory where to cd in and out of
stdin => file
stdout => file
etc.
Shades of t/test.pl:runperl(), don't you think? :-)

Re:abstract the abstract

schwern on 2004-12-18T00:36:42

See MM_Any->oneliner(). It makes the job barely tolerable. Here's an example from generating the clean target.

        # Equivalent to 'cd $dir && $(TESTF) $(FIRST_MAKEFILE) && $(MAKE) clean'
        for my $dir (@{$self->{DIR}}) {
                my $subclean = $self->oneliner(sprintf 'CODE', $dir);
chdir '%s'; system '$(MAKE) clean' if -f '$(FIRST_MAKEFILE)';
CODE

                $clean .= "\t$subclean\n";
        }

But you can't move everything to running individual perl scripts, its too bloody slow. And there's something depressingly Sisyphusian about a Perl module to write a Makefile full of shell scripts which are ultimately Perl one-liners.