Directory reorg: move code into redo/, generate binaries in bin/.

It's time to start preparing for a version of redo that doesn't work
unless we build it first (because it will rely on C modules, and
eventually be rewritten in C altogether).

To get rolling, remove the old-style symlinks to the main programs, and
rename those programs from redo-*.py to redo/cmd_*.py.  We'll also move
all library functions into the redo/ dir, which is a more python-style
naming convention.

Previously, install.do was generating wrappers for installing in
/usr/bin, which extend sys.path and then import+run the right file.
This made "installed" redo work quite differently from running redo
inside its source tree.  Instead, let's always generate the wrappers in
bin/, and not make anything executable except those wrappers.

Since we're generating wrappers anyway, let's actually auto-detect the
right version of python for the running system; distros can't seem to
agree on what to call their python2 binaries (sigh). We'll fill in the
right #! shebang lines.  Since we're doing that, we can stop using
/usr/bin/env, which will a) make things slightly faster, and b) let us
use "python -S", which tells python not to load a bunch of extra crap
we're not using, thus improving startup times.

Annoyingly, we now have to build redo using minimal/do, then run the
tests using bin/redo.  To make this less annoying, we add a toplevel
./do script that knows the right steps, and a Makefile (whee!) for
people who are used to typing 'make' and 'make test' and 'make clean'.
This commit is contained in:
Avery Pennarun 2018-12-03 21:39:15 -05:00
commit f6fe00db5c
140 changed files with 256 additions and 99 deletions

4
.gitignore vendored
View file

@ -4,8 +4,6 @@
/minimal/.do_built /minimal/.do_built
/minimal/.do_built.dir /minimal/.do_built.dir
*~ *~
*.pyc
*.tmp *.tmp
/redo-sh
*.did *.did
/website /docs.out

View file

@ -1,8 +0,0 @@
redo-ifchange md2man.py
if ./md2man.py /dev/null /dev/null >/dev/null; then
echo './md2man.py $2.md.tmp $2.html'
else
echo "Warning: md2man.py missing modules; can't generate manpages." >&2
echo "Warning: try this: sudo easy_install markdown BeautifulSoup" >&2
echo 'echo Skipping: $2.1 >&2'
fi

View file

@ -1,10 +1,21 @@
default: all
build:
+./do build
all: all:
+./do all
Makefile: test:
@ +./do test
%: FORCE clean:
+./redo $@ +./do clean
.PHONY: FORCE install:
+./do install
env:
env
.PHONY: build test clean env

View file

@ -11,6 +11,9 @@ This version, sometimes called apenwarr/redo, is probably the most advanced
one, including support for parallel builds, improved logging, and helpful one, including support for parallel builds, improved logging, and helpful
debugging features. debugging features.
To build and test redo, run `./do -j10 test`. To install it, run
`DESTDIR=/tmp/testinstall PREFIX=/usr/local ./do -j10 install`.
--- ---
- View the [documentation](https://redo.rtfd.io) via readthedocs.org - View the [documentation](https://redo.rtfd.io) via readthedocs.org

View file

@ -3,5 +3,7 @@ if [ "$1,$2" != "_all,_all" ]; then
exit 1 exit 1
fi fi
redo-ifchange redo-sh # Do this first, to ensure we're using a good shell
redo-ifchange version/all Documentation/all redo-ifchange redo/sh
redo-ifchange bin/all docs/all

2
all.do
View file

@ -1,2 +1,2 @@
redo-ifchange _all redo-ifchange _all
echo "Nothing much to do. Try 'redo t/all' or 'redo test'" >&2 echo "Nothing much to do. Try 'bin/redo -j10 test'" >&2

3
bin/.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
list
redo
redo-*

3
bin/all.do Normal file
View file

@ -0,0 +1,3 @@
exec >&2
redo-ifchange ../redo/version/all ../redo/python list redo-sh
xargs redo-ifchange <list

1
bin/clean.do Normal file
View file

@ -0,0 +1 @@
rm -f redo redo-* list whichpython

33
bin/default.do Normal file
View file

@ -0,0 +1,33 @@
exec >&2
case $1 in
redo-sh)
redo-ifchange ../redo/sh
cat >$3 <<-EOF
#!/bin/sh
d=\$(dirname "\$0")/..
[ -x \$d/lib/redo/sh ] && exec \$d/lib/redo/sh "\$@"
[ -x \$d/redo/sh ] && exec \$d/redo/sh "\$@"
echo "\$0: fatal: can't find \$d/lib/redo/sh or \$d/redo/sh" >&2
exit 98
EOF
chmod a+x "$3"
;;
redo|redo-*)
redo-ifchange ../redo/whichpython
read py <../redo/whichpython
cmd=${1#redo-}
cat >$3 <<-EOF
#!$py -S
import sys, os;
exe = os.path.realpath(os.path.abspath(sys.argv[0]))
exedir = os.path.dirname(exe)
sys.path.insert(0, os.path.join(exedir, '../lib'))
sys.path.insert(0, os.path.join(exedir, '..'))
import redo.cmd_$cmd
redo.cmd_$cmd.main()
EOF
chmod a+x "$3"
;;
*) echo "$0: don't know how to build '$1'" >&2; exit 99 ;;
esac

