-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathros_dev_builder.py
More file actions
125 lines (104 loc) · 4.11 KB
/
ros_dev_builder.py
File metadata and controls
125 lines (104 loc) · 4.11 KB
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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#!/usr/bin/env python
from copy import copy
import logging
from logging import debug, info, warning
import os
import subprocess
import sys
from time import sleep
def usage():
print "ros_dev_builder.py [--debug] <stack or package dir>"
print ""
print "Watches a ROS stack or package for changes to files. If any source"
print "files are changed, it rebuilds the executables. If any executables"
print "are changed (including because they were rebuilt), it kills any"
print "running instances of the executable."
print ""
print "You should set up your ROS launch files to respawn nodes that die"
print "so the new executable gets run when the old one is killed."
def main():
print "" # Makes it easier to read output
if len(sys.argv) == 1 or '--help' in sys.argv:
usage()
sys.exit(1)
warning("Python programs won't be killed when they're changed (yet).\n")
log_level = logging.DEBUG if '--debug' in sys.argv else logging.INFO
logging.basicConfig(level=log_level)
watch_dir = sys.argv[1]
while watch_dir.endswith('/'):
watch_dir = watch_dir[:-1]
info("Watching %s." % os.path.abspath(watch_dir))
file_db = {}
while True:
changed_sources = []
changed_executables = []
makes_run = set()
changed_sources, changed_executables = scan_files(watch_dir, file_db)
if len(changed_sources) > 0:
info("These source files changed: %s" % changed_sources)
debug("These executables changed: %s" % changed_executables)
make_files = [make_which_builds(f, watch_dir) for f in changed_sources]
for make in make_files:
if make not in makes_run:
makes_run.add(make)
make_dir = os.path.dirname(make)
subprocess.call("set -x; cd %s && make" % make_dir, shell=True)
if makes_run:
changed_sources2, changed_executables2 = scan_files(watch_dir,
file_db)
# Don't care about new changed sources
changed_executables.extend(changed_executables2)
if len(changed_executables) > 0:
info("These executables changed: %s" % changed_executables)
for executable in changed_executables:
subprocess.call("set -x; fuser -k %s" % executable, shell=True)
# TODO this won't kill python scripts. figure out how.
if not changed_sources and not changed_executables:
sleep(1)
def scan_files(top_dir, file_db):
changed_sources = []
changed_executables = []
for root, dirs, files in os.walk(top_dir):
for file_name in files:
path = os.path.join(root, file_name)
debug("Looking at %s." % path)
mtime = os.path.getmtime(path)
if path not in file_db or file_db[path] != mtime:
debug("%s was added or changed." % path)
file_db[path] = mtime
if path.endswith('.py') or os.path.split(root)[1] == 'bin':
debug("Adding %s to the changed executables list." % path)
changed_executables.append(path)
else:
debug("Adding %s to the changed sources list." % path)
changed_sources.append(path)
return changed_sources, changed_executables
def make_which_builds(path, watch_dir):
debug("Looking for Makefile which builds %s." % path)
orig_path = copy(path)
assert(path.startswith(watch_dir))
while path.startswith(watch_dir):
path = os.path.split(path)[0]
to_check = '%s/Makefile' % path
debug("Looking for %s." % to_check)
if os.path.exists(to_check):
return to_check
raise Exception("Can't find Makefile to build %s." % orig_path)
if __name__ == '__main__':
main()
"""
You can set up a test package structure by running the following.
mkdir -p test_pkg/src
mkdir -p test_pkg/bin
echo "#include <iostream>
using namespace std;
int main() {
int x;
cin >> x;
return 0;
}
" > test_pkg/src/main.cpp
echo "all:
g++ src/main.cpp -o bin/main
" > test_pkg/Makefile
"""