Handle .do files that start with "#!/" to specify an explicit interpreter.

Now you can have your .do files interpreted by whatever interpreter you
want.
This commit is contained in:
Avery Pennarun 2011-01-01 22:00:14 -08:00
commit f641e52e3b
7 changed files with 38 additions and 11 deletions

View file

@ -437,15 +437,28 @@ changed, you can run `redo-ifchange target` instead.
# Can my .do files be written in a language other than sh?
FIXME: Not presently. In theory, we could support starting your .do files
with the magic "#!/" sequence (eg. #!/usr/bin/python) and then using that
shell to run your .do script. But that opens new problems, like figuring
out what is the equivalent of the `redo-ifchange` command in python. Do you
just run it in a subprocess? That might be unnecessarily slow. And so on.
Yes. If the first line of your .do file starts with the
magic "#!/" sequence (eg. `#!/usr/bin/python`), then redo
will execute your script using that particular interpreter.
Right now, `redo` explicitly runs `sh filename.do`. The main reasons for
this are to make the #!/ line optional, and so you don't have to remember to
`chmod +x` your .do files.
Note that this is slightly different from normal Unix
execution semantics: redo never execs your script directly;
it only looks for the "#!/" line. The main reason for this
is so that your .do scripts don't have to be marked
executable (chmod +x). Executable .do scripts would
suggest to users that they should run them directly, and
they shouldn't; .do scripts should always be executed
inside an instance of redo, so that dependencies can be
tracked correctly.
WARNING: If your .do script *is* written in Unix sh, we
recommend *not* including the `#!/bin/sh` line. That's
because there are many variations of /bin/sh, and not all
of them are POSIX compliant. redo tries pretty hard to
find a good default shell that will be "as POSIXy as
possible," and if you override it using #!/bin/sh, you lose
this benefit and you'll have to worry more about
portability.
# Can a single .do script generate multiple outputs?

View file

@ -128,6 +128,9 @@ class BuildJob:
if vars.VERBOSE: argv[1] += 'v'
if vars.XTRACE: argv[1] += 'x'
if vars.VERBOSE or vars.XTRACE: log_('\n')
firstline = open(dofile).readline().strip()
if firstline.startswith('#!/'):
argv[0:2] = firstline[2:].split(' ')
log('%s\n' % _nice(t))
self.argv = argv
sf.is_generated = True

View file

@ -57,7 +57,13 @@ _run_dofile()
export DO_DEPTH="$DO_DEPTH "
export REDO_TARGET=$PWD/$TARGET
set -e
read line1 <"$PWD/$DOFILE"
cmd=${line1#"#!/"}
if [ "$cmd" != "$line1" ]; then
/$cmd "$PWD/$DOFILE" "$@" >"$TARGET.tmp2"
else
. "$PWD/$DOFILE" >"$TARGET.tmp2"
fi
}

1
t/.gitignore vendored
View file

@ -23,3 +23,4 @@ test2.args
/ifcreate[12]
/broken
/shellfile
/nonshelltest

View file

@ -1,6 +1,6 @@
redo example/clean curse/clean deps/clean "space dir/clean" stamp/clean \
defaults-flat/clean
rm -f broken shellfile mode1 makedir.log chdir1 deltest2 \
rm -f broken nonshelltest shellfile mode1 makedir.log chdir1 deltest2 \
hello [by]ellow *.o *~ .*~ *.log CC LD passfail silence silence.do \
touch1 touch1.do always1 ifcreate[12].dep ifcreate[12]
rm -rf makedir

3
t/nonshelltest.do Normal file
View file

@ -0,0 +1,3 @@
#!/usr/bin/env perl
$a="perly";
print "hello $a world\n";

View file

@ -1,5 +1,6 @@
redo-ifchange all
./hello >&2
redo shelltest deltest deltest2 test.args test2.args passfailtest chdirtest \
redo nonshelltest shelltest \
deltest deltest2 test.args test2.args passfailtest chdirtest \
curse/test deps/test "space dir/test" modetest makedir2 \
silencetest touchtest stamp/test alwaystest ifcreate-test