A python variant of the redo build system, with which You Can (Not) Redo.
Project description
dp-redo
A python variant of the redo build system, with which You Can (Not) Redo.
Example
Let's say we have a build process where we read test.c
and generate test.o
:
import os, sys
source_tree = os.path.dirname(os.path.abspath(sys.argv[0]))
def test():
source = os.path.join(source_tree, "test.c")
# The simplest compiler 😁
os.system("cat {} > {}".format(source, "test.o"))
if __name__ == "__main__":
test()
test
will be run every time no matter whether test.c
gets an update or not, which wastes much time. Now let's add some magic:
from dp_redo import *
import os, sys
source_tree = os.path.dirname(os.path.abspath(sys.argv[0]))
@do("test.o")
def test(target_name, target_base_name, output_path):
redo_ifchange("test.c")
source = os.path.join(source_tree, "test.c")
os.system("cat {} > {}".format(source, output_path))
if __name__ == "__main__":
redo_ifchange(test)
If you run it multiple times:
PS C:\Users\lishengq\source\repos\dp-redo\build> python ..\test2.py
Redoing target: test
PS C:\Users\lishengq\source\repos\dp-redo\build> python ..\test2.py
Skipping target test: it's up to date.
Fantastic, isn't it? If you changed test.c
, modified the test
method itself, or deleted test.o
, test
will be executed again:
PS C:\Users\lishengq\source\repos\dp-redo\build> python ..\test2.py
Redoing target: test. Reason: It's python code has changed
PS C:\Users\lishengq\source\repos\dp-redo\build> python ..\test2.py
Redoing target: test. Reason: The target file doesn't exist
PS C:\Users\lishengq\source\repos\dp-redo\build> python ..\test2.py
Redoing target: test. Reason: test.c has been modified
PS C:\Users\lishengq\source\repos\dp-redo\build>
A target method can also depend on another method, which is rather simple:
from dp_redo import *
import os, sys
source_tree = os.path.dirname(os.path.abspath(sys.argv[0]))
@do("test2.o")
def test2(target_name, target_base_name, output_path):
os.system("echo test2 > " + output_path)
@do("test.o")
def test(target_name, target_base_name, output_path):
redo_ifchange(test2, "test.c")
source = os.path.join(source_tree, "test.c")
os.system("cat {} > {}".format(source, output_path))
if __name__ == "__main__":
redo_ifchange(test)
What makes redo more interesting is that, you can call redo_ifchange
to add dependencies at any time, even after your compilation:
from dp_redo import *
import os, sys, re
source_tree = os.path.dirname(os.path.abspath(sys.argv[0]))
@do("test2.o")
def test2(target_name, target_base_name, output_path):
print("In test2")
os.system("echo test2 > " + output_path)
@do("test.o")
def test(target_name, target_base_name, output_path):
redo_ifchange(test2)
source = os.path.join(source_tree, "test.c")
os.system("gcc -M -MF test.c.dep -o {} {}".format(output_path, source))
# Dependent headers given by gcc
deps = open('test.c.dep', 'r').read().split(": ")[1].strip().split("\\\n")
redo_ifchange(*deps)
if __name__ == "__main__":
redo_ifchange(test)
Now when any headers are changed, the build process will be run again.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.