Skip to main content

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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Files for dp-redo, version 3.0.2
Filename, size File type Python version Upload date Hashes
Filename, size dp_redo-3.0.2-py3-none-any.whl (5.9 kB) File type Wheel Python version py3 Upload date Hashes View hashes
Filename, size dp-redo-3.0.2.tar.gz (4.4 kB) File type Source Python version None Upload date Hashes View hashes

Supported by

Elastic Elastic Search Pingdom Pingdom Monitoring Google Google BigQuery Sentry Sentry Error logging AWS AWS Cloud computing DataDog DataDog Monitoring Fastly Fastly CDN DigiCert DigiCert EV certificate StatusPage StatusPage Status page