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