16
bin/list.do Normal file
View file

@ -0,0 +1,16 @@
exec >&2
redo-always
(
cd ../redo
for d in cmd_*.py; do
d=${d#cmd_}
d=${d%.py}
if [ "$d" = "redo" ]; then
echo redo
else
echo "redo-${d%.py}"
fi
done
) >$3
redo-stamp <$3

View file

@ -1,13 +1,13 @@
exec >&2 exec >&2
rm -rf t/.redo redo-sh rm -rf t/.redo redo/sh
if [ -e .do_built ]; then if [ -e .do_built ]; then
while read x; do while read x; do
[ -d "$x" ] || rm -f "$x" [ -d "$x" ] || rm -f "$x"
done <.do_built done <.do_built
fi fi
[ -z "$DO_BUILT" ] && rm -rf .do_built .do_built.dir [ -z "$DO_BUILT" ] && rm -rf .do_built .do_built.dir
rm -rf minimal/.do_built minimal/.do_built.dir website rm -rf minimal/.do_built minimal/.do_built.dir docs.out
redo t/clean Documentation/clean version/clean redo t/clean docs/clean redo/clean
rm -f *~ .*~ */*~ */.*~ *.pyc install.wrapper rm -f *~ .*~ */*~ */.*~ *.pyc install.wrapper
find . -name '*.tmp' -exec rm -fv {} \; find . -name '*.tmp' -exec rm -f {} \;
find . -name '*.did' -exec rm -fv {} \; find . -name '*.did' -exec rm -f {} \;

83
do Executable file
View file

@ -0,0 +1,83 @@
#!/bin/sh
#
# Bootstrap script, so we can build and test redo using (mostly) redo.
# Before redo is available, we have to use minimal/do to build it. After
# that, we switch to real redo.
#
# NOTE: Don't use this as a model for your own redo projects! It's friendly
# to provide a 'do' script at the top of your project for people who haven't
# installed redo, but that script is usually just a copy of minimal/do,
# because your project probably doesn't have the same bootstrap problem that
# redo itself does.
#
die() {
echo "$0:" "$@" >&2
exit 42
}
usage() {
echo "Usage: $0 [redo-args...] <target>" >&2
echo " where valid targets are: build all test install clean" >&2
echo " and redo-args are optional args for redo, like -j10, -x" >&2
exit 10
}
mydir=$(dirname "$0")
cd "$mydir" || die "can't find self in dir: $mydir"
args=
while [ "$1" != "${1#-}" ]; do
args="$args $1"
shift
done
if [ "$#" -gt 1 ]; then
usage
fi
if [ -n "$args" -a "$#" -lt 1 ]; then
usage
fi
if [ "$#" -lt 1 ]; then
# if no extra args given, use a default target
target=all
else
target=$1
fi
build() {
./minimal/do -c bin/all || die "failed to compile redo."
bin/redo bin/all || die "redo failed self test."
}
clean() {
./minimal/do -c clean || die "failed to clean."
rm -rf .redo .do_built .do_built.dir
}
case $target in
build)
build
;;
all|install)
build && bin/redo $args "$target"
;;
test)
# Test both redo and minimal/do
build
PATH=$PWD/redo:$PATH minimal/do test || die "minimal/do test failed"
clean
build
bin/redo $args test || die "redo test failed"
;;
clean)
clean
;;
*)
echo "$0: unknown target '$target'" >&2
exit 11
;;
esac

View file

