-
Notifications
You must be signed in to change notification settings - Fork 45
/
make2.py
68 lines (58 loc) · 1.67 KB
/
make2.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
import os
from typing import List, Optional
from redun import File, task
from redun.functools import const
redun_namespace = "redun.examples.compile2"
# Custom DSL for describing targets, dependencies (deps), and commands.
rules = {
"all": {
"deps": ["prog", "prog2"],
},
"prog": {
"deps": ["prog.o", "lib.o"],
"command": "gcc -o prog prog.o lib.o",
},
"prog2": {
"deps": ["prog2.o", "lib.o"],
"command": "gcc -o prog2 prog2.o lib.o",
},
"prog.o": {
"deps": ["prog.c"],
"command": "gcc -c prog.c",
},
"prog2.o": {
"deps": ["prog2.c"],
"command": "gcc -c prog2.c",
},
"lib.o": {
"deps": ["lib.c"],
"command": "gcc -c lib.c",
},
}
@task()
def run_command(command: str, inputs: List[File], output_path: str) -> File:
"""
Run a shell command to produce a target.
"""
# Ignore inputs. We pass it as an argument to simply force a dependency.
assert os.system(command) == 0
return File(output_path)
@task()
def make(target: str = "all", rules: dict = rules) -> Optional[File]:
"""
Make a target (file) using a series of rules.
"""
rule = rules.get(target)
if not rule:
# No rule. See if target already exists.
file = File(target)
if not file.exists():
raise ValueError(f"No rule for target: {target}")
return file
# Recursively make dependencies.
inputs = [make(dep, rules=rules) for dep in rule.get("deps", [])]
# Run command, if needed.
if "command" in rule:
return run_command(rule["command"], inputs, target)
else:
return const(None, inputs)