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 if not isinstance(pstd_out, str):
395 pstd_out = pstd_out.decode()
396 return (command_line.returncode, pstd_out)
397
398 - def build(self, p, argument = None, robust_build=False):
399 """
400 Build package
401 @param p: package name
402 @type p: str
403 """
404 return_string = ""
405 try:
406
407
408 if argument == "test":
409 failed_packages = []
410 else:
411 with self._result_lock:
412 failed_packages = [j for j in self.result[argument] if not self.result[argument][j] == True]
413
414 (buildable, error, why) = self.flag_tracker.can_build(p, self.skip_blacklist, failed_packages)
415 if buildable or self.robust_build:
416 start_time = time.time()
417 (returncode, pstd_out) = self._build_package(p, argument)
418 self.profile[argument][p] = time.time() - start_time
419 self.output[argument][p] = pstd_out
420 if argument:
421 log_type = "build_%s"%argument
422 else:
423 log_type = "build"
424 if not returncode:
425 self.printer.print_full_verbose( pstd_out)
426 with self._result_lock:
427 self.result[argument][p] = True
428 warnings = Warnings( pstd_out )
429 num_warnings = len( warnings.warning_lines )
430 if num_warnings > 0:
431 return_string = "[PASS] [ %.2f seconds ] [ %d warnings "%(self.profile[argument][p], num_warnings)
432 warning_dict = warnings.analyze();
433 for warntype,warnlines in warning_dict.items():
434 if len( warnlines ) > 0:
435 return_string = return_string + '[ {0:d} {1} ] '.format(len(warnlines),warntype)
436 return_string = return_string + ' ]'
437 else:
438 return_string = ("[PASS] [ %.2f seconds ]"%( self.profile[argument][p]))
439 self.output_to_file(p, log_type, pstd_out, num_warnings > 0)
440 else:
441 success = False
442 no_target = len(re.findall("No rule to make target", pstd_out)) > 0
443 interrupt = len(re.findall("Interrupt", pstd_out)) > 0
444 if no_target:
445 return_string = ( "[SKIP] No rule to make target %s"%( argument))
446 success = True
447 elif interrupt:
448 return_string = ("[Interrupted]" )
449 else:
450 return_string = ( "[FAIL] [ %.2f seconds ]"%( self.profile[argument][p]))
451 with self._result_lock:
452 self.result[argument][p] = True if no_target else False
453
454 if success == False:
455 self.printer.print_tail( pstd_out)
456 self.output_to_file(p, log_type, pstd_out, always_print= not (no_target or interrupt))
457
458 return (success, return_string)
459 else:
460 with self._result_lock:
461 self.result[argument][p] = error
462
463 return_string += why
464 return(error, return_string)
465 return (True, return_string)
466 except rospkg.ResourceNotFound as ex:
467 with self._result_lock:
468 self.result[argument][p] = False
469 self.printer.print_verbose ("[SKIP] Package %s not found\n" % p)
470 self.output[argument][p] = "Package not found %s"%ex
471 return (False, return_string)
472
473
474 - def output_to_file(self, package, log_type, stdout, always_print= False):
475 if not self.logging_enabled:
476 return
477 package_log_dir = os.path.join(self.log_dir, package)
478
479 std_out_filename = os.path.join(package_log_dir, log_type + "_output.log")
480 if not os.path.exists (package_log_dir):
481 makedirs_with_parent_perms(package_log_dir)
482 with open(std_out_filename, 'w') as stdout_file:
483 stdout_file.write(stdout)
484 print_string = "Output from build of package %s written to:\n[ rosmake ] %s"%(package, std_out_filename)
485 if always_print:
486 self.printer.print_all(print_string)
487 else:
488 self.printer.print_full_verbose(print_string)
489
491 if not self.logging_enabled:
492 return
493
494 self.printer.print_all("Results:")
495 if 'clean' in self.result.keys():
496 self.printer.print_all("Cleaned %d packages."%len(self.result['clean']))
497 if None in self.result.keys():
498 build_failure_count = len([p for p in self.result[None].keys() if self.result[None][p] == False])
499 self.printer.print_all("Built %d packages with %d failures."%(len(self.result[None]), build_failure_count))
500 if 'test' in self.result.keys():
501 test_failure_count = len([p for p in self.result['test'].keys() if self.result['test'][p] == False])
502 self.printer.print_all("Tested %d packages with %d failures."%(len(self.result['test']), test_failure_count))
503 self.printer.print_all("Summary output to directory")
504 self.printer.print_all("%s"%self.log_dir)
505 if self.rejected_packages:
506 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)
507
508
509
510 if None in self.result.keys():
511 if len(self.result[None].keys()) > 0:
512 buildfail_filename = os.path.join(log_dir, "buildfailures.txt")
513 with open(buildfail_filename, 'w') as bf:
514 bf.write("Build failures:\n")
515 for key in self.build_list:
516 if key in self.result[None].keys() and self.result[None][key] == False:
517 bf.write("%s\n"%key)
518 if None in self.output.keys():
519 buildfail_context_filename = os.path.join(log_dir, "buildfailures-with-context.txt")
520 with open(buildfail_context_filename, 'w') as bfwc:
521 bfwc.write("Build failures with context:\n")
522 for key in self.build_list:
523 if key in self.result[None].keys() and self.result[None][key] == False:
524 bfwc.write("---------------------\n")
525 bfwc.write("%s\n"%key)
526 if key in self.output[None]:
527 bfwc.write(self.output[None][key])
528
529 if "test" in self.result.keys():
530 if len(self.result["test"].keys()) > 0:
531 testfail_filename = os.path.join(log_dir, "testfailures.txt")
532 with open(testfail_filename, 'w') as btwc:
533 btwc.write("Test failures:\n")
534 for key in self.build_list:
535 if key in self.result["test"].keys() and self.result["test"][key] == False:
536 btwc.write("%s\n"%key)
537
538 if "test" in self.output.keys():
539 testfail_filename = os.path.join(log_dir, "testfailures-with-context.txt")
540 with open(testfail_filename, 'w') as btwc:
541 btwc.write("Test failures with context:\n")
542 for key in self.build_list:
543 if key in self.result["test"].keys() and self.result["test"][key] == False:
544 btwc.write("%s\n"%key)
545 if key in self.output["test"]:
546 btwc.write(self.output["test"][key])
547
548 profile_filename = os.path.join(log_dir, "profile.txt")
549 with open(profile_filename, 'w') as pf:
550 pf.write(self.get_profile_string())
551
552
553
555 output = '--------------\nProfile\n--------------\n'
556 total = 0.0
557 count = 1
558 for key in self.build_list:
559 build_results = ["[Not Built ]", "[ Built ]", "[Build Fail]"];
560 test_results = ["[Untested ]", "[Test Pass]", "[Test Fail]"];
561 build_result = 0
562 test_result = 0
563 test_time = 0.0
564 build_time = 0.0
565
566 if None in self.result.keys():
567 if key in self.result[None].keys():
568 if self.result[None][key] == True:
569 build_result = 1
570 else:
571 build_result = 2
572
573 if "test" in self.profile.keys():
574 if key in self.result["test"].keys():
575 if self.result["test"][key] == True:
576 test_result = 1
577 else:
578 test_result = 2
579
580 if None in self.profile.keys():
581 if key in self.profile[None].keys():
582 build_time = self.profile[None][key]
583
584 if "test" in self.profile.keys():
585 if key in self.profile["test"].keys():
586 test_time = self.profile["test"][key]
587
588
589 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)
590 total = total + build_time
591 count = count + 1
592
593 elapsed_time = self.finish_time - self.start_time
594 output = output + "----------------\n" + "%.2f Cumulative, %.2f Elapsed, %.2f Speedup \n"%(total, elapsed_time, float(total) / float(elapsed_time))
595 return output
596
598 """
599 main command-line entrypoint
600 """
601 parser = OptionParser(usage="usage: %prog [options] [PACKAGE]...",
602 description="rosmake recursively builds all dependencies before building a package", prog='rosmake')
603 parser.add_option("--test-only", dest="test_only", default=False,
604 action="store_true", help="only run tests")
605 parser.add_option("-t", dest="test", default=False,
606 action="store_true", help="build and test packages")
607 parser.add_option("-a", "--all", dest="build_all", default=False,
608 action="store_true", help="select all packages")
609 parser.add_option("-i", "--mark-installed", dest="mark_installed", default=False,
610 action="store_true", help="On successful build, mark specified packages as installed with ROS_NOBUILD")
611 parser.add_option("-u", "--unmark-installed", dest="unmark_installed", default=False,
612 action="store_true", help="Remove ROS_NOBUILD from the specified packages. This will not build anything.")
613 parser.add_option("-v", dest="verbose", default=False,
614 action="store_true", help="display errored builds")
615 parser.add_option("-r","-k", "--robust", dest="best_effort", default=False,
616 action="store_true", help="do not stop build on error")
617 parser.add_option("--build-everything", dest="robust", default=False,
618 action="store_true", help="build all packages regardless of errors")
619 parser.add_option("-V", dest="full_verbose", default=False,
620 action="store_true", help="display all builds")
621 parser.add_option("-s", "--specified-only", dest="specified_only", default=False,
622 action="store_true", help="only build packages specified on the command line")
623 parser.add_option("--buildtest", dest="buildtest",
624 action="append", help="package to buildtest")
625 parser.add_option("--buildtest1", dest="buildtest1",
626 action="append", help="package to buildtest1")
627 parser.add_option("--output", dest="output_dir",
628 action="store", help="where to output results")
629 parser.add_option("--pre-clean", dest="pre_clean",
630 action="store_true", help="run make clean first")
631 parser.add_option("--bootstrap", dest="bootstrap", default=False,
632 action="store_true", help="DEPRECATED, UNUSED")
633 parser.add_option("--disable-logging", dest="logging_enabled", default=True,
634 action="store_false", help="turn off all logs")
635 parser.add_option("--target", dest="target",
636 action="store", help="run make with this target")
637 parser.add_option("--pjobs", dest="ros_parallel_jobs", type="int",
638 action="store", help="Override ROS_PARALLEL_JOBS environment variable with this number of jobs.")
639 parser.add_option("--threads", dest="threads", type="int", default = os.environ.get("ROSMAKE_THREADS", parallel_build.num_cpus()),
640 action="store", help="Build up to N packages in parallel")
641 parser.add_option("--profile", dest="print_profile", default=False,
642 action="store_true", help="print time profile after build")
643 parser.add_option("--skip-blacklist", dest="skip_blacklist",
644 default=False, action="store_true",
645 help="skip packages containing a file called ROS_BUILD_BLACKLIST (Default behavior will ignore the presence of ROS_BUILD_BLACKLIST)")
646 parser.add_option("--skip-blacklist-osx", dest="skip_blacklist_osx",
647 default=False, action="store_true",
648 help="deprecated option. it will do nothing, please use platform declarations and --require-platform instead")
649
650 parser.add_option("--status-rate", dest="status_update_rate",
651 action="store", help="How fast to update the status bar in Hz. Default: 5Hz")
652
653
654 options, args = parser.parse_args()
655 self.printer.print_all('rosmake starting...')
656
657 rospack = self.rospack
658 rosstack = self.rosstack
659
660 testing = False
661 building = True
662 if options.test_only:
663 testing = True
664 building = False
665 elif options.test:
666 testing = True
667
668 if options.ros_parallel_jobs:
669 self.ros_parallel_jobs = options.ros_parallel_jobs
670
671 self.robust_build = options.robust
672 self.best_effort = options.best_effort
673 self.threads = options.threads
674 self.skip_blacklist = options.skip_blacklist
675 if options.skip_blacklist_osx:
676 self.printer.print_all("Option --skip-blacklist-osx is deprecated. It will do nothing, please use platform declarations and --require-platform instead");
677 self.logging_enabled = options.logging_enabled
678
679
680 self.printer.full_verbose = options.full_verbose
681 self.printer.verbose = options.verbose
682 if options.status_update_rate:
683 if float(options.status_update_rate)> 0:
684 self.printer.duration = 1.0/float(options.status_update_rate)
685 else:
686 self.printer.duration = 0
687
688 packages = []
689
690 if options.build_all:
691 packages = [x for x in rospack.list() if not self.rospack.get_manifest(x).is_catkin]
692 self.printer.print_all( "Building all packages")
693 else:
694 if options.buildtest:
695 for p in options.buildtest:
696 packages.extend(self.rospack.get_depends_on(p))
697 self.printer.print_all( "buildtest requested for package %s adding it and all dependent packages: "%p)
698
699 if options.buildtest1:
700 for p in options.buildtest1:
701 packages.extend(self.rospack.get_depends_on(p, implicit=False))
702 self.printer.print_all( "buildtest1 requested for package %s adding it and all depends-on1 packages: "%p)
703
704 if len(packages) == 0 and len(args) == 0:
705 p = os.path.basename(os.path.abspath('.'))
706 try:
707 if os.path.samefile(rospack.get_path(p), '.'):
708 packages = [p]
709 self.printer.print_all( "No package specified. Building %s"%packages)
710 else:
711 self.printer.print_all("No package selected and the current directory is not the correct path for package '%s'."%p)
712
713 except rospkg.ResourceNotFound as ex:
714 try:
715 stack_dir = rosstack.get_path(p)
716 if os.path.samefile(stack_dir, '.'):
717 packages = [p]
718 self.printer.print_all( "No package specified. Building stack %s"%packages)
719 else:
720 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)))
721 except:
722 self.printer.print_all("No package or stack specified. And current directory '%s' is not a package name or stack name."%p)
723 else:
724 packages.extend(args)
725
726 self.printer.print_all( "Packages requested are: %s"%packages)
727
728
729 if self.logging_enabled:
730 date_time_stamp = "rosmake_output-" + time.strftime("%Y%m%d-%H%M%S")
731 if options.output_dir:
732
733 self.log_dir = os.path.abspath(options.output_dir)
734 else:
735 self.log_dir = os.path.join(rospkg.get_ros_home(), "rosmake", date_time_stamp);
736
737 self.printer.print_all("Logging to directory %s"%self.log_dir)
738 if os.path.exists (self.log_dir) and not os.path.isdir(self.log_dir):
739 self.printer.print_all( "Log destination %s is a file; please remove it or choose a new destination"%self.log_dir)
740 sys.exit(1)
741 if not os.path.exists (self.log_dir):
742 self.printer.print_verbose("%s doesn't exist: creating"%self.log_dir)
743 makedirs_with_parent_perms(self.log_dir)
744
745 self.printer.print_verbose("Finished setting up logging")
746
747 stacks_arguments = [s for s in packages if s in rosstack.list()]
748 (self.specified_packages, self.rejected_packages) = rospkg.expand_to_packages(packages, rospack, rosstack)
749
750 self.printer.print_all("Expanded args %s to:\n%s"%(packages, self.specified_packages))
751 if self.rejected_packages:
752 self.printer.print_all("WARNING: The following args could not be parsed as stacks or packages: %s"%self.rejected_packages)
753 if len(self.specified_packages) + len(stacks_arguments) == 0:
754 self.printer.print_all("ERROR: No arguments could be parsed into valid package or stack names.")
755 self.printer.running = False
756 return False
757
758 if options.unmark_installed:
759 for p in self.specified_packages:
760 if self.flag_tracker.remove_nobuild(p):
761 self.printer.print_all("Removed ROS_NOBUILD from %s"%p)
762 self.printer.running = False
763 return True
764
765 required_packages = self.specified_packages[:]
766
767
768
769 for s in stacks_arguments:
770 if not rosstack.packages_of(s):
771 for d in rosstack.get_depends(s, implicit=False):
772 try:
773 required_packages.extend(rosstack.packages_of(d))
774 except ResourceNotFound:
775 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)
776
777
778 required_packages = list(set(required_packages))
779
780
781 buildable_packages = []
782 for p in required_packages:
783 (buildable, error, str) = self.flag_tracker.can_build(p, self.skip_blacklist, [], False)
784 if buildable:
785 buildable_packages.append(p)
786
787
788 counter = 0
789 for p in required_packages:
790
791 counter = counter + 1
792 self.printer.print_verbose( "Processing %s and all dependencies(%d of %d requested)"%(p, counter, len(packages)))
793 self.build_or_recurse(p)
794
795
796 if options.specified_only:
797 new_list = []
798 for pkg in self.build_list:
799 if pkg in self.specified_packages:
800 new_list.append(pkg)
801 self.dependency_tracker = parallel_build.DependencyTracker(self.specified_packages, rospack=self.rospack)
802
803 self.printer.print_all("specified-only option was used, only building packages %s"%new_list)
804 self.build_list = new_list
805
806 if options.pre_clean:
807 build_queue = parallel_build.BuildQueue(self.build_list, parallel_build.DependencyTracker([], rospack=self.rospack), robust_build = True)
808 self.parallel_build_pkgs(build_queue, "clean", threads = options.threads)
809
810 build_passed = True
811
812 if building:
813 self.printer.print_verbose ("Building packages %s"% self.build_list)
814 build_queue = parallel_build.BuildQueue(self.build_list, self.dependency_tracker, robust_build = options.robust or options.best_effort)
815 if None not in self.result.keys():
816 self.result[None] = {}
817
818 build_passed = self.parallel_build_pkgs(build_queue, options.target, threads = options.threads)
819
820 tests_passed = True
821 if build_passed and testing:
822 self.printer.print_verbose ("Testing packages %s"% packages)
823 build_queue = parallel_build.BuildQueue(self.specified_packages, parallel_build.DependencyTracker(self.specified_packages, rospack=self.rospack), robust_build = True)
824 tests_passed = self.parallel_build_pkgs(build_queue, "test", threads = 1)
825
826
827 if options.mark_installed:
828 if build_passed and tests_passed:
829 for p in self.specified_packages:
830 if self.flag_tracker.add_nobuild(p):
831 self.printer.print_all("Marking %s as installed with a ROS_NOBUILD file"%p)
832 else:
833 self.printer.print_all("All builds and tests did not pass cannot mark packages as installed. ")
834
835
836 self.finish_time = time.time()
837 self.generate_summary_output(self.log_dir)
838
839 if options.print_profile:
840 self.printer.print_all (self.get_profile_string())
841
842 self.printer.running = False
843 return build_passed and tests_passed
844