@ -8,7 +8,7 @@ today's date.
To play with this code on your own machine, get the [redo To play with this code on your own machine, get the [redo
source code](https://github.com/apenwarr/redo) and look in the source code](https://github.com/apenwarr/redo) and look in the
`Documentation/cookbook/defaults/` directory. `docs/cookbook/defaults/` directory.
### Input files ### Input files

View file

@ -7,7 +7,7 @@ compile it.
To play with the code on your own machine, get the [redo To play with the code on your own machine, get the [redo
source code](https://github.com/apenwarr/redo) and look in the source code](https://github.com/apenwarr/redo) and look in the
`Documentation/cookbook/hello/` directory. `docs/cookbook/hello/` directory.
### Compiling the code ### Compiling the code

View file

@ -10,7 +10,7 @@ ggplot2](https://ggplot2.tidyverse.org/).
To play with this code on your own machine, get the [redo To play with this code on your own machine, get the [redo
source code](https://github.com/apenwarr/redo) and look in the source code](https://github.com/apenwarr/redo) and look in the
`Documentation/cookbook/latex/` directory. `docs/cookbook/latex/` directory.
### Generating a plot from an R script ### Generating a plot from an R script

View file

@ -1,5 +1,5 @@
redo-ifchange ../version/vars $2.md redo-ifchange ../redo/version/vars $2.md
. ../version/vars . ../redo/version/vars
cat - $2.md <<-EOF cat - $2.md <<-EOF
% $2(1) Redo $TAG % $2(1) Redo $TAG
% Avery Pennarun <apenwarr@gmail.com> % Avery Pennarun <apenwarr@gmail.com>

View file

@ -8,7 +8,7 @@ rm -f $GIT_INDEX_FILE
git add -f *.1 git add -f *.1
MSG="Autogenerated man pages for $(git describe)" MSG="Autogenerated man pages for $(git describe)"
TREE=$(git write-tree --prefix=Documentation) TREE=$(git write-tree --prefix=docs)
git show-ref refs/heads/man >/dev/null && PARENT="-p refs/heads/man" git show-ref refs/heads/man >/dev/null && PARENT="-p refs/heads/man"
COMMITID=$(echo "$MSG" | git commit-tree $TREE $PARENT) COMMITID=$(echo "$MSG" | git commit-tree $TREE $PARENT)

View file

@ -170,7 +170,7 @@ easily be linked from this document. Here are a few open source examples:
in order to clean up its dependency logic. in order to clean up its dependency logic.
* You can also find some curated examples in the * You can also find some curated examples in the
[Documentation/cookbook/](https://github.com/apenwarr/redo/tree/master/Documentation/cookbook/) subdir of the redo project itself. [docs/cookbook/](https://github.com/apenwarr/redo/tree/master/docs/cookbook/) subdir of the redo project itself.
* A [github search for all.do](https://github.com/search?p=9&q=path%3A%2F+extension%3Ado+filename%3A%2Fall.do&type=Code) * A [github search for all.do](https://github.com/search?p=9&q=path%3A%2F+extension%3Ado+filename%3A%2Fall.do&type=Code)
shows an ever-growing number of projects using redo. shows an ever-growing number of projects using redo.

9
docs/md-to-man.do Normal file
View file

@ -0,0 +1,9 @@
redo-ifchange md2man.py ../redo/whichpython
read py <../redo/whichpython
if ../redo/python ./md2man.py /dev/null /dev/null >/dev/null; then
echo '../redo/python ./md2man.py $2.md.tmp $2.html'
else
echo "Warning: md2man.py missing modules; can't generate manpages." >&2
echo "Warning: try this: sudo easy_install markdown BeautifulSoup" >&2
echo 'echo Skipping: $2.1 >&2'
fi

1
Documentation/md2man.py → docs/md2man.py Executable file → Normal file
View file

@ -1,4 +1,3 @@
#!/usr/bin/env python2
import sys, os, markdown, re import sys, os, markdown, re
from BeautifulSoup import BeautifulSoup from BeautifulSoup import BeautifulSoup

View file

@ -1,49 +1,42 @@
exec >&2 exec >&2
redo-ifchange _all
: ${INSTALL:=install} : ${INSTALL:=install}
: ${DESTDIR:=} : ${DESTDIR=NONE}
: ${PREFIX:=/usr} : ${PREFIX:=/usr}
: ${MANDIR:=$DESTDIR$PREFIX/share/man} : ${MANDIR:=$DESTDIR$PREFIX/share/man}
: ${DOCDIR:=$DESTDIR$PREFIX/share/doc/redo} : ${DOCDIR:=$DESTDIR$PREFIX/share/doc/redo}
: ${BINDIR:=$DESTDIR$PREFIX/bin} : ${BINDIR:=$DESTDIR$PREFIX/bin}
: ${LIBDIR:=$DESTDIR$PREFIX/lib/redo} : ${LIBDIR:=$DESTDIR$PREFIX/lib/redo}
if [ "$DESTDIR" = "NONE" ]; then
echo "$0: fatal: set DESTDIR before trying to install."
exit 99
fi
redo-ifchange _all redo/whichpython
read py <redo/whichpython
echo "Installing to: $DESTDIR$PREFIX" echo "Installing to: $DESTDIR$PREFIX"
# make dirs # make dirs
$INSTALL -d $MANDIR/man1 $DOCDIR $BINDIR $LIBDIR $LIBDIR/version $INSTALL -d $MANDIR/man1 $DOCDIR $BINDIR $LIBDIR $LIBDIR/version
# docs # docs
for d in Documentation/*.1; do for d in docs/*.1; do
[ "$d" = "Documentation/*.1" ] && continue [ "$d" = "docs/*.1" ] && continue
$INSTALL -m 0644 $d $MANDIR/man1 $INSTALL -m 0644 $d $MANDIR/man1
done done
$INSTALL -m 0644 README.md $DOCDIR $INSTALL -m 0644 README.md $DOCDIR
# .py files (precompiled to .pyc files for speed) # .py files (precompiled to .pyc files for speed)
for d in *.py version/*.py; do $INSTALL -m 0644 redo/*.py $LIBDIR/
fix=$(echo $d | sed 's,-,_,g') $INSTALL -m 0644 redo/version/*.py $LIBDIR/version/
$INSTALL -m 0644 $d $LIBDIR/$fix $py -mcompileall $LIBDIR
done
python2 -mcompileall $LIBDIR
# It's important for the file to actually be named 'sh'. Some shells (like # It's important for the file to actually be named 'sh'. Some shells (like
# bash and zsh) only go into POSIX-compatible mode if they have that name. # bash and zsh) only go into POSIX-compatible mode if they have that name.
cp -R redo-sh/sh $LIBDIR/sh cp -R redo/sh $LIBDIR/sh
# binaries # binaries
for dd in redo*.py; do bins=$(ls bin/redo* | grep '^bin/redo[-a-z]*$')
d=$(basename $dd .py) $INSTALL -m 0755 $bins $BINDIR/
fix=$(echo $d | sed -e 's,-,_,g')
cat >install.wrapper <<-EOF
#!/usr/bin/python2
import sys, os;
exedir = os.path.dirname(os.path.realpath(os.path.abspath(sys.argv[0])))
sys.path.insert(0, os.path.join(exedir, '../lib/redo'))
import $fix
$fix.main()
EOF
$INSTALL -m 0755 install.wrapper $BINDIR/$d
done
rm -f install.wrapper

View file

@ -1,10 +1,10 @@
site_name: "redo: a recursive build system" site_name: "redo: a recursive build system"
theme: readthedocs theme: readthedocs
docs_dir: Documentation docs_dir: docs
site_dir: website site_dir: docs.out
strict: true strict: true
repo_url: https://github.com/apenwarr/redo repo_url: https://github.com/apenwarr/redo
edit_uri: edit/master/Documentation edit_uri: edit/master/docs
extra_javascript: extra_javascript:
- fetchcode.js - fetchcode.js
extra_css: extra_css:

1
redo
View file

@ -1 +0,0 @@
redo.py

View file

@ -1 +0,0 @@
redo-always.py

View file

@ -1 +0,0 @@
redo-ifchange.py

View file

@ -1 +0,0 @@
redo-ifcreate.py

View file

@ -1 +0,0 @@
redo-log.py

View file

@ -1 +0,0 @@
redo-ood.py

View file

@ -1 +0,0 @@
redo-sources.py

View file

@ -1 +0,0 @@
redo-stamp.py

View file

@ -1 +0,0 @@
redo-targets.py

View file

@ -1 +0,0 @@
redo-unlocked.py

View file

@ -1 +0,0 @@
redo-whichdo.py

4
redo/.gitignore vendored Normal file
View file

@ -0,0 +1,4 @@
*.pyc
sh
whichpython
python

0
redo/__init__.py Normal file
View file

2
redo/clean.do Normal file
View file

@ -0,0 +1,2 @@
redo version/clean
rm -f whichpython python *.pyc */*.pyc

1
redo-always.py → redo/cmd_always.py Executable file → Normal file
View file

@ -1,4 +1,3 @@
#!/usr/bin/env python2
import sys, os import sys, os
import vars, state import vars, state

1
redo-ifchange.py → redo/cmd_ifchange.py Executable file → Normal file
View file

@ -1,4 +1,3 @@
#!/usr/bin/env python2
import os, sys, traceback import os, sys, traceback
import vars_init import vars_init

Some files were not shown because too many files have changed in this diff Show more