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 from __future__ import print_function
33
34 import os
35 import re
36 import signal
37 import sys
38 import subprocess
39 import time
40 import threading
41 import traceback
42
43 import rospkg
44 from rospkg import ResourceNotFound
45
46 try:
47 from exceptions import SystemExit
48 except ImportError:
49 pass
50
51 from operator import itemgetter
52
53 from . import parallel_build
54 from . import package_stats
55
56 from optparse import OptionParser
57 from gcc_output_parse import Warnings
58
59
60 _popen_lock = threading.Lock()
63 """
64 @return: name of 'make' command
65 @rtype: str
66 """
67 return os.environ.get("MAKE", "make")
68
72 """
73 Create the directory using the permissions of the nearest
74 (existing) parent directory. This is useful for logging, where a
75 root process sometimes has to log in the user's space.
76 @param p: directory to create
77 @type p: str
78 """
79 p = os.path.abspath(p)
80 parent = os.path.dirname(p)
81
82
83 if not os.path.exists(p) and p and parent != p:
84 makedirs_with_parent_perms(parent)
85 s = os.stat(parent)
86 os.mkdir(p)
87
88
89 s2 = os.stat(p)
90 if s.st_uid != s2.st_uid or s.st_gid != s2.st_gid:
91 os.chown(p, s.st_uid, s.st_gid)
92 if s.st_mode != s2.st_mode:
93 os.chmod(p, s.st_mode)
94
96
97 __instance = None
98
108
110 """ Delegate access to implementation """
111 return getattr(self.__instance, attr)
112
114 """ Delegate access to implementation """
115 return setattr(self.__instance, attr, value)
116
118 """Pass through for the __enter__ function for the __instance"""
119 return self.__instance.__enter__()
120
122 """Pass through for the __exit__ function for the __instance"""
123 return self.__instance.__exit__(mtype, value, tb)
124
125 - class __impl(threading.Thread):
127 threading.Thread.__init__(self)
128 self.build_queue = None
129 self.condition = threading.Condition()
130 self.running = True
131 self.done = False
132 self.status = ""
133 self.verbose = False
134 self.full_verbose = False
135 self.duration = 1./10.
136 self._last_status = None
137
138
139 self.cache_argument = None
140 self.cache_right = ''
141 self.pkg_start_times = {}
142
144 self.running = False
145 cycles = 10
146 for i in range(0,cycles):
147 if self.done:
148
149 return True
150
151 time.sleep(max(self.duration, 0.1)/cycles*2)
152 raise Exception("Failed to shutdown status thread in %.2f seconds"%(self.duration * 2))
153
157 self.shutdown()
158 if value:
159 if not mtype == type(SystemExit()):
160 traceback.print_exception(mtype, value, tb)
161 else:
162 sys.exit(value)
163
165 while self.running:
166
167 if self.duration <= 0:
168 self.running = False
169 break
170 self.set_status_from_cache()
171 if len(self.pkg_start_times.keys()) > 0:
172 n = self.terminal_width() - len(self.status)
173 status = self.status
174 if n > 0:
175 status = " "*n + self.status
176 if status != self._last_status:
177 self._print_status("%s"%status)
178 self._last_status = status
179 time.sleep(self.duration)
180 self.done = True
181
182
184 self.cache_argument = argument
185 self.pkg_start_times = start_times
186 self.cache_right = right
187
189 threads = []
190 for p, t in sorted(start_times.items(), key=itemgetter(1)):
191 threads.append("[ %s: %.1f sec ]"%(p, time.time() - t))
192
193 return " ".join(threads)
194
196 if self.cache_argument:
197 self.set_status("[ make %s ] "%self.cache_argument + self.rosmake_pkg_times_to_string(self.pkg_start_times), self.cache_right)
198 else:
199 self.set_status("[ make ] " + self.rosmake_pkg_times_to_string(self.pkg_start_times), self.cache_right)
200
202 header = "[ rosmake ] "
203 h = len(header)
204 l = len(left)
205 r = len(right)
206 w = self.terminal_width()
207 if l + r < w - h:
208 padding = w - h - l - r
209 self.status = header + left + " "*padding + right
210 else:
211 self.status = header + left[:(w - h - r - 4)] + "... " + right
212
214 if thread_name is None:
215 str = "[ rosmake ] %s"%s
216
217
218 else:
219 str = "[rosmake-%s] %s"%(thread_name, s)
220 sys.stdout.write(self.pad_str_to_width(str, self.terminal_width())+"\n")
221 sys.stdout.flush()
222
224 if self.verbose or self.full_verbose:
225 self.print_all(s, thread_name=thread_name)
226
228 if self.full_verbose:
229 print("[ rosmake ] %s"%(s))
230
232 lines = s.splitlines()
233 if self.full_verbose:
234 tail_lines = len(lines)
235
236 num_lines = min(len(lines), tail_lines)
237 if num_lines == tail_lines:
238 print("[ rosmake ] Last %d lines"%(num_lines))
239 else:
240 print("[ rosmake ] All %d lines"%(num_lines))
241 print("{" + "-"*79)
242 for l in range(-num_lines, -1):
243 print(" %s"%(lines[l]))
244 print("-"*79 + "}")
245
247 sys.stdout.write("%s\r"%(s))
248 sys.stdout.flush()
249
250 @staticmethod
252 """Estimate the width of the terminal"""
253 width = 0
254 try:
255 import struct, fcntl, termios
256 s = struct.pack('HHHH', 0, 0, 0, 0)
257 x = fcntl.ioctl(1, termios.TIOCGWINSZ, s)
258 width = struct.unpack('HHHH', x)[1]
259 except IOError:
260 pass
261 if width <= 0:
262 try:
263 width = int(os.environ['COLUMNS'])
264 except:
265 pass
266 if width <= 0:
267 width = 80
268
269 return width
270
271 @staticmethod
273 """ Pad the string to be terminal width"""
274 length = len(str)
275 excess = 0
276 if length < width:
277 excess = width - length
278 return str + " "* excess
279
284 self._result_lock = threading.Lock()
285
286 self.rospack = rospkg.RosPack()
287 self.rosstack = rospkg.RosStack()
288
289 self.printer = Printer()
290 self.result = {}
291 self.paths = {}
292 self.dependency_tracker = parallel_build.DependencyTracker(rospack=self.rospack)
293 self.flag_tracker = package_stats.PackageFlagTracker(self.dependency_tracker)
294 self.output = {}
295 self.profile = {}
296 self.ros_parallel_jobs = 0
297 self.build_list = []
298 self.start_time = time.time()
299 self.log_dir = ""
300 self.logging_enabled = True
301
303 """
304 @return: number of packages that were built
305 @rtype: int
306 """
307 return len(list(self.result[argument].keys()))
308
310 self.printer.rosmake_cache_info(argument, start_times, right)
311
313 if p in self.build_list:
314 return
315 for d in self.dependency_tracker.get_deps_1(p):
316 self.build_or_recurse(d)
317 try:
318 self.rospack.get_path(p)
319 self.build_list.append(p)
320 except rospkg.ResourceNotFound as ex:
321 if not self.robust_build:
322 self.printer.print_all("Exiting due to missing package: %s"%ex)
323 sys.exit(-1)
324 else:
325 self.printer.print_all("!"*20 + " Package %s does not exist. %s"%(p, ex) + "!"*20)
326
327
329 self.profile[argument] = {}
330 self.output[argument] = {}
331 with self._result_lock:
332 if argument not in self.result.keys():
333 self.result[argument] = {}
334
335 cts = []
336 for i in range(0, threads):
337 ct = parallel_build.CompileThread(str(i), build_queue, self, argument)
338
339 ct.start()
340 cts.append(ct)
341 for ct in cts:
342 try:
343
344 ct.join()
345
346 except KeyboardInterrupt:
347 self.printer.print_all( "TTTH Caught KeyboardInterrupt. Stopping build.")
348 build_queue.stop()
349 ct.join()
350 except:
351 self.printer.print_all("TTTH OTHER exception thrown!!!!!!!!!!!!!!!!!!!!!")
352 ct.join()
353
354 all_pkgs_passed = True
355 with self._result_lock:
356 for v in self.result[argument].values():
357 all_pkgs_passed = v and all_pkgs_passed
358
359 build_passed = build_queue.succeeded() and all_pkgs_passed
360 return build_passed
361
362
363
365
366
367 signal.signal(signal.SIGPIPE, signal.SIG_DFL)
368
370 """
371 Lower-level routine for building a package. Handles execution of actual build command.
372 @param package: package name
373 @type package: str
374 """
375 local_env = os.environ.copy()
376 if self.ros_parallel_jobs > 0:
377 local_env['ROS_PARALLEL_JOBS'] = "-j%d -l%d" % (self.ros_parallel_jobs, self.ros_parallel_jobs)
378 elif "ROS_PARALLEL_JOBS" not in os.environ:
379
380
381 with _popen_lock:
382 num_cpus = parallel_build.num_cpus()
383 local_env['ROS_PARALLEL_JOBS'] = "-j%d -l%d" % (num_cpus, num_cpus)
384 local_env['SVN_CMDLINE'] = "svn --non-interactive"
385 cmd = ["bash", "-c", "cd %s && %s "%(self.rospack.get_path(package), make_command()) ]
386 if argument:
387 cmd[-1] += argument
388 self.printer.print_full_verbose (cmd)
389
390
391 with _popen_lock:
392 command_line = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env=local_env, preexec_fn=self._subprocess_setup)
393 (pstd_out, pstd_err) = command_line.communicate()
394 return (command_line.returncode, pstd_out)
395
396 - def build(self, p, argument = None, robust_build=False):
397 """
398 Build package
399 @param p: package name
400 @type p: str
401 """
402 return_string = ""
403 try:
404
405
406 if argument == "test":
407 failed_packages = []
408 else:
409 with self._result_lock:
410 failed_packages = [j for j in self.result[argument] if not self.result[argument][j] == True]
411
412 (buildable, error, why) = self.flag_tracker.can_build(p, self.skip_blacklist, failed_packages)
413 if buildable or self.robust_build:
414 start_time = time.time()
415 (returncode, pstd_out) = self._build_package(p, argument)
416 self.profile[argument][p] = time.time() - start_time
417 self.output[argument][p] = pstd_out
418 if argument:
419 log_type = "build_%s"%argument
420 else:
421 log_type = "build"
422 if not returncode:
423 self.printer.print_full_verbose( pstd_out)
424 with self._result_lock:
425 self.result[argument][p] = True
426 warnings = Warnings( pstd_out )
427 num_warnings = len( warnings.warning_lines )
428 if num_warnings > 0:
429 return_string = "[PASS] [ %.2f seconds ] [ %d warnings "%(self.profile[argument][p], num_warnings)
430 warning_dict = warnings.analyze();
431 for warntype,warnlines in warning_dict.iteritems():
432 if len( warnlines ) > 0:
433 return_string = return_string + '[ {0:d} {1} ] '.format(len(warnlines),warntype)
434 return_string = return_string + ' ]'
435 else:
436 return_string = ("[PASS] [ %.2f seconds ]"%( self.profile[argument][p]))
437 self.output_to_file(p, log_type, pstd_out, num_warnings > 0)
438 else:
439 success = False
440 no_target = len(re.findall("No rule to make target", pstd_out)) > 0
441 interrupt = len(re.findall("Interrupt", pstd_out)) > 0
442 if no_target:
443 return_string = ( "[SKIP] No rule to make target %s"%( argument))
444 success = True
445 elif interrupt:
446 return_string = ("[Interrupted]" )
447 else:
448 return_string = ( "[FAIL] [ %.2f seconds ]"%( self.profile[argument][p]))
449 with self._result_lock:
450 self.result[argument][p] = True if no_target else False
451
452 if success == False:
453 self.printer.print_tail( pstd_out)
454 self.output_to_file(p, log_type, pstd_out, always_print= not (no_target or interrupt))
455
456 return (success, return_string)
457 else:
458 with self._result_lock:
459 self.result[argument][p] = error
460
461 return_string += why
462 return(error, return_string)
463 return (True, return_string)
464 except rospkg.ResourceNotFound as ex:
465 with self._result_lock:
466 self.result[argument][p] = False
467 self.printer.print_verbose ("[SKIP] Package %s not found\n" % p)
468 self.output[argument][p] = "Package not found %s"%ex
469 return (False, return_string)
470
471
472 - def output_to_file(self, package, log_type, stdout, always_print= False):
473 if not self.logging_enabled:
474 return
475 package_log_dir = os.path.join(self.log_dir, package)
476
477 std_out_filename = os.path.join(package_log_dir, log_type + "_output.log")
478 if not os.path.exists (package_log_dir):
479 makedirs_with_parent_perms(package_log_dir)
480 with open(std_out_filename, 'w') as stdout_file:
481 stdout_file.write(stdout)
482 print_string = "Output from build of package %s written to:\n[ rosmake ] %s"%(package, std_out_filename)
483 if always_print:
484 self.printer.print_all(print_string)
485 else:
486 self.printer.print_full_verbose(print_string)
487
489 if not self.logging_enabled:
490 return
491
492 self.printer.print_all("Results:")
493 if 'clean' in self.result.keys():
494 self.printer.print_all("Cleaned %d packages."%len(self.result['clean']))
495 if None in self.result.keys():
496 build_failure_count = len([p for p in self.result[None].keys() if self.result[None][p] == False])
497 self.printer.print_all("Built %d packages with %d failures."%(len(self.result[None]), build_failure_count))
498 if 'test' in self.result.keys():
499 test_failure_count = len([p for p in self.result['test'].keys() if self.result['test'][p] == False])
500 self.printer.print_all("Tested %d packages with %d failures."%(len(self.result['test']), test_failure_count))
501 self.printer.print_all("Summary output to directory")
502 self.printer.print_all("%s"%self.log_dir)
503 if self.rejected_packages:
504 self.printer.print_all("WARNING: Skipped command line arguments: %s because they could not be resolved to a stack name or a package name. "%self.rejected_packages)
505
506
507
508 if None in self.result.keys():
509 if len(self.result[None].keys()) > 0:
510 buildfail_filename = os.path.join(log_dir, "buildfailures.txt")
511 with open(buildfail_filename, 'w') as bf:
512 bf.write("Build failures:\n")
513 for key in self.build_list:
514 if key in self.result[None].keys() and self.result[None][key] == False:
515 bf.write("%s\n"%key)
516 if None in self.output.keys():
517 buildfail_context_filename = os.path.join(log_dir, "buildfailures-with-context.txt")
518 with open(buildfail_context_filename, 'w') as bfwc:
519 bfwc.write("Build failures with context:\n")
520 for key in self.build_list:
521 if key in self.result[None].keys() and self.result[None][key] == False:
522 bfwc.write("---------------------\n")
523 bfwc.write("%s\n"%key)
524 if key in self.output[None]:
525 bfwc.write(self.output[None][key])
526
527 if "test" in self.result.keys():
528 if len(self.result["test"].keys()) > 0:
529 testfail_filename = os.path.join(log_dir, "testfailures.txt")
530 with open(testfail_filename, 'w') as btwc:
531 btwc.write("Test failures:\n")
532 for key in self.build_list:
533 if key in self.result["test"].keys() and self.result["test"][key] == False:
534 btwc.write("%s\n"%key)
535
536 if "test" in self.output.keys():
537 testfail_filename = os.path.join(log_dir, "testfailures-with-context.txt")
538 with open(testfail_filename, 'w') as btwc:
539 btwc.write("Test failures with context:\n")
540 for key in self.build_list:
541 if key in self.result["test"].keys() and self.result["test"][key] == False:
542 btwc.write("%s\n"%key)
543 if key in self.output["test"]:
544 btwc.write(self.output["test"][key])
545
546 profile_filename = os.path.join(log_dir, "profile.txt")
547 with open(profile_filename, 'w') as pf:
548 pf.write(self.get_profile_string())
549
550
551
553 output = '--------------\nProfile\n--------------\n'
554 total = 0.0
555 count = 1
556 for key in self.build_list:
557 build_results = ["[Not Built ]", "[ Built ]", "[Build Fail]"];
558 test_results = ["[Untested ]", "[Test Pass]", "[Test Fail]"];
559 build_result = 0
560 test_result = 0
561 test_time = 0.0
562 build_time = 0.0
563
564 if None in self.result.keys():
565 if key in self.result[None].keys():
566 if self.result[None][key] == True:
567 build_result = 1
568 else:
569 build_result = 2
570
571 if "test" in self.profile.keys():
572 if key in self.result["test"].keys():
573 if self.result["test"][key] == True:
574 test_result = 1
575 else:
576 test_result = 2
577
578 if None in self.profile.keys():
579 if key in self.profile[None].keys():
580 build_time = self.profile[None][key]
581
582 if "test" in self.profile.keys():
583 if key in self.profile["test"].keys():
584 test_time = self.profile["test"][key]
585
586
587 output = output + "%3d: %s in %.2f %s in %.2f --- %s\n"% (count, build_results[build_result], build_time , test_results[test_result], test_time, key)
588 total = total + build_time
589 count = count + 1
590
591 elapsed_time = self.finish_time - self.start_time
592 output = output + "----------------\n" + "%.2f Cumulative, %.2f Elapsed, %.2f Speedup \n"%(total, elapsed_time, float(total) / float(elapsed_time))
593 return output
594
596 """
597 main command-line entrypoint
598 """
599 parser = OptionParser(usage="usage: %prog [options] [PACKAGE]...",
600 description="rosmake recursively builds all dependencies before building a package", prog='rosmake')
601 parser.add_option("--test-only", dest="test_only", default=False,
602 action="store_true", help="only run tests")
603 parser.add_option("-t", dest="test", default=False,
604 action="store_true", help="build and test packages")
605 parser.add_option("-a", "--all", dest="build_all", default=False,
606 action="store_true", help="select all packages")
607 parser.add_option("-i", "--mark-installed", dest="mark_installed", default=False,
608 action="store_true", help="On successful build, mark specified packages as installed with ROS_NOBUILD")
609 parser.add_option("-u", "--unmark-installed", dest="unmark_installed", default=False,
610 action="store_true", help="Remove ROS_NOBUILD from the specified packages. This will not build anything.")
611 parser.add_option("-v", dest="verbose", default=False,
612 action="store_true", help="display errored builds")
613 parser.add_option("-r","-k", "--robust", dest="best_effort", default=False,
614 action="store_true", help="do not stop build on error")
615 parser.add_option("--build-everything", dest="robust", default=False,
616 action="store_true", help="build all packages regardless of errors")
617 parser.add_option("-V", dest="full_verbose", default=False,
618 action="store_true", help="display all builds")
619 parser.add_option("-s", "--specified-only", dest="specified_only", default=False,
620 action="store_true", help="only build packages specified on the command line")
621 parser.add_option("--buildtest", dest="buildtest",
622 action="append", help="package to buildtest")
623 parser.add_option("--buildtest1", dest="buildtest1",
624 action="append", help="package to buildtest1")
625 parser.add_option("--output", dest="output_dir",
626 action="store", help="where to output results")
627 parser.add_option("--pre-clean", dest="pre_clean",
628 action="store_true", help="run make clean first")
629 parser.add_option("--bootstrap", dest="bootstrap", default=False,
630 action="store_true", help="DEPRECATED, UNUSED")
631 parser.add_option("--disable-logging", dest="logging_enabled", default=True,
632 action="store_false", help="turn off all logs")
633 parser.add_option("--target", dest="target",
634 action="store", help="run make with this target")
635 parser.add_option("--pjobs", dest="ros_parallel_jobs", type="int",
636 action="store", help="Override ROS_PARALLEL_JOBS environment variable with this number of jobs.")
637 parser.add_option("--threads", dest="threads", type="int", default = os.environ.get("ROSMAKE_THREADS", parallel_build.num_cpus()),
638 action="store", help="Build up to N packages in parallel")
639 parser.add_option("--profile", dest="print_profile", default=False,
640 action="store_true", help="print time profile after build")
641 parser.add_option("--skip-blacklist", dest="skip_blacklist",
642 default=False, action="store_true",
643 help="skip packages containing a file called ROS_BUILD_BLACKLIST (Default behavior will ignore the presence of ROS_BUILD_BLACKLIST)")
644 parser.add_option("--skip-blacklist-osx", dest="skip_blacklist_osx",
645 default=False, action="store_true",
646 help="deprecated option. it will do nothing, please use platform declarations and --require-platform instead")
647
648 parser.add_option("--status-rate", dest="status_update_rate",
649 action="store", help="How fast to update the status bar in Hz. Default: 5Hz")
650
651
652 options, args = parser.parse_args()
653 self.printer.print_all('rosmake starting...')
654
655 rospack = self.rospack
656 rosstack = self.rosstack
657
658 testing = False
659 building = True
660 if options.test_only:
661 testing = True
662 building = False
663 elif options.test:
664 testing = True
665
666 if options.ros_parallel_jobs:
667 self.ros_parallel_jobs = options.ros_parallel_jobs
668
669 self.robust_build = options.robust
670 self.best_effort = options.best_effort
671 self.threads = options.threads
672 self.skip_blacklist = options.skip_blacklist
673 if options.skip_blacklist_osx:
674 self.printer.print_all("Option --skip-blacklist-osx is deprecated. It will do nothing, please use platform declarations and --require-platform instead");
675 self.logging_enabled = options.logging_enabled
676
677
678 self.printer.full_verbose = options.full_verbose
679 self.printer.verbose = options.verbose
680 if options.status_update_rate:
681 if float(options.status_update_rate)> 0:
682 self.printer.duration = 1.0/float(options.status_update_rate)
683 else:
684 self.printer.duration = 0
685
686 packages = []
687
688 if options.build_all:
689 packages = [x for x in rospack.list() if not self.rospack.get_manifest(x).is_catkin]
690 self.printer.print_all( "Building all packages")
691 else:
692 if options.buildtest:
693 for p in options.buildtest:
694 packages.extend(self.rospack.get_depends_on(p))
695 self.printer.print_all( "buildtest requested for package %s adding it and all dependent packages: "%p)
696
697 if options.buildtest1:
698 for p in options.buildtest1:
699 packages.extend(self.rospack.get_depends_on(p, implicit=False))
700 self.printer.print_all( "buildtest1 requested for package %s adding it and all depends-on1 packages: "%p)
701
702 if len(packages) == 0 and len(args) == 0:
703 p = os.path.basename(os.path.abspath('.'))
704 try:
705 if os.path.samefile(rospack.get_path(p), '.'):
706 packages = [p]
707 self.printer.print_all( "No package specified. Building %s"%packages)
708 else:
709 self.printer.print_all("No package selected and the current directory is not the correct path for package '%s'."%p)
710
711 except rospkg.ResourceNotFound as ex:
712 try:
713 stack_dir = rosstack.get_path(p)
714 if os.path.samefile(stack_dir, '.'):
715 packages = [p]
716 self.printer.print_all( "No package specified. Building stack %s"%packages)
717 else:
718 self.printer.print_all("No package or stack arguments and the current directory is not the correct path for stack '%s'. Stack directory is: %s."%(p, rosstack.get_path(p)))
719 except:
720 self.printer.print_all("No package or stack specified. And current directory '%s' is not a package name or stack name."%p)
721 else:
722 packages.extend(args)
723
724 self.printer.print_all( "Packages requested are: %s"%packages)
725
726
727 if self.logging_enabled:
728 date_time_stamp = "rosmake_output-" + time.strftime("%Y%m%d-%H%M%S")
729 if options.output_dir:
730
731 self.log_dir = os.path.abspath(options.output_dir)
732 else:
733 self.log_dir = os.path.join(rospkg.get_ros_home(), "rosmake", date_time_stamp);
734
735 self.printer.print_all("Logging to directory %s"%self.log_dir)
736 if os.path.exists (self.log_dir) and not os.path.isdir(self.log_dir):
737 self.printer.print_all( "Log destination %s is a file; please remove it or choose a new destination"%self.log_dir)
738 sys.exit(1)
739 if not os.path.exists (self.log_dir):
740 self.printer.print_verbose("%s doesn't exist: creating"%self.log_dir)
741 makedirs_with_parent_perms(self.log_dir)
742
743 self.printer.print_verbose("Finished setting up logging")
744
745 stacks_arguments = [s for s in packages if s in rosstack.list()]
746 (self.specified_packages, self.rejected_packages) = rospkg.expand_to_packages(packages, rospack, rosstack)
747
748 self.printer.print_all("Expanded args %s to:\n%s"%(packages, self.specified_packages))
749 if self.rejected_packages:
750 self.printer.print_all("WARNING: The following args could not be parsed as stacks or packages: %s"%self.rejected_packages)
751 if len(self.specified_packages) + len(stacks_arguments) == 0:
752 self.printer.print_all("ERROR: No arguments could be parsed into valid package or stack names.")
753 self.printer.running = False
754 return False
755
756 if options.unmark_installed:
757 for p in self.specified_packages:
758 if self.flag_tracker.remove_nobuild(p):
759 self.printer.print_all("Removed ROS_NOBUILD from %s"%p)
760 self.printer.running = False
761 return True
762
763 required_packages = self.specified_packages[:]
764
765
766
767 for s in stacks_arguments:
768 if not rosstack.packages_of(s):
769 for d in rosstack.get_depends(s, implicit=False):
770 try:
771 required_packages.extend(rosstack.packages_of(d))
772 except ResourceNotFound:
773 self.printer.print_all('WARNING: The stack "%s" was not found. We will assume it is using the new buildsystem and try to continue...' % d)
774
775
776 required_packages = list(set(required_packages))
777
778
779 buildable_packages = []
780 for p in required_packages:
781 (buildable, error, str) = self.flag_tracker.can_build(p, self.skip_blacklist, [], False)
782 if buildable:
783 buildable_packages.append(p)
784
785
786 counter = 0
787 for p in required_packages:
788
789 counter = counter + 1
790 self.printer.print_verbose( "Processing %s and all dependencies(%d of %d requested)"%(p, counter, len(packages)))
791 self.build_or_recurse(p)
792
793
794 if options.specified_only:
795 new_list = []
796 for pkg in self.build_list:
797 if pkg in self.specified_packages:
798 new_list.append(pkg)
799 self.dependency_tracker = parallel_build.DependencyTracker(self.specified_packages, rospack=self.rospack)
800
801 self.printer.print_all("specified-only option was used, only building packages %s"%new_list)
802 self.build_list = new_list
803
804 if options.pre_clean:
805 build_queue = parallel_build.BuildQueue(self.build_list, parallel_build.DependencyTracker([], rospack=self.rospack), robust_build = True)
806 self.parallel_build_pkgs(build_queue, "clean", threads = options.threads)
807
808 build_passed = True
809
810 if building:
811 self.printer.print_verbose ("Building packages %s"% self.build_list)
812 build_queue = parallel_build.BuildQueue(self.build_list, self.dependency_tracker, robust_build = options.robust or options.best_effort)
813 if None not in self.result.keys():
814 self.result[None] = {}
815
816 build_passed = self.parallel_build_pkgs(build_queue, options.target, threads = options.threads)
817
818 tests_passed = True
819 if build_passed and testing:
820 self.printer.print_verbose ("Testing packages %s"% packages)
821 build_queue = parallel_build.BuildQueue(self.specified_packages, parallel_build.DependencyTracker(self.specified_packages, rospack=self.rospack), robust_build = True)
822 tests_passed = self.parallel_build_pkgs(build_queue, "test", threads = 1)
823
824
825 if options.mark_installed:
826 if build_passed and tests_passed:
827 for p in self.specified_packages:
828 if self.flag_tracker.add_nobuild(p):
829 self.printer.print_all("Marking %s as installed with a ROS_NOBUILD file"%p)
830 else:
831 self.printer.print_all("All builds and tests did not pass cannot mark packages as installed. ")
832
833
834 self.finish_time = time.time()
835 self.generate_summary_output(self.log_dir)
836
837 if options.print_profile:
838 self.printer.print_all (self.get_profile_string())
839
840 self.printer.running = False
841 return build_passed and tests_passed
842