Pyke
This weekend project is a small clone (most of the code is in a single file of just about 200LoC) of GNU Make with the twist that it rebuilds a target only if the hash of any of its sources changes. This is named Pyke as in Python + Make (I have no hope of being the first coming up with this name for a project).
Usage
Installation
Clone the project and then install it locally with pip.
$ git clone https://github.com/aziis98/pyke
$ cd pyke
$ pip install -e .
Files
Create a pykefile.py in your project folder and add recipes to build your targets (for now just read below and look at the examples for the syntax).
-
pykefile.pyThe provided globals in this file are
-
pikefileis of typePikefileand holds all the rules and handles the building of the project. -
ruleis a function and an alias forpikefile.ruleand is used as a decorator to define new rules. -
runis just an alias foros.systemused to directly call shell commands.
-
-
.pykecache.jsonThis file stores the checksums of all built targets.
Examples
There are some examples in ./examples.
Simple
This example shows how the checksums approach is better in this case with respect to Make.
@rule('b.txt', ['a.txt'])
def _(target, source, sources):
run(f'head -n 3 {source} > {target}')
run(f'printf "\n" >> {target}')
@rule('c.txt', ['b.txt'])
def _(target, source, sources):
run(f'cat {source} {source} {source} > {target}')
The file b.txt depends only on a part of a.txt so changes to its end don't trigger the recompilation of targets that depend only on b.txt. In this case, Make couldn't have figured that changes to the end of a.txt don't affect b.txt.
C
A simple example that shows a generic rule with "%" for creating object files from the sources main.c and util.c and then linking them.
@rule('%.o', ['%.c'])
def _(target, source, sources):
run(f'gcc -c {source} -o {target}')
@rule('main', ['main.o', 'util.o'])
def _(target, source, sources):
run(f'gcc -o {target} {" ".join(sources)}')
Cycle
This example shows the cycle detection feature
@rule('a', ['c'])
def _(target, source, sources):
print("A")
@rule('b', ['a'])
def _(target, source, sources):
print("B")
@rule('c', ['b'])
def _(target, source, sources):
print("C")
Trying to execute pyke for this project gives
$ pyke
[ERROR] Found dependency cycle caused by "c", aborting! Trace: ['c', 'b', 'a']
TODOs
- Move the code of
pyke.build_with_args()directly insidebin/pikeand decouple the logging code in its own module to let the logging level be changed from the start script.