pax_global_header00006660000000000000000000000064140761504650014522gustar00rootroot0000000000000052 comment=294823fa58b4710094bdabb561a1bd8cb27b5ae6 ros-1.15.8/000077500000000000000000000000001407615046500124215ustar00rootroot00000000000000ros-1.15.8/.gitignore000066400000000000000000000000061407615046500144050ustar00rootroot00000000000000*.pyc ros-1.15.8/AUTHORS000066400000000000000000000006601407615046500134730ustar00rootroot00000000000000Morgan Quigley Eric Berger Ken Conley Rosen Diankov Josh Faust Tully Foote Brian Gerkey Jeremy Leibs Bhaskara Marthi Troy Straszheim Rob Wheeler ros-1.15.8/LICENSE000066400000000000000000000026371407615046500134360ustar00rootroot00000000000000Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ros-1.15.8/README000066400000000000000000000007011407615046500132770ustar00rootroot00000000000000Robot Operating System (ROS) =============================================================================== ROS is a meta-operating system for your robot. It provides language-independent and network-transparent communication for a distributed robot control system. Installation Notes ------------------ For full installation instructions, including system prerequisites and platform-specific help, see: http://wiki.ros.org/ROS/Installation ros-1.15.8/core/000077500000000000000000000000001407615046500133515ustar00rootroot00000000000000ros-1.15.8/core/mk/000077500000000000000000000000001407615046500137605ustar00rootroot00000000000000ros-1.15.8/core/mk/CHANGELOG.rst000066400000000000000000000063631407615046500160110ustar00rootroot00000000000000^^^^^^^^^^^^^^^^^^^^^^^^ Changelog for package mk ^^^^^^^^^^^^^^^^^^^^^^^^ 1.15.8 (2021-07-21) ------------------- * Update maintainers (`#272 `_) * Contributors: Jacob Perron 1.15.7 (2020-09-28) ------------------- 1.15.6 (2020-07-20) ------------------- 1.15.5 (2020-07-06) ------------------- 1.15.4 (2020-05-28) ------------------- 1.15.3 (2020-05-14) ------------------- 1.15.2 (2020-04-07) ------------------- 1.15.1 (2020-03-17) ------------------- 1.15.0 (2020-02-11) ------------------- 1.14.8 (2020-02-11) ------------------- * update style to pass flake8 (`#240 `_) * Bump CMake version to avoid CMP0048 warning (`#234 `_) 1.14.7 (2019-10-03) ------------------- 1.14.6 (2019-03-18) ------------------- 1.14.5 (2019-03-04) ------------------- * add depend on rospack (`#205 `_) 1.14.4 (2018-05-01) ------------------- 1.14.3 (2018-01-30) ------------------- 1.14.2 (2017-10-26) ------------------- 1.14.1 (2017-07-27) ------------------- 1.14.0 (2017-02-22) ------------------- 1.13.6 (2017-10-31) ------------------- 1.13.5 (2017-02-14) ------------------- 1.13.4 (2016-09-19) ------------------- 1.13.3 (2016-09-16) ------------------- 1.13.2 (2016-09-02) ------------------- 1.13.1 (2016-03-13) ------------------- 1.13.0 (2016-03-10) ------------------- 1.12.6 (2016-03-10) ------------------- 1.12.5 (2015-10-13) ------------------- 1.12.4 (2015-10-12) ------------------- 1.12.3 (2015-09-19) ------------------- 1.12.2 (2015-04-27) ------------------- 1.12.1 (2015-04-16) ------------------- 1.12.0 (2014-12-26) ------------------- 1.11.6 (2014-12-22) ------------------- 1.11.5 (2014-08-18) ------------------- 1.11.4 (2014-07-23) ------------------- 1.11.3 (2014-07-18) ------------------- 1.11.2 (2014-06-16) ------------------- 1.11.1 (2014-05-07) ------------------- * add missing run dependency on rosbuild (`#47 `_) * python 3 compatibility 1.11.0 (2014-01-31) ------------------- 1.10.9 (2014-01-07) ------------------- 1.10.8 (2013-10-15) ------------------- 1.10.7 (2013-10-04) ------------------- 1.10.6 (2013-08-22) ------------------- 1.10.5 (2013-08-21) ------------------- 1.10.4 (2013-07-05) ------------------- * update eclipse-project target to not try to delete CATKIN_IGNORE marker files and check before trying to delete other files/folders (`#20 `_) 1.10.3 (2013-07-03) ------------------- 1.10.2 (2013-06-18) ------------------- 1.10.1 (2013-06-06) ------------------- * add missing environment exports to make eclipse-projects of dry packages build * cleanup catkin generated files/directories after make eclips-project 1.10.0 (2013-03-22 09:23) ------------------------- 1.9 (Groovy) ============ 1.9.44 (2013-03-13) ------------------- 1.9.43 (2013-03-08) ------------------- 1.9.42 (2013-01-25) ------------------- 1.9.41 (2013-01-24) ------------------- * modified install location of download_checkmd5 script to work in devel space and be consistent with other files 1.9.40 (2013-01-13) ------------------- 1.9.39 (2012-12-30) ------------------- * first public release for Groovy ros-1.15.8/core/mk/CMakeLists.txt000066400000000000000000000007061407615046500165230ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.0.2) project(mk) find_package(catkin REQUIRED) catkin_package() # do not wildcard install files since the root folder of the package will contain a debian folder for releasing install(FILES buildtest.mk bzr_checkout.mk cmake.mk cmake_stack.mk download_unpack_build.mk eclipse.awk git_checkout.mk hg_checkout.mk make_pydev_project.py svn_checkout.mk DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}) ros-1.15.8/core/mk/buildtest.mk000066400000000000000000000016271407615046500163160ustar00rootroot00000000000000# A target to test building of a package, all of its dependencies, and all # of the things that depend on it # # For internal use only. # HACK: assume that the package name is the name of the directory we're # sitting in pkg = $(shell basename $(PWD)) rosalldeps = $(shell rospack find rospack)/rosalldeps deps = $(shell $(rosalldeps) -H 1 $(pkg)) rules = $(foreach d, $(deps), cd $(shell rospack find $(d)) && make &&) true; .PHONY: build build: $(rules) rules_test = $(foreach d, $(deps), cd $(shell rospack find $(d)) && make test &&) true; .PHONY: build-test build-test: $(rules_test) deps_all = $(shell $(rosalldeps) $(pkg)) rules_all = $(foreach d, $(deps_all), cd $(shell rospack find $(d)) && make &&) true; .PHONY: build-all build-all: $(rules_all) rules_all_test = $(foreach d, $(deps_all), cd $(shell rospack find $(d)) && make test &&) true; .PHONY: build-test-all build-test-all: $(rules_all_test) ros-1.15.8/core/mk/bzr_checkout.mk000066400000000000000000000015301407615046500167720ustar00rootroot00000000000000# This file can be used to automate cloning and patching of 3rd # party software. # # Before including this file, e.g.: # include $(shell rospack find mk)/bzr_checkout.mk # define the following make variables: # BZR_DIR: name of directory into which you want to clone to # BZR_URL: full URL to download # BZR_PATCH: your (list of) patch file(s) to patch the downloaded software # BZR_REVISION: a bzr revisionspec string ifneq ($(BZR_REVISION),) BZR_REV=-r $(BZR_REVISION) else BZR_REV= endif $(BZR_DIR): bzr branch $(BZR_URL) $(BZR_REV) $(BZR_DIR) touch rospack_nosubdirs patched: $(BZR_DIR) $(BZR_PATCH) Makefile cd $(BZR_DIR) && bzr revert $(BZR_REV) ifneq ($(strip $(BZR_PATCH)),) $(foreach PATCH, $(BZR_PATCH), patch -d $(BZR_DIR) -p1 < $(PATCH) && ) echo patched touch rospack_nosubdirs touch patched endif download: $(BZR_DIR) patched ros-1.15.8/core/mk/cmake.mk000066400000000000000000000042531407615046500153750ustar00rootroot00000000000000# set EXTRA_CMAKE_FLAGS in the including Makefile in order to add tweaks CMAKE_FLAGS= -Wdev -DCMAKE_TOOLCHAIN_FILE=$(ROS_ROOT)/core/rosbuild/rostoolchain.cmake $(EXTRA_CMAKE_FLAGS) # The all target does the heavy lifting, creating the build directory and # invoking CMake all: @mkdir -p build -mkdir -p bin @rm -rf msg/cpp srv/cpp # make sure there are no msg/cpp or srv/cpp directories cd build && cmake $(CMAKE_FLAGS) .. ifneq ($(MAKE),) cd build && $(MAKE) $(ROS_PARALLEL_JOBS) else cd build && make $(ROS_PARALLEL_JOBS) endif PACKAGE_NAME=$(shell basename $(PWD)) # The clean target blows everything away # It also removes auto-generated message/service code directories, # to handle the case where the original .msg/.srv file has been removed, # and thus CMake no longer knows about it. clean: -cd build && make clean rm -rf build # All other targets are just passed through test: all if cd build && make -k $@; then make test-results; else make test-results && exit 1; fi test-nobuild: @mkdir -p build cd build && cmake $(CMAKE_FLAGS) -Drosbuild_test_nobuild=1 .. if cd build && make rosbuild_clean-test-results && make -k test; then make test-results; else make test-results && exit 1; fi tests: all cd build && make $@ test-future: all cd build && make -k $@ gcoverage: all cd build && make $@ # generate eclipse projects in the root of the package # remove all generated files and folders since after replacing the Makefile # they will all be regenerated in the subfolder build eclipse-project: mv Makefile Makefile.ros if ! (cmake -G"Eclipse CDT4 - Unix Makefiles" -Wno-dev . && rm Makefile && rm CMakeCache.txt && rm -rf CMakeFiles); then mv Makefile.ros Makefile && echo "**ERROR building Eclipse project!**" && false; fi mv Makefile.ros Makefile mv .project .project-cmake awk -f $(shell rospack find mk)/eclipse.awk .project-cmake > .project rm .project-cmake python $(shell rospack find mk)/make_pydev_project.py rm -r catkin catkin_generated cmake_install.cmake devel if test -e CTestTestfile.cmake; then rm CTestTestfile.cmake; fi if test -d gtest; then rm -r gtest; fi if test -d test_results; then rm -r test_results; fi include $(shell rospack find mk)/buildtest.mk ros-1.15.8/core/mk/cmake_stack.mk000066400000000000000000000023121407615046500165540ustar00rootroot00000000000000# set EXTRA_CMAKE_FLAGS in the including Makefile in order to add tweaks CMAKE_FLAGS= -Wdev -DCMAKE_TOOLCHAIN_FILE=$(ROS_ROOT)/core/rosbuild/rostoolchain.cmake $(EXTRA_CMAKE_FLAGS) # The all target does the heavy lifting, creating the build directory and # invoking CMake all: @mkdir -p build cd build && cmake $(CMAKE_FLAGS) .. #cd build && make $(ROS_PARALLEL_JOBS) # The clean target blows everything away # It also removes auto-generated message/service code directories, # to handle the case where the original .msg/.srv file has been removed, # and thus CMake no longer knows about it. clean: -cd build && make clean #rm -rf msg/cpp msg/lisp msg/oct msg/java srv/cpp srv/lisp srv/oct srv/java src/$(PACKAGE_NAME)/msg src/$(PACKAGE_NAME)/srv rm -rf build # Build a source package. Assumes that you're in a clean tree. package_source: all $(shell rospack find rosbuild)/bin/package_source.py $(CURDIR) # All other targets are just passed through #test: all # if cd build && make -k $@; then make test-results; else make test-results && exit 1; fi #tests: all # cd build && make $@ #test-future: all # cd build && make -k $@ #gcoverage: all # cd build && make $@ #include $(shell rospack find mk)/buildtest.mk ros-1.15.8/core/mk/download_unpack_build.mk000066400000000000000000000043301407615046500206400ustar00rootroot00000000000000# This file can be used to automate downloading and unpacking of source # distributions # # Before including this file, define the following make variables: # # TARBALL: name of source distribution to be downloaded # TARBALL_URL: full URL (including the file itself) to download # SOURCE_DIR: name of directory into which TARBALL will unpack # UNPACK_CMD: command to use when unpacking (e.g., tar xzf) # TARBALL_PATCH: patch files to apply to SOURCE_DIR # INITIAL_DIR: set this if the tarball unpacks to a different dir than SOURCE_DIR, # and you want the directory moved # # Optional variables: # MD5SUM_FILE: name of md5sum file to check before unpacking # # Because this file declares targets, you almost certainly want to declare # your own 'all' target before including this file. Otherwise, the first # target declared here will become the default. # This target is pretty much vestigial, and is only here to support the # download target. The intended use it to depend on the unpacked file, # below, which repeats the download and check logic. $(TARBALL): -mkdir -p build ifneq ($(strip $(MD5SUM_FILE)),) if [ ! -f $(MD5SUM_FILE) ]; then echo "Error: Couldn't find md5sum file $(MD5SUM_FILE)" && false; fi $(ROS_ROOT)/core/rosbuild/bin/download_checkmd5.py $(TARBALL_URL) $(TARBALL) `awk {'print $$1'} $(MD5SUM_FILE)` else $(ROS_ROOT)/core/rosbuild/bin/download_checkmd5.py $(TARBALL_URL) $(TARBALL) endif touch -c $(TARBALL) download: $(TARBALL) $(SOURCE_DIR)/unpacked: $(TARBALL_PATCH) -mkdir -p build ifneq ($(strip $(MD5SUM_FILE)),) if [ ! -f $(MD5SUM_FILE) ]; then echo "Error: Couldn't find md5sum file $(MD5SUM_FILE)" && false; fi $(ROS_ROOT)/core/rosbuild/bin/download_checkmd5.py $(TARBALL_URL) $(TARBALL) `awk {'print $$1'} $(MD5SUM_FILE)` else $(ROS_ROOT)/core/rosbuild/bin/download_checkmd5.py $(TARBALL_URL) $(TARBALL) endif touch -c $(TARBALL) rm -rf $(SOURCE_DIR) $(INITIAL_DIR) ifneq ($(strip $(UNPACK_CMD)),) cd build; $(UNPACK_CMD) ../$(TARBALL) else cd build; tar xzf ../$(TARBALL) endif ifneq ($(strip $(INITIAL_DIR)),) mv $(INITIAL_DIR) $(SOURCE_DIR) endif ifneq ($(strip $(TARBALL_PATCH)),) $(foreach patch,$(TARBALL_PATCH), patch -d $(SOURCE_DIR) -p0 < $(patch);) endif touch $(SOURCE_DIR)/unpacked ros-1.15.8/core/mk/eclipse.awk000066400000000000000000000011771407615046500161160ustar00rootroot00000000000000//{ if(index($0,"VERBOSE=1")>0) { printf "\t\t\t\t\tVERBOSE=1|" printf "ROS_ROOT="ENVIRON["ROS_ROOT"]"|" printf "ROS_PACKAGE_PATH="ENVIRON["ROS_PACKAGE_PATH"]"|" printf "PYTHONPATH="ENVIRON["PYTHONPATH"]"|" printf "PATH="ENVIRON["PATH"]"|" printf "LD_LIBRARY_PATH="ENVIRON["LD_LIBRARY_PATH"]"|" printf "PKG_CONFIG_PATH="ENVIRON["PKG_CONFIG_PATH"]"|" printf "CMAKE_PREFIX_PATH="ENVIRON["CMAKE_PREFIX_PATH"]"|" print "" } else { print $0 } } ros-1.15.8/core/mk/git_checkout.mk000066400000000000000000000014201407615046500167560ustar00rootroot00000000000000# This file can be used to automate cloning and patching of 3rd # party software. # # Before including this file, e.g.: # include $(shell rospack find mk)/git_checkout.mk # define the following make variables: # GIT_DIR: name of directory into which you want to clone to # GIT_URL: full URL to download # GIT_PATCH: your (list of) patch file(s) to patch the downloaded software # GIT_REVISION: - $(GIT_DIR): git clone $(GIT_URL) $(GIT_DIR) cd $(GIT_DIR) && git checkout $(GIT_REVISION) touch rospack_nosubdirs patched: $(GIT_DIR) $(GIT_PATCH) Makefile cd $(GIT_DIR) && git reset --hard ifneq ($(strip $(GIT_PATCH)),) $(foreach PATCH, $(GIT_PATCH), patch -d $(GIT_DIR) -p1 < $(PATCH) && ) echo patched touch rospack_nosubdirs touch patched endif download: $(GIT_DIR) patched ros-1.15.8/core/mk/hg_checkout.mk000066400000000000000000000015561407615046500166030ustar00rootroot00000000000000# This file can be used to automate cloning and patching of 3rd # party software. # # Before including this file, e.g.: # include $(shell rospack find mk)/hg_checkout.mk # define the following make variables: # HG_DIR: name of directory into which you want to clone to # HG_URL: full URL to download # HG_PATCH: your (list of) patch file(s) to patch the downloaded software # HG_BRANCH: the branch of the repository to update # HG_REVISION: the revision to update $(HG_DIR): mkdir -p $(HG_DIR) hg clone $(HG_URL) $(HG_DIR) cd $(HG_DIR) && hg update $(HG_BRANCH) && hg update $(HG_REVISION) touch rospack_nosubdirs patched: $(HG_PATCH) Makefile ifneq ($(strip $(HG_PATCH)),) cd $(HG_DIR) && hg revert --all $(foreach PATCH, $(HG_PATCH), patch -d $(HG_DIR) -p1 < $(PATCH) && ) echo patched touch rospack_nosubdirs touch patched endif download: $(HG_DIR) patched ros-1.15.8/core/mk/make_pydev_project.py000066400000000000000000000046341407615046500202130ustar00rootroot00000000000000#!/usr/bin/python # Software License Agreement (BSD License) # # Copyright (c) 2010. Willow Garage, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following # disclaimer in the documentation and/or other materials provided # with the distribution. # * Neither the name of Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. import os import sys PKG = os.path.split(os.getcwd())[1] print("Creating pydev project for package '%s'" % PKG) import roslib # noqa: E402 roslib.load_manifest(PKG) pathlist = '\n'.join( ['%s' % path for path in sys.path if os.path.exists(path)]) pydev_project = """ Default python 2.6 %s """ % pathlist print('Writing .pydevproject, adding %d modules' % len(sys.path)) f = open('.pydevproject', 'w') f.write(pydev_project) f.close() ros-1.15.8/core/mk/package.xml000066400000000000000000000015611407615046500161000ustar00rootroot00000000000000 mk 1.15.8 A collection of .mk include files for building ROS architectural elements. Most package authors should use cmake .mk, which calls CMake for the build of the package. The other files in this package are intended for use in exotic situations that mostly arise when importing 3rdparty code. Michel Hidalgo Jacob Perron BSD http://www.ros.org/wiki/ROS Brian Gerkey Morgan Quigley Dirk Thomas catkin rosbuild rospack ros-1.15.8/core/mk/svn_checkout.mk000066400000000000000000000016671407615046500170160ustar00rootroot00000000000000 ifeq ($(strip $(SVN_CMDLINE)),) SVN_CMDLINE = svn endif $(SVN_DIR): $(SVN_CMDLINE) co $(SVN_REVISION) $(SVN_URL) $(SVN_DIR) ifneq ($(strip $(SVN_PATCH)),) $(foreach patch,$(SVN_PATCH), patch -d $(SVN_DIR) -p0 < $(patch);) endif -if test -z "$(SVN_REVISION)" -o "x$(SVN_REVISION)" != "x-r `svn info $(SVN_DIR) | grep Revision | cut -d " " -f 2,2`"; then \ cd $(SVN_DIR) && $(SVN_CMDLINE) up $(SVN_REVISION); \ fi touch rospack_nosubdirs touch patched SVN_UP: $(SVN_DIR) # Note that 'svn revert' can't use the --non-interactive option, so we # invoke 'svn' directly, instead of calling $(SVN_CMDLINE) patched: $(SVN_PATCH) Makefile ifneq ($(strip $(SVN_PATCH)),) svn revert -R $(SVN_DIR) endif -cd $(SVN_DIR) && $(SVN_CMDLINE) up $(SVN_REVISION) $(foreach PATCH, $(SVN_PATCH), patch -d $(SVN_DIR) -p0 < $(PATCH) && ) echo patched touch rospack_nosubdirs touch patched SVN_UP_REVERT_PATCH: $(SVN_DIR) patched download: SVN_UP ros-1.15.8/core/rosbuild/000077500000000000000000000000001407615046500151745ustar00rootroot00000000000000ros-1.15.8/core/rosbuild/CHANGELOG.rst000066400000000000000000000106011407615046500172130ustar00rootroot00000000000000^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Changelog for package rosbuild ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 1.15.8 (2021-07-21) ------------------- * Fix spelling (`#277 `_) * Update maintainers (`#272 `_) * Contributors: Jacob Perron, freddii 1.15.7 (2020-09-28) ------------------- 1.15.6 (2020-07-20) ------------------- 1.15.5 (2020-07-06) ------------------- 1.15.4 (2020-05-28) ------------------- * fix download_checkmd5 for Python 3 (`#260 `_) 1.15.3 (2020-05-14) ------------------- 1.15.2 (2020-04-07) ------------------- 1.15.1 (2020-03-17) ------------------- 1.15.0 (2020-02-11) ------------------- 1.14.8 (2020-02-11) ------------------- * update style to pass flake8 (`#240 `_) * Bump CMake version to avoid CMP0048 warning (`#234 `_) 1.14.7 (2019-10-03) ------------------- 1.14.6 (2019-03-18) ------------------- 1.14.5 (2019-03-04) ------------------- * pull in CATKIN_ENV_HOOK_WORKSPACE if defined (`#15 `_) (`#196 `_) 1.14.4 (2018-05-01) ------------------- 1.14.3 (2018-01-30) ------------------- 1.14.2 (2017-10-26) ------------------- 1.14.1 (2017-07-27) ------------------- 1.14.0 (2017-02-22) ------------------- 1.13.6 (2017-10-31) ------------------- 1.13.5 (2017-02-14) ------------------- 1.13.4 (2016-09-19) ------------------- 1.13.3 (2016-09-16) ------------------- 1.13.2 (2016-09-02) ------------------- 1.13.1 (2016-03-13) ------------------- 1.13.0 (2016-03-10) ------------------- 1.12.6 (2016-03-10) ------------------- 1.12.5 (2015-10-13) ------------------- 1.12.4 (2015-10-12) ------------------- 1.12.3 (2015-09-19) ------------------- * fix rosbuild with newer ld versions (`#87 `_) 1.12.2 (2015-04-27) ------------------- 1.12.1 (2015-04-16) ------------------- 1.12.0 (2014-12-26) ------------------- 1.11.6 (2014-12-22) ------------------- * fix dry clean-test-results target (`#71 `_) 1.11.5 (2014-08-18) ------------------- 1.11.4 (2014-07-23) ------------------- * fix dry rosboost_cfg to support finding boost in multiarch lib folder (`#62 `_) 1.11.3 (2014-07-18) ------------------- * suppress warning for rosbuild target "test" with CMake 3.0 (`#61 `_) 1.11.2 (2014-06-16) ------------------- 1.11.1 (2014-05-07) ------------------- * fix CMake warning with 2.8.12 and newer (`#44 `_) * use catkin_install_python() to install Python scripts (`#46 `_) * python 3 compatibility 1.11.0 (2014-01-31) ------------------- * ensure escaping of preprocessor definition (`#43 `_) 1.10.9 (2014-01-07) ------------------- 1.10.8 (2013-10-15) ------------------- 1.10.7 (2013-10-04) ------------------- * compatibility of env hooks with old workspace setup files (`#36 `_) 1.10.6 (2013-08-22) ------------------- 1.10.5 (2013-08-21) ------------------- * make rosbuild relocatable (`ros/catkin#490 `_) 1.10.4 (2013-07-05) ------------------- 1.10.3 (2013-07-03) ------------------- 1.10.2 (2013-06-18) ------------------- * update rosbuild to use moved roslaunch-check script (`ros/ros_comm#241 `_) 1.10.1 (2013-06-06) ------------------- 1.10.0 (2013-03-22 09:23) ------------------------- 1.9 (Groovy) ============ 1.9.44 (2013-03-13) ------------------- 1.9.43 (2013-03-08) ------------------- * fix handling spaces in folder names (`ros/catkin#375 `_) 1.9.42 (2013-01-25) ------------------- * fix install location of relocated rosbuild stuff 1.9.41 (2013-01-24) ------------------- * modified ROS_ROOT in devel space and moved all rosbuild files to a location which fits how the files are relatively looked up * modified install location of download_checkmd5 script to work in devel space and be consistent with other files * fix wrong comments about location of rosconfig.cmake 1.9.40 (2013-01-13) ------------------- 1.9.39 (2012-12-30) ------------------- * first public release for Groovy ros-1.15.8/core/rosbuild/CMakeLists.txt000066400000000000000000000020571407615046500177400ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.0.2) project(rosbuild) find_package(catkin REQUIRED) catkin_package() if(CMAKE_HOST_UNIX) catkin_add_env_hooks(10.rosbuild SHELLS sh DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/env-hooks) else() catkin_add_env_hooks(10.rosbuild SHELLS bat DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/env-hooks) endif() # do not wildcard install files since the root folder of the package will contain a debian folder for releasing install(FILES core/rosbuild/FindPkgConfig.cmake core/rosbuild/private.cmake core/rosbuild/ProcessorCount.cmake core/rosbuild/public.cmake core/rosbuild/rosbuild.cmake core/rosbuild/rosconfig.cmake core/rosbuild/rostoolchain.cmake DESTINATION ${CATKIN_GLOBAL_SHARE_DESTINATION}/ros/core/rosbuild) catkin_install_python(PROGRAMS tests/count_cores.py DESTINATION ${CATKIN_GLOBAL_SHARE_DESTINATION}/ros/core/rosbuild/tests) catkin_install_python(PROGRAMS core/rosbuild/bin/check_same_directories.py core/rosbuild/bin/download_checkmd5.py DESTINATION ${CATKIN_GLOBAL_SHARE_DESTINATION}/ros/core/rosbuild/bin) ros-1.15.8/core/rosbuild/bin/000077500000000000000000000000001407615046500157445ustar00rootroot00000000000000ros-1.15.8/core/rosbuild/bin/rosgcov000077500000000000000000000003571407615046500173610ustar00rootroot00000000000000#!/bin/sh # A helper script to invoke gcov from CMake, which seems to have problems # with pipes inside an add_custom_target() src=$1 p=$2 for f in `find $p -name \`basename $src\`.o`; do gcov -b -o $f $src 1>/dev/null 2>&1 done true ros-1.15.8/core/rosbuild/bin/rosgcov_summarize000077500000000000000000000052641407615046500214570ustar00rootroot00000000000000#!/usr/bin/env python import fileinput import os.path import re import sys USAGE = 'USAGE: rosgcov_summarize ' if len(sys.argv) != 3: print(USAGE) sys.exit(-1) pkg = sys.argv[1] fname = sys.argv[2] if not os.path.exists(fname): print('[rosgcov] %s : %.2f%% (no coverage results)' % (os.path.split(pkg)[1], 0.0)) sys.exit(0) re_hit = re.compile('^ *[0-9]*:.*') re_miss = re.compile('^ *#####:.*') re_branch_hit = re.compile('^branch *[0-9] *taken [0-9]*.*') re_branch_miss = re.compile('^branch *[0-9] *never executed.*') files = [] finput = fileinput.input(fname) for l in finput: ls = l.strip().split(' ') f = os.path.join(ls[0], os.path.split(ls[1])[1]) files.append(f.strip()) total = 0 hits = 0 misses = 0 branch_total = 0 branch_hits = 0 branch_misses = 0 print('-------------------------------------------------------') print('Coverage summary: ') print('-------------------------------------------------------') for f in files: prefix = os.path.commonprefix([pkg, f]) display_name = f[len(prefix):] if display_name[0] == '/': display_name = display_name[1:] print(' ' + display_name + ': ') gcov_fname = f + '.gcov' if not os.path.exists(gcov_fname): print('WARNING: no coverage results for %s' % (display_name)) continue gcovf = fileinput.input(gcov_fname) local_total = 0 local_hits = 0 local_misses = 0 local_branch_total = 0 local_branch_hits = 0 local_branch_misses = 0 for s in gcovf: if re_hit.match(s): local_hits += 1 local_total += 1 elif re_miss.match(s): local_misses += 1 local_total += 1 if re_branch_hit.match(s): local_branch_hits += 1 elif re_branch_miss.match(s): local_branch_misses += 1 local_branch_total += 1 print(' line: %.2f%% (%d / %d)' % ((100.0 * local_hits / max(local_total, 1)), local_hits, local_total)) hits += local_hits misses += local_misses total += local_total print(' branch: %.2f%% (%d / %d)' % ((100.0 * local_branch_hits / max(local_branch_total, 1)), local_branch_hits, local_branch_total)) branch_hits += local_branch_hits branch_misses += local_branch_misses branch_total += local_branch_total print('-------------------------------------------------------') print('[rosgcov] %s : %.2f%% (%d / %d)' % (os.path.split(pkg)[1], (100.0 * hits / max(total, 1)), hits, total)) print('[rosgcov] %s : branch %.2f%% (%d / %d)' % (os.path.split(pkg)[1], (100.0 * branch_hits / max(branch_total, 1)), branch_hits, branch_total)) print('-------------------------------------------------------') ros-1.15.8/core/rosbuild/core/000077500000000000000000000000001407615046500161245ustar00rootroot00000000000000ros-1.15.8/core/rosbuild/core/rosbuild/000077500000000000000000000000001407615046500177475ustar00rootroot00000000000000ros-1.15.8/core/rosbuild/core/rosbuild/FindPkgConfig.cmake000066400000000000000000000361101407615046500234220ustar00rootroot00000000000000# - a pkg-config module for CMake # # Usage: # pkg_check_modules( [REQUIRED] []*) # checks for all the given modules # # pkg_search_module( [REQUIRED] []*) # checks for given modules and uses the first working one # # When the 'REQUIRED' argument was set, macros will fail with an error # when module(s) could not be found # # It sets the following variables: # PKG_CONFIG_FOUND ... true iff pkg-config works on the system # PKG_CONFIG_EXECUTABLE ... pathname of the pkg-config program # _FOUND ... set to 1 iff module(s) exist # # For the following variables two sets of values exist; first one is the # common one and has the given PREFIX. The second set contains flags # which are given out when pkgconfig was called with the '--static' # option. # _LIBRARIES ... only the libraries (w/o the '-l') # _LIBRARY_DIRS ... the paths of the libraries (w/o the '-L') # _LDFLAGS ... all required linker flags # _LDFLAGS_OTHER ... all other linker flags # _INCLUDE_DIRS ... the '-I' preprocessor flags (w/o the '-I') # _CFLAGS ... all required cflags # _CFLAGS_OTHER ... the other compiler flags # # = for common case # = _STATIC for static linking # # There are some special variables whose prefix depends on the count # of given modules. When there is only one module, stays # unchanged. When there are multiple modules, the prefix will be # changed to _: # _VERSION ... version of the module # _PREFIX ... prefix-directory of the module # _INCLUDEDIR ... include-dir of the module # _LIBDIR ... lib-dir of the module # # = when |MODULES| == 1, else # = _ # # A parameter can have the following formats: # {MODNAME} ... matches any version # {MODNAME}>={VERSION} ... at least version is required # {MODNAME}={VERSION} ... exactly version is required # {MODNAME}<={VERSION} ... modules must not be newer than # # Examples # pkg_check_modules (GLIB2 glib-2.0) # # pkg_check_modules (GLIB2 glib-2.0>=2.10) # requires at least version 2.10 of glib2 and defines e.g. # GLIB2_VERSION=2.10.3 # # pkg_check_modules (FOO glib-2.0>=2.10 gtk+-2.0) # requires both glib2 and gtk2, and defines e.g. # FOO_glib-2.0_VERSION=2.10.3 # FOO_gtk+-2.0_VERSION=2.8.20 # # pkg_check_modules (XRENDER REQUIRED xrender) # defines e.g.: # XRENDER_LIBRARIES=Xrender;X11 # XRENDER_STATIC_LIBRARIES=Xrender;X11;pthread;Xau;Xdmcp # # pkg_search_module (BAR libxml-2.0 libxml2 libxml>=2) # Copyright (C) 2006 Enrico Scholz # # Redistribution and use, with or without modification, are permitted # provided that the following conditions are met: # # 1. Redistributions must retain the above copyright notice, this # list of conditions and the following disclaimer. # 2. The name of the author may not be used to endorse or promote # products derived from this software without specific prior # written permission. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER # IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR # OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN # IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ### Common stuff #### set(PKG_CONFIG_VERSION 1) set(PKG_CONFIG_FOUND 0) find_program(PKG_CONFIG_EXECUTABLE NAMES pkg-config DOC "pkg-config executable") mark_as_advanced(PKG_CONFIG_EXECUTABLE) if(PKG_CONFIG_EXECUTABLE) set(PKG_CONFIG_FOUND 1) endif(PKG_CONFIG_EXECUTABLE) # Unsets the given variables macro(_pkgconfig_unset var) set(${var} "" CACHE INTERNAL "") endmacro(_pkgconfig_unset) macro(_pkgconfig_set var value) set(${var} ${value} CACHE INTERNAL "") endmacro(_pkgconfig_set) # Invokes pkgconfig, cleans up the result and sets variables macro(_pkgconfig_invoke _pkglist _prefix _varname _regexp) set(_pkgconfig_invoke_result) execute_process( COMMAND ${PKG_CONFIG_EXECUTABLE} ${ARGN} ${_pkglist} OUTPUT_VARIABLE _pkgconfig_invoke_result RESULT_VARIABLE _pkgconfig_failed) if (_pkgconfig_failed) set(_pkgconfig_${_varname} "") _pkgconfig_unset(${_prefix}_${_varname}) else(_pkgconfig_failed) string(REGEX REPLACE "[\r\n]" " " _pkgconfig_invoke_result "${_pkgconfig_invoke_result}") string(REGEX REPLACE " +$" "" _pkgconfig_invoke_result "${_pkgconfig_invoke_result}") if (NOT ${_regexp} STREQUAL "") string(REGEX REPLACE "${_regexp}" " " _pkgconfig_invoke_result "${_pkgconfig_invoke_result}") endif(NOT ${_regexp} STREQUAL "") separate_arguments(_pkgconfig_invoke_result) #message(STATUS " ${_varname} ... ${_pkgconfig_invoke_result}") set(_pkgconfig_${_varname} ${_pkgconfig_invoke_result}) _pkgconfig_set(${_prefix}_${_varname} "${_pkgconfig_invoke_result}") endif(_pkgconfig_failed) endmacro(_pkgconfig_invoke) # Invokes pkgconfig two times; once without '--static' and once with # '--static' macro(_pkgconfig_invoke_dyn _pkglist _prefix _varname cleanup_regexp) _pkgconfig_invoke("${_pkglist}" ${_prefix} ${_varname} "${cleanup_regexp}" ${ARGN}) _pkgconfig_invoke("${_pkglist}" ${_prefix} STATIC_${_varname} "${cleanup_regexp}" --static ${ARGN}) endmacro(_pkgconfig_invoke_dyn) # Splits given arguments into options and a package list macro(_pkgconfig_parse_options _result _is_req) set(${_is_req} 0) foreach(_pkg ${ARGN}) if (_pkg STREQUAL "REQUIRED") set(${_is_req} 1) endif (_pkg STREQUAL "REQUIRED") endforeach(_pkg ${ARGN}) set(${_result} ${ARGN}) list(REMOVE_ITEM ${_result} "REQUIRED") endmacro(_pkgconfig_parse_options) ### macro(_pkg_check_modules_internal _is_required _is_silent _prefix) _pkgconfig_unset(${_prefix}_FOUND) _pkgconfig_unset(${_prefix}_VERSION) _pkgconfig_unset(${_prefix}_PREFIX) _pkgconfig_unset(${_prefix}_INCLUDEDIR) _pkgconfig_unset(${_prefix}_LIBDIR) _pkgconfig_unset(${_prefix}_LIBS) _pkgconfig_unset(${_prefix}_LIBS_L) _pkgconfig_unset(${_prefix}_LIBS_PATHS) _pkgconfig_unset(${_prefix}_LIBS_OTHER) _pkgconfig_unset(${_prefix}_CFLAGS) _pkgconfig_unset(${_prefix}_CFLAGS_I) _pkgconfig_unset(${_prefix}_CFLAGS_OTHER) _pkgconfig_unset(${_prefix}_STATIC_LIBDIR) _pkgconfig_unset(${_prefix}_STATIC_LIBS) _pkgconfig_unset(${_prefix}_STATIC_LIBS_L) _pkgconfig_unset(${_prefix}_STATIC_LIBS_PATHS) _pkgconfig_unset(${_prefix}_STATIC_LIBS_OTHER) _pkgconfig_unset(${_prefix}_STATIC_CFLAGS) _pkgconfig_unset(${_prefix}_STATIC_CFLAGS_I) _pkgconfig_unset(${_prefix}_STATIC_CFLAGS_OTHER) # create a better addressable variable of the modules and calculate its size set(_pkg_check_modules_list ${ARGN}) list(LENGTH _pkg_check_modules_list _pkg_check_modules_cnt) if(PKG_CONFIG_EXECUTABLE) # give out status message telling checked module if (NOT ${_is_silent}) if (_pkg_check_modules_cnt EQUAL 1) message(STATUS "checking for module '${_pkg_check_modules_list}'") else(_pkg_check_modules_cnt EQUAL 1) message(STATUS "checking for modules '${_pkg_check_modules_list}'") endif(_pkg_check_modules_cnt EQUAL 1) endif(NOT ${_is_silent}) set(_pkg_check_modules_packages) set(_pkg_check_modules_failed) # iterate through module list and check whether they exist and match the required version foreach (_pkg_check_modules_pkg ${_pkg_check_modules_list}) set(_pkg_check_modules_exist_query) # check whether version is given if (_pkg_check_modules_pkg MATCHES ".*(>=|=|<=).*") string(REGEX REPLACE "(.*[^><])(>=|=|<=)(.*)" "\\1" _pkg_check_modules_pkg_name "${_pkg_check_modules_pkg}") string(REGEX REPLACE "(.*[^><])(>=|=|<=)(.*)" "\\2" _pkg_check_modules_pkg_op "${_pkg_check_modules_pkg}") string(REGEX REPLACE "(.*[^><])(>=|=|<=)(.*)" "\\3" _pkg_check_modules_pkg_ver "${_pkg_check_modules_pkg}") else(_pkg_check_modules_pkg MATCHES ".*(>=|=|<=).*") set(_pkg_check_modules_pkg_name "${_pkg_check_modules_pkg}") set(_pkg_check_modules_pkg_op) set(_pkg_check_modules_pkg_ver) endif(_pkg_check_modules_pkg MATCHES ".*(>=|=|<=).*") # handle the operands if (_pkg_check_modules_pkg_op STREQUAL ">=") list(APPEND _pkg_check_modules_exist_query --atleast-version) endif(_pkg_check_modules_pkg_op STREQUAL ">=") if (_pkg_check_modules_pkg_op STREQUAL "=") list(APPEND _pkg_check_modules_exist_query --exact-version) endif(_pkg_check_modules_pkg_op STREQUAL "=") if (_pkg_check_modules_pkg_op STREQUAL "<=") list(APPEND _pkg_check_modules_exist_query --max-version) endif(_pkg_check_modules_pkg_op STREQUAL "<=") # create the final query which is of the format: # * --atleast-version # * --exact-version # * --max-version # * --exists if (_pkg_check_modules_pkg_op) list(APPEND _pkg_check_modules_exist_query "${_pkg_check_modules_pkg_ver}") else(_pkg_check_modules_pkg_op) list(APPEND _pkg_check_modules_exist_query --exists) endif(_pkg_check_modules_pkg_op) _pkgconfig_unset(${_prefix}_${_pkg_check_modules_pkg_name}_VERSION) _pkgconfig_unset(${_prefix}_${_pkg_check_modules_pkg_name}_PREFIX) _pkgconfig_unset(${_prefix}_${_pkg_check_modules_pkg_name}_INCLUDEDIR) _pkgconfig_unset(${_prefix}_${_pkg_check_modules_pkg_name}_LIBDIR) list(APPEND _pkg_check_modules_exist_query "${_pkg_check_modules_pkg_name}") list(APPEND _pkg_check_modules_packages "${_pkg_check_modules_pkg_name}") # execute the query execute_process( COMMAND ${PKG_CONFIG_EXECUTABLE} ${_pkg_check_modules_exist_query} RESULT_VARIABLE _pkgconfig_retval) # evaluate result and tell failures if (_pkgconfig_retval) if(NOT ${_is_silent}) message(STATUS " package '${_pkg_check_modules_pkg}' not found") endif(NOT ${_is_silent}) set(_pkg_check_modules_failed 1) endif(_pkgconfig_retval) endforeach(_pkg_check_modules_pkg) if(_pkg_check_modules_failed) # fail when requested if (${_is_required}) message(SEND_ERROR "A required package was not found") endif (${_is_required}) else(_pkg_check_modules_failed) # when we are here, we checked whether requested modules # exist. Now, go through them and set variables _pkgconfig_set(${_prefix}_FOUND 1) list(LENGTH _pkg_check_modules_packages pkg_count) # iterate through all modules again and set individual variables foreach (_pkg_check_modules_pkg ${_pkg_check_modules_packages}) # handle case when there is only one package required if (pkg_count EQUAL 1) set(_pkg_check_prefix "${_prefix}") else(pkg_count EQUAL 1) set(_pkg_check_prefix "${_prefix}_${_pkg_check_modules_pkg}") endif(pkg_count EQUAL 1) _pkgconfig_invoke(${_pkg_check_modules_pkg} "${_pkg_check_prefix}" VERSION "" --modversion ) _pkgconfig_invoke(${_pkg_check_modules_pkg} "${_pkg_check_prefix}" PREFIX "" --variable=prefix ) _pkgconfig_invoke(${_pkg_check_modules_pkg} "${_pkg_check_prefix}" INCLUDEDIR "" --variable=includedir ) _pkgconfig_invoke(${_pkg_check_modules_pkg} "${_pkg_check_prefix}" LIBDIR "" --variable=libdir ) message(STATUS " found ${_pkg_check_modules_pkg}, version ${_pkgconfig_VERSION}") endforeach(_pkg_check_modules_pkg) # set variables which are combined for multiple modules _pkgconfig_invoke_dyn("${_pkg_check_modules_packages}" "${_prefix}" LIBRARIES "(^| )-l" --libs-only-l ) _pkgconfig_invoke_dyn("${_pkg_check_modules_packages}" "${_prefix}" LIBRARY_DIRS "(^| )-L" --libs-only-L ) _pkgconfig_invoke_dyn("${_pkg_check_modules_packages}" "${_prefix}" LDFLAGS "" --libs ) _pkgconfig_invoke_dyn("${_pkg_check_modules_packages}" "${_prefix}" LDFLAGS_OTHER "" --libs-only-other ) _pkgconfig_invoke_dyn("${_pkg_check_modules_packages}" "${_prefix}" INCLUDE_DIRS "(^| )-I" --cflags-only-I ) _pkgconfig_invoke_dyn("${_pkg_check_modules_packages}" "${_prefix}" CFLAGS "" --cflags ) _pkgconfig_invoke_dyn("${_pkg_check_modules_packages}" "${_prefix}" CFLAGS_OTHER "" --cflags-only-other ) endif(_pkg_check_modules_failed) else(PKG_CONFIG_EXECUTABLE) if (${_is_required}) message(SEND_ERROR "pkg-config tool not found") endif (${_is_required}) endif(PKG_CONFIG_EXECUTABLE) endmacro(_pkg_check_modules_internal) ### ### User visible macros start here ### ### macro(pkg_check_modules _prefix _module0) # check cached value if (NOT DEFINED __pkg_config_checked_${_prefix} OR __pkg_config_checked_${_prefix} LESS ${PKG_CONFIG_VERSION}) _pkgconfig_parse_options (_pkg_modules _pkg_is_required "${_module0}" ${ARGN}) _pkg_check_modules_internal("${_pkg_is_required}" 0 "${_prefix}" ${_pkg_modules}) _pkgconfig_set(__pkg_config_checked_${_prefix} ${PKG_CONFIG_VERSION}) endif(NOT DEFINED __pkg_config_checked_${_prefix} OR __pkg_config_checked_${_prefix} LESS ${PKG_CONFIG_VERSION}) endmacro(pkg_check_modules) ### macro(pkg_search_module _prefix _module0) # check cached value if (NOT DEFINED __pkg_config_checked_${_prefix} OR __pkg_config_checked_${_prefix} LESS ${PKG_CONFIG_VERSION} OR NOT ${_prefix}_FOUND) set(_pkg_modules_found 0) _pkgconfig_parse_options(_pkg_modules_alt _pkg_is_required "${_module0}" ${ARGN}) message(STATUS "checking for one of the modules '${_pkg_modules_alt}'") # iterate through all modules and stop at the first working one. foreach(_pkg_alt ${_pkg_modules_alt}) if(NOT _pkg_modules_found) _pkg_check_modules_internal(0 1 "${_prefix}" "${_pkg_alt}") endif(NOT _pkg_modules_found) if (${_prefix}_FOUND) set(_pkg_modules_found 1) endif(${_prefix}_FOUND) endforeach(_pkg_alt) if (NOT ${_prefix}_FOUND) if(${_pkg_is_required}) message(SEND_ERROR "None of the required '${_pkg_modules_alt}' found") endif(${_pkg_is_required}) endif(NOT ${_prefix}_FOUND) _pkgconfig_set(__pkg_config_checked_${_prefix} ${PKG_CONFIG_VERSION}) endif(NOT DEFINED __pkg_config_checked_${_prefix} OR __pkg_config_checked_${_prefix} LESS ${PKG_CONFIG_VERSION} OR NOT ${_prefix}_FOUND) endmacro(pkg_search_module) ### Local Variables: ### mode: cmake ### End: ros-1.15.8/core/rosbuild/core/rosbuild/ProcessorCount.cmake000066400000000000000000000050671407615046500237510ustar00rootroot00000000000000# - ProcessorCount(var) # Determine the number of processors/cores and save value in ${var} # # Sets the variable named ${var} to the number of physical cores available on # the machine if the information can be determined. Otherwise it is set to 0. # Currently this functionality is only implemented for Windows, Mac OS X and # Unix systems providing getconf or the /proc/cpuinfo interface (e.g. Linux). # A more reliable way might be to compile a small C program that uses the CPUID # instruction, but that again requires compiler support or compiling assembler # code. #============================================================================= # Copyright 2010 Kitware, Inc. # # Distributed under the OSI-approved BSD License (the "License"); # see accompanying file Copyright.txt for details. # # This software is distributed WITHOUT ANY WARRANTY; without even the # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # See the License for more information. #============================================================================= # (To distribute this file outside of CMake, substitute the full # License text for the above reference.) function(ProcessorCount var) # Unknown: set(count 0) if(WIN32) # Windows: set(count "$ENV{NUMBER_OF_PROCESSORS}") #message("ProcessorCount: using environment variable") elseif(APPLE) # Mac: find_program(ProcessorCount_cmd_sysctl sysctl PATHS /usr/sbin) if(ProcessorCount_cmd_sysctl) execute_process(COMMAND ${ProcessorCount_cmd_sysctl} -n hw.ncpu OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE count) #message("ProcessorCount: using sysctl '${ProcessorCount_cmd_sysctl}'") endif() else() # Linux (and other systems with getconf): find_program(ProcessorCount_cmd_getconf getconf) if(ProcessorCount_cmd_getconf) execute_process(COMMAND ${ProcessorCount_cmd_getconf} _NPROCESSORS_ONLN OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE count) #message("ProcessorCount: using getconf '${ProcessorCount_cmd_getconf}'") endif() endif() # Execute this code when there is no 'sysctl' or 'getconf' or # when previously executed methods return empty output: # if(NOT count) # Systems with /proc/cpuinfo: set(cpuinfo_file /proc/cpuinfo) if(EXISTS "${cpuinfo_file}") file(STRINGS "${cpuinfo_file}" procs REGEX "^processor.: [0-9]+$") list(LENGTH procs count) #message("ProcessorCount: using cpuinfo '${cpuinfo_file}'") endif() endif() set(${var} ${count} PARENT_SCOPE) endfunction() ros-1.15.8/core/rosbuild/core/rosbuild/bin/000077500000000000000000000000001407615046500205175ustar00rootroot00000000000000ros-1.15.8/core/rosbuild/core/rosbuild/bin/check_same_directories.py000077500000000000000000000041771407615046500255630ustar00rootroot00000000000000#!/usr/bin/env python # Software License Agreement (BSD License) # # Copyright (c) 2009, Willow Garage, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following # disclaimer in the documentation and/or other materials provided # with the distribution. # * Neither the name of Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # Simple script to check whether two directories are the same. I'm doing # it in this script because the following command-line invocation produces # a syntax error for reasons that I don't understand: # # python -c 'import os; if os.path.realpath("/u/gerkey/code/ros/ros/core/rosconsole") != os.path.realpath("/u/gerkey/code/ros/ros/core/rosconsole"): raise Exception' import os import sys if __name__ == '__main__': if len(sys.argv) != 3: raise Exception if os.path.realpath(sys.argv[1]) != os.path.realpath(sys.argv[2]): raise Exception ros-1.15.8/core/rosbuild/core/rosbuild/bin/download_checkmd5.py000077500000000000000000000062061407615046500244520ustar00rootroot00000000000000#!/usr/bin/env python # Software License Agreement (BSD License) # # Copyright (c) 2009, Willow Garage, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following # disclaimer in the documentation and/or other materials provided # with the distribution. # * Neither the name of Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. import hashlib import os import sys import urllib.request from optparse import OptionParser NAME = 'download_checkmd5.py' def main(): parser = OptionParser(usage='usage: %prog URI dest [md5sum]', prog=NAME) options, args = parser.parse_args() md5sum = None if len(args) == 2: uri, dest = args elif len(args) == 3: uri, dest, md5sum = args else: parser.error('wrong number of arguments') # Create intermediate directories as necessary, #2970 d = os.path.dirname(dest) if len(d) and not os.path.exists(d): os.makedirs(d) fresh = False if not os.path.exists(dest): sys.stdout.write('[rosbuild] Downloading %s to %s...' % (uri, dest)) sys.stdout.flush() urllib.request.urlretrieve(uri, dest) sys.stdout.write('Done\n') fresh = True if md5sum: m = hashlib.md5(open(dest, "rb").read()) d = m.hexdigest() print('[rosbuild] Checking md5sum on %s' % (dest)) if d != md5sum: if not fresh: print('[rosbuild] WARNING: md5sum mismatch (%s != %s); re-downloading file %s' % (d, md5sum, dest)) os.remove(dest) # Try one more time urllib.request.urlretrieve(uri, dest) m = hashlib.md5(open(dest).read()) d = m.hexdigest() if d != md5sum: print('[rosbuild] ERROR: md5sum mismatch (%s != %s) on %s; aborting' % (d, md5sum, dest)) return 1 return 0 if __name__ == '__main__': sys.exit(main()) ros-1.15.8/core/rosbuild/core/rosbuild/private.cmake000066400000000000000000000441431407615046500224310ustar00rootroot00000000000000############################################################################### # Internal macros below macro(_rosbuild_warn) message("[rosbuild] WARNING: " ${ARGV}) endmacro(_rosbuild_warn) macro(_rosbuild_warn_deprecate_rospack_prefix name) string(REPLACE rospack rosbuild new_name ${name}) message("[rosbuild] WARNING: ${name} is deprecated; please use ${new_name} instead") endmacro(_rosbuild_warn_deprecate_rospack_prefix) macro(_rosbuild_warn_deprecate_no_prefix name) message("[rosbuild] WARNING: ${name} is deprecated; please use rosbuild_${name} instead") endmacro(_rosbuild_warn_deprecate_no_prefix) # look up python interpreter, store in ${PYTHON_EXECUTABLE} find_package(PythonInterp) ############################################################################### # Macro to turn a list into a string (why doesn't CMake have this # built-in?) macro(_rosbuild_list_to_string _string _list) set(${_string}) foreach(_item ${_list}) string(LENGTH "${${_string}}" _len) if(${_len} GREATER 0) set(${_string} "${${_string}} ${_item}") else(${_len} GREATER 0) set(${_string} "${_item}") endif(${_len} GREATER 0) endforeach(_item) endmacro(_rosbuild_list_to_string) ############################################################################### # Macro to dequote a string, in order to properly construct a command line. # There must be an easier way to do this. macro(_rosbuild_dequote_string _out _in) set(${_out}) string(REGEX REPLACE " " ";" tmp "${_in}") foreach(_item ${tmp}) string(LENGTH "${${_out}}" _len) if(${_len} GREATER 0) set(${_out} ${${_out}} ${_item}) else(${_len} GREATER 0) set(${_out} ${_item}) endif(${_len} GREATER 0) endforeach(_item) endmacro(_rosbuild_dequote_string) # list(FIND) was introduced after cmake 2.4.6, so we write our own macro(_rosbuild_list_find _list _item _idx) set(${_idx} -1) list(LENGTH ${_list} _len) math(EXPR _total "${_len} - 1") foreach(_i RANGE ${_total}) list(GET ${_list} ${_i} _it) if(_it STREQUAL ${_item}) set(${_idx} ${_i}) endif(_it STREQUAL ${_item}) endforeach(_i) endmacro(_rosbuild_list_find) # Check validity of manifest.xml, to avoid esoteric build errors macro(_rosbuild_check_manifest) execute_process( COMMAND ${PYTHON_EXECUTABLE} -c "import roslib.manifest; roslib.manifest.parse_file('manifest.xml')" OUTPUT_VARIABLE _manifest_error ERROR_VARIABLE _manifest_error RESULT_VARIABLE _manifest_failed WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} OUTPUT_STRIP_TRAILING_WHITESPACE ) if(_manifest_failed) message("[rosbuild] Error from syntax check of ${PROJECT_NAME}/manifest.xml") message("${_manifest_error}") message(FATAL_ERROR "[rosbuild] Syntax check of ${PROJECT_NAME}/manifest.xml failed; aborting") endif(_manifest_failed) endmacro(_rosbuild_check_manifest) # Check that the directory where we're building is also where rospack # thinks that the package lives, to avoid esoteric build errors. macro(_rosbuild_check_package_location) # Ask rospack where our package is rosbuild_find_ros_package(${PROJECT_NAME}) # Compare to where we are execute_process( COMMAND $ENV{ROS_ROOT}/core/rosbuild/bin/check_same_directories.py ${${PROJECT_NAME}_PACKAGE_PATH} ${PROJECT_SOURCE_DIR} OUTPUT_VARIABLE _rosbuild_check_package_location_error ERROR_VARIABLE _rosbuild_check_package_location_error RESULT_VARIABLE _rosbuild_check_package_location_failed WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} OUTPUT_STRIP_TRAILING_WHITESPACE ) if(_rosbuild_check_package_location_failed) message("[rosbuild] Error from directory check: $ENV{ROS_ROOT}/core/rosbuild/bin/check_same_directories.py ${${PROJECT_NAME}_PACKAGE_PATH} ${PROJECT_SOURCE_DIR}") message("${_rosbuild_check_package_location_failed}") message("${_rosbuild_check_package_location_error}") message(FATAL_ERROR "[rosbuild] rospack found package \"${PROJECT_NAME}\" at \"${${PROJECT_NAME}_PACKAGE_PATH}\", but the current directory is \"${PROJECT_SOURCE_DIR}\". You should double-check your ROS_PACKAGE_PATH to ensure that packages are found in the correct precedence order.") endif(_rosbuild_check_package_location_failed) endmacro(_rosbuild_check_package_location) # helper function to register check that results were generated (#580) macro(_rosbuild_check_rostest_xml_result test_name test_file) add_custom_target(${test_name}_result COMMAND ${ROSUNIT_SCRIPTS_DIR}/check_test_ran.py ${test_file} VERBATIM) # Redeclaration of target is to workaround bug in 2.4.6 if(CMAKE_MINOR_VERSION LESS 6) add_custom_target(test-results-run) endif(CMAKE_MINOR_VERSION LESS 6) add_dependencies(test-results-run ${test_name}_result) endmacro(_rosbuild_check_rostest_xml_result test_name) macro(_rosbuild_add_gtest exe) # Look for optional TIMEOUT argument, #2645 cmake_parse_arguments(_gtest "" "TIMEOUT" "" ${ARGN}) if(NOT _gtest_TIMEOUT) set(_gtest_TIMEOUT 60.0) endif(NOT _gtest_TIMEOUT) # Create the program, with basic + gtest build flags rosbuild_add_executable(${exe} EXCLUDE_FROM_ALL ${_gtest_UNPARSED_ARGUMENTS}) rosbuild_add_gtest_build_flags(${exe}) # Create a legal target name, in case the target name has slashes in it string(REPLACE "/" "_" _testname ${exe}) # Create target for this test # We use rosunit to call the executable to get process control, #1629, #3112 # But don't depend on the gtest executable if rosbuild_test_nobuild is set, #3008 if(NOT rosbuild_test_nobuild) add_custom_target(test_${_testname} COMMAND ${ROSUNIT_EXE} --name=${_testname} --time-limit=${_gtest_TIMEOUT} ${EXECUTABLE_OUTPUT_PATH}/${exe} DEPENDS ${EXECUTABLE_OUTPUT_PATH}/${exe} WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} VERBATIM) else(NOT rosbuild_test_nobuild) add_custom_target(test_${_testname} COMMAND ${ROSUNIT_EXE} --name=${_testname} --time-limit=${_gtest_TIMEOUT} ${EXECUTABLE_OUTPUT_PATH}/${exe} WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} VERBATIM) endif(NOT rosbuild_test_nobuild) # Don't register to check xml output here, because we may have gotten # here through registration of a future test. Eventually, we should pass # in the overriding target (e.g., test-results vs. test-future-results). # For now, we call _rosbuild_check_rostest_xml_result() in rosbuild_add_gtest() instead. #_rosbuild_check_rostest_xml_result(test_${_testname} ${rosbuild_test_results_dir}/${PROJECT_NAME}/${_testname}.xml) # Make sure that any messages get generated prior to building this target add_dependencies(${exe} rospack_genmsg) add_dependencies(${exe} rospack_gensrv) # Make sure all test programs are built before running this test # but not if rosbuild_test_nobuild is set, #3008 if(NOT rosbuild_test_nobuild) add_dependencies(test_${_testname} tests) endif(NOT rosbuild_test_nobuild) endmacro(_rosbuild_add_gtest) # helper function to register check that results were generated (#580) # this one specifically targets rostest. rostest requires different # arguments as cmake doesn't know the name of the output file macro(_rosbuild_check_rostest_result test_name test_pkg test_file) add_custom_target(${test_name}_result COMMAND ${ROSUNIT_SCRIPTS_DIR}/check_test_ran.py --rostest ${test_pkg} ${test_file} WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} VERBATIM) # Redeclaration of target is to workaround bug in 2.4.6 if(CMAKE_MINOR_VERSION LESS 6) add_custom_target(test-results-run) endif(CMAKE_MINOR_VERSION LESS 6) add_dependencies(test-results-run ${test_name}_result) endmacro(_rosbuild_check_rostest_result test_name) macro(_rosbuild_add_rostest file) # Check that the file exists, #1621 set(_file_name _file_name-NOTFOUND) find_file(_file_name ${file} ${PROJECT_SOURCE_DIR} /) if(NOT _file_name) message(FATAL_ERROR "Can't find rostest file \"${file}\"") endif(NOT _file_name) # Create a legal target name, in case the target name has slashes in it string(REPLACE "/" "_" _testname ${file}) # Create target for this test add_custom_target(rostest_${_testname} COMMAND ${ARGN} rostest ${file} DEPENDS ${file} WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} VERBATIM) # Make sure all test programs are built before running this test # but not if rosbuild_test_nobuild is set, #3008 if(NOT rosbuild_test_nobuild) add_dependencies(rostest_${_testname} tests) endif(NOT rosbuild_test_nobuild) # rostest-check-results will do the magic of fixing an incorrect file extension # Don't register to check rostest output here, because we may have gotten # here through registration of a future test. Eventually, we should pass # in the overriding target (e.g., test-results vs. test-future-results). # For now, we call _rosbuild_check_rostest_xml_result() in # rosbuild_add_rostest() # and rosbuild_add_rostest_future() instead. #_rosbuild_check_rostest_result(rostest_${_testname} ${PROJECT_NAME} ${file}) endmacro(_rosbuild_add_rostest) macro(_rosbuild_add_pyunit file) # Look for optional TIMEOUT argument, #2645 cmake_parse_arguments(_pyunit "" "TIMEOUT" "" ${ARGN}) if(NOT _pyunit_TIMEOUT) set(_pyunit_TIMEOUT 60.0) endif(NOT _pyunit_TIMEOUT) # Check that the file exists, #1621 set(_file_name _file_name-NOTFOUND) find_file(_file_name ${file} ${PROJECT_SOURCE_DIR} /) if(NOT _file_name) message(FATAL_ERROR "Can't find pyunit file \"${file}\"") endif(NOT _file_name) # Create a legal target name, in case the target name has slashes in it string(REPLACE "/" "_" _testname ${file}) # We look for ROS_TEST_COVERAGE=1 # to indicate that coverage reports are being requested. if("$ENV{ROS_TEST_COVERAGE}" STREQUAL "1") set(_covarg "--cov") else("$ENV{ROS_TEST_COVERAGE}" STREQUAL "1") set(_covarg) endif("$ENV{ROS_TEST_COVERAGE}" STREQUAL "1") # Create target for this test # We use rostest to call the executable to get process control, #1629 add_custom_target(pyunit_${_testname} COMMAND ${ROSUNIT_EXE} --name=${_testname} --time-limit=${_pyunit_TIMEOUT} -- ${file} ${_covarg} DEPENDS ${file} WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} VERBATIM) # Make sure all test programs are built before running this test # but not if rosbuild_test_nobuild is set, #3008 if(NOT rosbuild_test_nobuild) add_dependencies(pyunit_${_testname} tests) endif(NOT rosbuild_test_nobuild) endmacro(_rosbuild_add_pyunit) # Actual signature: # _rosbuild_add_roslaunch_check targetname file var=val var=val... macro(_rosbuild_add_roslaunch_check targetname file) # Check that the file exists, #1621 set(_file_name _file_name-NOTFOUND) find_file(_file_name ${file} ${CMAKE_CURRENT_SOURCE_DIR} /) if(NOT _file_name) message(FATAL_ERROR "Can't find roslaunch file or directory \"${file}\"") endif(NOT _file_name) # Find roslaunch rosbuild_invoke_rospack("" roslaunch path find roslaunch) # Create target for this test. add_custom_target(${targetname} COMMAND ${roslaunch_path}/scripts/roslaunch-check -o ${rosbuild_test_results_dir}/${PROJECT_NAME}/TEST-${targetname}.xml ${file} ${ARGN} DEPENDS ${file} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} VERBATIM) # Make sure all test programs are built before running this test # but not if rosbuild_test_nobuild is set, #3008 if(NOT rosbuild_test_nobuild) add_dependencies(${targetname} tests) endif(NOT rosbuild_test_nobuild) endmacro(_rosbuild_add_roslaunch_check) macro(_rosbuild_wget_and_build tarball tarball_url tarball_dir unpack_cmd configure_cmd make_cmd install_cmd) find_package(Wget REQUIRED) _rosbuild_dequote_string(_unpack_cmd ${unpack_cmd}) _rosbuild_dequote_string(_configure_cmd ${configure_cmd}) _rosbuild_dequote_string(_make_cmd ${make_cmd}) _rosbuild_dequote_string(_install_cmd ${install_cmd}) add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/${tarball} COMMAND ${WGET_EXECUTABLE} ${tarball_url} -O ${tarball} VERBATIM) add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/${tarball_dir} COMMAND ${_unpack_cmd} ${tarball} COMMAND touch ${tarball_dir} DEPENDS ${PROJECT_BINARY_DIR}/${tarball} VERBATIM) add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/installed COMMAND cmake -E chdir ${PROJECT_BINARY_DIR}/${tarball_dir} ${_configure_cmd} COMMAND cmake -E chdir ${PROJECT_BINARY_DIR}/${tarball_dir} ${_make_cmd} COMMAND cmake -E chdir ${PROJECT_BINARY_DIR}/${tarball_dir} ${_install_cmd} COMMAND touch ${PROJECT_BINARY_DIR}/installed DEPENDS ${PROJECT_BINARY_DIR}/${tarball_dir} VERBATIM) add_custom_target(fetch_and_build ALL DEPENDS ${PROJECT_BINARY_DIR}/installed) endmacro(_rosbuild_wget_and_build) macro(_rosbuild_add_library lib libname type) add_library(${lib} ${type} ${ARGN}) if(${type} STREQUAL STATIC) # Set output name to be the same as shared lib (may not work on Windows) set_target_properties(${lib} PROPERTIES OUTPUT_NAME ${libname}) # Also add -fPIC, because CMake leaves it out when building static # libs, even though it's necessary on 64-bit machines for linking this # lib against shared libs downstream. The only exception is mingw gcc # which doesn't specifically need to worry about building # position independent libs. if(NOT MINGW) rosbuild_add_compile_flags(${lib} -fPIC) endif() endif(${type} STREQUAL STATIC) # Add explicit dependency of each file on our manifest.xml and those of # our dependencies get_target_property(_srclist ${lib} SOURCES) foreach(_src ${_srclist}) set(_file_name _file_name-NOTFOUND) find_file(_file_name ${_src} ${CMAKE_CURRENT_SOURCE_DIR} /) if(NOT _file_name) message("[rosbuild] Couldn't find source file ${_src}; assuming that it is in ${CMAKE_CURRENT_SOURCE_DIR} and will be generated later") set(_file_name ${CMAKE_CURRENT_SOURCE_DIR}/${_src}) endif(NOT _file_name) add_file_dependencies(${_file_name} ${ROS_MANIFEST_LIST}) endforeach(_src) # Prevent deletion of existing lib of same name set_target_properties(${lib} PROPERTIES CLEAN_DIRECT_OUTPUT 1) # Attach compile and link flags rosbuild_add_compile_flags(${lib} ${${PROJECT_NAME}_CFLAGS_OTHER}) rosbuild_add_link_flags(${lib} ${${PROJECT_NAME}_LDFLAGS_OTHER}) # Link lib against dependent libs target_link_libraries(${lib} ${${PROJECT_NAME}_LIBRARIES}) # Add ROS-wide compile and link flags (usually things like -Wall). These # are set in rosconfig.cmake. rosbuild_add_compile_flags(${lib} ${ROS_COMPILE_FLAGS}) rosbuild_add_link_flags(${lib} ${ROS_LINK_FLAGS}) # Make sure to do any prebuild work (e.g., msg/srv generation) before # building this target. add_dependencies(${lib} rosbuild_precompile) endmacro(_rosbuild_add_library) macro(_rosbuild_get_clock var) execute_process( COMMAND ${PYTHON_EXECUTABLE} -c "import time, sys; sys.stdout.write(str(time.time()));" OUTPUT_VARIABLE ${var} ERROR_VARIABLE _time_error RESULT_VARIABLE _time_failed OUTPUT_STRIP_TRAILING_WHITESPACE ) if(_time_failed) message("[rosbuild] Error from calling to Python to get system time:") message("${_time_error}") message(FATAL_ERROR "[rosbuild] Failed to get system time; aborting") endif(_time_failed) endmacro(_rosbuild_get_clock var) macro(_rosbuild_cmakelist_to_pylist _cmakelist _pylist) # Convert a CMake list into a Python list set(_pyl "[") foreach(_f ${_cmakelist}) set(_pyl "${_pyl} '${_f}',") endforeach(_f) set(_pyl "${_pyl}]") set(${_pylist} "${_pyl}") endmacro(_rosbuild_cmakelist_to_pylist _cmakelist _pylist) macro(_rosbuild_compare_manifests var _t _c _m) if("${_t}" STREQUAL "") # No time was given, so it's too old set(${var} 1) else("${_t}" STREQUAL "") _rosbuild_cmakelist_to_pylist("${_m}" _pylist) _rosbuild_cmakelist_to_pylist("${_c}" _cached_pylist) # Call Python to compare the provided time to the latest mtime on all # the files execute_process( COMMAND ${PYTHON_EXECUTABLE} -c "import os, sys; sys.stdout.write('1' if set(${_pylist}) != set(${_cached_pylist}) or ${_t} < max(os.stat(f).st_mtime for f in ${_pylist}) else '0');" OUTPUT_VARIABLE ${var} ERROR_VARIABLE _mtime_error RESULT_VARIABLE _mtime_failed OUTPUT_STRIP_TRAILING_WHITESPACE ) if(_mtime_failed) message("[rosbuild] Error from calling to Python to get latest mtime:") message("${_mtime_error}") message(FATAL_ERROR "[rosbuild] Failed to get latest mtime; aborting") endif(_mtime_failed) endif("${_t}" STREQUAL "") endmacro(_rosbuild_compare_manifests var _t) # parse_arguments() taken from # http://www.itk.org/Wiki/CMakeMacroParseArguments MACRO(PARSE_ARGUMENTS prefix arg_names option_names) SET(DEFAULT_ARGS) FOREACH(arg_name ${arg_names}) SET(${prefix}_${arg_name}) ENDFOREACH(arg_name) FOREACH(option ${option_names}) SET(${prefix}_${option} FALSE) ENDFOREACH(option) SET(current_arg_name DEFAULT_ARGS) SET(current_arg_list) FOREACH(arg ${ARGN}) SET(larg_names ${arg_names}) LIST(FIND larg_names "${arg}" is_arg_name) IF (is_arg_name GREATER -1) SET(${prefix}_${current_arg_name} ${current_arg_list}) SET(current_arg_name ${arg}) SET(current_arg_list) ELSE (is_arg_name GREATER -1) SET(loption_names ${option_names}) LIST(FIND loption_names "${arg}" is_option) IF (is_option GREATER -1) SET(${prefix}_${arg} TRUE) ELSE (is_option GREATER -1) SET(current_arg_list ${current_arg_list} ${arg}) ENDIF (is_option GREATER -1) ENDIF (is_arg_name GREATER -1) ENDFOREACH(arg) SET(${prefix}_${current_arg_name} ${current_arg_list}) ENDMACRO(PARSE_ARGUMENTS) # Internal macros above ############################################################################### ros-1.15.8/core/rosbuild/core/rosbuild/public.cmake000066400000000000000000001472221407615046500222370ustar00rootroot00000000000000# Set a flag to indicate that rosbuild_init() has not been called, so that # we can later catch out-of-order calls to macros that must be called prior # to rosbuild_init(), related to #1487. set(ROSBUILD_init_called 0) # Use this package to get add_file_dependencies() include(AddFileDependencies) # Used to check if a function exists include(CheckFunctionExists) # look up python interpreter, store in ${PYTHON_EXECUTABLE}, #3763 BSD support find_package(PythonInterp) # Find a ros package. macro(rosbuild_find_ros_package pkgname) # catch the error output to suppress it execute_process( COMMAND rospack find ${pkgname} ERROR_VARIABLE __rospack_err_ignore OUTPUT_VARIABLE __pkg_dir OUTPUT_STRIP_TRAILING_WHITESPACE) # todo: catch return code and be smart about it set(${pkgname}_PACKAGE_PATH ${__pkg_dir}) endmacro(rosbuild_find_ros_package) # Find a ros stack. macro(rosbuild_find_ros_stack stackname) # catch the error output to suppress it execute_process( COMMAND rosstack find ${stackname} ERROR_VARIABLE __rospack_err_ignore OUTPUT_VARIABLE __stack_dir OUTPUT_STRIP_TRAILING_WHITESPACE) # todo: catch return code and be smart about it set(${stackname}_STACK_PATH ${__stack_dir}) endmacro(rosbuild_find_ros_stack) # Retrieve the current COMPILE_FLAGS for the given target, append the new # ones, and set the result. macro(rosbuild_add_compile_flags target) set(args ${ARGN}) separate_arguments(args) get_target_property(_flags ${target} COMPILE_FLAGS) if(NOT _flags) set(_flags ${ARGN}) else(NOT _flags) separate_arguments(_flags) list(APPEND _flags "${args}") endif(NOT _flags) _rosbuild_list_to_string(_flags_str "${_flags}") set_target_properties(${target} PROPERTIES COMPILE_FLAGS "${_flags_str}") endmacro(rosbuild_add_compile_flags) # Retrieve the current COMPILE_FLAGS for the given target, remove the given # ones, and set the result. macro(rosbuild_remove_compile_flags target) set(args ${ARGN}) separate_arguments(args) get_target_property(_flags ${target} COMPILE_FLAGS) separate_arguments(_flags) list(REMOVE_ITEM _flags ${args}) _rosbuild_list_to_string(_flags_str "${_flags}") set_target_properties(${target} PROPERTIES COMPILE_FLAGS "${_flags_str}") endmacro(rosbuild_remove_compile_flags) # Retrieve the current LINK_FLAGS for the given target, append the new # ones, and set the result. macro(rosbuild_add_link_flags target) set(args ${ARGN}) separate_arguments(args) get_target_property(_flags ${target} LINK_FLAGS) if(NOT _flags) set(_flags ${ARGN}) else(NOT _flags) separate_arguments(_flags) list(APPEND _flags "${args}") endif(NOT _flags) _rosbuild_list_to_string(_flags_str "${_flags}") set_target_properties(${target} PROPERTIES LINK_FLAGS "${_flags_str}") endmacro(rosbuild_add_link_flags) # Retrieve the current LINK_FLAGS for the given target, remove the given # ones, and set the result. macro(rosbuild_remove_link_flags target) set(args ${ARGN}) separate_arguments(args) get_target_property(_flags ${target} LINK_FLAGS) separate_arguments(_flags) list(REMOVE_ITEM _flags ${args}) _rosbuild_list_to_string(_flags_str "${_flags}") set_target_properties(${target} PROPERTIES LINK_FLAGS "${_flags_str}") endmacro(rosbuild_remove_link_flags) macro(rosbuild_invoke_rospack pkgname _prefix _varname) # Check that our cached location of rospack is valid. It can be invalid # if rospack has moved since last time we ran, #1154. If it's invalid, # search again. if(NOT EXISTS ${ROSPACK_EXE}) message("Cached location of rospack is invalid; searching for rospack...") set(ROSPACK_EXE ROSPACK_EXE-NOTFOUND) # Only look in PATH for rospack, #3831 find_program(ROSPACK_EXE NAMES rospack DOC "rospack executable" NO_CMAKE_PATH NO_CMAKE_ENVIRONMENT_PATH NO_CMAKE_SYSTEM_PATH) if (NOT ROSPACK_EXE) message(FATAL_ERROR "Couldn't find rospack. Please run 'make' in $ROS_ROOT") endif(NOT ROSPACK_EXE) endif(NOT EXISTS ${ROSPACK_EXE}) set(_rospack_invoke_result) execute_process( COMMAND ${ROSPACK_EXE} ${ARGN} ${pkgname} OUTPUT_VARIABLE _rospack_invoke_result ERROR_VARIABLE _rospack_err_ignore RESULT_VARIABLE _rospack_failed OUTPUT_STRIP_TRAILING_WHITESPACE ) if (_rospack_failed) #set(_rospack_${_varname} "") #set(${_prefix}_${_varname} "" CACHE INTERNAL "") message("Failed to invoke ${ROSPACK_EXE} ${ARGN} ${pkgname}") message("${_rospack_err_ignore}") message("${_rospack_invoke_result}") message(FATAL_ERROR "\nFailed to invoke rospack to get compile flags for package '${pkgname}'. Look above for errors from rospack itself. Aborting. Please fix the broken dependency!\n") else(_rospack_failed) separate_arguments(_rospack_invoke_result) set(_rospack_${_varname} ${_rospack_invoke_result}) # We don't cache results that contain newlines, because # they make CMake's cache unhappy. This check should only affect calls # to `rospack plugins`, which we don't need to cache. if(_rospack_invoke_result MATCHES ".*\n.*") set(${_prefix}_${_varname} "${_rospack_invoke_result}") else(_rospack_invoke_result MATCHES ".*\n.*") set(${_prefix}_${_varname} "${_rospack_invoke_result}" CACHE INTERNAL "") endif(_rospack_invoke_result MATCHES ".*\n.*") endif(_rospack_failed) endmacro(rosbuild_invoke_rospack) ############################################################################### # This is the user's main entry point. A *lot* of work gets done here. It # should probably be split up into multiple macros. macro(rosbuild_init) # Record that we've been called set(ROSBUILD_init_called 1) # Don't override the project name if the user said not to, #3119 if(NOT DEFINED ROSBUILD_DONT_REDEFINE_PROJECT) # Infer package name from directory name. get_filename_component(_project ${CMAKE_SOURCE_DIR} NAME) project(${_project}) else(NOT DEFINED ROSBUILD_DONT_REDEFINE_PROJECT) set(_project ${PROJECT_NAME}) endif(NOT DEFINED ROSBUILD_DONT_REDEFINE_PROJECT) # Declare that the minimum version of OSX we support is 10.6, #3491. # For background on how CMAKE_OSX_DEPLOYMENT_TARGET works, see: # http://public.kitware.com/Bug/view.php?id=6195 if(APPLE) SET(CMAKE_OSX_DEPLOYMENT_TARGET "10.6" CACHE STRING "Deployment target for OSX" FORCE) endif(APPLE) message("[rosbuild] Building package ${_project}") # Must call include(rosconfig) after project, because rosconfig uses # PROJECT_SOURCE_DIR include($ENV{ROS_ROOT}/core/rosbuild/rosconfig.cmake) # Check that manifest.xml is valid _rosbuild_check_manifest() # Check that the package directory is correct _rosbuild_check_package_location() # force automatic escaping of preprocessor definitions cmake_policy(PUSH) cmake_policy(SET CMP0005 NEW) # Add ROS_PACKAGE_NAME define add_definitions(-DROS_PACKAGE_NAME=\"${PROJECT_NAME}\") cmake_policy(POP) # ROS_BUILD_TYPE is set by rosconfig # RelWithAsserts is our own type, not supported by CMake if("${ROS_BUILD_TYPE}" STREQUAL "RelWithAsserts") set(CMAKE_BUILD_TYPE "") set(ROS_COMPILE_FLAGS "-O3 ${ROS_COMPILE_FLAGS}") else("${ROS_BUILD_TYPE}" STREQUAL "RelWithAsserts") set(CMAKE_BUILD_TYPE ${ROS_BUILD_TYPE}) endif("${ROS_BUILD_TYPE}" STREQUAL "RelWithAsserts") # Set default output directories set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}) set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib) # By default, look in the local include dir include_directories(${PROJECT_SOURCE_DIR}/include) set(_prefix ${PROJECT_NAME}) set(${_prefix}_INCLUDEDIR "" CACHE INTERNAL "") # Get the full paths to the manifests for all packages on which # we depend rosbuild_invoke_rospack(${PROJECT_NAME} _rospack deps_manifests_invoke_result deps-manifests) rosbuild_invoke_rospack(${PROJECT_NAME} _rospack msgsrv_gen_invoke_result deps-msgsrv) set(ROS_MANIFEST_LIST "${PROJECT_SOURCE_DIR}/manifest.xml ${_rospack_deps_manifests_invoke_result} ${_rospack_msgsrv_gen_invoke_result}") # convert whitespace-separated string to ;-separated list separate_arguments(ROS_MANIFEST_LIST) # Check the time at which we last cached flags against the latest # modification time for all manifests that we depend on. If our cache # time is smaller, then we need to rebuild our cached values by calling # out to rospack to get flags. This is an optimization in the service of # speeding up the build, #2109. _rosbuild_compare_manifests(_rebuild_cache "${_rosbuild_cached_flag_time}" "${${_prefix}_cached_manifest_list}" "${ROS_MANIFEST_LIST}") if(_rebuild_cache) # Explicitly unset all cached variables, to avoid possible accumulation # across builds, #2389. set(${_prefix}_INCLUDE_DIRS "" CACHE INTERNAL "") set(${_prefix}_CFLAGS_OTHER "" CACHE INTERNAL "") set(${_prefix}_LIBRARY_DIRS "" CACHE INTERNAL "") set(${_prefix}_LIBRARIES "" CACHE INTERNAL "") set(${_prefix}_LDFLAGS_OTHER "" CACHE INTERNAL "") set(${_prefix}_cached_manifest_list "" CACHE INTERNAL "") message("[rosbuild] Cached build flags older than manifests; calling rospack to get flags") # Get the include dirs rosbuild_invoke_rospack(${PROJECT_NAME} ${_prefix} INCLUDE_DIRS cflags-only-I --deps-only) #message("${pkgname} include dirs: ${${_prefix}_INCLUDE_DIRS}") set(${_prefix}_INCLUDE_DIRS ${${_prefix}_INCLUDE_DIRS} CACHE INTERNAL "") # Get the other cflags rosbuild_invoke_rospack(${PROJECT_NAME} ${_prefix} temp cflags-only-other --deps-only) _rosbuild_list_to_string(${_prefix}_CFLAGS_OTHER "${${_prefix}_temp}") #message("${pkgname} other cflags: ${${_prefix}_CFLAGS_OTHER}") set(${_prefix}_CFLAGS_OTHER ${${_prefix}_CFLAGS_OTHER} CACHE INTERNAL "") # Get the lib dirs rosbuild_invoke_rospack(${PROJECT_NAME} ${_prefix} LIBRARY_DIRS libs-only-L --deps-only) #message("${pkgname} library dirs: ${${_prefix}_LIBRARY_DIRS}") set(${_prefix}_LIBRARY_DIRS ${${_prefix}_LIBRARY_DIRS} CACHE INTERNAL "") # Get the libs rosbuild_invoke_rospack(${PROJECT_NAME} ${_prefix} LIBRARIES libs-only-l --deps-only) # # The following code removes duplicate libraries from the link line, # saving only the last one. # if(${_prefix}_LIBRARIES) find_package(catkin REQUIRED) set(_${_prefix}_LIBRARIES ${${_prefix}_LIBRARIES}) set(${_prefix}_LIBRARIES "") list(REVERSE _${_prefix}_LIBRARIES) list_append_unique(${_prefix}_LIBRARIES ${_${_prefix}_LIBRARIES}) list(REVERSE ${_prefix}_LIBRARIES) endif() # Strip the leading ':' from any library that was given to us as # ':/path/to/lib'. Those kinds of libraries generally come from # catkin-generated .pc files that are parsed by rospack via pkg-config. # Newer versions of ld (and gold) don't accept the '-l:/path/to/lib' # syntax. They've long accepted the '/path/to/lib' syntax, so it # should be safe to just strip the ':' here. We could remove it at # the source, from the .pc file, but the lib argument needs to start # with '-l' to ensure proper ordering of libs in the return from # pkg-config. # https://github.com/ros/catkin/issues/694 if(${_prefix}_LIBRARIES) set(_${_prefix}_LIBRARIES ${${_prefix}_LIBRARIES}) set(${_prefix}_LIBRARIES "") foreach(_lib ${_${_prefix}_LIBRARIES}) string(REGEX REPLACE "^:/" "/" _lib_nocolon ${_lib}) list(APPEND ${_prefix}_LIBRARIES ${_lib_nocolon}) endforeach(_lib) endif() # Also throw in the libs that we want to link everything against (only # use case for this so far is -lgcov when building with code coverage # support). list(APPEND ${_prefix}_LIBRARIES "${ROS_LINK_LIBS}") set(${_prefix}_LIBRARIES ${${_prefix}_LIBRARIES} CACHE INTERNAL "") # Get the other lflags rosbuild_invoke_rospack(${PROJECT_NAME} ${_prefix} temp libs-only-other --deps-only) _rosbuild_list_to_string(${_prefix}_LDFLAGS_OTHER "${${_prefix}_temp}") #message("${pkgname} other ldflags: ${${_prefix}_LDFLAGS_OTHER}") set(${_prefix}_LDFLAGS_OTHER ${${_prefix}_LDFLAGS_OTHER} CACHE INTERNAL "") # Record the time at which we cached those values _rosbuild_get_clock(_time) set(_rosbuild_cached_flag_time ${_time} CACHE INTERNAL "") set(${_prefix}_cached_manifest_list ${ROS_MANIFEST_LIST} CACHE INTERNAL "") endif(_rebuild_cache) # Use the (possibly cached) values returned by rospack. include_directories(${${_prefix}_INCLUDE_DIRS}) link_directories(${${_prefix}_LIBRARY_DIRS}) # # Catch absolute pathnames to archive libraries and bracket them with # linker args necessary to force extraction of the entire archive. # # The OS X linker doesn't accept the -whole-archive and -no-whole-archive # arguments. # if(NOT APPLE) foreach(_lib ${${_prefix}_LIBRARIES}) if(_lib MATCHES "/[^ ]*\\.a") set(_bracket_str "-Wl,-whole-archive ${_lib} -Wl,-no-whole-archive") list(APPEND ${_prefix}_LDFLAGS_OTHER "${_bracket_str}") endif(_lib MATCHES "/[^ ]*\\.a") endforeach(_lib) endif(NOT APPLE) # determine multiarch name since Boost might be installed there set(_rosbuild_multiarch "") if(UNIX AND NOT APPLE) # Two step looking for multiarch support: check for gcc -print-multiarch # and, if failed, try to run dpkg-architecture execute_process(COMMAND gcc -print-multiarch OUTPUT_VARIABLE _rosbuild_multiarch OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET ) if ("${_rosbuild_multiarch}" STREQUAL "") execute_process(COMMAND dpkg-architecture -qDEB_HOST_MULTIARCH OUTPUT_VARIABLE _rosbuild_multiarch OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET ) endif() if ("${_rosbuild_multiarch}" STREQUAL "") message("[rosbuild] not using multiarch for finding Boost") else() message("[rosbuild] using multiarch '${_rosbuild_multiarch}' for finding Boost") set(_rosbuild_multiarch "--multiarch=${_rosbuild_multiarch}") endif() endif() # Set up the test targets. Subsequent calls to rosbuild_add_gtest and # friends add targets and dependencies from these targets. # # find rosunit since ROSUNIT_SCRIPTS_DIR and ROSUNIT_EXE will be used later find_package(rosunit REQUIRED) # Record where we're going to put test results (#2003) execute_process(COMMAND ${ROSUNIT_SCRIPTS_DIR}/test_results_dir.py OUTPUT_VARIABLE rosbuild_test_results_dir RESULT_VARIABLE _test_results_dir_failed OUTPUT_STRIP_TRAILING_WHITESPACE) if(_test_results_dir_failed) message(FATAL_ERROR "Failed to invoke '${ROSUNIT_SCRIPTS_DIR}/test_results_dir.py'") endif(_test_results_dir_failed) # The 'tests' target builds the test program if(NOT TARGET tests) add_custom_target(tests) endif() # The 'test' target runs all but the future tests cmake_policy(PUSH) if(POLICY CMP0037) cmake_policy(SET CMP0037 OLD) endif() add_custom_target(test) cmake_policy(POP) # We need to build tests before running them. Addition of this # dependency also ensures that old test results get cleaned prior to a # new test run. # but not if rosbuild_test_nobuild is set, #3008 if(NOT rosbuild_test_nobuild) add_dependencies(test tests) endif(NOT rosbuild_test_nobuild) # Clean out previous test results before running tests. Use bash # conditional to ignore failures (most often happens when a stale NFS # handle lingers in the test results directory), because CMake doesn't # seem to be able to do it. add_custom_target(rosbuild_clean-test-results if ! rm -rf ${rosbuild_test_results_dir}/${PROJECT_NAME}\; then echo "\"WARNING: failed to remove test-results directory\";" fi) # Make the tests target depend on rosbuild_clean-test-results, which will ensure # that test results are deleted before we try to build tests, and thus # before we try to run tests. add_dependencies(tests rosbuild_clean-test-results) # The 'test-future' target runs the future tests add_custom_target(test-future) add_custom_target(test-results-run) add_custom_target(test-results COMMAND ${ROSUNIT_SCRIPTS_DIR}/summarize_results.py --nodeps ${_project}) add_dependencies(test-results test-results-run) # Do we want coverage reporting (only matters for Python, because # Bullseye already collects everything into a single file). if("$ENV{ROS_TEST_COVERAGE}" STREQUAL "1") add_custom_target(test-results-coverage COMMAND ${ROSUNIT_SCRIPTS_DIR}/pycoverage_to_html.py WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}) # Make tests run before collecting coverage results add_dependencies(test-results-coverage test-results-run) # Make coverage collection happen add_dependencies(test-results test-results-coverage) endif("$ENV{ROS_TEST_COVERAGE}" STREQUAL "1") # Initialize a counter to be used to uniquify target names for # calls to rosbuild_add_roslaunch_check(), #3674. set(ROSBUILD_roslaunch_check_count 1) # Find roslib; roslib_path will be used later rosbuild_invoke_rospack("" roslib path find roslib) # Create targets for client libs attach their message-generation output to add_custom_target(rospack_genmsg) add_custom_target(rospack_gensrv) # Add a target that will fire before doing message or service generation. # This is used by packages that do automatic generation of message and # service files. add_custom_target(rosbuild_premsgsrvgen) # Add a target that will fire before compiling anything. This is used by # message and service generation, as well as things outside of ros, like # dynamic_reconfigure. add_custom_target(rosbuild_precompile) # The rospack_genmsg_libexe target is defined for backward compatibility, # and will eventually be removed. add_custom_target(rospack_genmsg_libexe) add_dependencies(rosbuild_precompile rospack_genmsg_libexe) # ${gendeps_exe} is a convenience variable that roslang cmake rules # must reference as a dependency of msg/srv generation # ${gendeps_exe} is set by roslib-extras.cmake find_package(catkin REQUIRED COMPONENTS roslib) # If the roslang package is available, pull in cmake/roslang.cmake from # there; it will in turn include message-generation logic from client # libs. This is to allow roslang to live outside the ros stack, #3108. rosbuild_find_ros_package("roslang") if(roslang_PACKAGE_PATH) # Can't use rosbuild_include() here, because there's no guarantee that # the package we're building depends on roslang (in fact, it probably # doesn't. include("${roslang_PACKAGE_PATH}/cmake/roslang.cmake") endif(roslang_PACKAGE_PATH) # Collect cmake fragments exported by packages that depend on # rosbuild. This behavior is deprecated, in favor of using # rosbuild_include() to explicitly include cmake code from other packages. rosbuild_invoke_rospack(rosbuild _rosbuild EXPORTS plugins --attrib=cmake --top=${_project}) list(LENGTH _rosbuild_EXPORTS _rosbuild_EXPORTS_length) # rospack plugins outputs the list as: # # Here we remove in all cases by: # 1) Remove the first element of the returned list # 2) Search for all instances of , replacing them with just a semicolon # 1) Remove the first package name if the list has at least one element if (${_rosbuild_EXPORTS_length} GREATER 0) list(REMOVE_AT _rosbuild_EXPORTS 0) endif(${_rosbuild_EXPORTS_length} GREATER 0) # 2) Remove the rest of the package names string(REGEX REPLACE "\n[^;]*;" ";" _rosbuild_EXPORTS_stripped "${_rosbuild_EXPORTS}") set(_rosbuild_EXPORTS "" CACHE INTERNAL "") set(_cmake_fragments) foreach(_f ${_rosbuild_EXPORTS_stripped}) list(APPEND _cmake_fragments ${_f}) message("\n[rosbuild] WARNING: the file ${_f} is being included automatically. This behavior is deprecated. The package containing that file should instead export the directory containing the file, and you should use rosbuild_include() to include the file explicitly.\n") endforeach(_f) # Now include them all foreach(_f ${_cmake_fragments}) if(NOT EXISTS ${_f}) message(FATAL_ERROR "Cannot include non-existent exported cmake file ${_f}") endif(NOT EXISTS ${_f}) # Include this cmake fragment; presumably it will do / # provide something useful. Only include each file once (a file # might be multiply referenced because of package dependencies # dependencies). if(NOT ${_f}_INCLUDED) message("[rosbuild] Including ${_f}") include(${_f}) set(${_f}_INCLUDED Y) endif(NOT ${_f}_INCLUDED) endforeach(_f) # gtest has been found by catkin if(GTEST_FOUND) include_directories(${GTEST_INCLUDE_DIRS}) endif() # Delete the files that let rospack know messages/services have been generated file(REMOVE ${PROJECT_SOURCE_DIR}/msg_gen/generated) file(REMOVE ${PROJECT_SOURCE_DIR}/srv_gen/generated) endmacro(rosbuild_init) ############################################################################### # A wrapper around add_executable(), using info from the rospack # invocation to set up compiling and linking. macro(rosbuild_add_executable exe) add_executable(${ARGV}) # Add explicit dependency of each file on our manifest.xml and those of # our dependencies. get_target_property(_srclist ${exe} SOURCES) foreach(_src ${_srclist}) set(_file_name _file_name-NOTFOUND) find_file(_file_name ${_src} ${CMAKE_CURRENT_SOURCE_DIR} /) if(NOT _file_name) message("[rosbuild] Couldn't find source file ${_src}; assuming that it is in ${CMAKE_CURRENT_SOURCE_DIR} and will be generated later") set(_file_name ${CMAKE_CURRENT_SOURCE_DIR}/${_src}) endif(NOT _file_name) add_file_dependencies(${_file_name} ${ROS_MANIFEST_LIST}) endforeach(_src) rosbuild_add_compile_flags(${exe} ${${PROJECT_NAME}_CFLAGS_OTHER}) rosbuild_add_link_flags(${exe} ${${PROJECT_NAME}_LDFLAGS_OTHER}) if(ROS_BUILD_STATIC_EXES AND ${CMAKE_SYSTEM_NAME} STREQUAL "Linux") # This will probably only work on Linux. The LINK_SEARCH_END_STATIC # property should be sufficient, but it doesn't appear to work # properly. rosbuild_add_link_flags(${exe} -static-libgcc -Wl,-Bstatic) endif(ROS_BUILD_STATIC_EXES AND ${CMAKE_SYSTEM_NAME} STREQUAL "Linux") target_link_libraries(${exe} ${${PROJECT_NAME}_LIBRARIES}) # Add ROS-wide compile and link flags (usually things like -Wall). These # are set in rosconfig.cmake. rosbuild_add_compile_flags(${exe} ${ROS_COMPILE_FLAGS}) rosbuild_add_link_flags(${exe} ${ROS_LINK_FLAGS}) # Make sure to do any prebuild work (e.g., msg/srv generation) before # building this target. add_dependencies(${exe} rosbuild_precompile) # If we're linking boost statically, we have to force allow multiple definitions because # rospack does not remove duplicates if ("$ENV{ROS_BOOST_LINK}" STREQUAL "static") rosbuild_add_link_flags(${exe} "-Wl,--allow-multiple-definition") endif("$ENV{ROS_BOOST_LINK}" STREQUAL "static") endmacro(rosbuild_add_executable) # Wrapper around add_library. We can build shared static and shared libs, and # set up compile and link flags for both. macro(rosbuild_add_library lib) # Sanity check; must build at least one kind of library. if(NOT ROS_BUILD_STATIC_LIBS AND NOT ROS_BUILD_SHARED_LIBS) message(FATAL_ERROR "Neither shared nor static libraries are enabled. Please set either ROS_BUILD_STATIC_LIBS or ROS_BUILD_SHARED_LIBS to true in your $ROS_ROOT/rosconfig.cmake") endif(NOT ROS_BUILD_STATIC_LIBS AND NOT ROS_BUILD_SHARED_LIBS) # Sanity check; it's too hard to support building shared libs and static # executables. if(ROS_BUILD_STATIC_EXES AND ROS_BUILD_SHARED_LIBS) message(FATAL_ERROR "Static executables are requested, but so are shared libs. This configuration is unsupported. Please either set ROS_BUILD_SHARED_LIBS to false or set ROS_BUILD_STATIC_EXES to false.") endif(ROS_BUILD_STATIC_EXES AND ROS_BUILD_SHARED_LIBS) # What are we building? if(ROS_BUILD_SHARED_LIBS) # If shared libs are being built, they get the default CMake target name # No matter what, the libraries get the same name in the end. _rosbuild_add_library(${lib} ${lib} SHARED ${ARGN}) endif(ROS_BUILD_SHARED_LIBS) if(ROS_BUILD_STATIC_LIBS) # If we're only building static libs, then they get the default CMake # target name. if(NOT ROS_BUILD_SHARED_LIBS) set(static_lib_name "${lib}") else(NOT ROS_BUILD_SHARED_LIBS) set(static_lib_name "${lib}-static") endif(NOT ROS_BUILD_SHARED_LIBS) _rosbuild_add_library(${static_lib_name} ${lib} STATIC ${ARGN}) endif(ROS_BUILD_STATIC_LIBS) endmacro(rosbuild_add_library) # Wrapper around add_library for the specific case of building a MODULE, # which works a little differently on dyld systems (e.g., OS X) macro(rosbuild_add_library_module lib) _rosbuild_add_library(${lib} ${lib} MODULE ${ARGN}) endmacro(rosbuild_add_library_module) # Explicitly add flags for gtest. We do this here, instead of using # manifest dependencies, because there are situations in which it is # undesirable to link in gtest where's it's not being used. gtest is # part of the "core" build that happens during a 'make' in ros, so we can # assume that's already built. macro(rosbuild_add_gtest_build_flags exe) if (NOT GTEST_FOUND) message(WARNING "GTest not found; C++ tests will fail to build.") endif() if (LIBRARY_OUTPUT_PATH) # add this as GTest builds there set_target_properties(${exe} PROPERTIES LINK_FLAGS "-L${LIBRARY_OUTPUT_PATH}") endif() target_link_libraries(${exe} ${GTEST_LIBRARIES}) link_directories(${GTEST_LIBRARY_DIRS}) rosbuild_declare_test(${exe}) add_dependencies(${exe} gtest gtest_main) endmacro(rosbuild_add_gtest_build_flags) # Declare an executable to be a test harness, which excludes it from the # all target, and adds a dependency to the tests target. macro(rosbuild_declare_test exe) # We provide a 'tests' target that just builds the tests. # Redeclaration of target is to workaround bug in 2.4.6 if(CMAKE_MINOR_VERSION LESS 6) add_custom_target(tests) endif(CMAKE_MINOR_VERSION LESS 6) add_dependencies(tests ${exe}) # Don't build this target with the all target, #3110 set_target_properties(${exe} PROPERTIES EXCLUDE_FROM_ALL TRUE) endmacro(rosbuild_declare_test) # A helper to create test programs. It calls rosbuild_add_executable() to # create the program, and augments a test target that was created in the # call rospack() macro(rosbuild_add_gtest exe) _rosbuild_add_gtest(${ARGV}) # Create a legal target name, in case the target name has slashes in it string(REPLACE "/" "_" _testname ${exe}) # Redeclaration of test target is to workaround bug in 2.4.6 if(CMAKE_MINOR_VERSION LESS 6) add_custom_target(test) endif(CMAKE_MINOR_VERSION LESS 6) add_dependencies(test test_${_testname}) # Register check for test output _rosbuild_check_rostest_xml_result(${_testname} ${rosbuild_test_results_dir}/${PROJECT_NAME}/rostest-${_testname}.xml) endmacro(rosbuild_add_gtest) # A version of add_gtest that checks a label against ROS_BUILD_TEST_LABEL macro(rosbuild_add_gtest_labeled label) if("$ENV{ROS_BUILD_TEST_LABEL}" STREQUAL "" OR "${label}" STREQUAL "$ENV{ROS_BUILD_TEST_LABEL}") rosbuild_add_gtest(${ARGN}) endif("$ENV{ROS_BUILD_TEST_LABEL}" STREQUAL "" OR "${label}" STREQUAL "$ENV{ROS_BUILD_TEST_LABEL}") endmacro(rosbuild_add_gtest_labeled) # A helper to run rostests. It generates a command to run rostest on # the specified file and makes this target a dependency of test. macro(rosbuild_add_rostest file) string(REPLACE "/" "_" _testname ${file}) _rosbuild_add_rostest(${file}) # Redeclaration of target is to workaround bug in 2.4.6 if(CMAKE_MINOR_VERSION LESS 6) add_custom_target(test) endif(CMAKE_MINOR_VERSION LESS 6) add_dependencies(test rostest_${_testname}) _rosbuild_check_rostest_result(rostest_${_testname} ${PROJECT_NAME} ${file}) endmacro(rosbuild_add_rostest) # A version of add_rostest that checks a label against ROS_BUILD_TEST_LABEL macro(rosbuild_add_rostest_labeled label) if("$ENV{ROS_BUILD_TEST_LABEL}" STREQUAL "" OR "${label}" STREQUAL "$ENV{ROS_BUILD_TEST_LABEL}") rosbuild_add_rostest(${ARGN}) endif("$ENV{ROS_BUILD_TEST_LABEL}" STREQUAL "" OR "${label}" STREQUAL "$ENV{ROS_BUILD_TEST_LABEL}") endmacro(rosbuild_add_rostest_labeled) # A helper to run Python unit tests. It generates a command to run python # the specified file macro(rosbuild_add_pyunit file) string(REPLACE "/" "_" _testname ${file}) _rosbuild_add_pyunit(${ARGV}) # Redeclaration of target is to workaround bug in 2.4.6 if(CMAKE_MINOR_VERSION LESS 6) add_custom_target(test) endif(CMAKE_MINOR_VERSION LESS 6) add_dependencies(test pyunit_${_testname}) # Register check for test output _rosbuild_check_rostest_xml_result(${_testname} ${rosbuild_test_results_dir}/${PROJECT_NAME}/rosunit-${_testname}.xml) endmacro(rosbuild_add_pyunit) # A version of add_pyunit that checks a label against ROS_BUILD_TEST_LABEL macro(rosbuild_add_pyunit_labeled label) if("$ENV{ROS_BUILD_TEST_LABEL}" STREQUAL "" OR "${label}" STREQUAL "$ENV{ROS_BUILD_TEST_LABEL}") rosbuild_add_pyunit(${ARGN}) endif("$ENV{ROS_BUILD_TEST_LABEL}" STREQUAL "" OR "${label}" STREQUAL "$ENV{ROS_BUILD_TEST_LABEL}") endmacro(rosbuild_add_pyunit_labeled) # Declare as a unit test a check of a roslaunch file, or a directory # containing roslaunch files. Following the file/directory, you can # specify environment variables as var=val var=val ... macro(rosbuild_add_roslaunch_check file) string(REPLACE "/" "_" _testname ${file}) # Append a unique count to avoid target name collisions when the same # launch file is tested in different environment variable configurations, # #3674. The counter is initialized in rosbuild_init(). set(_targetname roslaunch_check_${_testname}_${ROSBUILD_roslaunch_check_count}) # Increment counter for the next call math(EXPR ROSBUILD_roslaunch_check_count "${ROSBUILD_roslaunch_check_count} + 1") _rosbuild_add_roslaunch_check(${_targetname} ${ARGV}) # Redeclaration of target is to workaround bug in 2.4.6 if(CMAKE_MINOR_VERSION LESS 6) add_custom_target(test) endif(CMAKE_MINOR_VERSION LESS 6) add_dependencies(test ${_targetname}) endmacro(rosbuild_add_roslaunch_check) set(_ROSBUILD_GENERATED_MSG_FILES "") macro(rosbuild_add_generated_msgs) if(ROSBUILD_init_called) message(FATAL_ERROR "rosbuild_add_generated_msgs() cannot be called after rosbuild_init()") endif(ROSBUILD_init_called) list(APPEND _ROSBUILD_GENERATED_MSG_FILES ${ARGV}) endmacro(rosbuild_add_generated_msgs) # Return a list of all msg/.msg files macro(rosbuild_get_msgs msgvar) file(GLOB _msg_files RELATIVE "${PROJECT_SOURCE_DIR}/msg" "${PROJECT_SOURCE_DIR}/msg/*.msg") set(${msgvar} ${_ROSBUILD_GENERATED_MSG_FILES}) # Loop over each .msg file, establishing a rule to compile it foreach(_msg ${_msg_files}) # Make sure we didn't get a bogus match (e.g., .#Foo.msg, which Emacs # might create as a temporary file). the file() # command doesn't take a regular expression, unfortunately. if(${_msg} MATCHES "^[^\\.].*\\.msg$") list(APPEND ${msgvar} ${_msg}) endif(${_msg} MATCHES "^[^\\.].*\\.msg$") endforeach(_msg) endmacro(rosbuild_get_msgs) set(_ROSBUILD_GENERATED_SRV_FILES "") macro(rosbuild_add_generated_srvs) if(ROSBUILD_init_called) message(FATAL_ERROR "rosbuild_add_generated_srvs() cannot be called after rosbuild_init()") endif(ROSBUILD_init_called) list(APPEND _ROSBUILD_GENERATED_SRV_FILES ${ARGV}) endmacro(rosbuild_add_generated_srvs) # Return a list of all srv/.srv files macro(rosbuild_get_srvs srvvar) file(GLOB _srv_files RELATIVE "${PROJECT_SOURCE_DIR}/srv" "${PROJECT_SOURCE_DIR}/srv/*.srv") set(${srvvar} ${_ROSBUILD_GENERATED_SRV_FILES}) # Loop over each .srv file, establishing a rule to compile it foreach(_srv ${_srv_files}) # Make sure we didn't get a bogus match (e.g., .#Foo.srv, which Emacs # might create as a temporary file). the file() # command doesn't take a regular expression, unfortunately. if(${_srv} MATCHES "^[^\\.].*\\.srv$") list(APPEND ${srvvar} ${_srv}) endif(${_srv} MATCHES "^[^\\.].*\\.srv$") endforeach(_srv) endmacro(rosbuild_get_srvs) # Compute msg/srv dependency list, with simple caching macro(rosbuild_gendeps _pkg _msgfile) # Did we already compute it? if(NOT ${_pkg}_${_msgfile}_GENDEPS_COMPUTED) # Call out to the gendeps tool to get full paths to .msg files on # which this one depends, for proper dependency tracking execute_process( COMMAND ${gendeps_exe} ${_input} OUTPUT_VARIABLE __other_msgs ERROR_VARIABLE __rospack_err_ignore OUTPUT_STRIP_TRAILING_WHITESPACE) # For some reason, the output from gendeps has escaped spaces in it. # Converting to a string and then back to a list removes them. _rosbuild_list_to_string(${_pkg}_${_msgfile}_GENDEPS "${__other_msgs}") separate_arguments(${_pkg}_${_msgfile}_GENDEPS) set(${_pkg}_${_msgfile}_GENDEPS_COMPUTED Y) endif(NOT ${_pkg}_${_msgfile}_GENDEPS_COMPUTED) endmacro(rosbuild_gendeps) # gensrv processes srv/*.srv files into language-specific source files macro(rosbuild_gensrv) # roslang_PACKAGE_PATH was set in rosbuild_init(), if roslang was found if(NOT roslang_PACKAGE_PATH) _rosbuild_warn("rosbuild_gensrv() was called, but the roslang package cannot be found. Service generation will NOT occur") endif(NOT roslang_PACKAGE_PATH) # Check whether there are any .srv files rosbuild_get_srvs(_srvlist) if(NOT _srvlist) _rosbuild_warn("rosbuild_gensrv() was called, but no .srv files were found") else(NOT _srvlist) file(WRITE ${PROJECT_SOURCE_DIR}/srv_gen/generated "yes") # Now set the mtime to something consistent. We only want whether or not this file exists to matter # But we set it to the current time, because setting it to zero causes # annoying warning, #3396. execute_process( COMMAND ${PYTHON_EXECUTABLE} -c "import os; os.utime('${PROJECT_SOURCE_DIR}/srv_gen/generated', (1, 1))" ERROR_VARIABLE _set_mtime_error RESULT_VARIABLE _set_mtime_failed OUTPUT_STRIP_TRAILING_WHITESPACE) if(_set_mtime_failed) message("[rosbuild] Error from calling to Python to set the mtime on ${PROJECT_SOURCE_DIR}/srv_gen/generated:") message("${_mtime_error}") message(FATAL_ERROR "[rosbuild] Failed to set mtime; aborting") endif(_set_mtime_failed) endif(NOT _srvlist) # Create target to trigger service generation in the case where no libs # or executables are made. add_custom_target(rospack_gensrv_all ALL) add_dependencies(rospack_gensrv_all rospack_gensrv) # Make the precompile target, on which libraries and executables depend, # depend on the message generation. add_dependencies(rosbuild_precompile rospack_gensrv) # add in the directory that will contain the auto-generated .h files include_directories(${PROJECT_SOURCE_DIR}/srv_gen/cpp/include) endmacro(rosbuild_gensrv) # genmsg processes msg/*.msg files into language-specific source files macro(rosbuild_genmsg) # roslang_PACKAGE_PATH was set in rosbuild_init(), if roslang was found if(NOT roslang_PACKAGE_PATH) _rosbuild_warn("rosbuild_genmsg() was called, but the roslang package cannot be found. Message generation will NOT occur") endif(NOT roslang_PACKAGE_PATH) # Check whether there are any .srv files rosbuild_get_msgs(_msglist) if(NOT _msglist) _rosbuild_warn("rosbuild_genmsg() was called, but no .msg files were found") else(NOT _msglist) file(WRITE ${PROJECT_SOURCE_DIR}/msg_gen/generated "yes") # Now set the mtime to something consistent. We only want whether or not this file exists to matter # But we set it to the current time, because setting it to zero causes # annoying warning, #3396. execute_process( COMMAND ${PYTHON_EXECUTABLE} -c "import os; os.utime('${PROJECT_SOURCE_DIR}/msg_gen/generated', (1, 1))" ERROR_VARIABLE _set_mtime_error RESULT_VARIABLE _set_mtime_failed OUTPUT_STRIP_TRAILING_WHITESPACE) if(_set_mtime_failed) message("[rosbuild] Error from calling to Python to set the mtime on ${PROJECT_SOURCE_DIR}/msg_gen/generated:") message("${_mtime_error}") message(FATAL_ERROR "[rosbuild] Failed to set mtime; aborting") endif(_set_mtime_failed) endif(NOT _msglist) # Create target to trigger message generation in the case where no libs # or executables are made. add_custom_target(rospack_genmsg_all ALL) add_dependencies(rospack_genmsg_all rospack_genmsg) # Make the precompile target, on which libraries and executables depend, # depend on the message generation. add_dependencies(rosbuild_precompile rospack_genmsg) # add in the directory that will contain the auto-generated .h files include_directories(${PROJECT_SOURCE_DIR}/msg_gen/cpp/include) endmacro(rosbuild_genmsg) macro(rosbuild_add_boost_directories) set(_sysroot "--sysroot=${CMAKE_FIND_ROOT_PATH}") execute_process(COMMAND "rosboost-cfg" ${_sysroot} ${_rosbuild_multiarch} "--include_dirs" OUTPUT_VARIABLE BOOST_INCLUDE_DIRS RESULT_VARIABLE _boostcfg_failed OUTPUT_STRIP_TRAILING_WHITESPACE) if (_boostcfg_failed) message(FATAL_ERROR "rosboost-cfg ${_rosbuild_multiarch} --include_dirs failed") endif(_boostcfg_failed) set(_sysroot "--sysroot=${CMAKE_FIND_ROOT_PATH}") execute_process(COMMAND "rosboost-cfg" ${_sysroot} ${_rosbuild_multiarch} "--lib_dirs" OUTPUT_VARIABLE BOOST_LIB_DIRS RESULT_VARIABLE _boostcfg_failed OUTPUT_STRIP_TRAILING_WHITESPACE) if (_boostcfg_failed) message(FATAL_ERROR "rosboost-cfg ${_rosbuild_multiarch} --lib_dirs failed") endif(_boostcfg_failed) add_definitions(-DBOOST_CB_DISABLE_DEBUG) include_directories(${BOOST_INCLUDE_DIRS}) link_directories(${BOOST_LIB_DIRS}) endmacro(rosbuild_add_boost_directories) macro(rosbuild_link_boost target) set(_libs "") set(_first 1) foreach(arg ${ARGN}) if (_first) set(_first 0) set(_libs "${arg}") else(_first) set(_libs "${_libs},${arg}") endif(_first) endforeach(arg) set(_sysroot "--sysroot=${CMAKE_FIND_ROOT_PATH}") # We ask for --lflags, as recommended in #3773. This means that we might # pass non-library arguments to target_link_libraries() below, but CMake # doesn't seem to mind. execute_process(COMMAND "rosboost-cfg" ${_sysroot} ${_rosbuild_multiarch} "--lflags" ${_libs} OUTPUT_VARIABLE BOOST_LIBS ERROR_VARIABLE _boostcfg_error RESULT_VARIABLE _boostcfg_failed OUTPUT_STRIP_TRAILING_WHITESPACE) if (_boostcfg_failed) message(FATAL_ERROR "[rosboost-cfg ${_rosbuild_multiarch} --libs ${_libs}] failed with error: ${_boostcfg_error}") endif(_boostcfg_failed) separate_arguments(BOOST_LIBS) target_link_libraries(${target} ${BOOST_LIBS}) endmacro(rosbuild_link_boost) # Macro to download data on the tests target # The real signature is: #macro(rosbuild_download_test_data _url _filename _md5) macro(rosbuild_download_test_data _url _filename) if("${ARGN}" STREQUAL "") _rosbuild_warn("The 2-argument rosbuild_download_test_data(url file) is deprecated; please switch to the 3-argument form, supplying an md5sum for the file: rosbuild_download_test_data(url file md5)") endif("${ARGN}" STREQUAL "") # Create a legal target name, in case the target name has slashes in it string(REPLACE "/" "_" _testname download_data_${_filename}) add_custom_command(OUTPUT ${PROJECT_SOURCE_DIR}/${_filename} COMMAND $ENV{ROS_ROOT}/core/rosbuild/bin/download_checkmd5.py ${_url} ${PROJECT_SOURCE_DIR}/${_filename} ${ARGN} VERBATIM) add_custom_target(${_testname} DEPENDS ${PROJECT_SOURCE_DIR}/${_filename}) # Redeclaration of target is to workaround bug in 2.4.6 if(CMAKE_MINOR_VERSION LESS 6) add_custom_target(tests) endif(CMAKE_MINOR_VERSION LESS 6) add_dependencies(tests ${_testname}) endmacro(rosbuild_download_test_data) # There's an optional 3rd arg, which is a target that should be made to # depend on the result of untarring the file (can be ALL). macro(rosbuild_untar_file _filename _unpacked_name) get_filename_component(unpack_dir ${_filename} PATH) # Check whether the filename has a directory component, #3034 if(NOT unpack_dir) set(unpack_dir ${PROJECT_SOURCE_DIR}) endif(NOT unpack_dir) add_custom_command(OUTPUT ${PROJECT_SOURCE_DIR}/${_unpacked_name} COMMAND rm -rf ${PROJECT_SOURCE_DIR}/${_unpacked_name} COMMAND tar xvCf ${unpack_dir} ${PROJECT_SOURCE_DIR}/${_filename} COMMAND touch -c ${PROJECT_SOURCE_DIR}/${_unpacked_name} DEPENDS ${PROJECT_SOURCE_DIR}/${_filename} WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} VERBATIM) string(REPLACE "/" "_" _target_name untar_file_${_filename}_${_unpacked_name}) if("${ARGN}" STREQUAL "ALL") add_custom_target(${_target_name} ALL DEPENDS ${PROJECT_SOURCE_DIR}/${_unpacked_name}) else("${ARGN}" STREQUAL "ALL") add_custom_target(${_target_name} DEPENDS ${PROJECT_SOURCE_DIR}/${_unpacked_name}) if(NOT "${ARGN}" STREQUAL "") # Redeclaration of target is to workaround bug in 2.4.6 if(CMAKE_MINOR_VERSION LESS 6) add_custom_target(${ARGN}) endif(CMAKE_MINOR_VERSION LESS 6) add_dependencies(${ARGN} ${_target_name}) endif(NOT "${ARGN}" STREQUAL "") endif("${ARGN}" STREQUAL "ALL") endmacro(rosbuild_untar_file) # Macro to download data on the all target # The real signature is: #macro(rosbuild_download_data _url _filename _md5) macro(rosbuild_download_data _url _filename) if("${ARGN}" STREQUAL "") _rosbuild_warn("The 2-argument rosbuild_download_data(url file) is deprecated; please switch to the 3-argument form, supplying an md5sum for the file: rosbuild_download_data(url file md5)") endif("${ARGN}" STREQUAL "") # Create a legal target name, in case the target name has slashes in it string(REPLACE "/" "_" _testname download_data_${_filename}) add_custom_command(OUTPUT ${PROJECT_SOURCE_DIR}/${_filename} COMMAND $ENV{ROS_ROOT}/core/rosbuild/bin/download_checkmd5.py ${_url} ${PROJECT_SOURCE_DIR}/${_filename} ${ARGN} VERBATIM) add_custom_target(${_testname} ALL DEPENDS ${PROJECT_SOURCE_DIR}/${_filename}) endmacro(rosbuild_download_data) macro(rosbuild_add_openmp_flags target) # Bullseye's wrappers appear to choke on OpenMP pragmas. So if # ROS_TEST_COVERAGE is set (which indicates that we're doing a coverage # build with Bullseye), we make this macro a no-op. if("$ENV{ROS_TEST_COVERAGE}" STREQUAL "1") _rosbuild_warn("because ROS_TEST_COVERAGE is set, OpenMP support is disabled") else("$ENV{ROS_TEST_COVERAGE}" STREQUAL "1") # First, try to use the standard FindOpenMP module (#3184). If that # fails, fall back on manual detection. I don't know why the standard # detection would ever fail; it's possible that the manual # detection is now vestigial and could be removed. include(FindOpenMP) if(${OPENMP_FOUND} STREQUAL "TRUE") rosbuild_add_compile_flags(${target} ${OpenMP_C_FLAGS}) rosbuild_add_link_flags(${target} ${OpenMP_C_FLAGS}) else(${OPENMP_FOUND} STREQUAL "TRUE") # list of OpenMP flags to check set(_rospack_check_openmp_flags "-fopenmp" # gcc "-openmp" # icc "-mp" # SGI & PGI "-xopenmp" # Sun "-omp" # Tru64 "-qsmp=omp" # AIX ) # backup for a variable we will change set(_rospack_openmp_flags_backup ${CMAKE_REQUIRED_FLAGS}) # mark the fact we do not yet know the flag set(_rospack_openmp_flag_found FALSE) set(_rospack_openmp_flag_value) # find an OpenMP flag that works foreach(_rospack_openmp_test_flag ${_rospack_check_openmp_flags}) if(NOT _rospack_openmp_flag_found) set(CMAKE_REQUIRED_FLAGS ${_rospack_openmp_test_flag}) check_function_exists(omp_set_num_threads _rospack_openmp_function_found${_rospack_openmp_test_flag}) if(_rospack_openmp_function_found${_rospack_openmp_test_flag}) set(_rospack_openmp_flag_value ${_rospack_openmp_test_flag}) set(_rospack_openmp_flag_found TRUE) endif(_rospack_openmp_function_found${_rospack_openmp_test_flag}) endif(NOT _rospack_openmp_flag_found) endforeach(_rospack_openmp_test_flag ${_rospack_check_openmp_flags}) # restore the CMake variable set(CMAKE_REQUIRED_FLAGS ${_rospack_openmp_flags_backup}) # add the flags or warn if(_rospack_openmp_flag_found) rosbuild_add_compile_flags(${target} ${_rospack_openmp_flag_value}) rosbuild_add_link_flags(${target} ${_rospack_openmp_flag_value}) else(_rospack_openmp_flag_found) message("WARNING: OpenMP compile flag not found") endif(_rospack_openmp_flag_found) endif(${OPENMP_FOUND} STREQUAL "TRUE") endif("$ENV{ROS_TEST_COVERAGE}" STREQUAL "1") endmacro(rosbuild_add_openmp_flags) macro(rosbuild_make_distribution) # Noop. This logic is handled in Python instead. endmacro(rosbuild_make_distribution) # Compute the number of hardware cores on the machine. Intended to use for # gating tests that have heavy processor requirements. include($ENV{ROS_ROOT}/core/rosbuild/ProcessorCount.cmake) macro(rosbuild_count_cores num) ProcessorCount(${num}) endmacro(rosbuild_count_cores) # Check whether we're running as a VM Intended to use for # gating tests that have heavy processor requirements. It checks for # /proc/xen macro(rosbuild_check_for_vm var) set(_xen_dir _xen_dir-NOTFOUND) find_file(_xen_dir "xen" PATHS "/proc" NO_DEFAULT_PATH) if(_xen_dir) set(${var} 1) else(_xen_dir) set(${var} 0) endif(_xen_dir) endmacro(rosbuild_check_for_vm var) # Check whether there's an X display. Intended to use in gating tests that # require a display. macro(rosbuild_check_for_display var) execute_process(COMMAND "xdpyinfo" OUTPUT_VARIABLE _dummy ERROR_VARIABLE _dummy RESULT_VARIABLE _xdpyinfo_failed) if(_xdpyinfo_failed) set(${var} 0) else(_xdpyinfo_failed) set(${var} 1) endif(_xdpyinfo_failed) endmacro(rosbuild_check_for_display) macro(rosbuild_add_swigpy_library target lib) rosbuild_add_library(${target} ${ARGN}) # swig python needs a shared library named _.[so|dll|...] # this renames the output file to conform to that by prepending # an underscore in place of the "lib" prefix. # If on Darwin, force the suffix so ".so", because the MacPorts # version of Python won't find _foo.dylib for 'import _foo' if(APPLE) set_target_properties(${target} PROPERTIES OUTPUT_NAME ${lib} PREFIX "_" SUFFIX ".so") else(APPLE) set_target_properties(${target} PROPERTIES OUTPUT_NAME ${lib} PREFIX "_") endif(APPLE) endmacro(rosbuild_add_swigpy_library) macro(rosbuild_check_for_sse) # check for SSE extensions include(CheckCXXSourceRuns) if( CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX ) set(SSE_FLAGS) set(CMAKE_REQUIRED_FLAGS "-msse3") check_cxx_source_runs(" #include int main() { __m128d a, b; double vals[2] = {0}; a = _mm_loadu_pd(vals); b = _mm_hadd_pd(a,a); _mm_storeu_pd(vals, b); return 0; }" HAS_SSE3_EXTENSIONS) set(CMAKE_REQUIRED_FLAGS "-msse2") check_cxx_source_runs(" #include int main() { __m128d a, b; double vals[2] = {0}; a = _mm_loadu_pd(vals); b = _mm_add_pd(a,a); _mm_storeu_pd(vals,b); return 0; }" HAS_SSE2_EXTENSIONS) set(CMAKE_REQUIRED_FLAGS "-msse") check_cxx_source_runs(" #include int main() { __m128 a, b; float vals[4] = {0}; a = _mm_loadu_ps(vals); b = a; b = _mm_add_ps(a,b); _mm_storeu_ps(vals,b); return 0; }" HAS_SSE_EXTENSIONS) set(CMAKE_REQUIRED_FLAGS) if(HAS_SSE3_EXTENSIONS) set(SSE_FLAGS "-msse3 -mfpmath=sse") message(STATUS "[rosbuild] Found SSE3 extensions, using flags: ${SSE_FLAGS}") elseif(HAS_SSE2_EXTENSIONS) set(SSE_FLAGS "-msse2 -mfpmath=sse") message(STATUS "[rosbuild] Found SSE2 extensions, using flags: ${SSE_FLAGS}") elseif(HAS_SSE_EXTENSIONS) set(SSE_FLAGS "-msse -mfpmath=sse") message(STATUS "[rosbuild] Found SSE extensions, using flags: ${SSE_FLAGS}") endif() elseif(MSVC) check_cxx_source_runs(" #include int main() { __m128d a, b; double vals[2] = {0}; a = _mm_loadu_pd(vals); b = _mm_add_pd(a,a); _mm_storeu_pd(vals,b); return 0; }" HAS_SSE2_EXTENSIONS) if( HAS_SSE2_EXTENSIONS ) message(STATUS "[rosbuild] Found SSE2 extensions") set(SSE_FLAGS "/arch:SSE2 /fp:fast -D__SSE__ -D__SSE2__" ) endif() endif() endmacro(rosbuild_check_for_sse) macro(rosbuild_include pkg module) # Find exported cmake directories rosbuild_invoke_rospack(rosbuild _rosbuild EXPORTS plugins --attrib=cmake_directory --top=${_project}) string(REGEX REPLACE "\n" ";" _rosbuild_EXPORTS_stripped "${_rosbuild_EXPORTS}") list(LENGTH _rosbuild_EXPORTS_stripped _rosbuild_EXPORTS_stripped_length) set(_idx 0) set(_found False) while(_idx LESS ${_rosbuild_EXPORTS_stripped_length} AND NOT _found) list(GET _rosbuild_EXPORTS_stripped ${_idx} _pkg) math(EXPR _idx "${_idx} + 1") list(GET _rosbuild_EXPORTS_stripped ${_idx} _dir) if("${_pkg}" STREQUAL "${pkg}") message("[rosbuild] Including ${_dir}/${module}.cmake") # Add this directory to CMake's search path, so that included files # can include other files in a relative manner, #2813. if(NOT CMAKE_MODULE_PATH MATCHES ${_dir}) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${_dir}) endif() include(${_dir}/${module}.cmake) # Poor man's break set(_found True) endif("${_pkg}" STREQUAL "${pkg}") math(EXPR _idx "${_idx} + 1") endwhile(_idx LESS ${_rosbuild_EXPORTS_stripped_length} AND NOT _found) if(NOT _found) message(FATAL_ERROR "[rosbuild] Failed to include ${module} from ${pkg}") endif(NOT _found) endmacro(rosbuild_include) macro(rosbuild_get_package_version _var pkgname) execute_process( COMMAND rosstack contains ${pkgname} ERROR_VARIABLE __rosstack_err_ignore OUTPUT_VARIABLE __stack RESULT_VARIABLE _rosstack_failed OUTPUT_STRIP_TRAILING_WHITESPACE) if(_rosstack_failed OR NOT __stack) message(FATAL_ERROR "[rosbuild] Failed to find stack containing package ${pkgname}") else(_rosstack_failed OR NOT __stack) rosbuild_get_stack_version(${_var} ${__stack}) endif(_rosstack_failed OR NOT __stack) endmacro(rosbuild_get_package_version) macro(rosbuild_get_stack_version _var stackname) execute_process( COMMAND rosversion ${stackname} ERROR_VARIABLE __rosversion_err_ignore OUTPUT_VARIABLE __version RESULT_VARIABLE _rosversion_failed OUTPUT_STRIP_TRAILING_WHITESPACE) if(_rosversion_failed OR NOT __version) message(FATAL_ERROR "[rosbuild] Failed to find version of stack ${stackname}") else(_rosversion_failed OR NOT __version) set(${_var} ${__version}) endif(_rosversion_failed OR NOT __version) endmacro(rosbuild_get_stack_version _var stackname) # *_future() calls are deprecated macro(rosbuild_add_gtest_future exe) _rosbuild_warn("The *_future() macros are deprecated.") # Still need to create the executable, just in case somebody is using # this macro, then doing something that refers to the executable target. _rosbuild_add_gtest(${ARGV}) endmacro(rosbuild_add_gtest_future) macro(rosbuild_add_rostest_future file) _rosbuild_warn("The *_future() macros are deprecated.") endmacro(rosbuild_add_rostest_future) macro(rosbuild_add_pyunit_future file) _rosbuild_warn("The *_future() macros are deprecated.") endmacro(rosbuild_add_pyunit_future) ros-1.15.8/core/rosbuild/core/rosbuild/rosbuild.cmake000066400000000000000000000026071407615046500226010ustar00rootroot00000000000000 cmake_minimum_required(VERSION 2.4.6) # # Catkin-compat thunks # cmake_policy(SET CMP0011 OLD) macro(rosbuild_catkinize) endmacro() # Policy settings to prevent warnings on 2.6 but ensure proper operation on # 2.4. if(COMMAND cmake_policy) # Logical target names must be globally unique. cmake_policy(SET CMP0002 OLD) # Libraries linked via full path no longer produce linker search paths. cmake_policy(SET CMP0003 OLD) # Preprocessor definition values are now escaped automatically. cmake_policy(SET CMP0005 OLD) if(POLICY CMP0011) # Included scripts do automatic cmake_policy PUSH and POP. cmake_policy(SET CMP0011 OLD) endif(POLICY CMP0011) endif(COMMAND cmake_policy) set(CMAKE_OSX_ARCHITECTURES "x86_64") ############################################################################## # First things first: we must have rospack. But only look at PATH, #3831 find_program(ROSPACK_EXE NAMES rospack DOC "rospack executable" NO_CMAKE_PATH NO_CMAKE_ENVIRONMENT_PATH NO_CMAKE_SYSTEM_PATH) if (NOT ROSPACK_EXE) message(FATAL_ERROR "Couldn't find rospack. Please run 'make' in $ROS_ROOT") endif(NOT ROSPACK_EXE) ############################################################################## # Load private macros (not to be used externally) include($ENV{ROS_ROOT}/core/rosbuild/private.cmake) # Load public macros (developer's API) include($ENV{ROS_ROOT}/core/rosbuild/public.cmake) ros-1.15.8/core/rosbuild/core/rosbuild/rosconfig.cmake000066400000000000000000000100371407615046500227430ustar00rootroot00000000000000# DO NOT EDIT THIS FILE # To change your build configuration, create a file called # 'rosconfig.cmake' and put it where it will be loaded from here. # The order of processing is the following, with later steps overriding # earlier ones: # - read the beginning of the package's CMakeLists.txt (i.e., the # content before the invocation of rosbuild_init()), # which is how we get here # - read this file # - if present, read $(ROS_ROOT)/core/rosbuild/rosconfig.cmake # - if present, read rosconfig.cmake from the current packages's top-level # directory. # Unset variables, to force cmake to go looking for the rosconfig.cmake # again (as opposed to looking up the variables' values in the cache). This # specifically avoids build failures when a rosconfig.cmake was created, # then removed, #617. set(USERCONFIG USERCONFIG-NOTFOUND) set(PROJECTCONFIG PROJECTCONFIG-NOTFOUND) ############################################################# # look for user's override in $ROS_ROOT/core/rosbuild/rosconfig.cmake find_file(USERCONFIG rosconfig.cmake PATHS ENV ROS_ROOT NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH) if(USERCONFIG) message("including user's config file: ${USERCONFIG}") include(${USERCONFIG}) endif(USERCONFIG) # look for user's override in rosconfig.cmake in current package directory find_file(PROJECTCONFIG rosconfig.cmake PATHS ${PROJECT_SOURCE_DIR} NO_DEFAULT_PATH) if(PROJECTCONFIG) message("including package's config file: ${PROJECTCONFIG}") include(${PROJECTCONFIG}) endif(PROJECTCONFIG) ############################################################# ############################################################# # These are default ROS-wide build configuration settings for CMake. These # settings are used wherever rospack() is done in a # CMakeLists.txt file. Note that these setting only affect packages # that are built with CMake. # Set the build type. Options are: # Debug : w/ debug symbols, w/o optimization # Release : w/o debug symbols, w/ optimization # RelWithDebInfo : w/ debug symbols, w/ optimization # RelWithAsserts : w/o debug symbols, w/ optimization # MinSizeRel : w/o debug symbols, w/ optimization, stripped binaries if(NOT DEFINED ROS_BUILD_TYPE) set(ROS_BUILD_TYPE RelWithDebInfo) endif(NOT DEFINED ROS_BUILD_TYPE) # Build static-only executables (e.g., for copying over to another # machine)? true or false if(NOT DEFINED ROS_BUILD_STATIC_EXES) set(ROS_BUILD_STATIC_EXES false) endif(NOT DEFINED ROS_BUILD_STATIC_EXES) # Build shared libs? true or false if(NOT DEFINED ROS_BUILD_SHARED_LIBS) set(ROS_BUILD_SHARED_LIBS true) endif(NOT DEFINED ROS_BUILD_SHARED_LIBS) # Build static libs? true or false if(NOT DEFINED ROS_BUILD_STATIC_LIBS) set(ROS_BUILD_STATIC_LIBS false) endif(NOT DEFINED ROS_BUILD_STATIC_LIBS) # Default compile flags for all source files include(CheckCXXCompilerFlag) if(NOT DEFINED ROS_COMPILE_FLAGS) set(ROS_COMPILE_FLAGS "-W -Wall -Wno-unused-parameter -fno-strict-aliasing") # Old versions of gcc need -pthread to enable threading, #2095. # Also, some linkers, e.g., goLD, require -pthread (or another way to # generate -lpthread). # CYGWIN gcc has their -pthread disabled if(UNIX AND NOT CYGWIN) set(ROS_COMPILE_FLAGS "${ROS_COMPILE_FLAGS} -pthread") endif(UNIX AND NOT CYGWIN) endif(NOT DEFINED ROS_COMPILE_FLAGS) # Default link flags for all executables and libraries if(NOT DEFINED ROS_LINK_FLAGS) set(ROS_LINK_FLAGS "") # Old versions of gcc need -pthread to enable threading, #2095. # Also, some linkers, e.g., goLD, require -pthread (or another way to # generate -lpthread). # CYGWIN gcc has their -pthread disabled if(UNIX AND NOT CYGWIN) set(ROS_LINK_FLAGS "${ROS_LINK_FLAGS} -pthread") endif(UNIX AND NOT CYGWIN) endif(NOT DEFINED ROS_LINK_FLAGS) # Default libraries to link against for all executables and libraries if(NOT DEFINED ROS_LINK_LIBS) set(ROS_LINK_LIBS "") endif(NOT DEFINED ROS_LINK_LIBS) ############################################################# ros-1.15.8/core/rosbuild/core/rosbuild/rostoolchain.cmake000066400000000000000000000024251407615046500234600ustar00rootroot00000000000000# DO NOT EDIT THIS FILE # # To set up cross-compilation, create the file # $(ROS_ROOT)/rostoolchain.cmake. It gets read first, prior to # any of cmake's system tests. ############################################################# # # An example for using the gumstix arm-linux toolchain is below. # Copy these lines to $(ROS_ROOT)/rostoolchain.cmake to try them out. # #set(CMAKE_SYSTEM_NAME Linux) #set(CMAKE_C_COMPILER /opt/arm-linux/bin/arm-linux-gcc) #set(CMAKE_CXX_COMPILER /opt/arm-linux/bin/arm-linux-g++) #set(CMAKE_FIND_ROOT_PATH /opt/arm-linux) # Have to set this one to BOTH, to allow CMake to find rospack #set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM BOTH) #set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) #set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) ############################################################# # Cross-compilation loader # # This file is passed to cmake on the command line via # -DCMAKE_TOOLCHAIN_FILE. ############################################################# # look for user's toolchain file in $ROS_ROOT/rostoolchain.cmake find_file(TOOLCHAINCONFIG rostoolchain.cmake PATHS ENV ROS_ROOT NO_DEFAULT_PATH) if(TOOLCHAINCONFIG) include(${TOOLCHAINCONFIG}) endif(TOOLCHAINCONFIG) ############################################################# ros-1.15.8/core/rosbuild/env-hooks/000077500000000000000000000000001407615046500171055ustar00rootroot00000000000000ros-1.15.8/core/rosbuild/env-hooks/10.rosbuild.bat.em000066400000000000000000000005661407615046500222460ustar00rootroot00000000000000REM generated from rosbuild/env-hooks/10.rosbuild.bat.em @[if DEVELSPACE]@ REM env variables in develspace set ROS_ROOT=@(CMAKE_CURRENT_SOURCE_DIR) @[else]@ REM env variables in installspace if "%CATKIN_ENV_HOOK_WORKSPACE%"=="" set CATKIN_ENV_HOOK_WORKSPACE=@(CMAKE_INSTALL_PREFIX) set ROS_ROOT=%CATKIN_ENV_HOOK_WORKSPACE%/@(CATKIN_GLOBAL_SHARE_DESTINATION)/ros @[end if]@ ros-1.15.8/core/rosbuild/env-hooks/10.rosbuild.sh.em000066400000000000000000000006031407615046500221020ustar00rootroot00000000000000# generated from rosbuild/env-hooks/10.rosbuild.sh.em @[if DEVELSPACE]@ # env variables in develspace export ROS_ROOT="@(CMAKE_CURRENT_SOURCE_DIR)" @[else]@ # env variables in installspace if [ -z "$CATKIN_ENV_HOOK_WORKSPACE" ]; then CATKIN_ENV_HOOK_WORKSPACE="@(CMAKE_INSTALL_PREFIX)" fi export ROS_ROOT="$CATKIN_ENV_HOOK_WORKSPACE/@(CATKIN_GLOBAL_SHARE_DESTINATION)/ros" @[end if]@ ros-1.15.8/core/rosbuild/package.xml000066400000000000000000000015521407615046500173140ustar00rootroot00000000000000 rosbuild 1.15.8 rosbuild contains scripts for managing the CMake-based build system for ROS. Michel Hidalgo Jacob Perron BSD http://ros.org/wiki/rosbuild Brian Gerkey Troy Straszheim Morgan Quigley Dirk Thomas catkin pkg-config catkin message_generation message_runtime ros-1.15.8/core/rosbuild/tests/000077500000000000000000000000001407615046500163365ustar00rootroot00000000000000ros-1.15.8/core/rosbuild/tests/count_cores.py000077500000000000000000000001341407615046500212340ustar00rootroot00000000000000#!/usr/bin/env python import os print(os.sysconf(os.sysconf_names['SC_NPROCESSORS_ONLN'])) ros-1.15.8/core/roslang/000077500000000000000000000000001407615046500150165ustar00rootroot00000000000000ros-1.15.8/core/roslang/CHANGELOG.rst000066400000000000000000000050661407615046500170460ustar00rootroot00000000000000^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Changelog for package roslang ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 1.15.8 (2021-07-21) ------------------- * Update maintainers (`#272 `_) * Contributors: Jacob Perron 1.15.7 (2020-09-28) ------------------- 1.15.6 (2020-07-20) ------------------- 1.15.5 (2020-07-06) ------------------- 1.15.4 (2020-05-28) ------------------- 1.15.3 (2020-05-14) ------------------- 1.15.2 (2020-04-07) ------------------- 1.15.1 (2020-03-17) ------------------- 1.15.0 (2020-02-11) ------------------- 1.14.8 (2020-02-11) ------------------- * Bump CMake version to avoid CMP0048 warning (`#234 `_) 1.14.7 (2019-10-03) ------------------- 1.14.6 (2019-03-18) ------------------- 1.14.5 (2019-03-04) ------------------- 1.14.4 (2018-05-01) ------------------- 1.14.3 (2018-01-30) ------------------- 1.14.2 (2017-10-26) ------------------- 1.14.1 (2017-07-27) ------------------- 1.14.0 (2017-02-22) ------------------- 1.13.6 (2017-10-31) ------------------- 1.13.5 (2017-02-14) ------------------- 1.13.4 (2016-09-19) ------------------- 1.13.3 (2016-09-16) ------------------- 1.13.2 (2016-09-02) ------------------- 1.13.1 (2016-03-13) ------------------- 1.13.0 (2016-03-10) ------------------- 1.12.6 (2016-03-10) ------------------- 1.12.5 (2015-10-13) ------------------- 1.12.4 (2015-10-12) ------------------- 1.12.3 (2015-09-19) ------------------- 1.12.2 (2015-04-27) ------------------- 1.12.1 (2015-04-16) ------------------- 1.12.0 (2014-12-26) ------------------- 1.11.6 (2014-12-22) ------------------- 1.11.5 (2014-08-18) ------------------- 1.11.4 (2014-07-23) ------------------- 1.11.3 (2014-07-18) ------------------- 1.11.2 (2014-06-16) ------------------- 1.11.1 (2014-05-07) ------------------- 1.11.0 (2014-01-31) ------------------- 1.10.9 (2014-01-07) ------------------- 1.10.8 (2013-10-15) ------------------- 1.10.7 (2013-10-04) ------------------- 1.10.6 (2013-08-22) ------------------- 1.10.5 (2013-08-21) ------------------- 1.10.4 (2013-07-05) ------------------- 1.10.3 (2013-07-03) ------------------- 1.10.2 (2013-06-18) ------------------- 1.10.1 (2013-06-06) ------------------- 1.10.0 (2013-03-22 09:23) ------------------------- 1.9 (Groovy) ============ 1.9.44 (2013-03-13) ------------------- 1.9.43 (2013-03-08) ------------------- 1.9.42 (2013-01-25) ------------------- 1.9.41 (2013-01-24) ------------------- 1.9.40 (2013-01-13) ------------------- 1.9.39 (2012-12-30) ------------------- * first public release for Groovy ros-1.15.8/core/roslang/CMakeLists.txt000066400000000000000000000003021407615046500175510ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.0.2) project(roslang) find_package(catkin REQUIRED) catkin_package() install(FILES cmake/roslang.cmake DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}/cmake) ros-1.15.8/core/roslang/cmake/000077500000000000000000000000001407615046500160765ustar00rootroot00000000000000ros-1.15.8/core/roslang/cmake/roslang.cmake000066400000000000000000000033401407615046500205450ustar00rootroot00000000000000# Figure out which languages we're building for. "rospack langs" will # return a list of packages that: # - depend directly on roslang # - are not in the env var ROS_LANG_DISABLE rosbuild_invoke_rospack("" _roslang LANGS langs) separate_arguments(_roslang_LANGS) # Iterate over the languages, retrieving any exported cmake fragment from # each one. set(_cmake_fragments) foreach(_l ${_roslang_LANGS}) # Get the roslang attributes from this package. # cmake rosbuild_invoke_rospack(${_l} ${_l} CMAKE export --lang=roslang --attrib=cmake) if(${_l}_CMAKE) foreach(_f ${${_l}_CMAKE}) list(APPEND _cmake_fragments ${_f}) endforeach(_f) endif(${_l}_CMAKE) endforeach(_l) # Hack to resolve languages from wet which rospack does not support yet find_package(catkin QUIET COMPONENTS genmsg) if(genmsg_FOUND) foreach(_l ${CATKIN_MESSAGE_GENERATORS}) string(REPLACE "gen" "ros" _l ${_l}) rosbuild_find_ros_package(${_l}) if(${_l}_PACKAGE_PATH) set(_cmake_fragment ${${_l}_PACKAGE_PATH}/rosbuild/${_l}.cmake) if(EXISTS ${_cmake_fragment}) list(APPEND _cmake_fragments ${_cmake_fragment}) endif() endif(${_l}_PACKAGE_PATH) endforeach(_l) endif() # Now include them all foreach(_f ${_cmake_fragments}) if(NOT EXISTS ${_f}) message(FATAL_ERROR "Cannot include non-existent exported cmake file ${_f}") endif(NOT EXISTS ${_f}) # Include this cmake fragment; presumably it will do / # provide something useful. Only include each file once (a file # might be multiply referenced because of package dependencies # dependencies). if(NOT ${_f}_INCLUDED) message("[rosbuild] Including ${_f}") include(${_f}) set(${_f}_INCLUDED Y) endif(NOT ${_f}_INCLUDED) endforeach(_f) ros-1.15.8/core/roslang/package.xml000066400000000000000000000014101407615046500171270ustar00rootroot00000000000000 roslang 1.15.8 roslang is a common package that all ROS client libraries depend on. This is mainly used to find client libraries (via 'rospack depends-on1 roslang'). Michel Hidalgo Jacob Perron BSD http://ros.org/wiki/roslang Brian Gerkey Dirk Thomas catkin catkin genmsg ros-1.15.8/core/roslib/000077500000000000000000000000001407615046500146435ustar00rootroot00000000000000ros-1.15.8/core/roslib/CHANGELOG.rst000066400000000000000000000146761407615046500167020ustar00rootroot00000000000000^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Changelog for package roslib ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 1.15.8 (2021-07-21) ------------------- * Fix spelling (`#277 `_) * Update maintainers (`#272 `_) * Contributors: Jacob Perron, freddii 1.15.7 (2020-09-28) ------------------- 1.15.6 (2020-07-20) ------------------- 1.15.5 (2020-07-06) ------------------- 1.15.4 (2020-05-28) ------------------- 1.15.3 (2020-05-14) ------------------- * fix TypeError str / bytes (`#256 `_) 1.15.2 (2020-04-07) ------------------- 1.15.1 (2020-03-17) ------------------- 1.15.0 (2020-02-11) ------------------- 1.14.8 (2020-02-11) ------------------- * fix various issues discovered by flake8 (`#241 `_) * update style to pass flake8 (`#240 `_) * restrict boost dependencies to components used (`#236 `_) * Use setuptools instead of distutils (`#235 `_) * Bump CMake version to avoid CMP0048 warning (`#234 `_) 1.14.7 (2019-10-03) ------------------- * use condition attributes to specify Python 2 and 3 dependencies (`#226 `_) * symlink search for roslib (`#225 `_) 1.14.6 (2019-03-18) ------------------- 1.14.5 (2019-03-04) ------------------- * disable test with invalid dependency (`#202 `_) * special handle Python script without extension on Windows (`#197 `_) * use _MSC_VER for ROS_FORCE_INLINE (`#194 `_) * chmod -x on Python modules (`#183 `_) * fix build issue on Windows (`#186 `_) * add missing dependencies (`#181 `_) 1.14.4 (2018-05-01) ------------------- 1.14.3 (2018-01-30) ------------------- * replace env hooks with a dependency on ros_environment (`#166 `_) 1.14.2 (2017-10-26) ------------------- 1.14.1 (2017-07-27) ------------------- 1.14.0 (2017-02-22) ------------------- * update ROS_DISTRO to lunar 1.13.6 (2017-10-31) ------------------- 1.13.5 (2017-02-14) ------------------- * fix missing export depends (`#128 `_) 1.13.4 (2016-09-19) ------------------- 1.13.3 (2016-09-16) ------------------- * allow expected ROS_DISTRO value to be overridden at compile time (`#122 `_) 1.13.2 (2016-09-02) ------------------- * avoid putting the rosbuild stacks dir on RPP if it doesn't exist (`#111 `_) 1.13.1 (2016-03-13) ------------------- 1.13.0 (2016-03-10) ------------------- * update ROS_DISTRO to kinetic 1.12.6 (2016-03-10) ------------------- * expose an API (ros::package::getPlugins) which can map multiple export values to one package name (`#103 `_) * deprecate API returning incomplete information (`#103 `_) * allow caching of rospack results (`#97 `_) 1.12.5 (2015-10-13) ------------------- 1.12.4 (2015-10-12) ------------------- * improve performance by caching the package mapping in the rospack instance (`#95 `_) 1.12.3 (2015-09-19) ------------------- 1.12.2 (2015-04-27) ------------------- 1.12.1 (2015-04-16) ------------------- * remove usage of CATKIN_TEST_RESULTS_DIR environment variable (`#80 `_) 1.12.0 (2014-12-26) ------------------- * update ROS_DISTRO to jade 1.11.6 (2014-12-22) ------------------- * consider std_msgs/Header to be a valid header in rosbuild-based messages (`#67 `_) 1.11.5 (2014-08-18) ------------------- 1.11.4 (2014-07-23) ------------------- 1.11.3 (2014-07-18) ------------------- * remove linking against "rt" library on Android (`#57 `_) * disable delayed expansion in Windows environment hook (`#60 `_) 1.11.2 (2014-06-16) ------------------- * use PYTHON_EXECUTABLE in environment hooks (`#55 `_) 1.11.1 (2014-05-07) ------------------- * add optional argument force_recrawl to getPlugins() function * use catkin_install_python() to install Python scripts (`#46 `_) * python 3 compatibility 1.11.0 (2014-01-31) ------------------- 1.10.9 (2014-01-07) ------------------- 1.10.8 (2013-10-15) ------------------- 1.10.7 (2013-10-04) ------------------- * compatibility of env hooks with old workspace setup files (`#36 `_) * allow python files to pass executable filter in Windows 1.10.6 (2013-08-22) ------------------- * fix regression of `#29 `_ introduced in 1.10.5 1.10.5 (2013-08-21) ------------------- * make roslib relocatable (`ros/catkin#490 `_) * improve performance of dry message generation 1.10.4 (2013-07-05) ------------------- 1.10.3 (2013-07-03) ------------------- * check for CATKIN_ENABLE_TESTING to enable configure without tests 1.10.2 (2013-06-18) ------------------- 1.10.1 (2013-06-06) ------------------- 1.10.0 (2013-03-22 09:23) ------------------------- * update ROS distro name to hydro (`#10 `_) 1.9 (Groovy) ============ 1.9.44 (2013-03-13) ------------------- 1.9.43 (2013-03-08) ------------------- * improve speed of message generation in dry packages (`ros/ros_comm#183 `_) * fix handling spaces in folder names (`ros/catkin#375 `_) * make Python scripts executable from launch files on Windows (`ros/ros_comm#54 `_) 1.9.42 (2013-01-25) ------------------- * fix location of (obsolete) environment variable ROS_ETC_DIR 1.9.41 (2013-01-24) ------------------- * modified ROS_ROOT in devel space and moved all rosbuild files to a location which fits how the files are relatively looked up 1.9.40 (2013-01-13) ------------------- 1.9.39 (2012-12-30) ------------------- * first public release for Groovy ros-1.15.8/core/roslib/CMakeLists.txt000066400000000000000000000035601407615046500174070ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.0.2) project(roslib) find_package(catkin REQUIRED COMPONENTS rospack) catkin_package( INCLUDE_DIRS include LIBRARIES roslib CATKIN_DEPENDS rospack CFG_EXTRAS roslib-extras.cmake) find_package(Boost REQUIRED COMPONENTS thread) include_directories(include ${catkin_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS}) link_directories(${catkin_LIBRARY_DIRS}) # Avoid a boost warning that pops up when using msvc compiler if(MSVC) add_definitions(-D_SCL_SECURE_NO_WARNINGS) endif() add_library(roslib src/package.cpp) target_link_libraries(roslib ${Boost_LIBRARIES} ${catkin_LIBRARIES}) if(NOT (APPLE OR WIN32 OR MINGW OR ANDROID)) target_link_libraries(roslib rt) endif() catkin_python_setup() install(TARGETS roslib ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION}) install(DIRECTORY include/ DESTINATION ${CATKIN_GLOBAL_INCLUDE_DESTINATION} FILES_MATCHING PATTERN "*.h" PATTERN ".svn" EXCLUDE) catkin_install_python(PROGRAMS scripts/gendeps DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}) if(CATKIN_ENABLE_TESTING) find_package(Boost REQUIRED COMPONENTS filesystem thread) catkin_add_nosetests(test) catkin_add_gtest(${PROJECT_NAME}-utest test/utest.cpp WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) if(TARGET ${PROJECT_NAME}-utest) target_link_libraries(${PROJECT_NAME}-utest roslib ${Boost_LIBRARIES} ${catkin_LIBRARIES}) endif() catkin_add_gtest(${PROJECT_NAME}-test_package test/package.cpp) if(TARGET ${PROJECT_NAME}-test_package) target_link_libraries(${PROJECT_NAME}-test_package roslib ${catkin_LIBRARIES}) endif() endif() file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/export.cmake "") export(TARGETS roslib FILE ${CMAKE_CURRENT_BINARY_DIR}/export.cmake APPEND) #include(${CMAKE_CURRENT_BINARY_DIR}/export.cmake) ros-1.15.8/core/roslib/cmake/000077500000000000000000000000001407615046500157235ustar00rootroot00000000000000ros-1.15.8/core/roslib/cmake/roslib-extras.cmake.em000066400000000000000000000005241407615046500221240ustar00rootroot00000000000000# generated from ros/core/roslib/cmake/roslib-extras.cmake.em @[if DEVELSPACE]@ # set path to gendeps executable in develspace set(gendeps_exe @(CMAKE_CURRENT_SOURCE_DIR)/scripts/gendeps) @[else]@ # set path to gendeps executable in installspace set(gendeps_exe ${roslib_DIR}/../../../@(CATKIN_PACKAGE_BIN_DESTINATION)/gendeps) @[end if]@ ros-1.15.8/core/roslib/epydoc.config000066400000000000000000000002071407615046500173140ustar00rootroot00000000000000[epydoc] name: roslib modules: roslib inheritance: included url: http://ros.org/wiki/rospy frames: yes private: no exclude: roslib.msg ros-1.15.8/core/roslib/include/000077500000000000000000000000001407615046500162665ustar00rootroot00000000000000ros-1.15.8/core/roslib/include/ros/000077500000000000000000000000001407615046500170715ustar00rootroot00000000000000ros-1.15.8/core/roslib/include/ros/package.h000066400000000000000000000134441407615046500206430ustar00rootroot00000000000000/* * Copyright (C) 2009, Willow Garage, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the names of Stanford University or Willow Garage, Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifndef ROSLIB_PACKAGE_H #define ROSLIB_PACKAGE_H #include #include #include #include #if defined(__GNUC__) # define ROS_DEPRECATED __attribute__((deprecated)) # define ROS_FORCE_INLINE __attribute__((always_inline)) #elif defined(_MSC_VER) # define ROS_DEPRECATED # define ROS_FORCE_INLINE __forceinline #else # define ROS_DEPRECATED # define ROS_FORCE_INLINE inline #endif /* Windows import/export and gnu http://gcc.gnu.org/wiki/Visibility macros. */ #if defined(_MSC_VER) # define ROS_HELPER_IMPORT __declspec(dllimport) # define ROS_HELPER_EXPORT __declspec(dllexport) #elif __GNUC__ >= 4 # define ROS_HELPER_IMPORT __attribute__ ((visibility("default"))) # define ROS_HELPER_EXPORT __attribute__ ((visibility("default"))) #else # define ROS_HELPER_IMPORT # define ROS_HELPER_EXPORT #endif // Ignore warnings about import/exports when deriving from std classes. #ifdef _MSC_VER # pragma warning(disable: 4251) # pragma warning(disable: 4275) #endif #ifdef ROS_BUILD_SHARED_LIBS // ros is being built around shared libraries # ifdef roslib_EXPORTS // we are building a shared lib/dll # define ROSLIB_DECL ROS_HELPER_EXPORT # else // we are using shared lib/dll # define ROSLIB_DECL ROS_HELPER_IMPORT # endif #else // ros is being built around static libraries # define ROSLIB_DECL #endif namespace ros { namespace package { typedef std::vector V_string; typedef std::map M_string; /** * \brief Runs a rospack command of the form 'rospack ', returning the output as a single string */ ROSLIB_DECL std::string command(const std::string& cmd); /** * \brief Runs a rospack command of the form 'rospack ', returning the output as a vector of strings, split by newlines */ ROSLIB_DECL void command(const std::string& cmd, V_string& output); /** * \brief Returns the fully-qualified path to a package, or an empty string if the package is not found */ ROSLIB_DECL std::string getPath(const std::string& package_name); /** * \brief Gets a list of all packages. Returns false if it could not run the command. */ ROSLIB_DECL bool getAll(V_string& packages); /** * \brief Call the "rospack plugins" command, eg. "rospack plugins --attrib= ". Returns a vector of strings which * are export values */ ROSLIB_DECL void getPlugins(const std::string& package, const std::string& attribute, V_string& plugins, bool force_recrawl=false); /** * \brief Call the "rospack plugins" command, eg. "rospack plugins --attrib= ". * Return a vector of string pairs which are package names and exported values respectively. * Note that there can be multiple values for any single package. * * Note that while this uses the original rospack 'plugin' terminology, * this effectively works for any exported tag with attributes in the * catkin package.xml export list. Typical examples include: * \code{.xml} \endcode * * \param name : name of the package export tag (has to be a package name) [in] * \param attribute : name of the attribute inside the export tag with which to filter results [in] * \param exports : package/value export pairs resulting from the search [out] * \param force_recrawl : force rospack to rediscover everything on the system before running the search [in] */ ROSLIB_DECL void getPlugins( const std::string& name, const std::string& attribute, std::vector >& exports, bool force_recrawl=false ); /** * \brief Call the "rospack plugins" command, eg. "rospack plugins --attrib= ". * Return a map of package name to export value. * * \warning If there are multiple export values, only the last one is saved in the map. * * \deprecated Prefer the ::getPlugins(const std::string&, const std::string&, std::vector>&, bool) api instead. */ ROS_DEPRECATED ROSLIB_DECL void getPlugins(const std::string& package, const std::string& attribute, M_string& plugins, bool force_recrawl=false); } // namespace package } // namespace ros #endif ros-1.15.8/core/roslib/mainpage.dox000066400000000000000000000012731407615046500171430ustar00rootroot00000000000000/** \mainpage \htmlinclude manifest.html \b %roslib is the base library support for ROS client implementations as well as ROS tools. It includes: - common message definitions used in ROS clients (e.g. Header) - a Python library for manipulating ROS system resources (e.g. .msg files, names) - message and services generation callout scripts \section codeapi Code API - Time-related: ros::Time, ros::Duration, ros::Rate, ros::WallTime, ros::WallDuration, ros::WallRate. Also see the roscpp Time overview. - Package-related: ros::package namespace - Debug-related: ros::debug namespace */ ros-1.15.8/core/roslib/package.xml000066400000000000000000000034351407615046500167650ustar00rootroot00000000000000 roslib 1.15.8 Base dependencies and support libraries for ROS. roslib contains many of the common data structures and tools that are shared across ROS client library implementations. Michel Hidalgo Jacob Perron BSD http://wiki.ros.org/roslib https://github.com/ros/ros/issues https://github.com/ros/ros Ken Conley Josh Faust Morgan Quigley Dirk Thomas rospack catkin python-setuptools python3-setuptools libboost-thread-dev catkin python-rospkg python3-rospkg ros_environment libboost-filesystem-dev rosmake ros-1.15.8/core/roslib/rosdoc.yaml000066400000000000000000000002531407615046500170200ustar00rootroot00000000000000 - builder: epydoc output_dir: python config: epydoc.config - builder: doxygen name: C++ API output_dir: c++ file_patterns: '*.c *.cpp *.h *.cc *.hh *.dox'ros-1.15.8/core/roslib/scripts/000077500000000000000000000000001407615046500163325ustar00rootroot00000000000000ros-1.15.8/core/roslib/scripts/gendeps000077500000000000000000000105631407615046500177120ustar00rootroot00000000000000#! /usr/bin/env python # Software License Agreement (BSD License) # # Copyright (c) 2008, Willow Garage, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following # disclaimer in the documentation and/or other materials provided # with the distribution. # * Neither the name of Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # # Revision $Id: gendeps 3009 2008-12-05 00:47:44Z sfkwc $ # $Author: sfkwc $ # Script for determining the ROS messages a particular message # depends on. This is important for determining messages file that # need to be rebuilt. from __future__ import print_function import sys import roslib.gentools import roslib.msgs import roslib.srvs import rospkg NAME = 'gendeps' def usage(progname, stdout=sys.stdout): print('%(progname)s msg-or-srv-file' % vars(), file=stdout) # main method for gendeps command # @param argv [str]: sys args # @param stdout pipe: stdout pipe # @param stderr pipe: stderr pipe def gendeps_main(argv, stdout, stderr): from optparse import OptionParser parser = OptionParser(usage='usage: %prog [options] [files...]', prog=NAME) parser.add_option('-m', '--md5', dest='md5', default=False, action='store_true', help='Generate md5 hash of files') parser.add_option('-s', '--sha1', dest='sha1', default=False, action='store_true', help='Generate SHA1 hash of files') parser.add_option('-c', '--cat', dest='cat_files', default=False, action='store_true', help='Generate concatenated list of files') (options, args) = parser.parse_args(argv) # get the file name if len(args) != 2: parser.error('you must specify one input file') f = args[1] # validate that options are compatible if options.md5 and (options.sha1 or options.cat_files): parser.error('md5 option is not compatible with other options') if options.sha1 and (options.md5 or options.cat_files): parser.error('sha1 option is not compatible with other options') if options.cat_files and (options.md5 or options.sha1): parser.error('cat option is not compatible with other options') # rospack instance for caching of deps rospack = rospkg.RosPack() retval = roslib.gentools.get_file_dependencies(f, stdout=stdout, stderr=stderr, rospack=rospack) if options.md5: print(roslib.gentools.compute_md5(retval, rospack=rospack), file=stdout) elif options.sha1: print(roslib.gentools.compute_sha1(retval, rospack=rospack), file=stdout) elif options.cat_files: # this option is used for the message definition that is # stored in exchanged in ROS handshakes and then stored in bag # files print(roslib.gentools.compute_full_text(retval), file=stdout) else: print(' '.join(retval['files'].values()), file=stdout) if __name__ == '__main__': try: gendeps_main(sys.argv, sys.stdout, sys.stderr) except Exception as e: print(e, file=sys.stderr) sys.exit(1) ros-1.15.8/core/roslib/setup.py000066400000000000000000000003341407615046500163550ustar00rootroot00000000000000from setuptools import setup from catkin_pkg.python_setup import generate_distutils_setup d = generate_distutils_setup( packages=['ros', 'roslib'], package_dir={'': 'src'}, requires=['rospkg'] ) setup(**d) ros-1.15.8/core/roslib/src/000077500000000000000000000000001407615046500154325ustar00rootroot00000000000000ros-1.15.8/core/roslib/src/package.cpp000066400000000000000000000120071407615046500175310ustar00rootroot00000000000000/* * Copyright (C) 2009, Willow Garage, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the names of Stanford University or Willow Garage, Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include "ros/package.h" #include "rospack/rospack.h" #include #include #include #include #include #include namespace ros { namespace package { // Mutex used to lock calls into librospack, which is not thread-safe. static boost::mutex librospack_mutex; std::string command(const std::string& _cmd) { boost::mutex::scoped_lock lock(librospack_mutex); // static allows caching of results in between calls (in same process) static rospack::ROSPack rp; int ret; try { ret = rp.run(_cmd); if(ret == 0) return rp.getOutput(); else { if ( !rp.is_quiet() ) std::cerr << "ROSPack::run returned non-zero." << std::endl; } } catch(std::runtime_error &e) { if ( !rp.is_quiet() ) std::cerr << "[rospack] " << e.what() << std::endl; } return std::string(""); } void command(const std::string& cmd, V_string& output) { std::string out_string = command(cmd); V_string full_list; boost::split(full_list, out_string, boost::is_any_of("\r\n")); // strip empties V_string::iterator it = full_list.begin(); V_string::iterator end = full_list.end(); for (; it != end; ++it) { if (!it->empty()) { output.push_back(*it); } } } std::string getPath(const std::string& package_name) { std::string path = command("find " + package_name); // scrape any newlines out of it for (size_t newline = path.find('\n'); newline != std::string::npos; newline = path.find('\n')) { path.erase(newline, 1); } return path; } bool getAll(V_string& packages) { command("list-names", packages); return true; } static void getPlugins(const std::string& package, const std::string& attribute, V_string& packages, V_string& plugins, bool force_recrawl) { if (force_recrawl) { command("profile"); } V_string lines; command("plugins --attrib=" + attribute + " " + package, lines); V_string::iterator it = lines.begin(); V_string::iterator end = lines.end(); for (; it != end; ++it) { V_string tokens; boost::split(tokens, *it, boost::is_any_of(" ")); if (tokens.size() >= 2) { std::string package = tokens[0]; std::string rest = boost::join(V_string(tokens.begin() + 1, tokens.end()), " "); packages.push_back(package); plugins.push_back(rest); } } } void getPlugins( const std::string& name, const std::string& attribute, std::vector >& exports, bool force_recrawl ) { V_string packages, plugins; getPlugins(name, attribute, packages, plugins, force_recrawl); // works on the assumption the previous call always return equal length package/plugin lists for (std::size_t i = 0; i < packages.size(); ++i ) { exports.push_back(std::pair(packages[i], plugins[i])); } } void getPlugins(const std::string& package, const std::string& attribute, V_string& plugins, bool force_recrawl) { V_string packages; getPlugins(package, attribute, packages, plugins, force_recrawl); } void getPlugins(const std::string& package, const std::string& attribute, M_string& plugins, bool force_recrawl) { V_string packages, plugins_v; getPlugins(package, attribute, packages, plugins_v, force_recrawl); for (std::size_t i = 0 ; i < packages.size() ; ++i) plugins[packages[i]] = plugins_v[i]; } } // namespace package } // namespace ros ros-1.15.8/core/roslib/src/ros/000077500000000000000000000000001407615046500162355ustar00rootroot00000000000000ros-1.15.8/core/roslib/src/ros/__init__.py000077500000000000000000000047111407615046500203540ustar00rootroot00000000000000# Software License Agreement (BSD License) # # Copyright (c) 2008, Willow Garage, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following # disclaimer in the documentation and/or other materials provided # with the distribution. # * Neither the name of Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # # Revision $Id: __init__.py 3544 2009-01-24 00:09:21Z sfkwc $ # The ros module enables dynamic importing of any ROS python module. # The common syntax is 'from ros import foo', where foo is a ROS package name. import sys import roslib # noqa: F401 # @internal class Module(object): def __init__(self, wrapped): self.wrapped = wrapped def __getattr__(self, name): try: return getattr(self.wrapped, name) except AttributeError: import roslib.packages try: roslib.load_manifest(name.split('.')[0]) except roslib.packages.InvalidROSPkgException as e: raise ImportError("Cannot import module '%s': \n%s" % (name, str(e))) return __import__(name) # rewrite our own entry in sys.modules so that dynamic loading works. sys.modules[__name__] = Module(sys.modules[__name__]) ros-1.15.8/core/roslib/src/roslib/000077500000000000000000000000001407615046500167245ustar00rootroot00000000000000ros-1.15.8/core/roslib/src/roslib/__init__.py000066400000000000000000000062201407615046500210350ustar00rootroot00000000000000# Software License Agreement (BSD License) # # Copyright (c) 2008, Willow Garage, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following # disclaimer in the documentation and/or other materials provided # with the distribution. # * Neither the name of Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. """ roslib is largely deprecated starting in the ROS Fuerte release. roslib has a very important role in all Python code written for ROS: it contains the L{load_manifest()} method, which updates the PYTHONPATH based on a set of ROS Package manifest.xml files. Beyond the important load_manifest() call, most of the rest of roslib consists of low-level libraries that 99% of ROS users need not interact with. These libraries are primarily to support higher-level ROS Python libraries, such as the rospy client library, as well as numerous ROS tools (e.g. rostopic). """ __version__ = '1.7.0' from roslib.launcher import load_manifest # noqa: F401 # this import is necessary due to a bug in purge_build.py in our # debian assets. import roslib.stacks # noqa: F401, I100 _is_interactive = False def set_interactive(interactive): """ General API for a script specifying that it is being run in an interactive environment. Many libraries may wish to change their behavior based on being interactive (e.g. disabling signal handlers on Ctrl-C). @param interactive: True if current script is being run in an interactive shell @type interactive: bool """ global _is_interactive _is_interactive = interactive def is_interactive(): """ General API for a script specifying that it is being run in an interactive environment. Many libraries may wish to change their behavior based on being interactive (e.g. disabling signal handlers on Ctrl-C). @return: True if interactive flag has been set @rtype: bool """ return _is_interactive ros-1.15.8/core/roslib/src/roslib/exceptions.py000066400000000000000000000034401407615046500214600ustar00rootroot00000000000000# Software License Agreement (BSD License) # # Copyright (c) 2009, Willow Garage, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following # disclaimer in the documentation and/or other materials provided # with the distribution. # * Neither the name of Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # # Revision $Id$ # $Author$ """ Provides the L{ROSLibException} class, which is common to many roslib libraries. """ class ROSLibException(Exception): """ Base class for exceptions in roslib """ pass ros-1.15.8/core/roslib/src/roslib/gentools.py000066400000000000000000000320321407615046500211300ustar00rootroot00000000000000#! /usr/bin/env python # Software License Agreement (BSD License) # # Copyright (c) 2008, Willow Garage, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following # disclaimer in the documentation and/or other materials provided # with the distribution. # * Neither the name of Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # # Revision $Id$ # $Author$ """ Library for supporting message and service generation for all ROS client libraries. This is mainly responsible for calculating the md5sums and message definitions of classes. """ # NOTE: this should not contain any rospy-specific code. The rospy # generator library is rospy.genpy. import sys try: from cStringIO import StringIO # Python 2.x except ImportError: from io import StringIO # Python 3.x import roslib.msgs import roslib.names import roslib.srvs from roslib.msgs import MsgSpecException import rospkg # name of the Header type as gentools knows it _header_type_name = 'std_msgs/Header' def _add_msgs_depends(rospack, spec, deps, package_context): """ Add the list of message types that spec depends on to depends. @param spec: message to compute dependencies for @type spec: roslib.msgs.MsgSpec/roslib.srvs.SrvSpec @param deps [str]: list of dependencies. This list will be updated with the dependencies of spec when the method completes @type deps: [str] @raise KeyError for invalid dependent types due to missing package dependencies. """ def _get_valid_packages(package_context, rospack): valid_packages = ['', package_context] try: valid_packages = valid_packages + rospack.get_depends(package_context, implicit=True) except rospkg.ResourceNotFound: # this happens in dynamic generation situations where the # package is not present. we soft fail here because we assume # missing messages will be caught later during lookup. pass return valid_packages valid_packages = None for t in spec.types: t = roslib.msgs.base_msg_type(t) if not roslib.msgs.is_builtin(t): t_package, t_base = roslib.names.package_resource_name(t) # special mapping for header if t == roslib.msgs.HEADER: # have to re-names Header deps.append(_header_type_name) if roslib.msgs.is_registered(t): depspec = roslib.msgs.get_registered(t) if t != roslib.msgs.HEADER: if '/' in t: deps.append(t) else: deps.append(package_context+'/'+t) else: if valid_packages is None: valid_packages = _get_valid_packages(package_context, rospack) if t_package in valid_packages: # if we are allowed to load the message, load it. key, depspec = roslib.msgs.load_by_type(t, package_context) if t != roslib.msgs.HEADER: deps.append(key) roslib.msgs.register(key, depspec) else: # not allowed to load the message, so error. raise KeyError(t) _add_msgs_depends(rospack, depspec, deps, package_context) def compute_md5_text(get_deps_dict, spec, rospack=None): """ Compute the text used for md5 calculation. MD5 spec states that we removes comments and non-meaningful whitespace. We also strip packages names from type names. For convenience sake, constants are reordered ahead of other declarations, in the order that they were originally defined. @return: text for ROS MD5-processing @rtype: str """ uniquedeps = get_deps_dict['uniquedeps'] package = get_deps_dict['package'] # #1554: need to suppress computation of files in dynamic generation case compute_files = 'files' in get_deps_dict buff = StringIO() for c in spec.constants: buff.write('%s %s=%s\n' % (c.type, c.name, c.val_text)) for type_, name in zip(spec.types, spec.names): base_msg_type = roslib.msgs.base_msg_type(type_) # md5 spec strips package names if roslib.msgs.is_builtin(base_msg_type): buff.write('%s %s\n' % (type_, name)) else: # recursively generate md5 for subtype. have to build up # dependency representation for subtype in order to # generate md5 # - ugly special-case handling of Header if base_msg_type == roslib.msgs.HEADER: base_msg_type = _header_type_name sub_pkg, _ = roslib.names.package_resource_name(base_msg_type) sub_pkg = sub_pkg or package sub_spec = roslib.msgs.get_registered(base_msg_type, package) sub_deps = get_dependencies(sub_spec, sub_pkg, compute_files=compute_files, rospack=rospack) sub_md5 = compute_md5(sub_deps, rospack) buff.write('%s %s\n' % (sub_md5, name)) return buff.getvalue().strip() # remove trailing new line def _compute_hash(get_deps_dict, hash, rospack=None): """ subroutine of compute_md5() @param get_deps_dict: dictionary returned by get_dependencies call @type get_deps_dict: dict @param hash: hash instance @type hash: hash instance """ # accumulate the hash # - root file from roslib.msgs import MsgSpec from roslib.srvs import SrvSpec spec = get_deps_dict['spec'] if isinstance(spec, MsgSpec): hash.update(compute_md5_text(get_deps_dict, spec, rospack=rospack).encode()) elif isinstance(spec, SrvSpec): hash.update(compute_md5_text(get_deps_dict, spec.request, rospack=rospack).encode()) hash.update(compute_md5_text(get_deps_dict, spec.response, rospack=rospack).encode()) else: raise Exception('[%s] is not a message or service' % spec) return hash.hexdigest() def _compute_hash_v1(get_deps_dict, hash): """ subroutine of compute_md5_v1() @param get_deps_dict: dictionary returned by get_dependencies call @type get_deps_dict: dict @param hash: hash instance @type hash: hash instance """ uniquedeps = get_deps_dict['uniquedeps'] spec = get_deps_dict['spec'] # accumulate the hash # - root file hash.update(spec.text) # - dependencies for d in uniquedeps: hash.update(roslib.msgs.get_registered(d).text) return hash.hexdigest() def compute_md5_v1(get_deps_dict): """ Compute original V1 md5 hash for message/service. This was replaced with V2 in ROS 0.6. @param get_deps_dict: dictionary returned by get_dependencies call @type get_deps_dict: dict @return: md5 hash @rtype: str """ import hashlib return _compute_hash_v1(get_deps_dict, hashlib.md5()) def compute_md5(get_deps_dict, rospack=None): """ Compute md5 hash for message/service @param get_deps_dict dict: dictionary returned by get_dependencies call @type get_deps_dict: dict @return: md5 hash @rtype: str """ try: # md5 is deprecated in Python 2.6 in favor of hashlib, but hashlib is # unavailable in Python 2.4 import hashlib return _compute_hash(get_deps_dict, hashlib.md5(), rospack=rospack) except ImportError: import md5 return _compute_hash(get_deps_dict, md5.new(), rospack=rospack) # alias compute_md5_v2 = compute_md5 def compute_full_text(get_deps_dict): """ Compute full text of message/service, including text of embedded types. The text of the main msg/srv is listed first. Embedded msg/srv files are denoted first by an 80-character '=' separator, followed by a type declaration line,'MSG: pkg/type', followed by the text of the embedded type. @param get_deps_dict dict: dictionary returned by get_dependencies call @type get_deps_dict: dict @return: concatenated text for msg/srv file and embedded msg/srv types. @rtype: str """ buff = StringIO() sep = '='*80+'\n' # write the text of the top-level type buff.write(get_deps_dict['spec'].text) buff.write('\n') # append the text of the dependencies (embedded types) for d in get_deps_dict['uniquedeps']: buff.write(sep) buff.write('MSG: %s\n' % d) buff.write(roslib.msgs.get_registered(d).text) buff.write('\n') # #1168: remove the trailing \n separator that is added by the concatenation logic return buff.getvalue()[:-1] def get_file_dependencies(f, stdout=sys.stdout, stderr=sys.stderr, rospack=None): """ Compute dependencies of the specified message/service file @param f: message or service file to get dependencies for @type f: str @param stdout pipe: stdout pipe @type stdout: file @param stderr pipe: stderr pipe @type stderr: file @return: 'files': list of files that \a file depends on, 'deps': list of dependencies by type, 'spec': Msgs/Srvs instance. @rtype: dict """ package = rospkg.get_package_name(f) spec = None if f.endswith(roslib.msgs.EXT): _, spec = roslib.msgs.load_from_file(f) elif f.endswith(roslib.srvs.EXT): _, spec = roslib.srvs.load_from_file(f) else: raise Exception('[%s] does not appear to be a message or service' % spec) return get_dependencies(spec, package, stdout, stderr, rospack=rospack) def get_dependencies(spec, package, compute_files=True, stdout=sys.stdout, stderr=sys.stderr, rospack=None): """ Compute dependencies of the specified Msgs/Srvs @param spec: message or service instance @type spec: L{roslib.msgs.MsgSpec}/L{roslib.srvs.SrvSpec} @param package: package name @type package: str @param stdout: (optional) stdout pipe @type stdout: file @param stderr: (optional) stderr pipe @type stderr: file @param compute_files: (optional, default=True) compute file dependencies of message ('files' key in return value) @type compute_files: bool @return: dict: * 'files': list of files that \a file depends on * 'deps': list of dependencies by type * 'spec': Msgs/Srvs instance. * 'uniquedeps': list of dependencies with duplicates removed, * 'package': package that dependencies were generated relative to. @rtype: dict """ # #518: as a performance optimization, we're going to manually control the loading # of msgs instead of doing package-wide loads. # we're going to manipulate internal apis of msgs, so have to manually init roslib.msgs._init() deps = [] try: if not rospack: rospack = rospkg.RosPack() if isinstance(spec, roslib.msgs.MsgSpec): _add_msgs_depends(rospack, spec, deps, package) elif isinstance(spec, roslib.srvs.SrvSpec): _add_msgs_depends(rospack, spec.request, deps, package) _add_msgs_depends(rospack, spec.response, deps, package) else: raise MsgSpecException('spec does not appear to be a message or service') except KeyError as e: raise MsgSpecException('Cannot load type %s. Perhaps the package is missing a dependency.' % (str(e))) # convert from type names to file names if compute_files: files = {} for d in set(deps): d_pkg, t = roslib.names.package_resource_name(d) d_pkg = d_pkg or package # convert '' -> local package files[d] = roslib.msgs.msg_file(d_pkg, t) else: files = None # create unique dependency list uniquedeps = [] for d in deps: if d not in uniquedeps: uniquedeps.append(d) if compute_files: return {'files': files, 'deps': deps, 'spec': spec, 'package': package, 'uniquedeps': uniquedeps} else: return {'deps': deps, 'spec': spec, 'package': package, 'uniquedeps': uniquedeps} ros-1.15.8/core/roslib/src/roslib/launcher.py000066400000000000000000000077731407615046500211150ustar00rootroot00000000000000#! /usr/bin/env python # Software License Agreement (BSD License) # # Copyright (c) 2008, Willow Garage, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following # disclaimer in the documentation and/or other materials provided # with the distribution. # * Neither the name of Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. """ Python path loader for python scripts and applications. Paths are derived from dependency structure declared in ROS manifest files. """ import os import sys import rospkg # bootstrapped keeps track of which packages we've loaded so we don't # update the path multiple times _bootstrapped = [] # _rospack is our cache of ROS package data _rospack = rospkg.RosPack() def get_depends(package, rospack): vals = rospack.get_depends(package, implicit=True) return [v for v in vals if not rospack.get_manifest(v).is_catkin] def load_manifest(package_name, bootstrap_version='0.7'): """ Update the Python sys.path with package's dependencies :param package_name: name of the package that load_manifest() is being called from, ``str`` """ if package_name in _bootstrapped: return sys.path = _generate_python_path(package_name, _rospack) + sys.path def _append_package_paths(manifest_, paths, pkg_dir): """ Added paths for package to paths :param manifest_: package manifest, ``Manifest`` :param pkg_dir: package's filesystem directory path, ``str`` :param paths: list of paths, ``[str]`` """ exports = manifest_.get_export('python', 'path') if exports: for export in exports: if ':' in export: export = export.split(':') else: export = [export] for e in export: paths.append(e.replace('${prefix}', pkg_dir)) else: dirs = [os.path.join(pkg_dir, d) for d in ['src', 'lib']] paths.extend([d for d in dirs if os.path.isdir(d)]) def _generate_python_path(pkg, rospack): """ Recursive subroutine for building dependency list and python path :raises: :exc:`rospkg.ResourceNotFound` If an error occurs while attempting to load package or dependencies """ if pkg in _bootstrapped: return [] # short-circuit if this is a catkin-ized package m = rospack.get_manifest(pkg) if m.is_catkin: _bootstrapped.append(pkg) return [] packages = get_depends(pkg, rospack) packages.append(pkg) paths = [] try: for p in packages: m = rospack.get_manifest(p) d = rospack.get_path(p) _append_package_paths(m, paths, d) _bootstrapped.append(p) except Exception: if pkg in _bootstrapped: _bootstrapped.remove(pkg) raise return paths ros-1.15.8/core/roslib/src/roslib/manifest.py000066400000000000000000000125551407615046500211140ustar00rootroot00000000000000#! /usr/bin/env python # Software License Agreement (BSD License) # # Copyright (c) 2008, Willow Garage, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following # disclaimer in the documentation and/or other materials provided # with the distribution. # * Neither the name of Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # # Revision $Id$ # $Author$ """ Warning: do not use this library. It is unstable and most of the routines here have been superseded by other libraries (e.g. rospkg). These routines will likely be *deleted* in future releases. """ import os import roslib.manifestlib import roslib.packages # re-export symbols for backwards compatibility from roslib.manifestlib import Depend # noqa: F401 from roslib.manifestlib import Export # noqa: F401 from roslib.manifestlib import ManifestException from roslib.manifestlib import ROSDep # noqa: F401 from roslib.manifestlib import VersionControl # noqa: F401 MANIFEST_FILE = 'manifest.xml' class Manifest(roslib.manifestlib._Manifest): """ Object representation of a ROS manifest file """ __slots__ = [] def __init__(self): """ Initialize new empty manifest. """ super(Manifest, self).__init__('package') def get_export(self, tag, attr): """ @return: exports that match the specified tag and attribute, e.g. 'python', 'path' @rtype: [L{Export}] """ return [e.get(attr) for e in self.exports if e.tag == tag if e.get(attr) is not None] def _manifest_file_by_dir(package_dir, required=True, env=None): """ @param package_dir: path to package directory @type package_dir: str @param env: environment dictionary @type env: dict @param required: require that the directory exist @type required: bool @return: path to manifest file of package @rtype: str @raise InvalidROSPkgException: if required is True and manifest file cannot be located """ if env is None: env = os.environ try: p = os.path.join(package_dir, MANIFEST_FILE) if not required and not os.path.exists(p): return p if not os.path.isfile(p): raise roslib.packages.InvalidROSPkgException(""" Package '%(package_dir)s' is improperly configured: no manifest file is present. """ % locals()) return p except roslib.packages.InvalidROSPkgException: if required: raise def manifest_file(package, required=True, env=None): """ @param package str: package name @type package: str @param env: override os.environ dictionary @type env: dict @param required: require that the directory exist @type required: bool @return: path to manifest file of package @rtype: str @raise InvalidROSPkgException: if required is True and manifest file cannot be located """ # ros_root needs to be determined from the environment or else # everything breaks when trying to launch nodes via ssh where the # path isn't setup correctly. if env is None: env = os.environ d = roslib.packages.get_pkg_dir(package, required, ros_root=env['ROS_ROOT']) return _manifest_file_by_dir(d, required=required, env=env) def load_manifest(package): """ Load manifest for specified package. @param pacakge: package name @type package: str @return: Manifest instance @rtype: L{Manifest} @raise InvalidROSPkgException: if package is unknown """ return parse_file(manifest_file(package)) def parse_file(file): """ Parse manifest.xml file @param file: manifest.xml file path @type file: str @return: Manifest instance @rtype: L{Manifest} """ return roslib.manifestlib.parse_file(Manifest(), file) def parse(string, filename='string'): """ Parse manifest.xml string contents @param string: manifest.xml contents @type string: str @return: Manifest instance @rtype: L{Manifest} """ v = roslib.manifestlib.parse(Manifest(), string, filename) if v.version: raise ManifestException(' tag is not valid in a package manifest.xml file') return v ros-1.15.8/core/roslib/src/roslib/manifestlib.py000066400000000000000000000471211407615046500216000ustar00rootroot00000000000000#! /usr/bin/env python # Software License Agreement (BSD License) # # Copyright (c) 2008, Willow Garage, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following # disclaimer in the documentation and/or other materials provided # with the distribution. # * Neither the name of Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # # Revision $Id$ # $Author$ """ Internal library for processing 'manifest' files, i.e. manifest.xml and stack.xml. For external code apis, see L{roslib.manifest} and L{roslib.stack_manifest}. """ import os import xml.dom.minidom as dom import roslib.exceptions # stack.xml and manifest.xml have the same internal tags right now REQUIRED = ['author', 'license'] ALLOWXHTML = ['description'] OPTIONAL = ['logo', 'url', 'brief', 'description', 'status', 'notes', 'depend', 'rosdep', 'export', 'review', 'versioncontrol', 'platform', 'version', 'rosbuild2', 'catkin'] VALID = REQUIRED + OPTIONAL class ManifestException(roslib.exceptions.ROSLibException): pass def get_nodes_by_name(n, name): return [t for t in n.childNodes if t.nodeType == t.ELEMENT_NODE and t.tagName == name] def check_optional(name, allowXHTML=False, merge_multiple=False): """ Validator for optional elements. @raise ManifestException: if validation fails """ def check(n, filename): n = get_nodes_by_name(n, name) if len(n) > 1 and not merge_multiple: raise ManifestException("Invalid manifest file: must have a single '%s' element" % name) if n: values = [] for child in n: if allowXHTML: values.append(''.join([x.toxml() for x in child.childNodes])) else: values.append(_get_text(child.childNodes).strip()) return ', '.join(values) return check def check_required(name, allowXHTML=False, merge_multiple=False): """ Validator for required elements. @raise ManifestException: if validation fails """ def check(n, filename): n = get_nodes_by_name(n, name) if not n: # print >> sys.stderr, "Invalid manifest file[%s]: missing required '%s' element"%(filename, name) return '' if len(n) != 1 and not merge_multiple: raise ManifestException("Invalid manifest file: must have only one '%s' element" % name) values = [] for child in n: if allowXHTML: values.append(''.join([x.toxml() for x in child.childNodes])) else: values.append(_get_text(child.childNodes).strip()) return ', '.join(values) return check def check_platform(name): """ Validator for manifest platform. @raise ManifestException: if validation fails """ def check(n, filename): platforms = get_nodes_by_name(n, name) try: vals = [(p.attributes['os'].value, p.attributes['version'].value, p.getAttribute('notes')) for p in platforms] except KeyError as e: raise ManifestException(" tag is missing required '%s' attribute" % str(e)) return [Platform(*v) for v in vals] return check def check_depends(name): """ Validator for manifest depends. @raise ManifestException: if validation fails """ def check(n, filename): nodes = get_nodes_by_name(n, name) # TDS 20110419: this is a hack. # rosbuild2 has a tag, # which is confusing this subroutine with # KeyError: 'package' # for now, explicitly don't consider thirdparty depends depends = [e.attributes for e in nodes if 'thirdparty' not in e.attributes.keys()] try: packages = [d['package'].value for d in depends] except KeyError: raise ManifestException("Invalid manifest file: depends is missing 'package' attribute") return [Depend(p) for p in packages] return check def check_stack_depends(name): """ Validator for stack depends. @raise ManifestException: if validation fails """ def check(n, filename): nodes = get_nodes_by_name(n, name) depends = [e.attributes for e in nodes] packages = [d['stack'].value for d in depends] return [StackDepend(p) for p in packages] return check def check_rosdeps(name): """ Validator for stack rosdeps. @raise ManifestException: if validation fails """ def check(n, filename): nodes = get_nodes_by_name(n, name) rosdeps = [e.attributes for e in nodes] names = [d['name'].value for d in rosdeps] return [ROSDep(n) for n in names] return check def _attrs(node): attrs = {} for k in node.attributes.keys(): attrs[k] = node.attributes.get(k).value return attrs def check_exports(name): def check(n, filename): ret_val = [] for e in get_nodes_by_name(n, name): elements = [c for c in e.childNodes if c.nodeType == c.ELEMENT_NODE] ret_val.extend([Export(t.tagName, _attrs(t), _get_text(t.childNodes)) for t in elements]) return ret_val return check def check_versioncontrol(name): def check(n, filename): e = get_nodes_by_name(n, name) if not e: return None # note: 'url' isn't actually required, but as we only support type=svn it implicitly is for now return VersionControl(e[0].attributes['type'].value, e[0].attributes['url'].value) return check def check(name, merge_multiple=False): if name == 'depend': return check_depends('depend') elif name == 'export': return check_exports('export') elif name == 'versioncontrol': return check_versioncontrol('versioncontrol') elif name == 'rosdep': return check_rosdeps('rosdep') elif name == 'platform': return check_platform('platform') elif name in REQUIRED: if name in ALLOWXHTML: return check_required(name, True, merge_multiple) return check_required(name, merge_multiple=merge_multiple) elif name in OPTIONAL: if name in ALLOWXHTML: return check_optional(name, True, merge_multiple) return check_optional(name, merge_multiple=merge_multiple) class Export(object): """ Manifest 'export' tag """ def __init__(self, tag, attrs, str): """ Create new export instance. @param tag: name of the XML tag @type tag: str @param attrs: dictionary of XML attributes for this export tag @type attrs: dict @param str: string value contained by tag, if any @type str: str """ self.tag = tag self.attrs = attrs self.str = str def get(self, attr): """ @return: value of attribute or None if attribute not set @rtype: str """ return self.attrs.get(attr, None) def xml(self): """ @return: export instance represented as manifest XML @rtype: str """ attrs = ' '.join([' %s="%s"' % (k, v) for k, v in self.attrs.items()]) # py3k if self.str: return '<%s%s>%s' % (self.tag, attrs, self.str, self.tag) else: return '<%s%s />' % (self.tag, attrs) class Platform(object): """ Manifest 'platform' tag """ __slots__ = ['os', 'version', 'notes'] def __init__(self, os, version, notes=None): """ Create new depend instance. @param os: OS name. must be non-empty @type os: str @param version: OS version. must be non-empty @type version: str @param notes: (optional) notes about platform support @type notes: str """ if not os: raise ValueError("bad 'os' attribute") if not version: raise ValueError("bad 'version' attribute") self.os = os self.version = version self.notes = notes def __str__(self): return '%s %s' % (self.os, self.version) def __repr__(self): return '%s %s' % (self.os, self.version) def __eq__(self, obj): """ Override equality test. notes *are* considered in the equality test. """ if not isinstance(obj, Platform): return False return self.os == obj.os and self.version == obj.version and self.notes == obj.notes def xml(self): """ @return: instance represented as manifest XML @rtype: str """ if self.notes is not None: return '' % (self.os, self.version, self.notes) else: return '' % (self.os, self.version) class Depend(object): """ Manifest 'depend' tag """ __slots__ = ['package'] def __init__(self, package): """ Create new depend instance. @param package: package name. must be non-empty @type package: str """ if not package: raise ValueError("bad 'package' attribute") self.package = package def __str__(self): return self.package def __repr__(self): return self.package def __eq__(self, obj): if not isinstance(obj, Depend): return False return self.package == obj.package def xml(self): """ @return: depend instance represented as manifest XML @rtype: str """ return '' % self.package class StackDepend(object): """ Stack Manifest 'depend' tag """ __slots__ = ['stack', 'annotation'] def __init__(self, stack): """ @param stack: stack name. must be non-empty @type stack: str """ if not stack: raise ValueError("bad 'stack' attribute") self.stack = stack self.annotation = None def __str__(self): return self.stack def __repr__(self): return self.stack def __eq__(self, obj): if not isinstance(obj, StackDepend): return False return self.stack == obj.stack def xml(self): """ @return: stack depend instance represented as stack manifest XML @rtype: str """ if self.annotation: return ' ' % (self.stack, self.annotation) else: return '' % self.stack class ROSDep(object): """ Manifest 'rosdep' tag """ __slots__ = ['name', ] def __init__(self, name): """ Create new rosdep instance. @param name: dependency name. Must be non-empty. @type name: str """ if not name: raise ValueError("bad 'name' attribute") self.name = name def xml(self): """ @return: rosdep instance represented as manifest XML @rtype: str """ return '' % self.name class VersionControl(object): """ Manifest 'versioncontrol' tag """ __slots__ = ['type', 'url'] def __init__(self, type_, url): """ @param type_: version control type (e.g. 'svn'). must be non empty @type type_: str @param url: URL associated with version control. must be non empty @type url: str """ def is_string_type(obj): try: return isinstance(obj, basestring) except NameError: return isinstance(obj, str) if not type_ or not is_string_type(type_): raise ValueError("bad 'type' attribute") if url is not None and not is_string_type(url): raise ValueError("bad 'url' attribute") self.type = type_ self.url = url def xml(self): """ @return: versioncontrol instance represented as manifest XML @rtype: str """ if self.url: return '' % (self.type, self.url) else: return '' % self.type class _Manifest(object): """ Object representation of a ROS manifest file """ __slots__ = ['description', 'brief', 'author', 'license', 'license_url', 'url', 'depends', 'rosdeps', 'platforms', 'logo', 'exports', 'version', 'versioncontrol', 'status', 'notes', 'unknown_tags', '_type'] def __init__(self, _type='package'): self.description = self.brief = self.author = \ self.license = self.license_url = \ self.url = self.logo = self.status = \ self.version = self.notes = '' self.depends = [] self.rosdeps = [] self.exports = [] self.platforms = [] self._type = _type # store unrecognized tags during parsing self.unknown_tags = [] def __str__(self): return self.xml() def get_export(self, tag, attr): """ @return: exports that match the specified tag and attribute, e.g. 'python', 'path' @rtype: [L{Export}] """ return [e.get(attr) for e in self.exports if e.tag == tag if e.get(attr) is not None] def xml(self): """ @return: Manifest instance as ROS XML manifest @rtype: str """ if not self.brief: desc = ' %s' % self.description else: desc = ' %s' % (self.brief, self.description) author = ' %s' % self.author if self.license_url: license = ' %s' % (self.license_url, self.license) else: license = ' %s' % self.license versioncontrol = url = logo = exports = version = '' if self.url: url = ' %s' % self.url if self.version: version = ' %s' % self.version if self.logo: logo = ' %s' % self.logo depends = '\n'.join([' %s' % d.xml() for d in self.depends]) rosdeps = '\n'.join([' %s' % rd.xml() for rd in self.rosdeps]) platforms = '\n'.join([' %s' % p.xml() for p in self.platforms]) if self.exports: exports = ' \n' + '\n'.join([' %s' % e.xml() for e in self.exports]) + ' ' if self.versioncontrol: versioncontrol = ' %s' % self.versioncontrol.xml() if self.status or self.notes: review = ' ' % (self.status, self.notes) fields = filter(lambda x: x, [desc, author, license, review, url, logo, depends, rosdeps, platforms, exports, versioncontrol, version]) return '<%s>\n' % self._type + '\n'.join(fields) + '\n' % self._type def _get_text(nodes): """ DOM utility routine for getting contents of text nodes """ return ''.join([n.data for n in nodes if n.nodeType == n.TEXT_NODE]) def parse_file(m, file): """ Parse manifest file (package, stack) @param m: field to populate @type m: L{_Manifest} @param file: manifest.xml file path @type file: str @return: return m, populated with parsed fields @rtype: L{_Manifest} """ if not file: raise ValueError('Missing manifest file argument') if not os.path.isfile(file): raise ValueError('Invalid/non-existent manifest file: %s' % file) with open(file, 'r') as f: text = f.read() try: return parse(m, text, file) except ManifestException as e: raise ManifestException('Invalid manifest file [%s]: %s' % (os.path.abspath(file), e)) def parse(m, string, filename='string'): """ Parse manifest.xml string contents @param string: manifest.xml contents @type string: str @param m: field to populate @type m: L{_Manifest} @return: return m, populated with parsed fields @rtype: L{_Manifest} """ try: d = dom.parseString(string) except Exception as e: raise ManifestException('invalid XML: %s' % e) p = get_nodes_by_name(d, m._type) if len(p) != 1: raise ManifestException("manifest must have a single '%s' element" % m._type) p = p[0] m.description = check('description')(p, filename) m.brief = '' try: tag = get_nodes_by_name(p, 'description')[0] m.brief = tag.getAttribute('brief') or '' except Exception: # means that 'description' tag is missing pass # TODO: figure out how to multiplex if m._type == 'package': m.depends = check_depends('depend')(p, filename) elif m._type == 'stack': m.depends = check_stack_depends('depend')(p, filename) elif m._type == 'app': # not implemented yet pass m.rosdeps = check('rosdep')(p, filename) m.platforms = check('platform')(p, filename) m.exports = check('export')(p, filename) m.versioncontrol = check('versioncontrol')(p, filename) m.license = check('license')(p, filename) m.license_url = '' try: tag = get_nodes_by_name(p, 'license')[0] m.license_url = tag.getAttribute('url') or '' except Exception: pass # manifest is missing required 'license' tag m.status = 'unreviewed' try: tag = get_nodes_by_name(p, 'review')[0] m.status = tag.getAttribute('status') or '' except Exception: pass # manifest is missing optional 'review status' tag m.notes = '' try: tag = get_nodes_by_name(p, 'review')[0] m.notes = tag.getAttribute('notes') or '' except Exception: pass # manifest is missing optional 'review notes' tag m.author = check('author', True)(p, filename) m.url = check('url')(p, filename) m.version = check('version')(p, filename) m.logo = check('logo')(p, filename) # do some validation on what we just parsed if m._type == 'stack': if m.exports: raise ManifestException('stack manifests are not allowed to have exports') if m.rosdeps: raise ManifestException('stack manifests are not allowed to have rosdeps') # store unrecognized tags m.unknown_tags = [e for e in p.childNodes if e.nodeType == e.ELEMENT_NODE and e.tagName not in VALID] return m ros-1.15.8/core/roslib/src/roslib/message.py000066400000000000000000000115321407615046500207240ustar00rootroot00000000000000# Software License Agreement (BSD License) # # Copyright (c) 2008, Willow Garage, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following # disclaimer in the documentation and/or other materials provided # with the distribution. # * Neither the name of Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # # Revision $Id$ """ Support library for Python autogenerated message files. This defines the Message base class used by genmsg_py as well as support libraries for type checking and retrieving message classes by type name. """ import genmsg import genpy.message # for wrapping get_message_class, get_service_class # forward a bunch of old symbols from genpy for backwards compat from genpy import DeserializationError # noqa: F401 from genpy import Duration # noqa: F401 from genpy import Message # noqa: F401 from genpy import SerializationError # noqa: F401 from genpy import TVal # noqa: F401 from genpy import Time # noqa: F401 from genpy.message import check_type # noqa: F401 from genpy.message import fill_message_args # noqa: F401 from genpy.message import get_printable_message_args # noqa: F401 from genpy.message import strify_message # noqa: F401 import roslib import rospkg def _get_message_or_service_class(type_str, message_type, reload_on_error=False): # parse package and local type name for import package, base_type = genmsg.package_resource_name(message_type) if not package: if base_type == 'Header': package = 'std_msgs' else: raise ValueError('message type is missing package name: %s' % str(message_type)) pypkg = val = None try: # bootstrap our sys.path roslib.launcher.load_manifest(package) # import the package and return the class pypkg = __import__('%s.%s' % (package, type_str)) val = getattr(getattr(pypkg, type_str), base_type) except rospkg.ResourceNotFound: val = None except ImportError: val = None except AttributeError: val = None # this logic is mainly to support rosh, so that a user doesn't # have to exit a shell just because a message wasn't built yet if val is None and reload_on_error: try: reload # Python 2 except NameError: from importlib import reload # Python 3 try: if pypkg: reload(pypkg) val = getattr(getattr(pypkg, type_str), base_type) except Exception: val = None return val # cache for get_message_class _message_class_cache = {} # cache for get_service_class _service_class_cache = {} def get_message_class(message_type, reload_on_error=False): if message_type in _message_class_cache: return _message_class_cache[message_type] # try w/o bootstrapping cls = genpy.message.get_message_class(message_type, reload_on_error=reload_on_error) if cls is None: # try old loader w/ bootstrapping cls = _get_message_or_service_class('msg', message_type, reload_on_error=reload_on_error) if cls: _message_class_cache[message_type] = cls return cls def get_service_class(service_type, reload_on_error=False): if service_type in _service_class_cache: return _service_class_cache[service_type] cls = genpy.message.get_service_class(service_type, reload_on_error=reload_on_error) # try w/o bootstrapping if cls is None: # try old loader w/ bootstrapping cls = _get_message_or_service_class('srv', service_type, reload_on_error=reload_on_error) if cls: _service_class_cache[service_type] = cls return cls ros-1.15.8/core/roslib/src/roslib/msgs.py000066400000000000000000000643501407615046500202570ustar00rootroot00000000000000# Software License Agreement (BSD License) # # Copyright (c) 2008, Willow Garage, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following # disclaimer in the documentation and/or other materials provided # with the distribution. # * Neither the name of Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # # Revision $Id$ # $Author$ from __future__ import print_function """ Warning: do not use this library. It is unstable and most of the routines here have been superseded by other libraries (e.g. genmsg). These routines will likely be *deleted* in future releases. """ try: from cStringIO import StringIO # Python 2.x except ImportError: from io import StringIO # Python 3.x import os import sys import roslib.manifest import roslib.names import roslib.packages import roslib.resources import rospkg VERBOSE = False # @return: True if msg-related scripts should print verbose output def is_verbose(): return VERBOSE # set whether msg-related scripts should print verbose output def set_verbose(v): global VERBOSE VERBOSE = v EXT = '.msg' SEP = '/' # e.g. std_msgs/String # character that designates a constant assignment rather than a field CONSTCHAR = '=' COMMENTCHAR = '#' class MsgSpecException(Exception): pass # TODOXXX: unit test def base_msg_type(type_): """ Compute the base data type, e.g. for arrays, get the underlying array item type @param type_: ROS msg type (e.g. 'std_msgs/String') @type type_: str @return: base type @rtype: str """ if type_ is None: return None if '[' in type_: return type_[:type_.find('[')] return type_ def resolve_type(type_, package_context): """ Resolve type name based on current package context. NOTE: in ROS Diamondback, 'Header' resolves to 'std_msgs/Header'. In previous releases, it resolves to 'roslib/Header' (REP 100). e.g.:: resolve_type('String', 'std_msgs') -> 'std_msgs/String' resolve_type('String[]', 'std_msgs') -> 'std_msgs/String[]' resolve_type('std_msgs/String', 'foo') -> 'std_msgs/String' resolve_type('uint16', 'std_msgs') -> 'uint16' resolve_type('uint16[]', 'std_msgs') -> 'uint16[]' """ bt = base_msg_type(type_) if bt in BUILTIN_TYPES: return type_ elif bt == 'Header': return 'std_msgs/Header' elif SEP in type_: return type_ else: return '%s%s%s' % (package_context, SEP, type_) # NOTE: this assumes that we aren't going to support multi-dimensional def parse_type(type_): """ Parse ROS message field type @param type_: ROS field type @type type_: str @return: base_type, is_array, array_length @rtype: str, bool, int @raise MsgSpecException: if type_ cannot be parsed """ if not type_: raise MsgSpecException('Invalid empty type') if '[' in type_: var_length = type_.endswith('[]') splits = type_.split('[') if len(splits) > 2: raise MsgSpecException('Currently only support 1-dimensional array types: %s' % type_) if var_length: return type_[:-2], True, None else: try: length = int(splits[1][:-1]) return splits[0], True, length except ValueError: raise MsgSpecException('Invalid array dimension: [%s]' % splits[1][:-1]) else: return type_, False, None ################################################################################ # name validation def is_valid_msg_type(x): """ @return: True if the name is a syntatically legal message type name @rtype: bool """ if not x or len(x) != len(x.strip()): return False base = base_msg_type(x) if not roslib.names.is_legal_resource_name(base): return False # parse array indices x = x[len(base):] state = 0 for c in x: if state == 0: if c != '[': return False state = 1 # open elif state == 1: if c == ']': state = 0 # closed else: try: int(c) except Exception: return False return state == 0 def is_valid_constant_type(x): """ @return: True if the name is a legal constant type. Only simple types are allowed. @rtype: bool """ return x in PRIMITIVE_TYPES def is_valid_msg_field_name(x): """ @return: True if the name is a syntatically legal message field name @rtype: bool """ return roslib.names.is_legal_resource_base_name(x) # msg spec representation ########################################## class Constant(object): """ Container class for holding a Constant declaration """ __slots__ = ['type', 'name', 'val', 'val_text'] def __init__(self, type_, name, val, val_text): """ @param type_: constant type @type type_: str @param name: constant name @type name: str @param val: constant value @type val: str @param val_text: Original text definition of \a val @type val_text: str """ if type is None or name is None or val is None or val_text is None: raise ValueError('Constant must have non-None parameters') self.type = type_ self.name = name.strip() # names are always stripped of whitespace self.val = val self.val_text = val_text def __eq__(self, other): if not isinstance(other, Constant): return False return self.type == other.type and self.name == other.name and self.val == other.val def __repr__(self): return '%s %s=%s' % (self.type, self.name, self.val) def __str__(self): return '%s %s=%s' % (self.type, self.name, self.val) def _strify_spec(spec, buff=None, indent=''): """ Convert spec into a string representation. Helper routine for MsgSpec. @param indent: internal use only @type indent: str @param buff: internal use only @type buff: StringIO @return: string representation of spec @rtype: str """ if buff is None: buff = StringIO() for c in spec.constants: buff.write('%s%s %s=%s\n' % (indent, c.type, c.name, c.val_text)) for type_, name in zip(spec.types, spec.names): buff.write('%s%s %s\n' % (indent, type_, name)) base_type = base_msg_type(type_) if base_type not in BUILTIN_TYPES: subspec = get_registered(base_type) _strify_spec(subspec, buff, indent + ' ') return buff.getvalue() class Field(object): """ Container class for storing information about a single field in a MsgSpec Contains: name type base_type is_array array_len is_builtin is_header """ def __init__(self, name, type): self.name = name self.type = type (self.base_type, self.is_array, self.array_len) = parse_type(type) self.is_header = is_header_type(self.base_type) self.is_builtin = is_builtin(self.base_type) def __repr__(self): return '[%s, %s, %s, %s, %s]' % (self.name, self.type, self.base_type, self.is_array, self.array_len) class MsgSpec(object): """ Container class for storing loaded msg description files. Field types and names are stored in separate lists with 1-to-1 correspondence. MsgSpec can also return an md5 of the source text. """ def __init__(self, types, names, constants, text, full_name='', short_name='', package=''): """ @param types: list of field types, in order of declaration @type types: [str] @param names: list of field names, in order of declaration @type names: [str] @param constants: Constant declarations @type constants: [L{Constant}] @param text: text of declaration @type text: str @raise MsgSpecException: if spec is invalid (e.g. fields with the same name) """ self.types = types if len(set(names)) != len(names): raise MsgSpecException('Duplicate field names in message: %s' % names) self.names = names self.constants = constants assert len(self.types) == len(self.names), 'len(%s) != len(%s)' % (self.types, self.names) # Header.msg support if (len(self.types)): self.header_present = is_header_type(self.types[0]) and self.names[0] == 'header' else: self.header_present = False self.text = text self.full_name = full_name self.short_name = short_name self.package = package self._parsed_fields = [Field(name, type) for (name, type) in zip(self.names, self.types)] def fields(self): """ @return: zip list of types and names (e.g. [('int32', 'x'), ('int32', 'y')] @rtype: [(str,str),] """ return list(zip(self.types, self.names)) # py3k def parsed_fields(self): """ @return: list of Field classes @rtype: [Field,] """ return self._parsed_fields def has_header(self): """ @return: True if msg description contains a 'Header header' declaration at the beginning @rtype: bool """ return self.header_present def __eq__(self, other): if not other or not isinstance(other, MsgSpec): return False return self.types == other.types and self.names == other.names and \ self.constants == other.constants and self.text == other.text def __ne__(self, other): if not other or not isinstance(other, MsgSpec): return True return not self.__eq__(other) def __repr__(self): if self.constants: return 'MsgSpec[%s, %s, %s]' % (repr(self.constants), repr(self.types), repr(self.names)) else: return 'MsgSpec[%s, %s]' % (repr(self.types), repr(self.names)) def __str__(self): return _strify_spec(self) # msg spec loading utilities ########################################## def reinit(): """ Reinitialize roslib.msgs. This API is for message generators (e.g. genpy) that need to re-initialize the registration table. """ global _initialized, _loaded_packages # unset the initialized state and unregister everything _initialized = False del _loaded_packages[:] REGISTERED_TYPES.clear() _init() _initialized = False def _init(): # lazy-init global _initialized if _initialized: return fname = '%s%s' % (HEADER, EXT) std_msgs_dir = roslib.packages.get_pkg_dir('std_msgs') if std_msgs_dir is None: raise MsgSpecException('Unable to locate roslib: %s files cannot be loaded' % EXT) header = os.path.join(std_msgs_dir, 'msg', fname) if not os.path.isfile(header): sys.stderr.write("ERROR: cannot locate %s. Expected to find it at '%s'\n" % (fname, header)) return False # register Header under both contexted and de-contexted name _, spec = load_from_file(header, '') register(HEADER, spec) register('std_msgs/'+HEADER, spec) # backwards compat, REP 100 register('roslib/'+HEADER, spec) for k, spec in EXTENDED_BUILTINS.items(): register(k, spec) _initialized = True # .msg file routines ############################################################## def _msg_filter(f): """ Predicate for filtering directory list. matches message files @param f: filename @type f: str """ return os.path.isfile(f) and f.endswith(EXT) # also used by doxymaker def list_msg_types(package, include_depends): """ List all messages in the specified package @param package str: name of package to search @param include_depends bool: if True, will also list messages in package dependencies @return [str]: message type names """ types = roslib.resources.list_package_resources(package, include_depends, 'msg', _msg_filter) return [x[:-len(EXT)] for x in types] def msg_file(package, type_): """ Determine the file system path for the specified .msg resource. .msg resource does not have to exist. @param package: name of package .msg file is in @type package: str @param type_: type name of message, e.g. 'Point2DFloat32' @type type_: str @return: file path of .msg file in specified package @rtype: str """ return roslib.packages.resource_file(package, 'msg', type_+EXT) def get_pkg_msg_specs(package): """ List all messages that a package contains. @param package: package to load messages from @type package: str @return: list of message type names and specs for package, as well as a list of message names that could not be processed. @rtype: [(str, L{MsgSpec}), [str]] """ _init() types = list_msg_types(package, False) specs = [] # no fancy list comprehension as we want to show errors failures = [] for t in types: try: typespec = load_from_file(msg_file(package, t), package) specs.append(typespec) except Exception as e: failures.append(t) print('ERROR: unable to load %s, %s' % (t, e)) return specs, failures def load_package_dependencies(package, load_recursive=False): """ Register all messages that the specified package depends on. @param load_recursive: (optional) if True, load all dependencies, not just direct dependencies. By default, this is false to prevent packages from incorrectly inheriting dependencies. @type load_recursive: bool """ global _loaded_packages _init() if VERBOSE: print('Load dependencies for package', package) if not load_recursive: manifest_file = roslib.manifest.manifest_file(package, True) m = roslib.manifest.parse_file(manifest_file) depends = [d.package for d in m.depends] # #391 else: depends = rospkg.RosPack().get_depends(package, implicit=True) msgs = [] failures = [] for d in depends: if VERBOSE: print('Load dependency', d) # check if already loaded # - we are dependent on manifest.getAll returning first-order dependencies first if d in _loaded_packages or d == package: continue _loaded_packages.append(d) specs, failed = get_pkg_msg_specs(d) msgs.extend(specs) failures.extend(failed) for key, spec in msgs: register(key, spec) def load_package(package): """ Load package into the local registered namespace. All messages found in the package will be registered if they are successfully loaded. This should only be done with one package (i.e. the 'main' package) per Python instance. @param package: package name @type package: str """ global _loaded_packages _init() if VERBOSE: print('Load package', package) # check if already loaded # - we are dependent on manifest.getAll returning first-order dependencies first if package in _loaded_packages: if VERBOSE: print('Package %s is already loaded' % package) return _loaded_packages.append(package) specs, failed = get_pkg_msg_specs(package) if VERBOSE: print('Package contains the following messages: %s' % specs) for key, spec in specs: # register spec under both local and fully-qualified key register(key, spec) register(package + roslib.names.PRN_SEPARATOR + key, spec) def _convert_val(type_, val): """ Convert constant value declaration to python value. Does not do type-checking, so ValueError or other exceptions may be raised. @param type_: ROS field type @type type_: str @param val: string representation of constant @type val: str: @raise ValueError: if unable to convert to python representation @raise MsgSpecException: if value exceeds specified integer width """ if type_ in ['float32', 'float64']: return float(val) elif type_ in ['string']: return val.strip() # string constants are always stripped elif type_ in ['int8', 'uint8', 'int16', 'uint16', 'int32', 'uint32', 'int64', 'uint64', 'char', 'byte']: # bounds checking bits = [('int8', 8), ('uint8', 8), ('int16', 16), ('uint16', 16), ('int32', 32), ('uint32', 32), ('int64', 64), ('uint64', 64), ('byte', 8), ('char', 8)] b = [b for t, b in bits if t == type_][0] import math if type_[0] == 'u' or type_ == 'char': lower = 0 upper = int(math.pow(2, b)-1) else: upper = int(math.pow(2, b-1)-1) lower = -upper - 1 # two's complement min val = int(val) # python will autocast to long if necessary if val > upper or val < lower: raise MsgSpecException('cannot coerce [%s] to %s (out of bounds)' % (val, type_)) return val elif type_ == 'bool': # TODO: need to nail down constant spec for bool return True if eval(val) else False raise MsgSpecException('invalid constant type: [%s]' % type_) def load_by_type(msgtype, package_context=''): """ Load message specification for specified type @param package_context: package name to use for the type name or '' to use the local (relative) naming convention. @type package_context: str @return: Message type name and message specification @rtype: (str, L{MsgSpec}) """ pkg, basetype = roslib.names.package_resource_name(msgtype) pkg = pkg or package_context # convert '' -> local package try: m_f = msg_file(pkg, basetype) except roslib.packages.InvalidROSPkgException: raise MsgSpecException('Cannot locate message type [%s], package [%s] does not exist' % (msgtype, pkg)) return load_from_file(m_f, pkg) def load_from_string(text, package_context='', full_name='', short_name=''): """ Load message specification from a string. @param text: .msg text @type text: str @param package_context: package name to use for the type name or '' to use the local (relative) naming convention. @type package_context: str @return: Message specification @rtype: L{MsgSpec} @raise MsgSpecException: if syntax errors or other problems are detected in file """ types = [] names = [] constants = [] for orig_line in text.split('\n'): l = orig_line.split(COMMENTCHAR)[0].strip() # strip comments if not l: continue # ignore empty lines splits = [s for s in [x.strip() for x in l.split(' ')] if s] # split type/name, filter out empties type_ = splits[0] if not is_valid_msg_type(type_): raise MsgSpecException('%s is not a legal message type' % type_) if CONSTCHAR in l: if not is_valid_constant_type(type_): raise MsgSpecException('%s is not a legal constant type' % type_) if type_ == 'string': # strings contain anything to the right of the equals sign, there are no comments allowed idx = orig_line.find(CONSTCHAR) name = orig_line[orig_line.find(' ')+1:idx] val = orig_line[idx+1:] else: splits = [x.strip() for x in ' '.join(splits[1:]).split(CONSTCHAR)] # resplit on '=' if len(splits) != 2: raise MsgSpecException('Invalid declaration: %s' % l) name = splits[0] val = splits[1] try: val_converted = _convert_val(type_, val) except Exception as e: raise MsgSpecException('Invalid declaration: %s' % e) constants.append(Constant(type_, name, val_converted, val.strip())) else: if len(splits) != 2: raise MsgSpecException('Invalid declaration: %s' % l) name = splits[1] if not is_valid_msg_field_name(name): raise MsgSpecException('%s is not a legal message field name' % name) if package_context and SEP not in type_: if not base_msg_type(type_) in RESERVED_TYPES: # print "rewrite", type_, "to", "%s/%s"%(package_context, type_) type_ = '%s/%s' % (package_context, type_) types.append(type_) names.append(name) return MsgSpec(types, names, constants, text, full_name, short_name, package_context) def load_from_file(file_path, package_context=''): """ Convert the .msg representation in the file to a MsgSpec instance. This does *not* register the object. @param file_path: path of file to load from @type file_path: str: @param package_context: package name to prepend to type name or '' to use local (relative) naming convention. @type package_context: str @return: Message type name and message specification @rtype: (str, L{MsgSpec}) @raise MsgSpecException: if syntax errors or other problems are detected in file """ if VERBOSE: if package_context: print('Load spec from', file_path, 'into package [%s]' % package_context) else: print('Load spec from', file_path) file_name = os.path.basename(file_path) type_ = file_name[:-len(EXT)] base_type_ = type_ # determine the type name if package_context: while package_context.endswith(SEP): package_context = package_context[:-1] # strip message separators type_ = '%s%s%s' % (package_context, SEP, type_) if not roslib.names.is_legal_resource_name(type_): raise MsgSpecException('%s: [%s] is not a legal type name' % (file_path, type_)) f = open(file_path, 'r') try: try: text = f.read() return (type_, load_from_string(text, package_context, type_, base_type_)) except MsgSpecException as e: raise MsgSpecException('%s: %s' % (file_name, e)) finally: f.close() # data structures and builtins specification ########################### # adjustable constants, in case we change our minds HEADER = 'Header' TIME = 'time' DURATION = 'duration' def is_header_type(type_): """ @param type_: message type name @type type_: str @return: True if \a type_ refers to the ROS Header type @rtype: bool """ # for backwards compatibility, include roslib/Header. REP 100 return type_ in [HEADER, 'std_msgs/Header', 'roslib/Header'] # time and duration types are represented as aggregate data structures # for the purposes of serialization from the perspective of # roslib.msgs. genmsg_py will do additional special handling is required # to convert them into rospy.msg.Time/Duration instances. # time as msg spec. time is unsigned TIME_MSG = 'uint32 secs\nuint32 nsecs' # duration as msg spec. duration is just like time except signed DURATION_MSG = 'int32 secs\nint32 nsecs' # primitive types are those for which we allow constants, i.e. have primitive representation PRIMITIVE_TYPES = ['int8', 'uint8', 'int16', 'uint16', 'int32', 'uint32', 'int64', 'uint64', 'float32', 'float64', 'string', 'bool', # deprecated: 'char', 'byte'] BUILTIN_TYPES = PRIMITIVE_TYPES + [TIME, DURATION] def is_builtin(msg_type_name): """ @param msg_type_name: name of message type @type msg_type_name: str @return: True if msg_type_name is a builtin/primitive type @rtype: bool """ return msg_type_name in BUILTIN_TYPES # extended builtins are builtin types that can be represented as MsgSpec instances EXTENDED_BUILTINS = {TIME: load_from_string(TIME_MSG), DURATION: load_from_string(DURATION_MSG)} RESERVED_TYPES = BUILTIN_TYPES + [HEADER] REGISTERED_TYPES = {} _loaded_packages = [] # keep track of packages so that we only load once (note: bug #59) def is_registered(msg_type_name): """ @param msg_type_name: name of message type @type msg_type_name: str @return: True if msg spec for specified msg type name is registered. NOTE: builtin types are not registered. @rtype: bool """ return msg_type_name in REGISTERED_TYPES def get_registered(msg_type_name, default_package=None): """ @param msg_type_name: name of message type @type msg_type_name: str @return: msg spec for msg type name @rtype: L{MsgSpec} """ if msg_type_name in REGISTERED_TYPES: return REGISTERED_TYPES[msg_type_name] elif default_package: # if msg_type_name has no package specifier, try with default package resolution p, n = roslib.names.package_resource_name(msg_type_name) if not p: return REGISTERED_TYPES[roslib.names.resource_name(default_package, msg_type_name)] raise KeyError(msg_type_name) def register(msg_type_name, msg_spec): """ Load MsgSpec into the type dictionary @param msg_type_name: name of message type @type msg_type_name: str @param msg_spec: spec to load @type msg_spec: L{MsgSpec} """ if VERBOSE: print('Register msg %s' % msg_type_name) REGISTERED_TYPES[msg_type_name] = msg_spec ros-1.15.8/core/roslib/src/roslib/names.py000066400000000000000000000327601407615046500204110ustar00rootroot00000000000000# Software License Agreement (BSD License) # # Copyright (c) 2008, Willow Garage, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following # disclaimer in the documentation and/or other materials provided # with the distribution. # * Neither the name of Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # # Revision $Id$ """ Warning: do not use this library. It is unstable and most of the routines here have been superseded by other libraries (e.g. genmsg). These routines will likely be *deleted* in future releases. """ import os import re import sys # TODO: deprecate PRN_SEPARATOR PRN_SEPARATOR = '/' TYPE_SEPARATOR = PRN_SEPARATOR # alias SEP = '/' GLOBALNS = '/' PRIV_NAME = '~' REMAP = ':=' ANYTYPE = '*' if sys.hexversion > 0x03000000: # Python3 def isstring(s): return isinstance(s, str) # Python 3.x else: def isstring(s): """ Small helper version to check an object is a string in a way that works for both Python 2 and 3 """ return isinstance(s, basestring) # Python 2.x def get_ros_namespace(env=None, argv=None): """ @param env: environment dictionary (defaults to os.environ) @type env: dict @param argv: command-line arguments (defaults to sys.argv) @type argv: [str] @return: ROS namespace of current program @rtype: str """ # we force command-line-specified namespaces to be globally scoped if argv is None: argv = sys.argv for a in argv: if a.startswith('__ns:='): return make_global_ns(a[len('__ns:='):]) if env is None: env = os.environ return make_global_ns(env.get('ROS_NAMESPACE', GLOBALNS)) def make_caller_id(name): """ Resolve a local name to the caller ID based on ROS environment settings (i.e. ROS_NAMESPACE) @param name: local name to calculate caller ID from, e.g. 'camera', 'node' @type name: str @return: caller ID based on supplied local name @rtype: str """ return make_global_ns(ns_join(get_ros_namespace(), name)) def make_global_ns(name): """ Convert name to a global name with a trailing namespace separator. @param name: ROS resource name. Cannot be a ~name. @type name: str @return str: name as a global name, e.g. 'foo' -> '/foo/'. This does NOT resolve a name. @rtype: str @raise ValueError: if name is a ~name """ if is_private(name): raise ValueError('cannot turn [%s] into a global name' % name) if not is_global(name): name = SEP + name if name[-1] != SEP: name = name + SEP return name def is_global(name): """ Test if name is a global graph resource name. @param name: must be a legal name in canonical form @type name: str @return: True if name is a globally referenced name (i.e. /ns/name) @rtype: bool """ return name and name[0] == SEP def is_private(name): """ Test if name is a private graph resource name. @param name: must be a legal name in canonical form @type name: str @return bool: True if name is a privately referenced name (i.e. ~name) """ return name and name[0] == PRIV_NAME def namespace(name): """ Get the namespace of name. The namespace is returned with a trailing slash in order to favor easy concatenation and easier use within the global context. @param name: name to return the namespace of. Must be a legal name. NOTE: an empty name will return the global namespace. @type name: str @return str: Namespace of name. For example, '/wg/node1' returns '/wg/'. The global namespace is '/'. @rtype: str @raise ValueError: if name is invalid """ 'map name to its namespace' if name is None: raise ValueError('name') if not isstring(name): raise TypeError('name') if not name: return SEP elif name[-1] == SEP: name = name[:-1] return name[:name.rfind(SEP)+1] or SEP def ns_join(ns, name): """ Join a namespace and name. If name is unjoinable (i.e. ~private or /global) it will be returned without joining @param ns: namespace ('/' and '~' are both legal). If ns is the empty string, name will be returned. @type ns: str @param name str: a legal name @return str: name concatenated to ns, or name if it is unjoinable. @rtype: str """ if is_private(name) or is_global(name): return name if ns == PRIV_NAME: return PRIV_NAME + name if not ns: return name if ns[-1] == SEP: return ns + name return ns + SEP + name def load_mappings(argv): """ Load name mappings encoded in command-line arguments. This will filter out any parameter assignment mappings (see roslib.param.load_param_mappings()). @param argv: command-line arguments @type argv: [str] @return: name->name remappings. @rtype: dict {str: str} """ mappings = {} for arg in argv: if REMAP in arg: try: src, dst = [x.strip() for x in arg.split(REMAP)] if src and dst: if len(src) > 1 and src[0] == '_' and src[1] != '_': # ignore parameter assignment mappings pass else: mappings[src] = dst except Exception: sys.stderr.write("ERROR: Invalid remapping argument '%s'\n" % arg) return mappings ####################################################################### # RESOURCE NAMES # resource names refer to entities in a file system def resource_name(res_pkg_name, name, my_pkg=None): """ Convert package name + resource into a fully qualified resource name @param res_pkg_name: name of package resource is located in @type res_pkg_name: str @param name: resource base name @type name: str @param my_pkg: name of package resource is being referred to in. If specified, name will be returned in local form if res_pkg_name is my_pkg @type my_pkg: str @return: name for resource @rtype: str """ if res_pkg_name != my_pkg: return res_pkg_name+PRN_SEPARATOR+name return name def resource_name_base(name): """ pkg/typeName -> typeName, typeName -> typeName Convert fully qualified resource name into the package-less resource name @param name: package resource name, e.g. 'std_msgs/String' @type name: str @return: resource name sans package-name scope @rtype: str """ return name[name.rfind(PRN_SEPARATOR)+1:] def resource_name_package(name): """ pkg/typeName -> pkg, typeName -> None @param name: package resource name, e.g. 'std_msgs/String' @type name: str @return: package name of resource @rtype: str """ if PRN_SEPARATOR not in name: return None return name[:name.find(PRN_SEPARATOR)] def package_resource_name(name): """ Split a name into its package and resource name parts, e.g. 'std_msgs/String -> std_msgs, String' @param name: package resource name, e.g. 'std_msgs/String' @type name: str @return: package name, resource name @rtype: str @raise ValueError: if name is invalid """ if PRN_SEPARATOR in name: val = tuple(name.split(PRN_SEPARATOR)) if len(val) != 2: raise ValueError('invalid name [%s]' % name) else: return val else: return '', name def _is_safe_name(name, type_name): # windows long-file name length is 255 if not isstring(name) or not name or len(name) > 255: return False return is_legal_resource_name(name) ################################################################################ # NAME VALIDATORS # ascii char followed by (alphanumeric, _, /) RESOURCE_NAME_LEGAL_CHARS_P = re.compile(r'^[A-Za-z][\w_\/]*$') def is_legal_resource_name(name): """ Check if name is a legal ROS name for filesystem resources (alphabetical character followed by alphanumeric, underscore, or forward slashes). This constraint is currently not being enforced, but may start getting enforced in later versions of ROS. @param name: Name @type name: str """ # resource names can be unicode due to filesystem if name is None: return False m = RESOURCE_NAME_LEGAL_CHARS_P.match(name) # '//' check makes sure there isn't double-slashes return m is not None and m.group(0) == name and '//' not in name # ~,/, or ascii char followed by (alphanumeric, _, /) NAME_LEGAL_CHARS_P = re.compile(r'^[\~\/A-Za-z][\w_\/]*$') def is_legal_name(name): """ Check if name is a legal ROS name for graph resources (alphabetical character followed by alphanumeric, underscore, or forward slashes). This constraint is currently not being enforced, but may start getting enforced in later versions of ROS. @param name: Name @type name: str """ # should we enforce unicode checks? if name is None: return False # empty string is a legal name as it resolves to namespace if name == '': return True m = NAME_LEGAL_CHARS_P.match(name) return m is not None and m.group(0) == name and '//' not in name BASE_NAME_LEGAL_CHARS_P = re.compile(r'^[A-Za-z][\w_]*$') # ascii char followed by (alphanumeric, _) def is_legal_base_name(name): """ Validates that name is a legal base name for a graph resource. A base name has no namespace context, e.g. "node_name". """ if name is None: return False m = BASE_NAME_LEGAL_CHARS_P.match(name) return m is not None and m.group(0) == name BASE_RESOURCE_NAME_LEGAL_CHARS_P = re.compile(r'^[A-Za-z][\w_]*$') # ascii char followed by (alphanumeric, _) def is_legal_resource_base_name(name): """ Validates that name is a legal resource base name. A base name has no package context, e.g. "String". """ # resource names can be unicode due to filesystem if name is None: return False m = BASE_NAME_LEGAL_CHARS_P.match(name) return m is not None and m.group(0) == name def canonicalize_name(name): """ Put name in canonical form. Extra slashes '//' are removed and name is returned without any trailing slash, e.g. /foo/bar @param name: ROS name @type name: str """ if not name or name == SEP: return name elif name[0] == SEP: return '/' + '/'.join([x for x in name.split(SEP) if x]) else: return '/'.join([x for x in name.split(SEP) if x]) def resolve_name(name, namespace_, remappings=None): """ Resolve a ROS name to its global, canonical form. Private ~names are resolved relative to the node name. @param name: name to resolve. @type name: str @param namespace_: node name to resolve relative to. @type namespace_: str @param remappings: Map of resolved remappings. Use None to indicate no remapping. @return: Resolved name. If name is empty/None, resolve_name returns parent namespace_. If namespace_ is empty/None, @rtype: str """ if not name: # empty string resolves to parent of the namespace_ return namespace(namespace_) name = canonicalize_name(name) if name[0] == SEP: # global name resolved_name = name elif is_private(name): # ~name # #3044: be careful not to accidentally make rest of name global resolved_name = canonicalize_name(namespace_ + SEP + name[1:]) else: # relative resolved_name = namespace(namespace_) + name # Mappings override general namespace-based resolution # - do this before canonicalization as remappings are meant to # match the name as specified in the code if remappings and resolved_name in remappings: return remappings[resolved_name] else: return resolved_name def anonymous_name(id): """ Generate a ROS-legal 'anonymous' name @param id: prefix for anonymous name @type id: str """ import random import socket name = '%s_%s_%s_%s' % (id, socket.gethostname(), os.getpid(), random.randint(0, sys.maxsize)) # RFC 952 allows hyphens, IP addrs can have '.'s, both # of which are illegal for ROS names. For good # measure, screen ipv6 ':'. name = name.replace('.', '_') name = name.replace('-', '_') return name.replace(':', '_') ros-1.15.8/core/roslib/src/roslib/network.py000066400000000000000000000334751407615046500210030ustar00rootroot00000000000000# Software License Agreement (BSD License) # # Copyright (c) 2008, Willow Garage, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following # disclaimer in the documentation and/or other materials provided # with the distribution. # * Neither the name of Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # # Revision $Id$ """ Warning: do not use this library. It is unstable and most of the routines here have been superseded by other libraries (e.g. rosgraph). These routines will likely be *deleted* in future releases. """ import os import platform import socket import struct import sys try: # Python 2.x from cStringIO import StringIO # noqa: F401 python3 = 0 except ImportError: # Python 3.x from io import BytesIO # noqa: F401 python3 = 1 try: import urllib.parse as urlparse # noqa: F401 except ImportError: import urlparse # noqa: F401 # TODO: change this to rosgraph equivalents once we have ported this module ROS_IP = 'ROS_IP' ROS_HOSTNAME = 'ROS_HOSTNAME' SIOCGIFCONF = 0x8912 SIOCGIFADDR = 0x8915 if platform.system() == 'FreeBSD': SIOCGIFADDR = 0xc0206921 if platform.architecture()[0] == '64bit': SIOCGIFCONF = 0xc0106924 else: SIOCGIFCONF = 0xc0086924 if 0: # disabling netifaces as it accounts for 50% of startup latency try: import netifaces _use_netifaces = True except Exception: # NOTE: in rare cases, I've seen Python fail to extract the egg # cache when launching multiple python nodes. Thus, we do # except-all instead of except ImportError (kwc). _use_netifaces = False else: _use_netifaces = False def _is_unix_like_platform(): """ @return: true if the platform conforms to UNIX/POSIX-style APIs @rtype: bool """ # return platform.system() in ['Linux', 'Mac OS X', 'Darwin'] return platform.system() in ['Linux', 'FreeBSD'] def get_address_override(): """ @return: ROS_IP/ROS_HOSTNAME override or None @rtype: str @raise ValueError: if ROS_IP/ROS_HOSTNAME/__ip/__hostname are invalidly specified """ # #998: check for command-line remappings first for arg in sys.argv: if arg.startswith('__hostname:=') or arg.startswith('__ip:='): try: _, val = arg.split(':=') return val except Exception: # split didn't unpack properly raise ValueError("invalid ROS command-line remapping argument '%s'" % arg) # check ROS_HOSTNAME and ROS_IP environment variables, which are # aliases for each other if ROS_HOSTNAME in os.environ: return os.environ[ROS_HOSTNAME] elif ROS_IP in os.environ: return os.environ[ROS_IP] return None def is_local_address(hostname): """ @param hostname: host name/address @type hostname: str @return True: if hostname maps to a local address, False otherwise. False conditions include invalid hostnames. """ try: reverse_ip = socket.gethostbyname(hostname) except socket.error: return False # 127. check is due to #1260 if reverse_ip not in get_local_addresses() and not reverse_ip.startswith('127.'): return False return True def get_local_address(): """ @return: default local IP address (e.g. eth0). May be overridden by ROS_IP/ROS_HOSTNAME/__ip/__hostname @rtype: str """ override = get_address_override() if override: return override addrs = get_local_addresses() if len(addrs) == 1: return addrs[0] for addr in addrs: # pick first non 127/8 address if not addr.startswith('127.'): return addr else: # loopback return '127.0.0.1' # cache for performance reasons _local_addrs = None def get_local_addresses(): """ @return: known local addresses. Not affected by ROS_IP/ROS_HOSTNAME @rtype: [str] """ # cache address data as it can be slow to calculate global _local_addrs if _local_addrs is not None: return _local_addrs local_addrs = None if _use_netifaces: # #552: netifaces is a more robust package for looking up # #addresses on multiple platforms (OS X, Unix, Windows) local_addrs = [] # see http://alastairs-place.net/netifaces/ for i in netifaces.interfaces(): try: local_addrs.extend([d['addr'] for d in netifaces.ifaddresses(i)[netifaces.AF_INET]]) except KeyError: pass elif _is_unix_like_platform(): # unix-only branch # adapted from code from Rosen Diankov (rdiankov@cs.cmu.edu) # and from ActiveState recipe import fcntl import array ifsize = 32 if platform.system() == 'Linux' and platform.architecture()[0] == '64bit': ifsize = 40 # untested # 32 interfaces allowed, far more than ROS can sanely deal with max_bytes = 32 * ifsize # according to http://docs.python.org/library/fcntl.html, the buffer limit is 1024 bytes buff = array.array('B', b'\0' * max_bytes) # serialize the buffer length and address to ioctl sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) info = fcntl.ioctl(sock.fileno(), SIOCGIFCONF, struct.pack('iL', max_bytes, buff.buffer_info()[0])) retbytes = struct.unpack('iL', info)[0] buffstr = buff.tostring() if platform.system() == 'Linux': local_addrs = [socket.inet_ntoa(buffstr[i+20:i+24]) for i in range(0, retbytes, ifsize)] else: # in FreeBSD, ifsize is variable: 16 + (16 or 28 or 56) bytes # When ifsize is 32 bytes, it contains the interface name and address, # else it contains the interface name and other information # This means the buffer must be traversed in its entirety local_addrs = [] bufpos = 0 while bufpos < retbytes: bufpos += 16 ifreqsize = ord(buffstr[bufpos]) if ifreqsize == 16: local_addrs += [socket.inet_ntoa(buffstr[bufpos+4:bufpos+8])] bufpos += ifreqsize else: # cross-platform branch, can only resolve one address local_addrs = [socket.gethostbyname(socket.gethostname())] _local_addrs = local_addrs return local_addrs def get_bind_address(address=None): """ @param address: (optional) address to compare against @type address: str @return: address TCP/IP sockets should use for binding. This is generally 0.0.0.0, but if \a address or ROS_IP/ROS_HOSTNAME is set to localhost it will return 127.0.0.1 @rtype: str """ if address is None: address = get_address_override() if address and (address == 'localhost' or address.startswith('127.')): # localhost or 127/8 return '127.0.0.1' # loopback else: return '0.0.0.0' # #528: semi-complicated logic for determining XML-RPC URI def get_host_name(): """ Determine host-name for use in host-name-based addressing (e.g. XML-RPC URIs): - if ROS_IP/ROS_HOSTNAME is set, use that address - if the hostname returns a non-localhost value, use that - use whatever L{get_local_address()} returns """ hostname = get_address_override() if not hostname: try: hostname = socket.gethostname() except Exception: pass if not hostname or hostname == 'localhost' or hostname.startswith('127.'): hostname = get_local_address() return hostname def create_local_xmlrpc_uri(port): """ Determine the XMLRPC URI for local servers. This handles the search logic of checking ROS environment variables, the known hostname, and local interface IP addresses to determine the best possible URI. @param port: port that server is running on @type port: int @return: XMLRPC URI @rtype: str """ # TODO: merge logic in roslib.xmlrpc with this routine # in the future we may not want to be locked to http protocol nor root path return 'http://%s:%s/' % (get_host_name(), port) # handshake utils ########################################### class ROSHandshakeException(Exception): """ Exception to represent errors decoding handshake """ pass def decode_ros_handshake_header(header_str): """ Decode serialized ROS handshake header into a Python dictionary header is a list of string key=value pairs, each prefixed by a 4-byte length field. It is preceeded by a 4-byte length field for the entire header. @param header_str: encoded header string. May contain extra data at the end. @type header_str: str @return: key value pairs encoded in \a header_str @rtype: {str: str} """ (size, ) = struct.unpack(' header_len: raise ROSHandshakeException('Incomplete header. Expected %s bytes but only have %s' % ((size+4), header_len)) d = {} start = 4 while start < size: (field_size, ) = struct.unpack(' size: raise ROSHandshakeException('Invalid line length in handshake header: %s' % size) line = header_str[start-field_size:start] # python3 compatibility if python3 == 1: line = line.decode() idx = line.find('=') if idx < 0: raise ROSHandshakeException('Invalid line in handshake header: [%s]' % line) key = line[:idx] value = line[idx+1:] d[key.strip()] = value return d def read_ros_handshake_header(sock, b, buff_size): """ Read in tcpros header off the socket \a sock using buffer \a b. @param sock: socket must be in blocking mode @type sock: socket @param b: buffer to use @type b: StringIO for Python2, BytesIO for Python 3 @param buff_size: incoming buffer size to use @type buff_size: int @return: key value pairs encoded in handshake @rtype: {str: str} @raise ROSHandshakeException: If header format does not match expected """ header_str = None while not header_str: d = sock.recv(buff_size) if not d: raise ROSHandshakeException('connection from sender terminated before handshake header received. %s bytes were received. Please check sender for additional details.' % b.tell()) b.write(d) btell = b.tell() if btell > 4: # most likely we will get the full header in the first recv, so # not worth tiny optimizations possible here bval = b.getvalue() (size,) = struct.unpack('= size: header_str = bval # memmove the remnants of the buffer back to the start leftovers = bval[size+4:] b.truncate(len(leftovers)) b.seek(0) b.write(leftovers) # process the header return decode_ros_handshake_header(bval) def encode_ros_handshake_header(header): """ Encode ROS handshake header as a byte string. Each header field is a string key value pair. The encoded header is prefixed by a length field, as is each field key/value pair. key/value pairs a separated by a '=' equals sign. FORMAT: (4-byte length + [4-byte field length + field=value ]*) @param header: header field keys/values @type header: dict @return: header encoded as byte string @rtype: str """ fields = ['%s=%s' % (k, v) for k, v in header.items()] # in the usual configuration, the error 'TypeError: can't concat bytes to str' appears: if python3 == 0: # python 2 s = ''.join(['%s%s' % (struct.pack('bool """ package = os.path.basename(package_dir) resources = [] dir = roslib.packages._get_pkg_subdir_by_dir(package_dir, subdir, False) if os.path.isdir(dir): resources = [roslib.names.resource_name(package, f, my_pkg=package) for f in os.listdir(dir) if rfilter(os.path.join(dir, f))] else: resources = [] if include_depends: depends = _get_manifest_by_dir(package_dir).depends dirs = [roslib.packages.get_pkg_subdir(d.package, subdir, False) for d in depends] for (dep, dir_) in zip(depends, dirs): # py3k if not dir_ or not os.path.isdir(dir_): continue resources.extend( [roslib.names.resource_name(dep.package, f, my_pkg=package) for f in os.listdir(dir_) if rfilter(os.path.join(dir_, f))]) return resources def list_package_resources(package, include_depends, subdir, rfilter=os.path.isfile): """ List resources in a package within a particular subdirectory. This is useful for listing messages, services, etc... @param package: package name @type package: str @param subdir: name of subdirectory @type subdir: str @param include_depends: if True, include resources in dependencies as well @type include_depends: bool @param rfilter: resource filter function that returns true if filename is the desired resource type @type rfilter: fn(filename)->bool """ package_dir = roslib.packages.get_pkg_dir(package) return list_package_resources_by_dir(package_dir, include_depends, subdir, rfilter) ros-1.15.8/core/roslib/src/roslib/rosenv.py000066400000000000000000000171171407615046500206210ustar00rootroot00000000000000# Software License Agreement (BSD License) # # Copyright (c) 2008, Willow Garage, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following # disclaimer in the documentation and/or other materials provided # with the distribution. # * Neither the name of Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # # Revision $Id$ """ Warning: do not use this library. It is unstable and most of the routines here have been superseded by other libraries (e.g. rospkg). These routines will likely be *deleted* in future releases. """ import os import sys import warnings # Global, usually set in setup ROS_ROOT = 'ROS_ROOT' ROS_MASTER_URI = 'ROS_MASTER_URI' ROS_PACKAGE_PATH = 'ROS_PACKAGE_PATH' ROS_HOME = 'ROS_HOME' # Build-related ROS_BINDEPS_PATH = 'ROS_BINDEPS_PATH' ROS_BOOST_ROOT = 'ROS_BOOST_ROOT' # Per session # hostname/address to bind XML-RPC services to. ROS_IP = 'ROS_IP' ROS_HOSTNAME = 'ROS_HOSTNAME' ROS_NAMESPACE = 'ROS_NAMESPACE' # directory in which log files are written ROS_LOG_DIR = 'ROS_LOG_DIR' class ROSEnvException(Exception): """Base class of roslib.rosenv errors.""" pass warnings.warn('roslib.rosenv is deprecated, please use rospkg or rosgraph.rosenv', stacklevel=2) def get_ros_root(required=True, env=None): """ @param required: (default True). If True, ROS_ROOT must be set and point to a valid directory. @type required: bool @param env: override environment dictionary @type env: dict @raise ROSEnvException: if required is True and ROS_ROOT is not set """ if env is None: env = os.environ p = None try: if ROS_ROOT not in env: raise ROSEnvException(""" The %(ROS_ROOT)s environment variable has not been set. Please set to the location of your ROS installation before continuing. """ % globals()) return env[ROS_ROOT] except Exception: if required: raise return p def get_ros_package_path(required=False, env=None): """ @param required: (default False) if True, ROS_PACKAGE_PATH must be set and point to a valid directory. @type required: bool @raise ROSEnvException: if ROS_PACKAGE_PATH is not set and \a required is True """ if env is None: env = os.environ try: return env[ROS_PACKAGE_PATH] except KeyError: if required: raise ROSEnvException('%s has not been configured' % ROS_PACKAGE_PATH) def get_master_uri(required=True, env=None, argv=None): """ Get the ROS_MASTER_URI setting from the command-line args or environment, command-line args takes precedence. @param required: if True, enables exception raising @type required: bool @param env: override environment dictionary @type env: dict @param argv: override sys.argv @type argv: [str] @raise ROSEnvException: if ROS_MASTER_URI value is invalidly specified or if required and ROS_MASTER_URI is not set """ if env is None: env = os.environ if argv is None: argv = sys.argv try: for arg in argv: if arg.startswith('__master:='): val = None try: _, val = arg.split(':=') except Exception: pass # we ignore required here because there really is no # correct return value as the configuration is bad # rather than unspecified if not val: raise ROSEnvException("__master remapping argument '%s' improperly specified" % arg) return val return env[ROS_MASTER_URI] except KeyError: if required: raise ROSEnvException('%s has not been configured' % ROS_MASTER_URI) def get_ros_home(env=None): """ Get directory location of '.ros' directory (aka ROS home). possible locations for this. The ROS_LOG_DIR environment variable has priority. If that is not set, then ROS_HOME/log is used. If ROS_HOME is not set, $HOME/.ros/log is used. @param env: override os.environ dictionary @type env: dict @return: path to use use for log file directory @rtype: str """ if env is None: env = os.environ if ROS_HOME in env: return env[ROS_HOME] else: # slightly more robust than $HOME return os.path.join(os.path.expanduser('~'), '.ros') def get_log_dir(env=None): """ Get directory to use for writing log files. There are multiple possible locations for this. The ROS_LOG_DIR environment variable has priority. If that is not set, then ROS_HOME/log is used. If ROS_HOME is not set, $HOME/.ros/log is used. @param env: override os.environ dictionary @type env: dict @return: path to use use for log file directory @rtype: str """ if env is None: env = os.environ if ROS_LOG_DIR in env: return env[ROS_LOG_DIR] else: return os.path.join(get_ros_home(env), 'log') def get_test_results_dir(env=None): """ Get directory to use for writing test result files. There are multiple possible locations for this. If ROS_HOME is set ROS_HOME/test_results is used. Otherwise $HOME/.ros/test_results is used. @param env: environment dictionary (defaults to os.environ) @type env: dict @return: path to use use for log file directory @rtype: str """ return os.path.join(get_ros_home(env), 'test_results') # this is a copy of the roslogging utility. it's been moved here as it is a common # routine for programs using accessing ROS directories def makedirs_with_parent_perms(p): """ Create the directory using the permissions of the nearest (existing) parent directory. This is useful for logging, where a root process sometimes has to log in the user's space. @param p: directory to create @type p: str """ p = os.path.abspath(p) parent = os.path.dirname(p) # recurse upwards, checking to make sure we haven't reached the # top if not os.path.exists(p) and p and parent != p: makedirs_with_parent_perms(parent) s = os.stat(parent) os.mkdir(p) # if perms of new dir don't match, set anew s2 = os.stat(p) if s.st_uid != s2.st_uid or s.st_gid != s2.st_gid: os.chown(p, s.st_uid, s.st_gid) if s.st_mode != s2.st_mode: os.chmod(p, s.st_mode) ros-1.15.8/core/roslib/src/roslib/rospack.py000066400000000000000000000130771407615046500207500ustar00rootroot00000000000000# Software License Agreement (BSD License) # # Copyright (c) 2008, Willow Garage, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following # disclaimer in the documentation and/or other materials provided # with the distribution. # * Neither the name of Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # # Revision $Id$ # $Author$ """ Warning: do not use this library. It is unstable and most of the routines here have been superseded by other libraries (e.g. rospkg). These routines will likely be *deleted* in future releases. """ import subprocess import sys import warnings import roslib.exceptions import rospkg # noqa: F401 if sys.hexversion > 0x03000000: # Python3 python3 = True else: python3 = False warnings.warn('roslib.rospack is deprecated, please use rospkg', stacklevel=2) def rospackexec(args): """ @return: result of executing rospack command (via subprocess). string will be strip()ed. @rtype: str @raise roslib.exceptions.ROSLibException: if rospack command fails """ rospack_bin = 'rospack' if python3: val = subprocess.Popen([rospack_bin] + args, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()[0] val = val.decode().strip() else: val = (subprocess.Popen([rospack_bin] + args, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()[0] or '').strip() if val.startswith('rospack:'): # rospack error message raise roslib.exceptions.ROSLibException(val) return val def rospack_depends_on_1(pkg): """ @param pkg: package name @type pkg: str @return: A list of the names of the packages which depend directly on pkg @rtype: list """ return rospackexec(['depends-on1', pkg]).split() def rospack_depends_on(pkg): """ @param pkg: package name @type pkg: str @return: A list of the names of the packages which depend on pkg @rtype: list """ return rospackexec(['depends-on', pkg]).split() def rospack_depends_1(pkg): """ @param pkg: package name @type pkg: str @return: A list of the names of the packages which pkg directly depends on @rtype: list """ return rospackexec(['deps1', pkg]).split() def rospack_depends(pkg): """ @param pkg: package name @type pkg: str @return: A list of the names of the packages which pkg depends on @rtype: list """ return rospackexec(['deps', pkg]).split() def rospack_plugins(pkg): """ @param pkg: package name @type pkg: str @return: A list of the names of the packages which provide a plugin for pkg @rtype: list """ val = rospackexec(['plugins', '--attrib=plugin', pkg]) if val: return [tuple(x.split(' ')) for x in val.split('\n')] else: return [] def rosstackexec(args): """ @return: result of executing rosstack command (via subprocess). string will be strip()ed. @rtype: str @raise roslib.exceptions.ROSLibException: if rosstack command fails """ rosstack_bin = 'rosstack' if python3: val = subprocess.Popen([rosstack_bin] + args, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()[0] val = val.decode().strip() else: val = (subprocess.Popen([rosstack_bin] + args, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()[0] or '').strip() if val.startswith('rosstack:'): # rospack error message raise roslib.exceptions.ROSLibException(val) return val def rosstack_depends_on(s): """ @param s: stack name @type s: str @return: A list of the names of the stacks which depend on s @rtype: list """ return rosstackexec(['depends-on', s]).split() def rosstack_depends_on_1(s): """ @param s: stack name @type s: str @return: A list of the names of the stacks which depend directly on s @rtype: list """ return rosstackexec(['depends-on1', s]).split() def rosstack_depends(s): """ @param s: stack name @type s: str @return: A list of the names of the stacks which s depends on @rtype: list """ return rosstackexec(['depends', s]).split() def rosstack_depends_1(s): """ @param s: stack name @type s: str @return: A list of the names of the stacks which s depends on directly @rtype: list """ return rosstackexec(['depends1', s]).split() ros-1.15.8/core/roslib/src/roslib/scriptutil.py000066400000000000000000000101151407615046500214760ustar00rootroot00000000000000# Software License Agreement (BSD License) # # Copyright (c) 2008, Willow Garage, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following # disclaimer in the documentation and/or other materials provided # with the distribution. # * Neither the name of Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # # Revision $Id$ # $Author$ """ Warning: do not use this library. It is unstable and most of the routines here have been superseded by other libraries (e.g. rospkg). These routines will likely be *deleted* in future releases. """ import os import warnings import roslib.names # caller ID for master calls where caller ID is not vital _GLOBAL_CALLER_ID = '/script' def deprecated(func): """This is a decorator which can be used to mark functions as deprecated. It will result in a warning being emitted when the function is used.""" def newFunc(*args, **kwargs): warnings.warn('Call to deprecated function %s.' % func.__name__, category=DeprecationWarning, stacklevel=2) return func(*args, **kwargs) newFunc.__name__ = func.__name__ newFunc.__doc__ = func.__doc__ newFunc.__dict__.update(func.__dict__) return newFunc @deprecated def script_resolve_name(script_name, name): """ Name resolver for scripts. Supports ROS_NAMESPACE. Does not support remapping arguments. @param name: name to resolve @type name: str @param script_name: name of script. script_name must not contain a namespace. @type script_name: str @return: resolved name @rtype: str """ if not name: # empty string resolves to namespace return roslib.names.get_ros_namespace() # Check for global name: /foo/name resolves to /foo/name if roslib.names.is_global(name): return name # Check for private name: ~name resolves to /caller_id/name elif roslib.names.is_private(name): return roslib.names.ns_join(roslib.names.make_caller_id(script_name), name[1:]) return roslib.names.get_ros_namespace() + name @deprecated def get_master(): """ Get an XMLRPC handle to the Master. It is recommended to use the `rosgraph.masterapi` library instead, as it provides many conveniences. @return: XML-RPC proxy to ROS master @rtype: xmlrpclib.ServerProxy @raises ValueError if master URI is invalid """ try: import xmlrpc.client as xmlrpcclient # Python 3.x except ImportError: import xmlrpclib as xmlrpcclient # Python 2.x # changed this to not look as sys args and remove dependency on roslib.rosenv for cleaner cleanup uri = os.environ['ROS_MASTER_URI'] return xmlrpcclient.ServerProxy(uri) @deprecated def get_param_server(): """ @return: ServerProxy XML-RPC proxy to ROS parameter server @rtype: xmlrpclib.ServerProxy """ return get_master() ros-1.15.8/core/roslib/src/roslib/srvs.py000066400000000000000000000176201407615046500203010ustar00rootroot00000000000000# Software License Agreement (BSD License) # # Copyright (c) 2008, Willow Garage, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following # disclaimer in the documentation and/or other materials provided # with the distribution. # * Neither the name of Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # # Revision $Id$ # $Author$ """ ROS Service Description Language Spec Implements U{http://ros.org/wiki/srv} """ import os import sys try: from cStringIO import StringIO # Python 2.x except ImportError: from io import StringIO # Python 3.x # don't directly use code from this, though we do depend on the # manifest.Depend data type import roslib.manifest import roslib.msgs import roslib.names import roslib.packages import roslib.resources # file extension EXT = '.srv' # alias SEP = '/' # e.g. std_msgs/String # input/output deliminator IODELIM = '---' COMMENTCHAR = roslib.msgs.COMMENTCHAR VERBOSE = False # @return: True if msg-related scripts should print verbose output def is_verbose(): return VERBOSE # set whether msg-related scripts should print verbose output def set_verbose(v): global VERBOSE VERBOSE = v class SrvSpecException(Exception): pass # msg spec representation ########################################## class SrvSpec(object): def __init__(self, request, response, text, full_name='', short_name='', package=''): self.request = request self.response = response self.text = text self.full_name = full_name self.short_name = short_name self.package = package def __eq__(self, other): if not other or not isinstance(other, SrvSpec): return False return self.request == other.request and \ self.response == other.response and \ self.text == other.text and \ self.full_name == other.full_name and \ self.short_name == other.short_name and \ self.package == other.package def __ne__(self, other): if not other or not isinstance(other, SrvSpec): return True return not self.__eq__(other) def __repr__(self): return 'SrvSpec[%s, %s]' % (repr(self.request), repr(self.response)) # srv spec loading utilities ########################################## # @internal # predicate for filtering directory list. matches message files def _srv_filter(f): return os.path.isfile(f) and f.endswith(EXT) # also used by doxymaker def list_srv_types(package, include_depends): """ list all services in the specified package @param package: name of package to search @type package: str @param include_depends: if True, will also list services in package dependencies @type include_depends: bool @return: service type names @rtype: [str] """ types = roslib.resources.list_package_resources(package, include_depends, 'srv', _srv_filter) return [x[:-len(EXT)] for x in types] def srv_file(package, type_): """ @param package: name of package .srv file is in @type package: str @param type_: type name of service @type type_: str @return: file path of .srv file in specified package @rtype: str """ return roslib.packages.resource_file(package, 'srv', type_+EXT) def get_pkg_srv_specs(package): """ List all messages that a package contains @param depend: roslib.manifest.Depend object representing package to load messages from @type depend: Depend @return: list of message type names and specs for package, as well as a list of message names that could not be processed. @rtype: [(str,roslib.MsgSpec), [str]] """ # almost identical to roslib.msgs.get_pkg_msg_specs types = list_srv_types(package, False) specs = [] # no fancy list comprehension as we want to show errors failures = [] for t in types: try: spec = load_from_file(srv_file(package, t), package) specs.append(spec) except Exception: failures.append(t) sys.stderr.write('ERROR: unable to load %s\n' % (t)) return specs, failures def load_from_string(text, package_context='', full_name='', short_name=''): """ @param text: .msg text @type text: str @param package_context: context to use for msgTypeName, i.e. the package name, or '' to use local naming convention. @type package_context: str @return: Message type name and message specification @rtype: roslib.MsgSpec @raise roslib.MsgSpecException: if syntax errors or other problems are detected in file """ text_in = StringIO() text_out = StringIO() accum = text_in for l in text.split('\n'): l = l.split(COMMENTCHAR)[0].strip() # strip comments if l.startswith(IODELIM): # lenient, by request accum = text_out else: accum.write(l+'\n') # create separate roslib.msgs objects for each half of file msg_in = roslib.msgs.load_from_string(text_in.getvalue(), package_context, '%sRequest' % (full_name), '%sRequest' % (short_name)) msg_out = roslib.msgs.load_from_string(text_out.getvalue(), package_context, '%sResponse' % (full_name), '%sResponse' % (short_name)) return SrvSpec(msg_in, msg_out, text, full_name, short_name, package_context) def load_from_file(file_name, package_context=''): """ Convert the .srv representation in the file to a SrvSpec instance. @param file_name: name of file to load from @type file_name: str @param package_context: context to use for type name, i.e. the package name, or '' to use local naming convention. @type package_context: str @return: Message type name and message specification @rtype: (str, L{SrvSpec}) @raise SrvSpecException: if syntax errors or other problems are detected in file """ if VERBOSE: if package_context: sys.stdout.write('Load spec from %s into namespace [%s]\n' % (file_name, package_context)) else: sys.stdout.write('Load spec from %s\n' % (file_name)) base_file_name = os.path.basename(file_name) type_ = base_file_name[:-len(EXT)] base_type_ = type_ # determine the type name if package_context: while package_context.endswith(SEP): package_context = package_context[:-1] # strip message separators type_ = '%s%s%s' % (package_context, SEP, type_) if not roslib.names.is_legal_resource_name(type_): raise SrvSpecException('%s: %s is not a legal service type name' % (file_name, type_)) f = open(file_name, 'r') try: text = f.read() return (type_, load_from_string(text, package_context, type_, base_type_)) finally: f.close() ros-1.15.8/core/roslib/src/roslib/stack_manifest.py000066400000000000000000000101651407615046500222740ustar00rootroot00000000000000#! /usr/bin/env python # Software License Agreement (BSD License) # # Copyright (c) 2008, Willow Garage, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following # disclaimer in the documentation and/or other materials provided # with the distribution. # * Neither the name of Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # # Revision $Id$ # $Author$ """ Warning: do not use this library. It is unstable and most of the routines here have been superseded by other libraries (e.g. rospkg). These routines will likely be *deleted* in future releases. """ import os import roslib.manifestlib # re-export symbols so that external code does not have to import manifestlib as well from roslib.manifestlib import ManifestException # noqa: F401 from roslib.manifestlib import StackDepend # noqa: F401 STACK_FILE = 'stack.xml' class StackManifest(roslib.manifestlib._Manifest): """ Object representation of a ROS manifest file """ __slots__ = [] def __init__(self): """ Create an empty stack manifest instance. """ super(StackManifest, self).__init__('stack') def _stack_file_by_dir(stack_dir, required=True): """ @param stack_dir: path to stack directory @type stack_dir: str @param required: require that the directory exist @type required: bool @return: path to manifest file of stack @rtype: str @raise InvalidROSPkgException: if required is True and manifest file cannot be located """ try: p = os.path.join(stack_dir, STACK_FILE) if not required and not os.path.exists(p): return p if not os.path.isfile(p): raise roslib.stacks.InvalidROSStackException(""" Stack '%(stack_dir)s' is improperly configured: no manifest file is present. """ % locals()) return p except roslib.stacks.InvalidROSStackException: if required: raise def stack_file(stack, required=True): """ @param stack: stack name @type stack: str @param required: require that the directory exist @type required: bool @return: path to manifest file of stack @rtype: str @raise InvalidROSPkgException: if required is True and manifest file cannot be located """ d = roslib.stacks.get_stack_dir(stack) return _stack_file_by_dir(d, required) def parse_file(file): """ Parse stack.xml file @param file: stack.xml file path @param file: str @return: StackManifest instance @rtype: L{StackManifest} """ return roslib.manifestlib.parse_file(StackManifest(), file) def parse(string, filename='string'): """ Parse stack.xml string contents @param string: stack.xml contents @type string: str @return: StackManifest instance @rtype: L{StackManifest} """ s = roslib.manifestlib.parse(StackManifest(), string, filename) # TODO: validate return s ros-1.15.8/core/roslib/src/roslib/stacks.py000066400000000000000000000201601407615046500205650ustar00rootroot00000000000000#! /usr/bin/env python # Software License Agreement (BSD License) # # Copyright (c) 2008, Willow Garage, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following # disclaimer in the documentation and/or other materials provided # with the distribution. # * Neither the name of Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # # Revision $Id$ """ Warning: do not use this library. It is unstable and most of the routines here have been superseded by other libraries (e.g. rospkg). These routines will likely be *deleted* in future releases. """ import os import re import roslib.packages import roslib.stack_manifest import rospkg ROS_ROOT = rospkg.environment.ROS_ROOT ROS_PACKAGE_PATH = rospkg.environment.ROS_PACKAGE_PATH STACK_FILE = 'stack.xml' ROS_STACK = 'ros' class ROSStackException(Exception): pass class InvalidROSStackException(ROSStackException): pass def stack_of(pkg, env=None): """ @param env: override environment variables @type env: {str: str} @return: name of stack that pkg is in, or None if pkg is not part of a stack @rtype: str @raise roslib.packages.InvalidROSPkgException: if pkg cannot be located """ if env is None: env = os.environ pkg_dir = roslib.packages.get_pkg_dir(pkg, ros_root=env[ROS_ROOT], ros_package_path=env.get(ROS_PACKAGE_PATH, None)) d = pkg_dir while d and os.path.dirname(d) != d: stack_file = os.path.join(d, STACK_FILE) if os.path.exists(stack_file): # TODO: need to resolve issues regarding whether the # stack.xml or the directory defines the stack name return os.path.basename(d) d = os.path.dirname(d) def get_stack_dir(stack, env=None): """ Get the directory of a ROS stack. This will initialize an internal cache and return cached results if possible. This routine is not thread-safe to os.environ changes. @param env: override environment variables @type env: {str: str} @param stack: name of ROS stack to locate on disk @type stack: str @return: directory of stack. @rtype: str @raise InvalidROSStackException: if stack cannot be located. """ _init_rosstack(env=env) try: return _rosstack.get_path(stack) except rospkg.ResourceNotFound: # preserve old signature raise InvalidROSStackException(stack) _rosstack = None _ros_paths = None def _init_rosstack(env=None): global _rosstack, _ros_paths if env is None: env = os.environ ros_paths = rospkg.get_ros_paths(env) if ros_paths != _ros_paths: _ros_paths = ros_paths _rosstack = rospkg.RosStack(ros_paths) def list_stacks(env=None): """ Get list of all ROS stacks. This uses an internal cache. This routine is not thread-safe to os.environ changes. @param env: override environment variables @type env: {str: str} @return: complete list of stacks names in ROS environment @rtype: [str] """ _init_rosstack(env=env) return _rosstack.list() def list_stacks_by_path(path, stacks=None, cache=None): """ List ROS stacks within the specified path. Optionally, a cache dictionary can be provided, which will be updated with the stack->path mappings. list_stacks_by_path() does NOT returned cached results -- it only updates the cache. @param path: path to list stacks in @type path: str @param stacks: list of stacks to append to. If stack is already present in stacks, it will be ignored. @type stacks: [str] @param cache: (optional) stack path cache to update. Maps stack name to directory path. @type cache: {str: str} @return: complete list of stack names in ROS environment. Same as stacks parameter. @rtype: [str] """ if stacks is None: stacks = [] MANIFEST_FILE = rospkg.MANIFEST_FILE basename = os.path.basename for d, dirs, files in os.walk(path, topdown=True): if STACK_FILE in files: stack = basename(d) if stack not in stacks: stacks.append(stack) if cache is not None: cache[stack] = d del dirs[:] continue # leaf elif MANIFEST_FILE in files: del dirs[:] continue # leaf elif 'rospack_nosubdirs' in files: del dirs[:] continue # leaf # remove hidden dirs (esp. .svn/.git) [dirs.remove(di) for di in dirs if di[0] == '.'] for sub_d in dirs: # followlinks=True only available in Python 2.6, so we # have to implement manually sub_p = os.path.join(d, sub_d) if os.path.islink(sub_p): stacks.extend(list_stacks_by_path(sub_p, cache=cache)) return stacks # #2022 def expand_to_packages(names, env=None): """ Expand names into a list of packages. Names can either be of packages or stacks. @param names: names of stacks or packages @type names: [str] @return: ([packages], [not_found]). expand_packages() returns two lists. The first is of packages names. The second is a list of names for which no matching stack or package was found. Lists may have duplicates. @rtype: ([str], [str]) """ if env is None: env = os.environ ros_paths = rospkg.get_ros_paths(env) rospack = rospkg.RosPack(ros_paths) rosstack = rospkg.RosStack(ros_paths) return rospkg.expand_to_packages(names, rospack, rosstack) def get_stack_version(stack, env=None): """ @param env: override environment variables @type env: {str: str} @return: version number of stack, or None if stack is unversioned. @rtype: str """ _init_rosstack(env=env) return _rosstack.get_stack_version(stack) def get_stack_version_by_dir(stack_dir): """ Get stack version where stack_dir points to root directory of stack. @param env: override environment variables @type env: {str: str} @return: version number of stack, or None if stack is unversioned. @rtype: str """ # REP 109: check for tag first, then CMakeLists.txt manifest_filename = os.path.join(stack_dir, STACK_FILE) if os.path.isfile(manifest_filename): m = roslib.stack_manifest.parse_file(manifest_filename) if m.version: return m.version cmake_filename = os.path.join(stack_dir, 'CMakeLists.txt') if os.path.isfile(cmake_filename): with open(cmake_filename) as f: return _get_cmake_version(f.read()) else: return None def _get_cmake_version(text): for l in text.split('\n'): if l.strip().startswith('rosbuild_make_distribution'): x_re = re.compile(r'[()]') lsplit = x_re.split(l.strip()) if len(lsplit) < 2: raise ReleaseException("couldn't find version number in CMakeLists.txt:\n\n%s" % l) return lsplit[1] ros-1.15.8/core/roslib/test/000077500000000000000000000000001407615046500156225ustar00rootroot00000000000000ros-1.15.8/core/roslib/test/__init__.py000066400000000000000000000000001407615046500177210ustar00rootroot00000000000000ros-1.15.8/core/roslib/test/fake_node.py000077500000000000000000000001361407615046500201120ustar00rootroot00000000000000#!/usr/bin/env python # this node only exists to test find_node functionality print('hello') ros-1.15.8/core/roslib/test/manifest_tests/000077500000000000000000000000001407615046500206525ustar00rootroot00000000000000ros-1.15.8/core/roslib/test/manifest_tests/bad-package-version.xml000066400000000000000000000012601407615046500251750ustar00rootroot00000000000000 Line 1 Line 2 1.2.4 The authors go here Public Domain with other stuff http://pr.willowgarage.com/package/ http://www.willowgarage.com/files/willowgarage/robot10.jpg ros-1.15.8/core/roslib/test/manifest_tests/bad1.xml000066400000000000000000000000101407615046500221720ustar00rootroot00000000000000not xml ros-1.15.8/core/roslib/test/manifest_tests/bad2.xml000066400000000000000000000012161407615046500222040ustar00rootroot00000000000000 Line 1 Line 2 The authors go here Public Domain with other stuff http://pr.willowgarage.com/package/ http://www.willowgarage.com/files/willowgarage/robot10.jpg ros-1.15.8/core/roslib/test/manifest_tests/bad3.xml000066400000000000000000000004121407615046500222020ustar00rootroot00000000000000 Line 1 Second description The authors go here Public Domain with other stuff ros-1.15.8/core/roslib/test/manifest_tests/example1.xml000066400000000000000000000012101407615046500231020ustar00rootroot00000000000000 Line 1 Line 2 The authors go here Public Domain with other stuff http://pr.willowgarage.com/package/ http://www.willowgarage.com/files/willowgarage/robot10.jpg ros-1.15.8/core/roslib/test/manifest_tests/stack_example1.xml000066400000000000000000000005351407615046500243000ustar00rootroot00000000000000 Line 1 Line 2 The authors go here Public Domain with other stuff http://ros.org/stack/ http://www.willowgarage.com/files/willowgarage/robot10.jpg ros-1.15.8/core/roslib/test/manifest_tests/stack_version.xml000066400000000000000000000005701407615046500242500ustar00rootroot00000000000000 Line 1 Line 2 The authors go here Public Domain with other stuff http://ros.org/stack/ 1.2.3 http://www.willowgarage.com/files/willowgarage/robot10.jpg ros-1.15.8/core/roslib/test/package.cpp000066400000000000000000000043251407615046500177250ustar00rootroot00000000000000/* * Copyright (c) 2008, Willow Garage, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of Willow Garage, Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include #include using namespace ros; TEST(Package, getPath) { std::string path = package::getPath("roslib"); printf("Path: %s\n", path.c_str()); ASSERT_FALSE(path.empty()); } TEST(Package, getAll) { using package::V_string; V_string packages; ASSERT_TRUE(package::getAll(packages)); ASSERT_FALSE(packages.empty()); V_string::iterator it = packages.begin(); V_string::iterator end = packages.end(); for (; it != end; ++it) { printf("Package: %s\n", it->c_str()); } } int main(int argc, char **argv){ testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } ros-1.15.8/core/roslib/test/package_tests/000077500000000000000000000000001407615046500204375ustar00rootroot00000000000000ros-1.15.8/core/roslib/test/package_tests/p1/000077500000000000000000000000001407615046500207575ustar00rootroot00000000000000ros-1.15.8/core/roslib/test/package_tests/p1/bar/000077500000000000000000000000001407615046500215235ustar00rootroot00000000000000ros-1.15.8/core/roslib/test/package_tests/p1/bar/manifest.xml000066400000000000000000000003231407615046500240510ustar00rootroot00000000000000 bar Ken Conley BSD http://ros.org/wiki/bar ros-1.15.8/core/roslib/test/package_tests/p1/foo/000077500000000000000000000000001407615046500215425ustar00rootroot00000000000000ros-1.15.8/core/roslib/test/package_tests/p1/foo/manifest.xml000066400000000000000000000003231407615046500240700ustar00rootroot00000000000000 foo Ken Conley BSD http://ros.org/wiki/foo ros-1.15.8/core/roslib/test/package_tests/p2/000077500000000000000000000000001407615046500207605ustar00rootroot00000000000000ros-1.15.8/core/roslib/test/package_tests/p2/foo/000077500000000000000000000000001407615046500215435ustar00rootroot00000000000000ros-1.15.8/core/roslib/test/package_tests/p2/foo/manifest.xml000066400000000000000000000003231407615046500240710ustar00rootroot00000000000000 foo Ken Conley BSD http://ros.org/wiki/foo ros-1.15.8/core/roslib/test/platform_supported.manifest.xml000066400000000000000000000003551407615046500241050ustar00rootroot00000000000000 Unit tests verifying that roslib is operating as expected. none BSD ros-1.15.8/core/roslib/test/stack_tests/000077500000000000000000000000001407615046500201515ustar00rootroot00000000000000ros-1.15.8/core/roslib/test/stack_tests/s1/000077500000000000000000000000001407615046500204745ustar00rootroot00000000000000ros-1.15.8/core/roslib/test/stack_tests/s1/bar/000077500000000000000000000000001407615046500212405ustar00rootroot00000000000000ros-1.15.8/core/roslib/test/stack_tests/s1/bar/CMakeLists.txt000066400000000000000000000002361407615046500240010ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.0.2) include($ENV{ROS_ROOT}/core/rosbuild/rosbuild.cmake) set(ROSPACK_MAKEDIST true) rosbuild_make_distribution(1.5.0-cmake) ros-1.15.8/core/roslib/test/stack_tests/s1/bar/stack.xml000066400000000000000000000001761407615046500230730ustar00rootroot00000000000000 bar Ken Conley BSD ros-1.15.8/core/roslib/test/stack_tests/s1/foo/000077500000000000000000000000001407615046500212575ustar00rootroot00000000000000ros-1.15.8/core/roslib/test/stack_tests/s1/foo/CMakeLists.txt000066400000000000000000000002361407615046500240200ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.0.2) include($ENV{ROS_ROOT}/core/rosbuild/rosbuild.cmake) set(ROSPACK_MAKEDIST true) rosbuild_make_distribution(1.5.0-cmake) ros-1.15.8/core/roslib/test/stack_tests/s1/foo/foo_pkg/000077500000000000000000000000001407615046500227035ustar00rootroot00000000000000ros-1.15.8/core/roslib/test/stack_tests/s1/foo/foo_pkg/manifest.xml000066400000000000000000000003371407615046500252360ustar00rootroot00000000000000 foo_pkg Ken Conley BSD http://ros.org/wiki/foo_pkg ros-1.15.8/core/roslib/test/stack_tests/s1/foo/foo_pkg_2/000077500000000000000000000000001407615046500231245ustar00rootroot00000000000000ros-1.15.8/core/roslib/test/stack_tests/s1/foo/foo_pkg_2/manifest.xml000066400000000000000000000003451407615046500254560ustar00rootroot00000000000000 foo_pkg_2 Ken Conley BSD http://ros.org/wiki/foo_pkg_2 ros-1.15.8/core/roslib/test/stack_tests/s1/foo/stack.xml000066400000000000000000000003151407615046500231050ustar00rootroot00000000000000 foo foo Ken Conley 1.6.0-manifest BSD ros-1.15.8/core/roslib/test/stack_tests/s2/000077500000000000000000000000001407615046500204755ustar00rootroot00000000000000ros-1.15.8/core/roslib/test/stack_tests/s2/foo/000077500000000000000000000000001407615046500212605ustar00rootroot00000000000000ros-1.15.8/core/roslib/test/stack_tests/s2/foo/stack.xml000066400000000000000000000002021407615046500231010ustar00rootroot00000000000000 foo Ken Conley BSD ros-1.15.8/core/roslib/test/stack_tests2/000077500000000000000000000000001407615046500202335ustar00rootroot00000000000000ros-1.15.8/core/roslib/test/stack_tests2/s3000077700000000000000000000000001407615046500235062../stack_tests/s1ustar00rootroot00000000000000ros-1.15.8/core/roslib/test/stack_tests_unary/000077500000000000000000000000001407615046500213675ustar00rootroot00000000000000ros-1.15.8/core/roslib/test/stack_tests_unary/s1/000077500000000000000000000000001407615046500217125ustar00rootroot00000000000000ros-1.15.8/core/roslib/test/stack_tests_unary/s1/bar/000077500000000000000000000000001407615046500224565ustar00rootroot00000000000000ros-1.15.8/core/roslib/test/stack_tests_unary/s1/bar/manifest.xml000066400000000000000000000003501407615046500250040ustar00rootroot00000000000000 Fake No one BSD ros-1.15.8/core/roslib/test/stack_tests_unary/s1/bar/stack.xml000066400000000000000000000001761407615046500243110ustar00rootroot00000000000000 bar Ken Conley BSD ros-1.15.8/core/roslib/test/stack_tests_unary/s1/baz/000077500000000000000000000000001407615046500224665ustar00rootroot00000000000000ros-1.15.8/core/roslib/test/stack_tests_unary/s1/baz/stack.xml000066400000000000000000000001761407615046500243210ustar00rootroot00000000000000 bar Ken Conley BSD ros-1.15.8/core/roslib/test/stack_tests_unary/s1/foo/000077500000000000000000000000001407615046500224755ustar00rootroot00000000000000ros-1.15.8/core/roslib/test/stack_tests_unary/s1/foo/manifest.xml000066400000000000000000000003501407615046500250230ustar00rootroot00000000000000 Fake No one BSD ros-1.15.8/core/roslib/test/stack_tests_unary/s1/foo/stack.xml000066400000000000000000000001761407615046500243300ustar00rootroot00000000000000 foo Ken Conley BSD ros-1.15.8/core/roslib/test/test_roslib.py000066400000000000000000000037731407615046500205370ustar00rootroot00000000000000# Software License Agreement (BSD License) # # Copyright (c) 2009, Willow Garage, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following # disclaimer in the documentation and/or other materials provided # with the distribution. # * Neither the name of Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. def test_load_manifest(): # this is a bit of a noop as it's a prerequisite of running with rosunit import roslib roslib.load_manifest('roslib') def test_interactive(): import roslib # make sure that it's part of high-level API assert not roslib.is_interactive(), 'interactive should be false by default' for v in [True, False]: roslib.set_interactive(v) assert v == roslib.is_interactive() ros-1.15.8/core/roslib/test/test_roslib_exceptions.py000066400000000000000000000033031407615046500227650ustar00rootroot00000000000000# Software License Agreement (BSD License) # # Copyright (c) 2009, Willow Garage, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following # disclaimer in the documentation and/or other materials provided # with the distribution. # * Neither the name of Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. def test_exceptions(): from roslib.exceptions import ROSLibException assert isinstance(ROSLibException(), Exception) ros-1.15.8/core/roslib/test/test_roslib_manifest.py000066400000000000000000000146701407615046500224230ustar00rootroot00000000000000# Software License Agreement (BSD License) # # Copyright (c) 2009, Willow Garage, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following # disclaimer in the documentation and/or other materials provided # with the distribution. # * Neither the name of Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. import os import unittest def get_test_path(): return os.path.abspath(os.path.dirname(__file__)) class RoslibManifestTest(unittest.TestCase): def test_ManifestException(self): from roslib.manifest import ManifestException self.assert_(isinstance(ManifestException(), Exception)) def test_Depend(self): from roslib.manifestlib import Depend for bad in [None, '']: try: Depend(bad) self.fail('should have failed on [%s]' % bad) except ValueError: pass d = Depend('roslib') self.assertEquals('roslib', str(d)) self.assertEquals('roslib', repr(d)) self.assertEquals('', d.xml()) self.assertEquals(d, Depend('roslib')) self.assertNotEquals(d, Depend('roslib2')) self.assertNotEquals(d, 1) def test_ROSDep(self): from roslib.manifest import ROSDep for bad in [None, '']: try: rd = ROSDep(bad) self.fail('should have failed on [%s]' % bad) except ValueError: pass rd = ROSDep('python') self.assertEquals('', rd.xml()) def test_VersionControl(self): from roslib.manifest import VersionControl ros_svn = 'https://ros.svn.sf.net/svnroot' bad = [(None, ros_svn)] for type_, url in bad: try: VersionControl(type_, url) self.fail('should have failed on [%s] [%s]' % (type_, url)) except ValueError: pass tests = [ ('svn', ros_svn, '' % ros_svn), ('cvs', None, ''), ] for type_, url, xml in tests: vc = VersionControl(type_, url) self.assertEquals(type_, vc.type) self.assertEquals(url, vc.url) self.assertEquals(xml, vc.xml()) def _subtest_parse_example1(self, m): from roslib.manifest import Manifest self.assert_(isinstance(m, Manifest)) self.assertEquals('a brief description', m.brief) self.assertEquals('Line 1\nLine 2', m.description.strip()) self.assertEquals('The authors\ngo here', m.author.strip()) self.assertEquals('Public Domain\nwith other stuff', m.license.strip()) self.assertEquals('http://pr.willowgarage.com/package/', m.url) self.assertEquals('http://www.willowgarage.com/files/willowgarage/robot10.jpg', m.logo) dpkgs = [d.package for d in m.depends] self.assertEquals({'pkgname', 'common'}, set(dpkgs)) rdpkgs = [d.name for d in m.rosdeps] self.assertEquals({'python', 'bar', 'baz'}, set(rdpkgs)) def test_parse_example1_file(self): from roslib.manifest import parse_file p = os.path.join(get_test_path(), 'manifest_tests', 'example1.xml') self._subtest_parse_example1(parse_file(p)) def test_parse_example1_string(self): from roslib.manifest import parse self._subtest_parse_example1(parse(EXAMPLE1)) def test_Manifest_str(self): # just make sure it doesn't crash from roslib.manifest import parse str(parse(EXAMPLE1)) def test_Manifest_xml(self): from roslib.manifest import parse m = parse(EXAMPLE1) self._subtest_parse_example1(m) # verify roundtrip m2 = parse(m.xml()) self._subtest_parse_example1(m2) def test_parse_bad_file(self): from roslib.manifest import parse_file # have to import from ManifestException due to weirdness when run in --cov mode from roslib.manifestlib import ManifestException base_p = os.path.join(get_test_path(), 'manifest_tests') for b in ['bad1.xml', 'bad2.xml', 'bad3.xml']: p = os.path.join(base_p, b) try: parse_file(p) self.fail('parse should have failed on bad manifest') except ManifestException as e: print(str(e)) self.assert_(b in str(e), 'file name should be in error message: %s' % (str(e))) EXAMPLE1 = """ Line 1 Line 2 The authors go here Public Domain with other stuff http://pr.willowgarage.com/package/ http://www.willowgarage.com/files/willowgarage/robot10.jpg """ ros-1.15.8/core/roslib/test/test_roslib_manifestlib.py000066400000000000000000000272441407615046500231130ustar00rootroot00000000000000# Software License Agreement (BSD License) # # Copyright (c) 2009, Willow Garage, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following # disclaimer in the documentation and/or other materials provided # with the distribution. # * Neither the name of Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. import os import unittest class RoslibManifestlibTest(unittest.TestCase): def test_ManifestException(self): from roslib.manifestlib import ManifestException self.assert_(isinstance(ManifestException(), Exception)) def test_Platform(self): from roslib.manifestlib import Platform for bad in [None, '']: try: Platform(bad, '1') self.fail('should have failed on [%s]' % bad) except ValueError: pass try: Platform('ubuntu', bad) self.fail('should have failed on [%s]' % bad) except ValueError: pass p = Platform('ubuntu', '8.04') self.assertEquals('ubuntu 8.04', str(p)) self.assertEquals('ubuntu 8.04', repr(p)) self.assertEquals('', p.xml()) self.assertEquals(p, Platform('ubuntu', '8.04')) self.assertEquals(p, Platform('ubuntu', '8.04', notes=None)) self.assertNotEquals(p, Platform('ubuntu', '8.04', 'some notes')) self.assertNotEquals(p, 'foo') self.assertNotEquals(p, 1) # note: probably actually "osx" p = Platform('OS X', '10.6', 'macports') self.assertEquals('OS X 10.6', str(p)) self.assertEquals('OS X 10.6', repr(p)) self.assertEquals('', p.xml()) self.assertEquals(p, p) self.assertEquals(p, Platform('OS X', '10.6', 'macports')) self.assertNotEquals(p, Platform('OS X', '10.6')) self.assertNotEquals(p, 'foo') self.assertNotEquals(p, 1) def test_Depend(self): from roslib.manifestlib import Depend, StackDepend for bad in [None, '']: try: Depend(bad) self.fail('should have failed on [%s]' % bad) except ValueError: pass d = Depend('roslib') self.assertEquals('roslib', str(d)) self.assertEquals('roslib', repr(d)) self.assertEquals('', d.xml()) self.assertEquals(d, Depend('roslib')) self.assertNotEquals(d, StackDepend('roslib')) self.assertNotEquals(d, Depend('roslib2')) self.assertNotEquals(d, 1) def test_StackDepend(self): from roslib.manifestlib import Depend, StackDepend for bad in [None, '']: try: StackDepend(bad) self.fail('should have failed on [%s]' % bad) except ValueError: pass d = StackDepend('common') self.assertEquals('common', str(d)) self.assertEquals('common', repr(d)) self.assertEquals('', d.xml()) self.assertEquals(d, StackDepend('common')) self.assertNotEquals(d, Depend('common')) self.assertNotEquals(d, StackDepend('common2')) self.assertNotEquals(d, 1) def test_ROSDep(self): from roslib.manifestlib import ROSDep for bad in [None, '']: try: rd = ROSDep(bad) self.fail('should have failed on [%s]' % bad) except ValueError: pass rd = ROSDep('python') self.assertEquals('', rd.xml()) def test_VersionControl(self): from roslib.manifestlib import VersionControl ros_svn = 'https://ros.svn.sf.net/svnroot' bad = [ (None, ros_svn), ] for type_, url in bad: try: VersionControl(type_, url) self.fail('should have failed on [%s] [%s]' % (type_, url)) except ValueError: pass tests = [ ('svn', ros_svn, '' % ros_svn), ('cvs', None, ''), ] for type_, url, xml in tests: vc = VersionControl(type_, url) self.assertEquals(type_, vc.type) self.assertEquals(url, vc.url) self.assertEquals(xml, vc.xml()) def _subtest_parse_example1(self, m): from roslib.manifestlib import _Manifest self.assert_(isinstance(m, _Manifest)) self.assertEquals('a brief description', m.brief) self.assertEquals('Line 1\nLine 2', m.description.strip()) self.assertEquals('The authors\ngo here', m.author.strip()) self.assertEquals('Public Domain\nwith other stuff', m.license.strip()) self.assertEquals('http://pr.willowgarage.com/package/', m.url) self.assertEquals('http://www.willowgarage.com/files/willowgarage/robot10.jpg', m.logo) dpkgs = [d.package for d in m.depends] self.assertEquals({'pkgname', 'common'}, set(dpkgs)) rdpkgs = [d.name for d in m.rosdeps] self.assertEquals({'python', 'bar', 'baz'}, set(rdpkgs)) for p in m.platforms: if p.os == 'ubuntu': self.assertEquals('8.04', p.version) self.assertEquals('', p.notes) elif p.os == 'OS X': self.assertEquals('10.6', p.version) self.assertEquals('macports', p.notes) else: self.fail('unknown platform '+str(p)) def _subtest_parse_stack_example1(self, m): from roslib.manifestlib import _Manifest self.assert_(isinstance(m, _Manifest)) self.assertEquals('stack', m._type) self.assertEquals('a brief description', m.brief) self.assertEquals('Line 1\nLine 2', m.description.strip()) self.assertEquals('The authors\ngo here', m.author.strip()) self.assertEquals('Public Domain\nwith other stuff', m.license.strip()) self.assertEquals('http://ros.org/stack/', m.url) self.assertEquals('http://www.willowgarage.com/files/willowgarage/robot10.jpg', m.logo) dpkgs = [d.stack for d in m.depends] self.assertEquals({'stackname', 'common'}, set(dpkgs)) self.assertEquals([], m.rosdeps) self.assertEquals([], m.exports) def _subtest_parse_stack_version(self, m): self.assertEquals('1.2.3', m.version) def test_parse_example1_file(self): from roslib.manifestlib import parse_file, _Manifest p = os.path.join(get_test_path(), 'manifest_tests', 'example1.xml') self._subtest_parse_example1(parse_file(_Manifest(), p)) p = os.path.join(get_test_path(), 'manifest_tests', 'stack_example1.xml') self._subtest_parse_stack_example1(parse_file(_Manifest('stack'), p)) p = os.path.join(get_test_path(), 'manifest_tests', 'stack_version.xml') self._subtest_parse_stack_version(parse_file(_Manifest('stack'), p)) def test_parse_example1_string(self): from roslib.manifestlib import parse, _Manifest self._subtest_parse_example1(parse(_Manifest(), EXAMPLE1)) self._subtest_parse_stack_example1(parse(_Manifest('stack'), STACK_EXAMPLE1)) def test__Manifest(self): from roslib.manifestlib import _Manifest m = _Manifest() # check defaults self.assertEquals('package', m._type) m = _Manifest('stack') self.assertEquals('stack', m._type) def test_Manifest_str(self): # just make sure it doesn't crash from roslib.manifestlib import parse, _Manifest str(parse(_Manifest(), EXAMPLE1)) def test_Manifest_xml(self): from roslib.manifestlib import parse, _Manifest m = _Manifest() parse(m, EXAMPLE1) self._subtest_parse_example1(m) # verify roundtrip m2 = _Manifest() parse(m2, m.xml()) self._subtest_parse_example1(m2) # bad file examples should be more like the roslaunch tests where there is just 1 thing wrong def test_parse_bad_file(self): from roslib.manifestlib import parse_file, _Manifest, ManifestException base_p = os.path.join(get_test_path(), 'manifest_tests') m = _Manifest() for b in ['bad1.xml', 'bad2.xml', 'bad3.xml']: p = os.path.join(base_p, b) try: parse_file(m, p) self.fail('parse should have failed on bad manifest') except ManifestException as e: print(str(e)) self.assert_(b in str(e), 'file name should be in error message [%s]' % (str(e))) EXAMPLE1 = """ Line 1 Line 2 The authors go here Public Domain with other stuff http://pr.willowgarage.com/package/ http://www.willowgarage.com/files/willowgarage/robot10.jpg """ STACK_EXAMPLE1 = """ Line 1 Line 2 The authors go here Public Domain with other stuff http://ros.org/stack/ http://www.willowgarage.com/files/willowgarage/robot10.jpg """ STACK_INVALID1 = """ Line 1 The authors Public Domain """ STACK_INVALID2 = """ Line 1 The authors Public Domain """ def get_test_path(): return os.path.abspath(os.path.dirname(__file__)) ros-1.15.8/core/roslib/test/test_roslib_names.py000066400000000000000000000331331407615046500217130ustar00rootroot00000000000000# Software License Agreement (BSD License) # # Copyright (c) 2009, Willow Garage, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following # disclaimer in the documentation and/or other materials provided # with the distribution. # * Neither the name of Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. import os import sys import unittest import roslib.names class NamesTest(unittest.TestCase): def test_get_ros_namespace(self): if 'ROS_NAMESPACE' in os.environ: rosns = os.environ['ROS_NAMESPACE'] del os.environ['ROS_NAMESPACE'] else: rosns = None sysargv = sys.argv try: sys.argv = [] self.assertEquals('/', roslib.names.get_ros_namespace()) self.assertEquals('/', roslib.names.get_ros_namespace(argv=[])) self.assertEquals('/', roslib.names.get_ros_namespace(env={})) self.assertEquals('/', roslib.names.get_ros_namespace(env={}, argv=[])) os.environ['ROS_NAMESPACE'] = 'unresolved' self.assertEquals('/unresolved/', roslib.names.get_ros_namespace()) self.assertEquals('/unresolved/', roslib.names.get_ros_namespace(env={'ROS_NAMESPACE': 'unresolved'})) sys.argv = ['foo', '__ns:=unresolved_override'] self.assertEquals('/unresolved_override/', roslib.names.get_ros_namespace(env={'ROS_NAMESPACE': 'unresolved'})) self.assertEquals('/override2/', roslib.names.get_ros_namespace(env={'ROS_NAMESPACE': 'unresolved'}, argv=['foo', '__ns:=override2'])) sys.argv = [] os.environ['ROS_NAMESPACE'] = '/resolved/' self.assertEquals('/resolved/', roslib.names.get_ros_namespace()) self.assertEquals('/resolved/', roslib.names.get_ros_namespace(env={'ROS_NAMESPACE': '/resolved'})) del os.environ['ROS_NAMESPACE'] sys.argv = ['foo', '__ns:=unresolved_ns'] self.assertEquals('/unresolved_ns/', roslib.names.get_ros_namespace()) self.assertEquals('/unresolved_ns2/', roslib.names.get_ros_namespace(argv=['foo', '__ns:=unresolved_ns2'])) sys.argv = ['foo', '__ns:=/resolved_ns/'] self.assertEquals('/resolved_ns/', roslib.names.get_ros_namespace()) self.assertEquals('/resolved_ns2/', roslib.names.get_ros_namespace(argv=['foo', '__ns:=resolved_ns2'])) finally: sys.argv = sysargv # restore if rosns: os.environ['ROS_NAMESPACE'] = rosns def test_make_global_ns(self): from roslib.names import make_global_ns for n in ['~foo']: try: make_global_ns(n) self.fail('make_global_ns should fail on %s' % n) except ValueError: pass self.assertEquals('/foo/', make_global_ns('foo')) self.assertEquals('/', make_global_ns('')) self.assertEquals('/foo/', make_global_ns('/foo')) self.assertEquals('/foo/', make_global_ns('/foo/')) self.assertEquals('/foo/bar/', make_global_ns('/foo/bar')) self.assertEquals('/foo/bar/', make_global_ns('/foo/bar/')) def test_is_global(self): try: roslib.names.is_global(None) self.fail('is_global should raise exception on invalid param') except Exception: pass tests = ['/', '/global', '/global2'] for t in tests: self.assert_(roslib.names.is_global(t)) fails = ['', 'not_global', 'not/global'] for t in fails: self.failIf(roslib.names.is_global(t)) def test_is_private(self): try: roslib.names.is_private(None) self.fail('is_private should raise exception on invalid param') except Exception: pass tests = ['~name', '~name/sub'] for t in tests: self.assert_(roslib.names.is_private(t)) fails = ['', 'not_private', 'not/private', 'not/~private', '/not/~private'] for t in fails: self.failIf(roslib.names.is_private(t)) def test_namespace(self): from roslib.names import namespace try: namespace(1) self.fail('1') except TypeError: pass try: namespace(None) self.fail('None') except ValueError: pass self.assertEquals('/', namespace('')) self.assertEquals('/', namespace('/')) self.assertEquals('/', namespace('/foo')) self.assertEquals('/', namespace('/foo/')) self.assertEquals('/foo/', namespace('/foo/bar')) self.assertEquals('/foo/', namespace('/foo/bar/')) self.assertEquals('/foo/bar/', namespace('/foo/bar/baz')) self.assertEquals('/foo/bar/', namespace('/foo/bar/baz/')) # unicode tests self.assertEquals(u'/', namespace(u'')) self.assertEquals(u'/', namespace(u'/')) self.assertEquals(u'/foo/bar/', namespace(u'/foo/bar/baz/')) def test_nsjoin(self): from roslib.names import ns_join # private and global names cannot be joined self.assertEquals('~name', ns_join('/foo', '~name')) self.assertEquals('/name', ns_join('/foo', '/name')) self.assertEquals('~name', ns_join('~', '~name')) self.assertEquals('/name', ns_join('/', '/name')) # ns can be '~' or '/' self.assertEquals('~name', ns_join('~', 'name')) self.assertEquals('/name', ns_join('/', 'name')) self.assertEquals('/ns/name', ns_join('/ns', 'name')) self.assertEquals('/ns/name', ns_join('/ns/', 'name')) self.assertEquals('/ns/ns2/name', ns_join('/ns', 'ns2/name')) self.assertEquals('/ns/ns2/name', ns_join('/ns/', 'ns2/name')) # allow ns to be empty self.assertEquals('name', ns_join('', 'name')) def test_load_mappings(self): from roslib.names import load_mappings self.assertEquals({}, load_mappings([])) self.assertEquals({}, load_mappings(['foo'])) self.assertEquals({}, load_mappings([':='])) self.assertEquals({}, load_mappings([':=:='])) self.assertEquals({}, load_mappings(['f:='])) self.assertEquals({}, load_mappings([':=b'])) self.assertEquals({}, load_mappings(['foo:=bar:=baz'])) # should ignore node param assignments self.assertEquals({}, load_mappings(['_foo:=bar'])) self.assertEquals({'foo': 'bar'}, load_mappings(['foo:=bar'])) # should allow double-underscore names self.assertEquals({'__foo': 'bar'}, load_mappings(['__foo:=bar'])) self.assertEquals({'foo': 'bar'}, load_mappings(['./f', '-x', '--blah', 'foo:=bar'])) self.assertEquals({'a': '1', 'b': '2', 'c': '3'}, load_mappings(['c:=3', 'c:=', ':=3', 'a:=1', 'b:=2'])) def test_resource_name(self): from roslib.names import resource_name self.assertEquals('foo/bar', resource_name('foo', 'bar')) self.assertEquals('bar', resource_name('foo', 'bar', my_pkg='foo')) self.assertEquals('foo/bar', resource_name('foo', 'bar', my_pkg='bar')) self.assertEquals('foo/bar', resource_name('foo', 'bar', my_pkg='')) self.assertEquals('foo/bar', resource_name('foo', 'bar', my_pkg=None)) def test_resource_name_base(self): from roslib.names import resource_name_base self.assertEquals('', resource_name_base('')) self.assertEquals('bar', resource_name_base('bar')) self.assertEquals('bar', resource_name_base('foo/bar')) self.assertEquals('bar', resource_name_base('/bar')) self.assertEquals('', resource_name_base('foo/')) def test_resource_name_package(self): from roslib.names import resource_name_package self.assertEquals(None, resource_name_package('')) self.assertEquals(None, resource_name_package('foo')) self.assertEquals('foo', resource_name_package('foo/')) self.assertEquals('foo', resource_name_package('foo/bar')) def test_package_resource_name(self): from roslib.names import package_resource_name self.assertEquals(('', ''), package_resource_name('')) self.assertEquals(('', 'foo'), package_resource_name('foo')) self.assertEquals(('foo', 'bar'), package_resource_name('foo/bar')) self.assertEquals(('foo', ''), package_resource_name('foo/')) try: # only allowed single separator package_resource_name('foo/bar/baz') self.fail('should have raised ValueError') except ValueError: pass def test_is_legal_resource_name(self): from roslib.names import is_legal_resource_name failures = [None, '', 'hello\n', '\t', 'foo++', 'foo-bar', '#foo', ' name', 'name ', '~name', '/name', '1name', 'foo\\'] for f in failures: self.failIf(is_legal_resource_name(f), f) tests = ['f', 'f1', 'f_', 'foo', 'foo_bar', 'foo/bar', 'roslib/Log'] for t in tests: self.assert_(is_legal_resource_name(t), t) def test_is_legal_name(self): from roslib.names import is_legal_name failures = [None, 'foo++', 'foo-bar', '#foo', 'hello\n', '\t', ' name', 'name ', 'f//b', '1name', 'foo\\'] for f in failures: self.failIf(is_legal_name(f), f) tests = ['', 'f', 'f1', 'f_', 'f/', 'foo', 'foo_bar', 'foo/bar', 'foo/bar/baz', '~f', '~a/b/c', '~/f', '/a/b/c/d', '/'] for t in tests: self.assert_(is_legal_name(t), '[%s]' % t) def test_is_legal_base_name(self): from roslib.names import is_legal_base_name failures = [None, '', 'hello\n', '\t', 'foo++', 'foo-bar', '#foo', 'f/', 'foo/bar', '/', '/a', 'f//b', '~f', '~a/b/c', ' name', 'name ', '1name', 'foo\\'] for f in failures: self.failIf(is_legal_base_name(f), f) tests = ['f', 'f1', 'f_', 'foo', 'foo_bar'] for t in tests: self.assert_(is_legal_base_name(t), '[%s]' % t) def test_is_legal_resource_base_name(self): from roslib.names import is_legal_resource_base_name failures = [None, '', 'hello\n', '\t', 'foo++', 'foo-bar', '#foo', 'f/', 'foo/bar', '/', '/a', 'f//b', '~f', '~a/b/c', '~/f', ' name', 'name ', '1name', 'foo\\'] for f in failures: self.failIf(is_legal_resource_base_name(f), f) tests = ['f', 'f1', 'f_', 'foo', 'foo_bar'] for t in tests: self.assert_(is_legal_resource_base_name(t), '[%s]' % t) def test_resolve_name(self): from roslib.names import resolve_name # TODO: test with remappings tests = [ ('', '/', '/'), ('', '/node', '/'), ('', '/ns1/node', '/ns1/'), ('foo', '', '/foo'), ('foo/', '', '/foo'), ('/foo', '', '/foo'), ('/foo/', '', '/foo'), ('/foo', '/', '/foo'), ('/foo/', '/', '/foo'), ('/foo', '/bar', '/foo'), ('/foo/', '/bar', '/foo'), ('foo', '/ns1/ns2', '/ns1/foo'), ('foo', '/ns1/ns2/', '/ns1/foo'), ('foo', '/ns1/ns2/ns3/', '/ns1/ns2/foo'), ('foo/', '/ns1/ns2', '/ns1/foo'), ('/foo', '/ns1/ns2', '/foo'), ('foo/bar', '/ns1/ns2', '/ns1/foo/bar'), ('foo//bar', '/ns1/ns2', '/ns1/foo/bar'), ('foo/bar', '/ns1/ns2/ns3', '/ns1/ns2/foo/bar'), ('foo//bar//', '/ns1/ns2/ns3', '/ns1/ns2/foo/bar'), ('~foo', '/', '/foo'), ('~foo', '/node', '/node/foo'), ('~foo', '/ns1/ns2', '/ns1/ns2/foo'), ('~foo/', '/ns1/ns2', '/ns1/ns2/foo'), ('~foo/bar', '/ns1/ns2', '/ns1/ns2/foo/bar'), # #3044 ('~/foo', '/', '/foo'), ('~/foo', '/node', '/node/foo'), ('~/foo', '/ns1/ns2', '/ns1/ns2/foo'), ('~/foo/', '/ns1/ns2', '/ns1/ns2/foo'), ('~/foo/bar', '/ns1/ns2', '/ns1/ns2/foo/bar'), ] for name, node_name, v in tests: self.assertEquals(v, resolve_name(name, node_name)) ros-1.15.8/core/roslib/test/test_roslib_packages.py000066400000000000000000000061671407615046500223750ustar00rootroot00000000000000# Software License Agreement (BSD License) # # Copyright (c) 2009, Willow Garage, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following # disclaimer in the documentation and/or other materials provided # with the distribution. # * Neither the name of Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. import os import unittest class RoslibPackagesTest(unittest.TestCase): def test_find_node(self): import roslib.packages d = roslib.packages.get_pkg_dir('roslib') p = os.path.join(d, 'test', 'fake_node.py') self.assertEquals([p], roslib.packages.find_node('roslib', 'fake_node.py')) self.assertEquals([], roslib.packages.find_node('roslib', 'not_a_node')) def test_get_pkg_dir(self): import roslib.packages import roslib.rospack path = os.path.normpath(roslib.rospack.rospackexec(['find', 'roslib'])) self.assertEquals(path, roslib.packages.get_pkg_dir('roslib')) try: self.assertEquals(path, roslib.packages.get_pkg_dir('fake_roslib')) self.fail('should have raised') except roslib.packages.InvalidROSPkgException: pass def test_get_dir_pkg(self): import roslib.packages path = get_roslib_path() res = roslib.packages.get_dir_pkg(path) res = (os.path.realpath(res[0]), res[1]) self.assertEquals((path, 'roslib'), res) res = roslib.packages.get_dir_pkg(os.path.join(path, 'test')) res = (os.path.realpath(res[0]), res[1]) self.assertEquals((path, 'roslib'), res) # must fail on parent of roslib self.assertEquals((None, None), roslib.packages.get_dir_pkg(os.path.dirname(path))) def get_roslib_path(): return os.path.realpath(os.path.abspath(os.path.join(get_test_path(), '..'))) def get_test_path(): return os.path.abspath(os.path.dirname(__file__)) ros-1.15.8/core/roslib/test/test_roslib_rosenv.py000066400000000000000000000107311407615046500221230ustar00rootroot00000000000000# Software License Agreement (BSD License) # # Copyright (c) 2009, Willow Garage, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following # disclaimer in the documentation and/or other materials provided # with the distribution. # * Neither the name of Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. import os import unittest import roslib.rosenv class EnvTest(unittest.TestCase): def test_get_ros_root(self): from roslib.rosenv import get_ros_root self.assertEquals(None, get_ros_root(required=False, env={})) self.assertEquals(None, get_ros_root(False, {})) try: get_ros_root(required=True, env={}) self.fail('get_ros_root should have failed') except Exception: pass env = {'ROS_ROOT': '/fake/path'} self.assertEquals('/fake/path', get_ros_root(required=False, env=env)) try: get_ros_root(required=True, env=env) self.fail('get_ros_root should have failed') except Exception: pass def test_get_ros_package_path(self): from roslib.rosenv import get_ros_package_path self.assertEquals(None, get_ros_package_path(required=False, env={})) self.assertEquals(None, get_ros_package_path(False, {})) try: get_ros_package_path(required=True, env={}) self.fail('get_ros_package_path should have raised') except Exception: pass env = {'ROS_PACKAGE_PATH': ':'} self.assertEquals(':', get_ros_package_path(True, env=env)) self.assertEquals(':', get_ros_package_path(False, env=env)) # trip-wire tests. Cannot guarantee that ROS_PACKAGE_PATH is set # to valid value on test machine, just make sure logic doesn't crash self.assertEquals(os.environ.get('ROS_PACKAGE_PATH', None), get_ros_package_path(required=False)) def test_get_ros_master_uri(self): from roslib.rosenv import get_master_uri self.assertEquals(None, get_master_uri(required=False, env={})) self.assertEquals(None, get_master_uri(False, {})) try: get_master_uri(required=True, env={}) self.fail('get_ros_package_path should have raised') except Exception: pass env = {'ROS_MASTER_URI': 'http://localhost:1234'} self.assertEquals('http://localhost:1234', get_master_uri(True, env=env)) self.assertEquals('http://localhost:1234', get_master_uri(False, env=env)) argv = ['__master:=http://localhost:5678'] self.assertEquals('http://localhost:5678', get_master_uri(False, env=env, argv=argv)) try: argv = ['__master:=http://localhost:5678:=http://localhost:1234'] get_master_uri(required=False, env=env, argv=argv) self.fail('should have thrown') except roslib.rosenv.ROSEnvException: pass try: argv = ['__master:='] get_master_uri(False, env=env, argv=argv) self.fail('should have thrown') except roslib.rosenv.ROSEnvException: pass # make sure test works with os.environ self.assertEquals(os.environ.get('ROS_MASTER_URI', None), get_master_uri(required=False)) ros-1.15.8/core/roslib/test/test_roslib_stack_manifest.py000066400000000000000000000113701407615046500236020ustar00rootroot00000000000000# Software License Agreement (BSD License) # # Copyright (c) 2009, Willow Garage, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following # disclaimer in the documentation and/or other materials provided # with the distribution. # * Neither the name of Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. import os import unittest def get_test_path(): return os.path.abspath(os.path.dirname(__file__)) class RoslibStackManifestTest(unittest.TestCase): def _subtest_parse_stack_example1(self, m): from roslib.manifestlib import _Manifest self.assert_(isinstance(m, _Manifest)) self.assertEquals('stack', m._type) self.assertEquals('a brief description', m.brief) self.assertEquals('Line 1\nLine 2', m.description.strip()) self.assertEquals('The authors\ngo here', m.author.strip()) self.assertEquals('Public Domain\nwith other stuff', m.license.strip()) self.assertEquals('http://ros.org/stack/', m.url) self.assertEquals('http://www.willowgarage.com/files/willowgarage/robot10.jpg', m.logo) dpkgs = [d.stack for d in m.depends] self.assertEquals({'stackname', 'common'}, set(dpkgs)) self.assertEquals([], m.rosdeps) self.assertEquals([], m.exports) def _subtest_parse_stack_version(self, m): self.assertEquals('1.2.3', m.version) def test_parse_example1_file(self): from roslib.stack_manifest import parse_file p = os.path.join(get_test_path(), 'manifest_tests', 'stack_example1.xml') self._subtest_parse_stack_example1(parse_file(p)) p = os.path.join(get_test_path(), 'manifest_tests', 'stack_version.xml') self._subtest_parse_stack_version(parse_file(p)) def test_parse_example1_string(self): from roslib.manifestlib import parse, _Manifest self._subtest_parse_stack_example1(parse(_Manifest('stack'), STACK_EXAMPLE1)) def test_StackManifest(self): from roslib.stack_manifest import StackManifest m = StackManifest() self.assertEquals('stack', m._type) def test_StackManifest_str(self): # just make sure it doesn't crash from roslib.stack_manifest import parse str(parse(STACK_EXAMPLE1)) def test_StackManifest_xml(self): from roslib.stack_manifest import parse m = parse(STACK_EXAMPLE1) self._subtest_parse_stack_example1(m) # verify roundtrip m2 = parse(m.xml()) self._subtest_parse_stack_example1(m2) # bad file examples should be more like the roslaunch tests where there is just 1 thing wrong STACK_EXAMPLE1 = """ Line 1 Line 2 The authors go here Public Domain with other stuff http://ros.org/stack/ http://www.willowgarage.com/files/willowgarage/robot10.jpg """ STACK_INVALID1 = """ Line 1 The authors Public Domain """ STACK_INVALID2 = """ Line 1 The authors Public Domain """ ros-1.15.8/core/roslib/test/test_roslib_stacks.py000066400000000000000000000217271407615046500221060ustar00rootroot00000000000000# Software License Agreement (BSD License) # # Copyright (c) 2009, Willow Garage, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following # disclaimer in the documentation and/or other materials provided # with the distribution. # * Neither the name of Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. import os import unittest import roslib import rospkg class RoslibStacksTest(unittest.TestCase): def test_list_stacks(self): from roslib.stacks import list_stacks # roslib can't depend on ros and therefore can't expect it being in the environment # l = list_stacks() # self.assert_('ros' in l) # test with env test_dir = os.path.join(roslib.packages.get_pkg_dir('roslib'), 'test', 'stack_tests', 's1') env = os.environ.copy() env['ROS_PACKAGE_PATH'] = test_dir val = set(list_stacks(env=env)) # ros stack not guaranteed to list anymore as ROS_ROOT may not be set if 'ros' in val: val.remove('ros') self.assertEquals({'foo', 'bar'}, val) def test_list_stacks_by_path(self): from roslib.stacks import list_stacks_by_path # test with synthetic stacks test_dir = os.path.join(roslib.packages.get_pkg_dir('roslib'), 'test', 'stack_tests') self.assertEquals({'bar', 'foo'}, set(list_stacks_by_path(test_dir))) test_dir = os.path.join(roslib.packages.get_pkg_dir('roslib'), 'test', 'stack_tests', 's1') self.assertEquals({'bar', 'foo'}, set(list_stacks_by_path(test_dir))) test_dir = os.path.join(roslib.packages.get_pkg_dir('roslib'), 'test', 'stack_tests', 's1', 'bar') self.assertEquals(['bar'], list_stacks_by_path(test_dir)) # test symlink following test_dir = os.path.join(roslib.packages.get_pkg_dir('roslib'), 'test', 'stack_tests2') self.assertEquals({'foo', 'bar'}, set(list_stacks_by_path(test_dir))) def test_list_stacks_by_path_unary(self): from roslib.stacks import list_stacks_by_path # test with synthetic stacks test_dir = os.path.join(roslib.packages.get_pkg_dir('roslib'), 'test', 'stack_tests_unary') self.assertEquals({'bar', 'foo', 'baz'}, set(list_stacks_by_path(test_dir))) def test_get_stack_dir_unary(self): # now manipulate the environment to test precedence # - save original RPP as we popen rosstack in other tests d = roslib.packages.get_pkg_dir('roslib') d = os.path.join(d, 'test', 'stack_tests_unary') s1_d = os.path.join(d, 's1') rpp = rospkg.get_ros_package_path() try: paths = [d] os.environ[rospkg.environment.ROS_PACKAGE_PATH] = os.pathsep.join(paths) self.assertEquals(os.path.join(s1_d, 'foo'), roslib.stacks.get_stack_dir('foo')) self.assertEquals(os.path.join(s1_d, 'bar'), roslib.stacks.get_stack_dir('bar')) self.assertEquals(os.path.join(s1_d, 'baz'), roslib.stacks.get_stack_dir('baz')) finally: # restore rpp if rpp is not None: os.environ[rospkg.environment.ROS_PACKAGE_PATH] = rpp else: del os.environ[rospkg.environment.ROS_PACKAGE_PATH] def test_get_stack_dir(self): import roslib.packages from roslib.stacks import get_stack_dir try: get_stack_dir('non_existent') self.fail('should have raised') except roslib.stacks.InvalidROSStackException: pass # now manipulate the environment to test precedence # - save original RPP as we popen rosstack in other tests rpp = os.environ.get(rospkg.environment.ROS_PACKAGE_PATH, None) try: d = roslib.packages.get_pkg_dir('roslib') d = os.path.join(d, 'test', 'stack_tests') # - s1/s2/s3 print('s1/s2/s3') paths = [os.path.join(d, p) for p in ['s1', 's2', 's3']] os.environ[rospkg.environment.ROS_PACKAGE_PATH] = os.pathsep.join(paths) # - run multiple times to test caching for i in range(2): stacks = roslib.stacks.list_stacks() self.assert_('foo' in stacks) self.assert_('bar' in stacks) foo_p = os.path.join(d, 's1', 'foo') bar_p = os.path.join(d, 's1', 'bar') self.assertEquals(foo_p, roslib.stacks.get_stack_dir('foo')) self.assertEquals(bar_p, roslib.stacks.get_stack_dir('bar')) # - s2/s3/s1 print('s2/s3/s1') paths = [os.path.join(d, p) for p in ['s2', 's3', 's1']] os.environ[rospkg.environment.ROS_PACKAGE_PATH] = os.pathsep.join(paths) stacks = roslib.stacks.list_stacks() self.assert_('foo' in stacks) self.assert_('bar' in stacks) foo_p = os.path.join(d, 's2', 'foo') bar_p = os.path.join(d, 's1', 'bar') self.assertEquals(foo_p, roslib.stacks.get_stack_dir('foo')) self.assertEquals(bar_p, roslib.stacks.get_stack_dir('bar')) finally: # restore rpp if rpp is not None: os.environ[rospkg.environment.ROS_PACKAGE_PATH] = rpp else: del os.environ[rospkg.environment.ROS_PACKAGE_PATH] def test_expand_to_packages_unary(self): # test unary test_dir = os.path.join(roslib.packages.get_pkg_dir('roslib'), 'test', 'stack_tests_unary') env = os.environ.copy() env[rospkg.environment.ROS_PACKAGE_PATH] = test_dir from roslib.stacks import expand_to_packages self.assertEquals((['foo'], []), expand_to_packages(['foo'], env=env)) self.assertEquals((['foo', 'bar'], []), expand_to_packages(['foo', 'bar'], env=env)) def test_expand_to_packages(self): from roslib.stacks import expand_to_packages try: # it's possible to accidentally pass in a sequence type # like a string and get weird results, so check that we # don't self.assertEquals(([], []), expand_to_packages('ros')) self.fail('expand_to_packages should only take in a list of strings') except ValueError: pass self.assertEquals(([], []), expand_to_packages([])) self.assertEquals((['rosmake', 'roslib', 'roslib'], []), expand_to_packages(['rosmake', 'roslib', 'roslib'])) self.assertEquals(([], ['bogus_one', 'bogus_two']), expand_to_packages(['bogus_one', 'bogus_two'])) # this test case is no more valid in a package-only world # TODO: setup directory tree so that this can be more precisely calculated # valid, invalid = expand_to_packages(['ros', 'bogus_one']) # self.assertEquals(['bogus_one'], invalid) # check = ['rosbuild', 'rosunit', 'roslib'] # print valid # for c in check: # self.assert_(c in valid, "expected [%s] to be in ros expansion"%c) def test_get_stack_version(self): test_dir = os.path.join(get_test_path(), 'stack_tests', 's1') env = os.environ.copy() env[rospkg.environment.ROS_PACKAGE_PATH] = test_dir # REP 109: stack.xml has precedence over CMakeLists.txt, version is whitespace stripped self.assertEquals('1.6.0-manifest', roslib.stacks.get_stack_version('foo', env=env)) # REP 109: test fallback to CMakeLists.txt version self.assertEquals('1.5.0-cmake', roslib.stacks.get_stack_version('bar', env=env)) if 0: test_dir = os.path.join(roslib.packages.get_pkg_dir('roslib'), 'test', 'stack_tests_unary') env = os.environ.copy() env[rospkg.environment.ROS_PACKAGE_PATH] = test_dir def get_test_path(): return os.path.abspath(os.path.dirname(__file__)) ros-1.15.8/core/roslib/test/utest.cpp000066400000000000000000000112771407615046500175020ustar00rootroot00000000000000/* * Copyright (c) 2008, Willow Garage, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of Willow Garage, Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* Author: Brian Gerkey */ #include #include #include #ifndef _WIN32 #include #endif #include #include #include #include "ros/package.h" #ifdef _WIN32 int setenv(const char *name, const char *value, int overwrite) { if(!overwrite) { size_t envsize = 0; errno_t errcode = getenv_s(&envsize, NULL, 0, name); if(errcode || envsize) return errcode; } return _putenv_s(name, value); } #endif void string_split(const std::string &s, std::vector &t, const std::string &d) { t.clear(); size_t start = 0, end; while ((end = s.find_first_of(d, start)) != std::string::npos) { if((end-start) > 0) t.push_back(s.substr(start, end-start)); start = end + 1; } if(start < s.size()) t.push_back(s.substr(start)); } std::string g_rr_path; void set_env_vars(void) { // Point ROS_PACKAGE_PATH at the roslib directory, and point // ROS_ROOT into an empty directory. char rr_buf[1024]; getcwd(rr_buf, sizeof(rr_buf)); setenv("ROS_PACKAGE_PATH", rr_buf, 1); boost::filesystem::path temp_path = boost::filesystem::unique_path(); boost::filesystem::create_directories(temp_path); g_rr_path = temp_path.string(); setenv("ROS_ROOT", g_rr_path.c_str(), 1); } void cleanup_env_vars(void) { // Remove the empty directory that we created in set_env_vars(). rmdir(g_rr_path.c_str()); g_rr_path.clear(); } TEST(roslib, commandListNames) { set_env_vars(); std::string output = ros::package::command("list-names"); std::vector output_list; string_split(output, output_list, "\n"); ASSERT_EQ((int)output_list.size(), 1); ASSERT_STREQ(output_list[0].c_str(), "roslib"); cleanup_env_vars(); } TEST(roslib, commandList) { set_env_vars(); std::string output = ros::package::command("list"); std::vector output_list; std::vector name_path; string_split(output, output_list, "\n"); ASSERT_EQ((int)output_list.size(), 1); string_split(output_list[0], name_path, " "); ASSERT_EQ((int)name_path.size(), 2); ASSERT_STREQ(name_path[0].c_str(), "roslib"); cleanup_env_vars(); } TEST(roslib, getAll) { set_env_vars(); std::vector output_list; ASSERT_TRUE(ros::package::getAll(output_list)); ASSERT_EQ((int)output_list.size(), 1); ASSERT_STREQ(output_list[0].c_str(), "roslib"); cleanup_env_vars(); } void roslib_caller() { struct timespec ts = {0, 100000}; std::string output; for(int i=0;i<100;i++) { output = ros::package::command("plugins --attrib=foo roslib"); #ifndef _WIN32 nanosleep(&ts, NULL); #else boost::this_thread::sleep(boost::posix_time::milliseconds(1)); #endif } } TEST(roslib, concurrent_access) { set_env_vars(); const int size = 10; boost::thread t[size]; for(int i=0;i ros 1.15.8 ROS packaging system Michel Hidalgo Jacob Perron BSD http://www.ros.org/wiki/ROS https://github.com/ros/ros/issues https://github.com/ros/ros Eric Berger Ken Conley Josh Faust Tully Foote Brian Gerkey Jeremy Leibs Morgan Quigley Dirk Thomas Rob Wheeler catkin catkin mk rosbuild roslang roslib rosbash rosboost_cfg rosclean roscreate rosmake rosunit ros-1.15.8/tools/000077500000000000000000000000001407615046500135615ustar00rootroot00000000000000ros-1.15.8/tools/rosbash/000077500000000000000000000000001407615046500152225ustar00rootroot00000000000000ros-1.15.8/tools/rosbash/CHANGELOG.rst000066400000000000000000000202251407615046500172440ustar00rootroot00000000000000^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Changelog for package rosbash ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 1.15.8 (2021-07-21) ------------------- * Fix variable name (from $arg to $argv) in rosfish (`#279 `_) * Update maintainers (`#272 `_) * Contributors: Jacob Perron, Yuma Hiramatsu 1.15.7 (2020-09-28) ------------------- * add trailing := to roslaunch args:=value completion (`#259 `_) * add quoting to prevent unwanted globbing and word splitting in rosbash (`#269 `_) * fix ros_location_find with Python 3 (`#270 `_) 1.15.6 (2020-07-20) ------------------- 1.15.5 (2020-07-06) ------------------- * fix for sourcing rosfish (`#262 `_) 1.15.4 (2020-05-28) ------------------- 1.15.3 (2020-05-14) ------------------- * update rosmv function to move file and package both (`#254 `_) 1.15.2 (2020-04-07) ------------------- * add rosmv shell function to move a file from package to target (`#247 `_) 1.15.1 (2020-03-17) ------------------- 1.15.0 (2020-02-11) ------------------- * add heuristic to run python devel space relays (`#233 `_) 1.14.8 (2020-02-11) ------------------- * update style to pass flake8 (`#240 `_) * Replace $1 and $2 with $pkg_name and $file_name (`#239 `_) * add roscp. (`#237 `_) * Bump CMake version to avoid CMP0048 warning (`#234 `_) * fix find -perm /mode usage for FreeBSD (`#232 `_) 1.14.7 (2019-10-03) ------------------- * zsh launch args completion (`#217 `_) * use _rosrun\_ prefix for temporary variable (`#228 `_) * restore IFS after changing it in rosbash and rosrun (`#227 `_) * [revent filename glob expansion in _msg_opts in rosbash (`#218 `_) * correct name of the findpath script (`#27 `_) (`#213 `_) 1.14.6 (2019-03-18) ------------------- * add roscd, rosls support for Windows (`#210 `_) * exclude files when completing roslaunch args (`#211 `_) 1.14.5 (2019-03-04) ------------------- * add rosrun.bat (`#208 `_) * add verbose output to rosrun if catkin_find fails (`#182 `_) * add missing rospack dependency (`#189 `_) * fix rosfish (`#172 `_) 1.14.4 (2018-05-01) ------------------- * rosrun: array is now properly expanded in debug-echo (`#176 `_) * rosbash: replaced `...` with $(...) (`#177 `_) * rosrun: replaced `...` with $(...) (`#175 `_) * rosfish: fix syntax error (`#171 `_) * fix zsh tab completion for symlinks (`#169 `_) 1.14.3 (2018-01-30) ------------------- * do not remove paths containing ./ or ../ from completion (`#162 `_) 1.14.2 (2017-10-26) ------------------- 1.14.1 (2017-07-27) ------------------- * add options in completion for roslaunch to roszsh (`#147 `_) * allow arguments in EDITOR env in zsh rosed (`#144 `_) 1.14.0 (2017-02-22) ------------------- 1.13.6 (2017-10-31) ------------------- * add options in completion for roslaunch to roszsh (`#147 `_) * allow arguments in EDITOR env in zsh rosed (`#144 `_) 1.13.5 (2017-02-14) ------------------- * add completion for "rosmsg info" (`#138 `_) * add "rostopic pub" completion for message type (`#132 `_) * fix "rostopic pub" completion when options are provided (`#131 `_) 1.13.4 (2016-09-19) ------------------- 1.13.3 (2016-09-16) ------------------- * fix spelling of 'rosed' in usage (`#118 `_) 1.13.2 (2016-09-02) ------------------- * add missing verbs to rosservice completion (`#117 `_) 1.13.1 (2016-03-13) ------------------- 1.13.0 (2016-03-10) ------------------- 1.12.6 (2016-03-10) ------------------- * add roscat to display file contents (`#99 `_) * roszsh: Ignore hidden files and directory in completion (`#100 `_) 1.12.5 (2015-10-13) ------------------- * rosrun: allow spaces in command names and search paths (`#94 `_) 1.12.4 (2015-10-12) ------------------- * fix zsh rosservice completion (`#92 `_) 1.12.3 (2015-09-19) ------------------- * fix roslaunch completion if path contains white spaces (`ros/ros_comm#658 `_) * add rosconsole tab completion for bash (`#86 `_) * use --first-only option when calling catkin_find (`#83 `_) 1.12.2 (2015-04-27) ------------------- 1.12.1 (2015-04-16) ------------------- * add support for fish shell (`#77 `_) * enable roslaunch args completion in rosbash 1.12.0 (2014-12-26) ------------------- 1.11.6 (2014-12-22) ------------------- * match behaviour of 'roscd' in zsh with bash (`#73 `_) * improve rosbag zsh tab completion for bag files (`#70 `_) 1.11.5 (2014-08-18) ------------------- * fix zsh autocompletion for published topics, msg-type and YAML (`#64 `_) 1.11.4 (2014-07-23) ------------------- 1.11.3 (2014-07-18) ------------------- 1.11.2 (2014-06-16) ------------------- 1.11.1 (2014-05-07) ------------------- * add rosrun --prefix, update completion (`#52 `_) 1.11.0 (2014-01-31) ------------------- 1.10.9 (2014-01-07) ------------------- 1.10.8 (2013-10-15) ------------------- * fix check for permissions of executables (regression from `#37 `_ in 1.10.7) 1.10.7 (2013-10-04) ------------------- * use platform dependent argument for 'find -perm' (`#33 `_) * compatibility of env hooks with old workspace setup files (`#36 `_) * make rosawesome more awesome * fix return code for rospd for invalid package names (`#30 `_) 1.10.6 (2013-08-22) ------------------- 1.10.5 (2013-08-21) ------------------- * make rosunit relocatable (`ros/catkin#490 `_) * fix home expansion in completion on OS X (`#27 `_) 1.10.4 (2013-07-05) ------------------- 1.10.3 (2013-07-03) ------------------- 1.10.2 (2013-06-18) ------------------- 1.10.1 (2013-06-06) ------------------- 1.10.0 (2013-03-22 09:23) ------------------------- 1.9 (Groovy) ============ 1.9.44 (2013-03-13) ------------------- 1.9.43 (2013-03-08) ------------------- * fix handling spaces in folder names (`ros/catkin#375 `_) * modified 'roscd' to switch to latest sourced catkin space when invoked without arguments (`ros/ros_comm#123 `_) 1.9.42 (2013-01-25) ------------------- 1.9.41 (2013-01-24) ------------------- 1.9.40 (2013-01-13) ------------------- * add 'rosnode cleanup' to autocompletion 1.9.39 (2012-12-30) ------------------- * first public release for Groovy ros-1.15.8/tools/rosbash/CMakeLists.txt000066400000000000000000000020731407615046500177640ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.0.2) project(rosbash) find_package(catkin) catkin_package() install(FILES rosbash rosfish rostcsh roszsh DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}) if (WIN32) install(PROGRAMS scripts/rosrun.bat scripts/roscp.bat DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION}) install(PROGRAMS scripts/rosfindpath.py scripts/roscd.bat scripts/rosls.bat DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION}) else() install(PROGRAMS scripts/rosrun DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION}) endif() # making toplevel forward script for bash script rosrun if(NOT WIN32) set(BASH_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/scripts/rosrun) configure_file(${catkin_EXTRAS_DIR}/templates/script.bash.in ${CATKIN_DEVEL_PREFIX}/bin/rosrun @ONLY) else() set(BAT_SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/scripts/rosrun.bat) configure_file(${catkin_EXTRAS_DIR}/templates/script.bat.in ${CATKIN_DEVEL_PREFIX}/bin/rosrun.bat @ONLY) endif() catkin_add_env_hooks(15.rosbash SHELLS bash fish tcsh zsh DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/env-hooks) ros-1.15.8/tools/rosbash/env-hooks/000077500000000000000000000000001407615046500171335ustar00rootroot00000000000000ros-1.15.8/tools/rosbash/env-hooks/15.rosbash.bash.em000066400000000000000000000004401407615046500222550ustar00rootroot00000000000000# generated from rosbash/env-hooks/15.rosbash.bash.em @[if DEVELSPACE]@ . "@(CMAKE_CURRENT_SOURCE_DIR)/rosbash" @[else]@ if [ -z "$CATKIN_ENV_HOOK_WORKSPACE" ]; then CATKIN_ENV_HOOK_WORKSPACE="@(CMAKE_INSTALL_PREFIX)" fi . "$CATKIN_ENV_HOOK_WORKSPACE/share/rosbash/rosbash" @[end if]@ ros-1.15.8/tools/rosbash/env-hooks/15.rosbash.fish.em000066400000000000000000000004401407615046500222710ustar00rootroot00000000000000# generated from rosbash/env-hooks/15.rosbash.fish.em @[if DEVELSPACE]@ . "@(CMAKE_CURRENT_SOURCE_DIR)/rosfish" @[else]@ if [ -z "$CATKIN_ENV_HOOK_WORKSPACE" ]; then CATKIN_ENV_HOOK_WORKSPACE="@(CMAKE_INSTALL_PREFIX)" fi . "$CATKIN_ENV_HOOK_WORKSPACE/share/rosbash/rosfish" @[end if]@ ros-1.15.8/tools/rosbash/env-hooks/15.rosbash.tcsh.em000066400000000000000000000004401407615046500223010ustar00rootroot00000000000000# generated from rosbash/env-hooks/15.rosbash.tcsh.em @[if DEVELSPACE]@ . "@(CMAKE_CURRENT_SOURCE_DIR)/rostcsh" @[else]@ if [ -z "$CATKIN_ENV_HOOK_WORKSPACE" ]; then CATKIN_ENV_HOOK_WORKSPACE="@(CMAKE_INSTALL_PREFIX)" fi . "$CATKIN_ENV_HOOK_WORKSPACE/share/rosbash/rostcsh" @[end if]@ ros-1.15.8/tools/rosbash/env-hooks/15.rosbash.zsh.em000066400000000000000000000004351407615046500221500ustar00rootroot00000000000000# generated from rosbash/env-hooks/15.rosbash.zsh.em @[if DEVELSPACE]@ . "@(CMAKE_CURRENT_SOURCE_DIR)/roszsh" @[else]@ if [ -z "$CATKIN_ENV_HOOK_WORKSPACE" ]; then CATKIN_ENV_HOOK_WORKSPACE="@(CMAKE_INSTALL_PREFIX)" fi . "$CATKIN_ENV_HOOK_WORKSPACE/share/rosbash/roszsh" @[end if]@ ros-1.15.8/tools/rosbash/package.xml000066400000000000000000000012011407615046500173310ustar00rootroot00000000000000 rosbash 1.15.8 Assorted shell commands for using ros with bash. Michel Hidalgo Jacob Perron BSD http://www.ros.org/wiki/rosbash Jeremy Leibs Thibault Kruse Dirk Thomas catkin catkin rospack ros-1.15.8/tools/rosbash/rosbash000066400000000000000000001055011407615046500166100ustar00rootroot00000000000000# rosbash - functions to support ROS users # Useful things to know: # 'local' variables get unset after function, all others stay forever # COMPREPLY is the var used by bash complete builtin function _rossed { if [[ $(uname) == Darwin || $(uname) == FreeBSD ]]; then sed -E "$@" else sed -r "$@" fi } function _rosfind { if [[ $(uname) == Darwin || $(uname) == FreeBSD ]]; then # BSD find needs -E for extended regexp find -E "$@" else find "$@" fi } # _ros_location_find # based on $ROS_LOCATIONS, which the user can set to any colon # separated of key=folder pairs also resolves keys 'log' and # 'test_results' to ROS defaults finally resolves to package, then # stack echoes its result function _ros_location_find { local ROS_LOCATION_KEYS_ARR ROS_LOCATIONS_ARR loc ROS_LOCATION_KEYS_ARR=($(echo $ROS_LOCATIONS | _rossed -e 's/([^:=]*)=([^:=]*)(:*[^=])*(:|$)/\1 /g')) ROS_LOCATIONS_ARR=($(echo $ROS_LOCATIONS | _rossed -e 's/([^:=]*)=([^:=]*)(:*[^=])*(:|$)/\2 /g' -e "s|~|$HOME|g")) for (( i = 0 ; i < ${#ROS_LOCATION_KEYS_ARR[@]} ; i++ )); do if [[ $1 == ${ROS_LOCATION_KEYS_ARR[$i]} ]]; then echo ${ROS_LOCATIONS_ARR[i]} return 0 fi done if [[ $1 == log ]]; then echo $(roslaunch-logs) return 0 elif [[ $1 == test_results ]]; then echo $(rosrun rosunit test_results_dir.py) return 0 fi loc=$(export ROS_CACHE_TIMEOUT=-1.0 && rospack find "$1" 2> /dev/null) if [[ $? != 0 ]]; then loc=$(export ROS_CACHE_TIMEOUT=-1.0 && rosstack find "$1" 2> /dev/null) if [[ $? != 0 ]]; then return 1 fi echo "$loc" return 0 fi echo "$loc" return 0 } function _ros_list_locations { local ROS_LOCATION_KEYS packages stacks ROS_LOCATION_KEYS=$(echo $ROS_LOCATIONS | _rossed -e 's/([^:=]*)=([^:=]*)(:*[^=])*(:|$)/\1 /g') packages=$(export ROS_CACHE_TIMEOUT=-1.0 && rospack list-names) stacks=$(export ROS_CACHE_TIMEOUT=-1.0 && rosstack list-names) echo $packages $stacks log test_results $ROS_LOCATION_KEYS | tr ' ' '\n' return 0 } function _ros_package_find { local loc loc=$(export ROS_CACHE_TIMEOUT=-1.0 && rospack find "$1" 2> /dev/null) if [[ $? != 0 ]]; then return 1 fi echo $loc return 0 } function _ros_list_packages { local packages packages=$(export ROS_CACHE_TIMEOUT=-1.0 && rospack list-names) echo $packages | tr ' ' '\n' return 0 } function _ros_list_stacks { local stacks stacks=$(export ROS_CACHE_TIMEOUT=-1.0 && rosstack list-names) echo $stacks | tr ' ' '\n' return 0 } # takes as argument either just a package-path or just a pkgname # returns 0 for no argument or if package (+ path) exist, 1 else # on success with arguments returns [pkgname, abspath, relpath basename] function _ros_decode_path { local rosname rosdir reldir last rosvals=() if [[ -z "$1" ]]; then return 0 fi if [[ $1 =~ .+/.* ]]; then rosname=${1%%/*} reldir=/${1#*/} last=${reldir##*/} reldir=${reldir%/*}/ else rosname="$1" if [[ -z "$2" || "$2" != "forceeval" ]]; then rosvals=("${rosname}") return 1 fi fi rosdir=$(_ros_location_find "$rosname") if [[ $? != 0 ]]; then rosvals=("${rosname}") return 1 fi rosvals=("${rosname}" "${rosdir}" "${reldir}" "${last}") } function rospython { local pkgname if [[ $1 = "--help" ]]; then echo -e "usage: rospython [package] \n\nRun python loading package manifest first." return 0 fi if [[ -z "$1" ]]; then if [[ -f ./manifest.xml ]]; then pkgname=$(basename "$(pwd)") python -i -c "import roslib; roslib.load_manifest('$pkgname')" else python fi else python -i -c "import roslib; roslib.load_manifest('$1')" fi } function roscd { local rosvals if [[ $1 = "--help" ]] || [[ $# -gt 1 ]]; then echo -e "usage: roscd package\n\nJump to target package." return 0 fi if [ -z "$1" ]; then if [ ! -z $ROS_WORKSPACE ]; then cd ${ROS_WORKSPACE} return 0 fi if [ ! -z $CMAKE_PREFIX_PATH ]; then IFS=":" read -a workspaces <<< "$CMAKE_PREFIX_PATH" for ws in "${workspaces[@]}"; do if [ -f "$ws/.catkin" ]; then cd "${ws}" return 0 fi done fi echo -e "Neither ROS_WORKSPACE is set nor a catkin workspace is listed in CMAKE_PREFIX_PATH. Please set ROS_WORKSPACE or source a catkin workspace to use roscd with no arguments." return 1 fi _ros_decode_path "$1" forceeval if [ $? != 0 ]; then echo "roscd: No such package/stack '$1'" return 1 elif [ -z $rosvals ]; then if [ -z $ROS_WORKSPACE ]; then echo -e "No ROS_WORKSPACE set. Please set ROS_WORKSPACE to use roscd with no arguments." return 1 fi cd ${ROS_WORKSPACE} return 0 else cd "${rosvals[1]}${rosvals[2]}${rosvals[3]}" return 0 fi } function _is_integer { [ "$1" -eq "$1" ] > /dev/null 2>&1 return $? } function rosd { if [[ $1 = "--help" ]]; then echo -e "usage: rosd\n\nDisplays the list of currently remembered directories with indexes." return 0 fi let count=0; for items in $(dirs); do echo $count $items; let count=$((count+1)); done } function rospd { if [[ $1 = "--help" ]]; then echo -e "usage: rospd\n\nLike pushd, also accepts indexes from rosd." return 0 fi if _is_integer "$1"; then pushd "+$1" > /dev/null ; else local rosvals _ros_decode_path "$1" forceeval if [ $? != 0 ] && [[ $# -gt 0 ]]; then echo "rospd: No such package/stack '$1'" return 1 fi pushd "${rosvals[1]}${rosvals[2]}${rosvals[3]}" > /dev/null ; fi rosd } function rosls { local rosvals if [[ $1 = "--help" ]]; then echo -e "usage: rosls [package]\n\nLists contents of a package directory." return 0 fi _ros_decode_path "$1" forceeval ls "${rosvals[1]}${rosvals[2]}${rosvals[3]}" } function rosmv { local arg rosvals if [[ $1 = "--help" ]] || [[ $# -ne 3 && $# -ne 4 ]]; then echo -e "usage: rosmv [OPTION]... source... destination\n or: rosmv package... filename... destination" echo -e "\nMove a file from a package to target location\n-d Move package to target directory" return 0 fi if [[ $1 = "-d" ]]; then _ros_decode_path "${2}" forceeval pic="${rosvals[1]}${rosvals[2]}${rosvals[3]}" mv -t "${3}" "${pic}" else _roscmd "${1}" "${2}" mv "${arg}" "${3}" fi } # sets arg as return value function _roscmd { local pkgdir exepath opt catkin_package_libexec_dir opts if [[ -n $CMAKE_PREFIX_PATH ]]; then catkin_package_libexec_dir=$(catkin_find --first-only --without-underlays --libexec $1 2> /dev/null) fi pkgdir=$(_ros_package_find "$1") if [[ -z $catkin_package_libexec_dir && -z $pkgdir ]]; then echo "Couldn't find package [$1]" return 1 fi exepath=($(find -L $catkin_package_libexec_dir $pkgdir -name $2 -type f ! -regex .*/[.].* ! -regex .*$pkgdir\/build\/.* | uniq)) if [[ ${#exepath[@]} == 0 ]] ; then echo "That file does not exist in that package." return 1 elif [[ ${#exepath[@]} -gt 1 ]] ; then echo "You have chosen a non-unique filename, please pick one of the following:" select opt in ${exepath[@]}; do echo $opt break done else opt=${exepath[0]} fi arg=${opt} } function rosed { local arg if [[ $1 = "--help" ]]; then echo -e "usage: rosed [package] [file]\n\nEdit a file within a package." return 0 fi _roscmd "${1}" "${2}" if [[ -n ${arg} ]]; then if [[ -z $EDITOR ]]; then vim "${arg}" else $EDITOR "${arg}" fi fi } function roscp { local arg if [[ $1 = "--help" ]] || [[ $# -ne 3 ]]; then echo -e "usage: roscp package filename target\n\nCopy a file from a package to target location." return 0 fi _roscmd "${1}" "${2}" cp "${arg}" "${3}" } function roscat { local arg if [[ $1 = "--help" ]] || [[ $# -ne 2 ]]; then echo -e "usage: roscat [package] [file]\n\nDisplay a file content within a package." [[ $1 = "--help" ]] && return 0 || return 1 fi _roscmd "${1}" "${2}" [ $? -eq 1 ] && return 1 if [[ -n ${arg} ]]; then if [[ -z $CATTER ]]; then cat "${arg}" else $CATTER "${arg}" fi fi } function rosawesome { alias megamaid='rosbag record' alias suck2blow='rosbag play' alias botherder=roscore } function _roscomplete { local arg opts COMPREPLY=() arg="${COMP_WORDS[COMP_CWORD]}" opts="$(_ros_list_packages) $(_ros_list_stacks)" _rosbash_roscomplete_IFS="$IFS" IFS=$'\n' COMPREPLY=($(compgen -W "${opts}" -- ${arg})) IFS="$_rosbash_roscomplete_IFS" unset _rosbash_roscomplete_IFS } function _roscomplete_rosmake { local arg COMPREPLY=() arg="${COMP_WORDS[COMP_CWORD]}" _roscomplete if [[ ${arg} =~ \-\-.* ]]; then COMPREPLY=(${COMPREPLY[@]} $(compgen -W "--test-only --all --mark-installed --unmark-installed --robust --build-everything --specified-only --buildtest --buildtest1 --output --pre-clean --bootstrap --disable-logging --target --pjobs= --threads --profile --skip-blacklist --status-rate" -- ${arg})) fi } function _roscomplete_sub_dir { local arg opts rosvals COMPREPLY=() arg="${COMP_WORDS[COMP_CWORD]}" _ros_decode_path ${arg} if [[ -z "${rosvals[2]}" ]]; then opts=$(_ros_list_locations) _rosbash_roscomplete_sub_dir_IFS="$IFS" IFS=$'\n' COMPREPLY=($(compgen -W "${opts}" -S / -- ${rosvals[0]})) IFS="$_rosbash_roscomplete_sub_dir_IFS" unset _rosbash_roscomplete_sub_dir_IFS else if [ -e ${rosvals[1]}${rosvals[2]} ]; then opts=$(find -L ${rosvals[1]}${rosvals[2]} -maxdepth 1 -mindepth 1 -type d ! -regex ".*/[.][^./].*" -print0 | tr '\000' '\n' | sed -e "s/.*\/\(.*\)/\1\//g") else opts='' fi _rosbash_roscomplete_sub_dir_IFS="$IFS" IFS=$'\n' COMPREPLY=($(compgen -P ${rosvals[0]}${rosvals[2]} -W "${opts}" -- ${rosvals[3]})) IFS="$_rosbash_roscomplete_sub_dir_IFS" unset _rosbash_roscomplete_sub_dir_IFS fi } function _msg_opts { local arg pkgs pkgname msgname searchmsg path if [[ $1 =~ .+/.* ]]; then pkgname=${1%%/*} msgname=${1#*/} searchmsg=1 else pkgname=${1} fi if [[ -z ${searchmsg} ]]; then pkgs=($(rospack list)) for (( i = 0 ; i < ${#pkgs[@]} ; i=i+2 )); do if [[ -d ${pkgs[i+1]}/msg ]]; then echo ${pkgs[i]}/ fi done else path=$(rospack find ${pkgname}) if [ -d ${path}/msg ]; then echo $(find -L ${path}/msg -maxdepth 1 -mindepth 1 -name '*.msg' ! -regex ".*/[.][^./].*" -print0 | tr '\000' '\n' | sed -e "s/.*\/\(.*\)\.msg/${pkgname}\/\1/g") fi fi } function _srv_opts { local arg pkgs pkgname srvname searchsrv path count opts if [[ $1 =~ .+/.* ]]; then pkgname=${1%%/*} srvname=${1#*/} searchsrv=1 else pkgname=${1} fi if [[ -z ${searchsrv} ]]; then pkgs=($(rospack list | grep "^${pkgname}")) count=0 opts="" for (( i = 0 ; i < ${#pkgs[@]} ; i=i+2 )); do if [[ -d ${pkgs[i+1]}/srv ]]; then opts="$opts ${pkgs[i]}/" pkgname=${pkgs[i]} count=$((count+1)) fi done if [[ $count -gt 1 ]]; then echo $opts return 0 fi fi path=$(rospack find ${pkgname} 2> /dev/null) if [ $? -eq 0 ] && [ -d ${path}/srv ]; then echo $(find -L ${path}/srv -maxdepth 1 -mindepth 1 -name *.srv ! -regex ".*/[.][^./].*" -print0 | tr '\000' '\n' | sed -e "s/.*\/\(.*\)\.srv/${pkgname}\/\1/g") fi } function _roscomplete_rossrv { COMPREPLY=() arg="${COMP_WORDS[COMP_CWORD]}" if [[ $COMP_CWORD == 1 ]]; then opts="show list md5 package packages" COMPREPLY=($(compgen -W "$opts" -- ${arg})) elif [[ $COMP_CWORD == 2 ]]; then case ${COMP_WORDS[1]} in show|users|md5) opts=$(_srv_opts ${COMP_WORDS[$COMP_CWORD]}) COMPREPLY=($(compgen -W "$opts" -- ${arg})) ;; package) opts=$(rospack list-names) COMPREPLY=($(compgen -W "$opts" -- ${arg})) ;; packages|list) # This shouldn't really have a completion rule ;; esac fi } function _roscomplete_pkg { # complete package names that start with $1 local arg=${1} local opts=$(_ros_list_packages) _rosbash_roscomplete_pkg_IFS="$IFS" IFS=$'\n' COMPREPLY=($(compgen -W "${opts}" -- ${arg})) IFS="$_rosbash_roscomplete_pkg_IFS" unset _rosbash_roscomplete_pkg_IFS } function _roscomplete_find { # complete files that match $2 within $1, that start with $3 local opts pkgdir catkin_package_libexec_dir local perm=${1} local pkg=${2} local arg=${3} if [[ -n $CMAKE_PREFIX_PATH ]]; then catkin_package_libexec_dir=$(catkin_find --first-only --without-underlays --libexec ${pkg} 2> /dev/null) fi pkgdir=$(_ros_package_find ${pkg}) if [[ -n "$catkin_package_libexec_dir" || -n "$pkgdir" ]]; then opts=$(_rosfind -L $catkin_package_libexec_dir "$pkgdir" ${1} ! -regex ".*/[.][^./].*" ! -regex ".*$pkgdir\/build\/.*" -print0 | tr '\000' '\n' | sed -e "s/.*\/\(.*\)/\1/g") else opts="" fi _rosbash_roscomplete_find_IFS="$IFS" IFS=$'\n' COMPREPLY=($(compgen -W "${opts}" -- ${arg})) IFS="$_rosbash_roscomplete_find_IFS" unset _rosbash_roscomplete_find_IFS } function _roscomplete_search_dir { local arg opts COMPREPLY=() arg="${COMP_WORDS[COMP_CWORD]}" if [[ $COMP_CWORD == 1 ]]; then # complete packages _roscomplete_pkg "${arg}" elif [[ $COMP_CWORD == 2 ]]; then # complete files within package according to $1 _roscomplete_find "${1}" "${COMP_WORDS[1]}" "${arg}" else # complete filenames arg=$(echo ${arg} | sed -e "s|~|$HOME|g") if [[ $arg =~ ^/*.+/.* ]]; then path=${arg%/*} else path=. fi if [[ -e ${path} ]]; then opts=$(find -L $path -maxdepth 1 -type d ! -regex ".*/[.][^./].*" ! -regex "^[.]/" -print0 | tr '\000' '\n' | sed -e "s/$/\//g" -e "s/^[.]\///g" -e "s/'/\\\\\'/g" -e "s/ /\\\\\ /g")$'\n'$(find -L $path -maxdepth 1 -type f ! -regex ".*/[.][^.]*" ! -regex "^[.]/" -print0 | tr '\000' '\n' | sed -e "s/^[.]\///g" -e "s/'/\\\\\'/g" -e "s/ /\\\\\ /g") else opts="" fi _rosbash_roscomplete_search_dir_IFS="$IFS" IFS=$'\n' COMPREPLY=($(compgen -W "$opts" -- ${arg})) IFS="$_rosbash_roscomplete_search_dir_IFS" unset _rosbash_roscomplete_search_dir_IFS if [[ ${#COMPREPLY[*]} = 1 ]]; then newpath=${COMPREPLY[0]%/*} if [[ -d ${newpath} ]]; then opts=$(find -L $newpath -maxdepth 1 -type d ! -regex ".*/[.][^./].*" ! -regex "^[.]/" -print0 | tr '\000' '\n' | sed -e "s/$/\//g" -e "s/^[.]\///g" -e "s/'/\\\\\'/g" -e "s/ /\\\\\ /g")$'\n'$(find -L $newpath -maxdepth 1 -type f ! -regex ".*/[.][^.]*" ! -regex "^[.]/" -print0 | tr '\000' '\n' | sed -e "s/^[.]\///g" -e "s/'/\\\\\'/g" -e "s/ /\\\\\ /g") _rosbash_roscomplete_search_dir_IFS="$IFS" IFS=$'\n' COMPREPLY=($(compgen -W "$opts" -- ${arg})) IFS="$_rosbash_roscomplete_search_dir_IFS" unset _rosbash_roscomplete_search_dir_IFS fi fi fi } function _roscomplete_exe { local perm i prev_arg if [[ $(uname) == Darwin || $(uname) == FreeBSD ]]; then perm="+111" else perm="/111" fi rosrun_args=("--prefix" "--debug") # rosrun ONLY accepts arguments before the package names; we need to honor this local start_arg=1 # loop through args and skip --prefix, arg to prefix and --debug for (( i=1; i < ${#COMP_WORDS[*]}; i++ )) do arg="${COMP_WORDS[i]}" case ${arg} in "--prefix" | "-p") start_arg=$((start_arg+1)) ;; "--debug" | "-d") start_arg=$((start_arg+1)) ;; *) if [[ $prev_arg == "--prefix" || $prev_arg == "-p" ]] then start_arg=$((start_arg+1)) else break fi ;; esac prev_arg="${arg}" done local end_arg=$((${#COMP_WORDS[*]} - 1)) arg="${COMP_WORDS[COMP_CWORD]}" if [[ $start_arg > $end_arg ]] then # complete command names for --prefix COMPREPLY=($(compgen -c -- ${arg})) else if [[ $start_arg == $end_arg ]] then # completing first argument; can be --arg or package name if [[ ${arg} =~ \-.* ]]; then COMPREPLY=($(compgen -W "${rosrun_args[*]}" -- ${arg})) else _roscomplete_pkg "${arg}" fi elif [[ $((start_arg+1)) == ${end_arg} ]] then # completing second argument; node within package local pkg="${COMP_WORDS[start_arg]}" _roscomplete_find "-type f -perm $perm" "${pkg}" "${arg}" else # completing remaining arguments; per "normal" _roscomplete_search_dir "-type f -perm $perm" fi fi } function _roscomplete_file { _roscomplete_search_dir "-type f ! -regex .*[.][oa]$" } function _roscomplete_launch { arg="${COMP_WORDS[COMP_CWORD]}" COMPREPLY=() if [[ ${arg} =~ \-\-.* ]]; then COMPREPLY=(${COMPREPLY[@]} $(compgen -W "--files --args --nodes --find-node --child --local --screen --server_uri --run_id --wait --port --core --pid --dump-params --skip-log-check --ros-args" -- ${arg})) else _roscomplete_search_dir "( -type f -regex .*\.launch$ -o -type f -regex .*\.test$ )" if [[ $COMP_CWORD == 1 ]]; then COMPREPLY=($(compgen -o plusdirs -f -X "!*.launch" -- ${arg}) ${COMPREPLY[@]} $(compgen -o plusdirs -f -X "!*.test" -- ${arg}) ${COMPREPLY[@]}) elif [[ ${#COMP_WORDS[@]} -ge 2 ]]; then # complete roslaunch arguments for a launch file ROSLAUNCH_COMPLETE=$(which roslaunch-complete) if [[ -x ${ROSLAUNCH_COMPLETE} ]]; then # Call roslaunch-complete instead of roslaunch to get arg completion _roslaunch_args=$(${ROSLAUNCH_COMPLETE} ${COMP_WORDS[@]:1:2} 2> /dev/null) # roslaunch-complete should be very silent about # errors and return 0 if it produced usable completion. if [[ $? == 0 ]]; then COMPREPLY=($(compgen -W "${_roslaunch_args}" -- "${arg}")) fi fi fi fi } function _roscomplete_test { arg="${COMP_WORDS[COMP_CWORD]}" if [[ ${arg} =~ \-\-.* ]]; then COMPREPLY=(${COMPREPLY[@]} $(compgen -W "--bare --bare-limit --bare-name --pkgdir --package" -- ${arg})) else _roscomplete_search_dir "( -type f -regex .*\.launch$ -o -type f -regex .*\.test$ )" if [[ $COMP_CWORD == 1 ]]; then COMPREPLY=($(compgen -o plusdirs -f -X "!*.launch" -- ${arg}) ${COMPREPLY[@]} $(compgen -o plusdirs -f -X "!*.test" -- ${arg}) ${COMPREPLY[@]}) fi fi } function _roscomplete_rosbag { local opts COMPREPLY=() arg="${COMP_WORDS[COMP_CWORD]}" if [[ $COMP_CWORD == 1 ]]; then opts="check compress decompress filter fix help info play record reindex" COMPREPLY=($(compgen -W "$opts" -- ${arg})) else if [[ ${arg} =~ \-\-.* ]]; then case ${COMP_WORDS[1]} in check) opts="--genrules --append --noplugins --help" ;; compress|decompress) opts="--output-dir --force --quiet --help" ;; filter) opts="--print --help" ;; fix) opts="--force --noplugins --help" ;; info) opts="--yaml --key --freq --help" ;; play) opts="--help --quiet --immediate --pause --queue --clock --hz --delay --rate --start --skip-empty --loop --keep-alive --try-future-version --topics --bags" ;; record) opts="--help --all --regex --exclude --quiet --output-prefix --output-name --split --size --duration --buffsize --limit --node --bz2" ;; reindex) opts="--help --force --quiet --output-dir" ;; esac COMPREPLY=($(compgen -W "$opts" -- ${arg})) fi fi } function _roscomplete_rospack { local arg opts COMPREPLY=() arg="${COMP_WORDS[COMP_CWORD]}" if [[ $COMP_CWORD == 1 ]]; then opts="help find list list-names list-duplicates langs depends depends-manifests depends1 depends-indent depends-msgsrv depends-why rosdep rosdep0 vcs vcs0 depends-on depends-on1 export plugins cflags-only-I cflags-only-other libs-only-L libs-only-l libs-only-other profile" COMPREPLY=($(compgen -W "$opts" -- ${arg})) else opts=$(rospack list-names) COMPREPLY=($(compgen -W "$opts" -- ${arg})) fi } function _roscomplete_rosnode { local arg opts COMPREPLY=() arg="${COMP_WORDS[COMP_CWORD]}" if [[ $COMP_CWORD == 1 ]]; then opts="ping list info machine kill cleanup" COMPREPLY=($(compgen -W "$opts" -- ${arg})) elif [[ $COMP_CWORD == 2 ]]; then case ${COMP_WORDS[1]} in info) opts=$(rosnode list 2> /dev/null) COMPREPLY=($(compgen -W "$opts" -- ${arg})) ;; ping|list|kill) if [[ ${arg} =~ \-\-.* ]]; then opts="--all --help" else opts=$(rosnode list 2> /dev/null) fi COMPREPLY=($(compgen -W "$opts" -- ${arg})) ;; machine) # This takes more logic to determine which machines are present. ;; esac else case ${COMP_WORDS[1]} in kill) # complete on node name opts=$(rosnode list 2> /dev/null) COMPREPLY=($(compgen -W "$opts" -- ${arg})) ;; esac fi } function _roscomplete_rosparam { local arg opts COMPREPLY=() arg="${COMP_WORDS[COMP_CWORD]}" if [[ $COMP_CWORD == 1 ]]; then opts="set get load dump delete list" COMPREPLY=($(compgen -W "$opts" -- ${arg})) elif [[ $COMP_CWORD == 2 ]]; then case ${COMP_WORDS[1]} in set|get|delete|list) opts=$(rosparam list 2> /dev/null) COMPREPLY=($(compgen -W "$opts" -- ${arg})) ;; load|dump) # complete on files COMPREPLY=($(compgen -f -- ${arg})) ;; esac elif [[ $COMP_CWORD == 3 ]]; then case ${COMP_WORDS[1]} in load|dump) # complete on namespace opts=$(rosparam list 2> /dev/null) COMPREPLY=($(compgen -W "$opts" -- ${arg})) ;; esac fi } function _roscomplete_rostopic { local arg opts COMPREPLY=() arg="${COMP_WORDS[COMP_CWORD]}" if [[ $COMP_CWORD == 1 ]]; then opts="bw echo hz list pub type find info" COMPREPLY=($(compgen -W "$opts" -- ${arg})) elif [[ $COMP_CWORD -ge 2 ]]; then if [[ ${arg} =~ \-\-.* ]]; then case ${COMP_WORDS[1]} in pub) COMPREPLY=($(compgen -W "--rate --once --file --latch" -- ${arg})) ;; bw) COMPREPLY=($(compgen -W "--window" -- ${arg})) ;; echo) COMPREPLY=($(compgen -W "--bag --filter --nostr --noarr --clear --all offset" -- ${arg})) ;; hz) COMPREPLY=($(compgen -W "--window --filter" -- ${arg})) ;; list) COMPREPLY=($(compgen -W "--bag --verbose --host" -- ${arg})) ;; esac else case ${COMP_WORDS[1]} in bw|echo|hz|list|type|info) if [[ ${COMP_WORDS[$(( $COMP_CWORD - 1 ))]} == "-b" ]]; then COMPREPLY=($(compgen -f -- ${arg})) else opts=$(rostopic list 2> /dev/null) COMPREPLY=($(compgen -W "$opts" -- ${arg})) fi ;; find) opts=$(_msg_opts ${COMP_WORDS[$COMP_CWORD]}) COMPREPLY=($(compgen -W "$opts" -- ${arg})) ;; pub) local topic_pos type_pos msg_pos topic_pos=2 type_pos=3 msg_pos=4 while [ $topic_pos -lt ${#COMP_WORDS[*]} ]; do if [[ ${COMP_WORDS[$topic_pos]} =~ \-.* ]]; then # ignore any options starting with - if [[ ${COMP_WORDS[$topic_pos]} == "-f" || ${COMP_WORDS[$topic_pos]} == "-r" ]]; then # ignore additional argument of -f and -r topic_pos=$((topic_pos + 1)) type_pos=$((type_pos + 1)) msg_pos=$((msg_pos + 1)) fi topic_pos=$((topic_pos + 1)) type_pos=$((type_pos + 1)) msg_pos=$((msg_pos + 1)) else break fi done if [[ $COMP_CWORD == $topic_pos ]]; then opts=$(rostopic list 2> /dev/null) COMPREPLY=($(compgen -W "$opts" -- ${arg})) elif [[ $COMP_CWORD == $type_pos ]]; then opts=$(rostopic info ${COMP_WORDS[$COMP_CWORD-1]} 2> /dev/null | awk '/Type:/{print $2}') if [ -z "$opts" ]; then opts=$(_msg_opts ${COMP_WORDS[$COMP_CWORD]}) fi COMPREPLY=($(compgen -W "$opts" -- ${arg})) elif [[ $COMP_CWORD == $msg_pos ]]; then opts=$(rosmsg-proto msg 2> /dev/null -s ${COMP_WORDS[$COMP_CWORD - 1]}) if [ 0 -eq $? ]; then COMPREPLY="$opts" fi fi ;; esac fi fi } function _roscomplete_rosservice { local arg opts COMPREPLY=() arg="${COMP_WORDS[COMP_CWORD]}" if [[ $COMP_CWORD == 1 ]]; then opts="args call find info list type uri" COMPREPLY=($(compgen -W "$opts" -- ${arg})) elif [[ $COMP_CWORD == 2 ]]; then case ${COMP_WORDS[1]} in args|call|info|list|type|uri) opts=$(rosservice list 2> /dev/null) COMPREPLY=($(compgen -W "$opts" -- ${arg})) ;; find) # Need a clever way to do message searching opts=$(_srv_opts ${COMP_WORDS[$COMP_CWORD]}) COMPREPLY=($(compgen -W "$opts" -- ${arg})) ;; esac elif [[ $COMP_CWORD == 3 ]]; then case ${COMP_WORDS[1]} in call) type=$(rosservice type ${COMP_WORDS[2]}) opts=$(rosmsg-proto srv 2> /dev/null -s ${type}) if [ 0 -eq $? ]; then COMPREPLY="$opts" fi ;; esac fi } function _msg_opts { local arg pkgs pkgname msgname searchmsg path count opts if [[ $1 =~ .+/.* ]]; then pkgname=${1%%/*} msgname=${1#*/} searchmsg=1 else pkgname=${1} fi if [[ -z ${searchmsg} ]]; then pkgs=($(rospack list | grep "^${pkgname}")) count=0 opts="" for (( i = 0 ; i < ${#pkgs[@]} ; i=i+2 )); do if [[ -d ${pkgs[i+1]}/msg ]]; then opts="$opts ${pkgs[i]}/" pkgname=${pkgs[i]} count=$((count+1)) fi done if [[ $count -gt 1 ]]; then echo $opts return 0 fi fi path=$(rospack find ${pkgname} 2> /dev/null) if [ $? -eq 0 ] && [ -d ${path}/msg ]; then echo $(find -L ${path}/msg -maxdepth 1 -mindepth 1 -name '*.msg' ! -regex ".*/[.][^./].*" -print0 | tr '\000' '\n' | sed -e "s/.*\/\(.*\)\.msg/${pkgname}\/\1/g") fi } function _roscomplete_rosmsg { local arg opts COMPREPLY=() arg="${COMP_WORDS[COMP_CWORD]}" if [[ $COMP_CWORD == 1 ]]; then opts="show list md5 package packages" COMPREPLY=($(compgen -W "$opts" -- ${arg})) elif [[ $COMP_CWORD == 2 ]]; then case ${COMP_WORDS[1]} in show|info|users|md5) opts=$(_msg_opts ${COMP_WORDS[$COMP_CWORD]}) COMPREPLY=($(compgen -W "$opts" -- ${arg})) ;; package) opts=$(rospack list-names) COMPREPLY=($(compgen -W "$opts" -- ${arg})) ;; packages|list) # This shouldn't really have a completion rule ;; esac fi } function _roscomplete_roscreate_pkg { local arg opts COMPREPLY=() arg="${COMP_WORDS[COMP_CWORD]}" if [[ $COMP_CWORD != 1 ]]; then opts=$(rospack list-names) COMPREPLY=($(compgen -W "$opts" -- ${arg})) fi } function _roscomplete_roswtf { local arg COMPREPLY=() arg="${COMP_WORDS[COMP_CWORD]}" if [[ ${arg} =~ \-\-.* ]]; then COMPREPLY=($(compgen -W "--all --no-plugins --offline" -- ${arg})) else if [[ $COMP_CWORD == 1 ]]; then COMPREPLY=($(compgen -o plusdirs -f -X "!*.launch" -- ${arg})) fi fi } function _roscomplete_rosclean { local arg opts COMPREPLY=() arg="${COMP_WORDS[COMP_CWORD]}" if [[ $COMP_CWORD == 1 ]]; then opts="check purge" COMPREPLY=($(compgen -W "$opts" -- ${arg})) fi } function _roscomplete_rosconsole { local arg opts COMPREPLY=() arg="${COMP_WORDS[COMP_CWORD]}" if [[ $COMP_CWORD == 1 ]]; then opts="get list set" COMPREPLY=($(compgen -W "$opts" -- ${arg})) elif [[ $COMP_CWORD == 2 ]]; then case ${COMP_WORDS[1]} in get|set|list) opts=$(rosnode list 2> /dev/null) COMPREPLY=($(compgen -W "$opts" -- ${arg})) ;; esac elif [[ $COMP_CWORD == 3 ]]; then case ${COMP_WORDS[1]} in get|set) opts=$(rosconsole list ${COMP_WORDS[2]} 2> /dev/null) COMPREPLY=($(compgen -W "$opts" -- ${arg})) ;; esac elif [[ $COMP_CWORD == 4 ]]; then case ${COMP_WORDS[1]} in set) opts="debug info warn error fatal" COMPREPLY=($(compgen -W "$opts" -- ${arg})) ;; esac fi } function _roscomplete_filemv { _roscompletemv_search_dir "-type f ! -regex .*[.][oa]$" } function _roscompletemv_search_dir { local arg opts rosvals COMPREPLY=() arg="${COMP_WORDS[COMP_CWORD]}" option="$(echo -e "${COMP_WORDS[1]}" | tr -d '[:space:]')" if [[ $COMP_CWORD == 2 && ( $option == "-d" ) ]] || [[ $COMP_CWORD == 1 ]]; then # complete packages _roscomplete_pkg "${arg}" elif [[ $COMP_CWORD == 2 && ( $option != "-d" ) ]]; then # complete files within package according to $1 _roscomplete_find "${1}" "${COMP_WORDS[1]}" "${arg}" else # complete filenames arg=$(echo ${arg} | sed -e "s|~|$HOME|g") if [[ $arg =~ ^/*.+/.* ]]; then path=${arg%/*} else path=. fi if [[ -e ${path} ]]; then opts=$(find -L $path -maxdepth 1 -type d ! -regex ".*/[.][^./].*" ! -regex "^[.]/" -print0 | tr '\000' '\n' | sed -e "s/$/\//g" -e "s/^[.]\///g" -e "s/'/\\\\\'/g" -e "s/ /\\\\\ /g")$'\n'$(find -L $path -maxdepth 1 -type f ! -regex ".*/[.][^.]*" ! -regex "^[.]/" -print0 | tr '\000' '\n' | sed -e "s/^[.]\///g" -e "s/'/\\\\\'/g" -e "s/ /\\\\\ /g") else opts="" fi _rosbash_roscomplete_search_dir_IFS="$IFS" IFS=$'\n' COMPREPLY=($(compgen -W "$opts" -- ${arg})) IFS="$_rosbash_roscomplete_search_dir_IFS" unset _rosbash_roscomplete_search_dir_IFS if [[ ${#COMPREPLY[*]} = 1 ]]; then newpath=${COMPREPLY[0]%/*} if [[ -d ${newpath} ]]; then opts=$(find -L $newpath -maxdepth 1 -type d ! -regex ".*/[.][^./].*" ! -regex "^[.]/" -print0 | tr '\000' '\n' | sed -e "s/$/\//g" -e "s/^[.]\///g" -e "s/'/\\\\\'/g" -e "s/ /\\\\\ /g")$'\n'$(find -L $newpath -maxdepth 1 -type f ! -regex ".*/[.][^.]*" ! -regex "^[.]/" -print0 | tr '\000' '\n' | sed -e "s/^[.]\///g" -e "s/'/\\\\\'/g" -e "s/ /\\\\\ /g") _rosbash_roscomplete_search_dir_IFS="$IFS" IFS=$'\n' COMPREPLY=($(compgen -W "$opts" -- ${arg})) IFS="$_rosbash_roscomplete_search_dir_IFS" unset _rosbash_roscomplete_search_dir_IFS fi fi fi } complete -F "_roscomplete_sub_dir" -o "nospace" "roscd" complete -F "_roscomplete_sub_dir" -o "nospace" "rospd" complete -F "_roscomplete_sub_dir" -o "nospace" "rosls" complete -F "_roscomplete_rosmake" "rosmake" complete -F "_roscomplete_rosclean" "rosclean" complete -F "_roscomplete_exe" "rosrun" complete -F "_roscomplete_file" "rosed" complete -F "_roscomplete_file" "roscp" complete -F "_roscomplete_file" "roscat" complete -F "_roscomplete_launch" -o filenames "roslaunch" complete -F "_roscomplete_test" -o filenames "rostest" complete -F "_roscomplete_rospack" "rospack" complete -F "_roscomplete_rosbag" -o default "rosbag" complete -F "_roscomplete_rosnode" "rosnode" complete -F "_roscomplete_rosparam" "rosparam" complete -F "_roscomplete_rostopic" "rostopic" complete -F "_roscomplete_rosservice" "rosservice" complete -F "_roscomplete_rosmsg" "rosmsg" complete -F "_roscomplete_rossrv" "rossrv" complete -F "_roscomplete_roscreate_pkg" "roscreate-pkg" complete -F "_roscomplete_roswtf" -o filenames "roswtf" complete -F "_roscomplete_rosconsole" "rosconsole" complete -F "_roscomplete_filemv" "rosmv" ros-1.15.8/tools/rosbash/rosfish000066400000000000000000001013641407615046500166270ustar00rootroot00000000000000# rosfish - functions to support ROS users # Developed and tested on fish 2.7.1 function _ros_command_line set -l command (commandline -cpo) (commandline -ct) for i in $command echo -- "$i" end end function _rossed if test (uname) = "Darwin" -o (uname) = "FreeBSD" sed -E $argv else sed -r $argv end end function _rosfind if test (uname) = "Darwin" -o (uname) = "FreeBSD" # BSD find needs -E for extended regexp find -E $argv else find $argv end end # _ros_location_find # Takes a name of a ros location and returns it's path function _ros_location_find set -l homedir (echo $HOME | sed -e "s/\//\t\//g" -e "s/\t/\\\/g") set -l ROS_LOCATION_KEYS_ARR (echo $ROS_LOCATIONS | _rossed -e 's/([^:=]*)=([^:=]*)(:*[^=])*(:|$)/\1 /g') set -l ROS_LOCATIONS_ARR (echo $ROS_LOCATIONS | _rossed -e 's/([^:=]*)=([^:=]*)(:*[^=])*(:|$)/\2 /g' -e "s/~/{$homedir}/g") for key in $ROS_LOCATION_KEYS_ARR if test $argv[1] = $key echo $key return 0 end end if test $argv[1] = log echo (roslaunch-logs) return 0 else if test $argv[1] = test_results echo (rosrun rosunit test_results_dir.py) return 0 end set -l loc (set -x ROS_CACHE_TIMEOUT -1.0; rospack find $argv[1] 2> /dev/null) if test $status != 0 set loc (set -x ROS_CACHE_TIMEOUT -1.0; rosstack find $argv[1] 2> /dev/null) if test $status != 0 return 1 end echo $loc return 0 end echo $loc return 0 end function _ros_list_locations set -l ROS_LOCATION_KEYS (echo $ROS_LOCATIONS | _rossed -e 's/([^:=]*)=([^:=]*)(:*[^=])*(:|$)/\1 /g') set -l packages (set -x ROS_CACHE_TIMEOUT -1.0; rospack list-names) set -l stacks (set -x ROS_CACHE_TIMEOUT -1.0; rosstack list-names) for i in $packages echo -- "$i" end for i in $stacks echo -- "$i" end echo log echo test_results for i in (string split ' ' "$ROS_LOCATION_KEYS") echo -- "$i" end return 0 end function _ros_package_find set -l loc (set -x ROS_CACHE_TIMEOUT -1.0; rospack find $argv[1] 2> /dev/null) if test $status -ne 0 return 1 end echo $loc return 0 end function _ros_list_packages set -l packages (set -x ROS_CACHE_TIMEOUT -1.0; rospack list-names) for i in $packages echo -- $i end return 0 end function _ros_list_stacks set -l stacks (set -x ROS_CACHE_TIMEOUT -1.0; rosstack list-names) for i in $stacks echo -- $i end return 0 end # takes as argument either just a package-path or just a pkgname # returns 0 for no argument or if package (+ path) exist, 1 else # on success with arguments returns [name, abspath, basepath, remainder] function _ros_decode_path if test -z "$argv[1]" return 0 end set -l rosname set -l reldir set -l last set -l reldir if echo -- "$argv[1]" | grep -qE -- ".+/.*" set rosname (string split / $argv[1])[1] set reldir /(string split --max 1 / $argv[1])[-1] set last (string split / $reldir)[-1] set reldir (string split --max 1 --right / $reldir)[1]/ else set rosname "$argv[1]" if test -z "$argv[2]" -o "$argv[2]" != "forceeval" echo -- $rosname return 1 end end set -l rosdir (_ros_location_find $rosname) if test $status != 0 echo -- $rosname return 1 end echo -- $rosname echo -- $rosdir echo -- $reldir echo -- $last return 0 end function rospython if test (count $argv) = 1 if test $argv[1] = "--help" echo -e "usage: rospython [package] \n\nRun python loading package manifest first." return 0 end end if test -z $argv if test -f ./manifest.xml set -l pkgname (basename (pwd)) python -i -c "import roslib; roslib.load_manifest('$pkgname')" else python end else python -i -c "import roslib; roslib.load_manifest('$argv[1]')" end end function roscd if test (count $argv) != 0 -a "$argv[1]" = "--help" echo -e "usage: roscd package\n\nJump to target package." return 0 end if test -z "$argv[1]" if test -n "$ROS_WORKSPACE" cd "$ROS_WORKSPACE" return 0 end if test -n "$CMAKE_PREFIX_PATH" for ws in (string split : "$CMAKE_PREFIX_PATH") if test -f "$ws/.catkin" cd "$ws" return 0 end end end echo -e "Neither ROS_WORKSPACE is set nor a catkin workspace is listed in CMAKE_PREFIX_PATH. Please set ROS_WORKSPACE or source a catkin workspace to use roscd with no arguments." return 1 end set -l rosvals (_ros_decode_path $argv[1] forceeval) if test $status != 0 echo "roscd: No such package/stack '$argv[1]'" return 1 else if test -z "$rosvals" if test -z "$ROS_WORKSPACE" echo -e "No ROS_WORKSPACE set. Please set ROS_WORKSPACE to use roscd with no arguments." return 1 end cd "$ROS_WORKSPACE" return 0 else cd "$rosvals[2]$rosvals[3]$rosvals[4]" return 0 end end function _is_integer not test -z (expr $argv[1] - $argv[1] 2>/dev/null) return $status end function rosd if test (count $argv) != 0 if test $argv[1] = "--help" echo -e "usage: rosd\n\nDisplays the list of currently remembered directories with indexes." return 0 end end set -l count 0 for items in (dirs | sed -e 's/ /\n/g') echo -- $count $items; set count (expr $count + 1) end end function rospd if test (count $argv) != 0 if test $argv[1] = "--help" echo -e "usage: rospd\n\nLike pushd, also accepts indexes from rosd." return 0 end else echo -e "usage: rospd\n\nLike pushd, also accepts indexes from rosd." return 0 end if _is_integer $argv[1] pushd +$argv[1] > /dev/null else set -l rosvals (_ros_decode_path $argv[1] forceeval) if test $status != 0 -a (count $argv) -gt 0 echo "rospd: No such package/stack '$argv[1]'" return 1 end pushd $rosvals[2]$rosvals[3]$rosvals[4] > /dev/null end rosd end function rosls if test (count $argv) = 0 -o "$argv[1]" = "--help" echo -e "usage: rosls [package]\n\nLists contents of a package directory." return 0 end set -l rosvals (_ros_decode_path $argv[1] forceeval) ls $rosvals[2]$rosvals[3]$rosvals[4] $argv[2] end function rosmv set -l arg rosvals if test "$argv[1]" = "--help" -o [ test (count $argv) != 3 -a test (count $argv) != 4 ] echo -e "usage: rosmv [OPTION]... source... destination\n or: rosmv package... filename... destination" echo -e "\nMove a file from a package to target location\n-d Move package to target directory" return 0 end if test "$argv[1]" = "-d" set -l rosvals (_ros_decode_path $argv[2] forceeval) set pic "$rosvals[2]$rosvals[3]$rosvals[4]" mv -t $3 $pic else set -l arg (_roscmd $argv[1] $argv[2]) if test $status = 0 mv $arg $argv[3] end end end # sets arg as return value function _roscmd set -l opt set -l catkin_package_libexec_dir if test -n "$CMAKE_PREFIX_PATH" set catkin_package_libexec_dir (catkin_find --first-only --without-underlays --libexec $argv[1] 2> /dev/null) end set -l pkgdir (_ros_package_find $argv[1]) if test -z "$catkin_package_libexec_dir" -a -z "$pkgdir" echo "Couldn't find package $argv[1]" >&2 return 1 end set -l exepath (_rosfind -L $catkin_package_libexec_dir $pkgdir -name $argv[2] -type f ! -regex ".*/[.].*" ! -regex ".*$pkgdir\/build\/.*" | uniq) set -l opt if test (count $exepath) = 0 echo "That file does not exist in that package." >&2 return 1 else if test (count $exepath) -gt 1 echo "You have chosen a non-unique filename, please pick one of the following:" >&2 for i in (seq (count $exepath)) echo $i") " $exepath[$i] >&2 end read choice set opt $exepath[$choice] else set opt $exepath[1] end echo -- $opt end function rosed if test (count $argv) = 0 -o $argv[1] = "--help" echo -e "usage: rossed [package] [file]\n\nEdit a file within a package." return 0 end set -l arg (_roscmd $argv[1] $argv[2]) if test $status = 0 if test -z $EDITOR vim $arg else eval $EDITOR $arg end end end function roscp set -l arg if test (count $argv) != 3 echo -e "usage: roscp package filename target\n\nCopy a file from a package to target location." return 0 end set -l arg (_roscmd $argv[1] $argv[2]) if test $status = 0 cp $arg $argv[3] end end function roscat if test $argv[1] = "--help" -o (count $argv) -ne 2 echo -e "usage: roscat [package] [file]\n\nDisplay a file content within a package." test $argv[1] = "--help"; and return 0; or return 1 end set -l arg (_roscmd $argv[1] $argv[2]) test $status -eq 1; and return 1 if test -n $arg if test -z $CATTER cat $arg else eval $CATTER $arg end end end function _roscomplete _ros_list_locations _ros_list_stacks end function _roscomplete_rosmake set -l command (_ros_command_line) set -l arg $command[-1] set -l opts (_roscomplete) if echo -- $arg | grep -qE -- "^--.*" set opts $opts --test-only --all --mark-installed --unmark-installed --robust --build-everything --specified-only --buildtest --buildtest1 --output --pre-clean --bootstrap --disable-logging --target --pjobs= --threads --profile --skip-blacklist --status-rate end for i in $opts echo -- $i end end function _roscomplete_sub_dir set -l command (_ros_command_line) set -l arg $command[-1] set -l rosvals (_ros_decode_path $arg) if test -z "$rosvals[3]" # Not a full ROS location for i in (_ros_list_locations) echo -- "$i/" end else # The first section is a full ROS location, so we complete from it's subdirs set -l opts if test -e "$rosvals[2]$rosvals[3]" set opts (_rosfind -L "$rosvals[2]$rosvals[3]" -maxdepth 1 -mindepth 1 -type d ! -regex ".*/[.][^./].*" -print0 | tr '\000' '\n' | sed -e "s/.*\/\(.*\)/\1\//g") end for i in $opts echo -- "$rosvals[1]$rosvals[3]$i" end end end function _msg_opts if echo -- $argv[1] | grep -qE ".+/.*" set -l splitname (string split / $argv[1]) set -l pkgname $splitname[1] set -l msgname $splitname[-1] set -l path (rospack find $pkgname) if test -d "$path/msg" set -l opts (_rosfind -L $path/msg -maxdepth 1 -mindepth 1 -name "*.msg" ! -regex ".*/[.][^./].*" -print0 | tr '\000' '\n' | sed -e "s/.*\/\(.*\)\.msg/$pkgname\/\1/g") for i in $opts echo -- $i end end else set -l pkgname $argv[1] set -l pkgs (rospack list | sed 's/ /\n/g') for i in (seq 1 2 (count $pkgs)) if test -d $pkgs[(math $i + 1)]"/msg" echo $pkgs[$i]/ end end end end function _srv_opts set -l pkgname if echo -- $argv[1] | grep -qE ".+/.*" set -l splitname (string split / $argv[1]) set pkgname $splitname[1] else set pkgname $argv[1] set -l pkgs (rospack list | grep "^$pkgname") set -l count 0 set -l opts for i in $pkgs set -l parts (string split ' ' $i) set -l pkg_name $parts[1] set -l pkg_path $parts[2] if test -d $pkg_path/srv set opts $opts $pkg_name/ set pkgname $pkg_name set count (math $count + 1) end end if test $count -gt 1 for i in $opts echo -- $i end return 0 end end set -l path (rospack find $pkgname 2> /dev/null) if test $status -eq 0 -a -d $path/srv set -l opts (_rosfind -L $path/srv -maxdepth 1 -mindepth 1 -name "*.srv" ! -regex ".*/[.][^./].*" -print0 | tr '\000' '\n' | sed -e "s/.*\/\(.*\)\.srv/$pkgname\/\1/g") for i in $opts echo -- $i end end end function _roscomplete_rossrv set -l command (_ros_command_line) set -l arg $command[-1] if test (count $command) = 2 set -l opts show list md5 package packages for i in $opts echo $i end else if test (count $command) = 3 switch $command[2] case show users md5 for i in (_srv_opts $arg) echo -- $i end case package for i in (rospack list-names) echo -- $i end case packages list # This shouldn't really have a completion rule end end end function _roscomplete_find # complete files that match $argv[2] within $argv[1], that start with $argv[3] set -l opts set -l pkgdir set -l catkin_package_libexec_dir set -l perm $argv[1] set -l pkg $argv[2] set -l arg $argv[3] if test -n "$CMAKE_PREFIX_PATH" set catkin_package_libexec_dir (catkin_find --first-only --without-underlays --libexec $pkg 2> /dev/null) end set pkgdir (_ros_package_find $pkg) set -l opts if test -n "$catkin_package_libexec_dir" -o -n "$pkgdir" set -l args (echo -n -- $argv[1] | sed -e 's/ /\\n/g') set opts (_rosfind -L $catkin_package_libexec_dir "$pkgdir" $args ! -regex ".*/[.][^./].*" ! -regex ".*$pkgdir\/build\/.*" -print0 | tr '\000' '\n' | sed -e "s/.*\/\(.*\)/\1/g") else set opts "" end for i in $opts echo -- $i end end function _roscomplete_filemv _roscompletemv_search_dir '-type f ! -regex .*[.][oa]$' end function _roscompletemv_search_dir set -l command (_ros_command_line) set -l arg $command[-1] set option (echo -e "$COMP_WORDS[1]" | tr -d '[:space:]') if [ test (count $command) = 2 -a (option) = "-d" ] -o test (count $command) = 1 # complete packages _ros_list_packages $arg else if test (count $command) = 2 -a (option) != "-d" # complete files within package according to $argv[1] _roscomplete_find $argv[1] $command[1] $arg else # complete filenames set -l arg (echo $arg | sed -e "s|~|$HOME|g") set -l path if echo -- $arg | grep -qE -- "^/*.+/.*" set path (string split --max 1 --right / $argv[1])[1] else set path . end set -l opts if test -e $path set opts (find -L $path -maxdepth 1 -type d ! -regex ".*/[.][^./].*" ! -regex "^[.]/" -print0 | tr '\000' '\n' | sed -e "s/\$/\//g" -e "s/^[.]\///g" -e "s/'/\\\\\'/g" -e "s/ /\\\\\ /g") set opts $opts (find -L $path -maxdepth 1 -type f ! -regex ".*/[.][^.]*" ! -regex "^[.]/" -print0 | tr '\000' '\n' | sed -e "s/^[.]\///g" -e "s/'/\\\\\'/g" -e "s/ /\\\\\ /g") for i in $opts echo -- $i end end # TODO rosbash does some extra stuff here for some reason end end function _roscomplete_search_dir set -l command (_ros_command_line) set -l arg $command[-1] if test (count $command) = 2 # complete packages _ros_list_packages $arg else if test (count $command) = 3 # complete files within package according to $argv[1] _roscomplete_find $argv[1] $command[2] $arg else # complete filenames set -l arg (echo $arg | sed -e "s|~|$HOME|g") set -l path if echo -- $arg | grep -qE -- "^/*.+/.*" set path (string split --max 1 --right / $argv[1])[1] else set path . end set -l opts if test -e $path set opts (find -L $path -maxdepth 1 -type d ! -regex ".*/[.][^./].*" ! -regex "^[.]/" -print0 | tr '\000' '\n' | sed -e "s/\$/\//g" -e "s/^[.]\///g" -e "s/'/\\\\\'/g" -e "s/ /\\\\\ /g") set opts $opts (find -L $path -maxdepth 1 -type f ! -regex ".*/[.][^.]*" ! -regex "^[.]/" -print0 | tr '\000' '\n' | sed -e "s/^[.]\///g" -e "s/'/\\\\\'/g" -e "s/ /\\\\\ /g") for i in $opts echo -- $i end end # TODO rosbash does some extra stuff here for some reason end end function _roscomplete_rosrun set -l perm if test (uname) = "Darwin" -o (uname) = "FreeBSD" set perm "+111" else set perm "/111" end set -l command (_ros_command_line) # rosrun ONLY accepts arguments before the package names; we need to honor this set -l start_arg 2 set -l prev_arg # loop through args and skip --prefix, arg to prefix and --debug for i in (seq 2 (count $command)) set -l arg $command[$i] switch $arg case --prefix -p --debug -d set start_arg (math $start_arg + 1) case '*' if test "$prev_arg" = '--prefix' -o "$prev_arg" = '-p' set start_arg (math $start_arg + 1) else break end end set prev_arg $arg end set -l end_arg (count $command) set -l arg $command[-1] if test $start_arg -gt $end_arg # complete command names for --prefix complete -C$arg else if test $start_arg = $end_arg # completing first argument; can be --arg or package name if echo -- $arg | grep -qE -- "-.*" set -l opts --prefix --debug for i in $opts echo $i end else _ros_list_packages $arg end else if test (math $start_arg + 1) = $end_arg # completing second argument; node within package set -l pkg $command[2] _roscomplete_find "-type f -perm $perm" $pkg $arg else # completing remaining arguments; per "normal" _roscomplete_search_dir "-type f -perm $perm" end end function _roscomplete_file _roscomplete_search_dir '-type f ! -regex .*[.][oa]$' end function _roscomplete_roslaunch set -l command (_ros_command_line) set -l arg $command[-1] if echo -- $command[-1] | grep -qE "^--" set options --files --args --nodes --find-node --child --local --screen --server_uri --run_id --wait --port --core --pid --dump-params for i in $options echo -- $i end else set -l opts (_roscomplete_search_dir '( -type f -regex .*\.launch$ -o -type f -regex .*\.test$ )') # Add launchfiles and directories in the current directory if test (count $command) = 2 set opts $opts (__fish_complete_directories "$arg") set opts $opts (_rosfind (string split --max 1 --right / "$arg")[1]/ -mindepth 1 -maxdepth 1 -name "*.launch" -o -name "*.test" 2> /dev/null) end # complete roslaunch arguments for a launch file if test (count $command) -ge 2 set -l roslaunch_complete (which roslaunch-complete) if test -x $roslaunch_complete # Call roslaunch-complete instead of roslaunch to get arg completion set -l roslaunch_args (eval $roslaunch_complete $command[2..3] 2> /dev/null | sed 's/ /\n/g') # roslaunch-complete should be very silent about # errors and return 0 if it produced usable completion. if test $status = 0 set opts $opts $roslaunch_args # FIXME maybe leave $opts out if we completed successfully. end end end for i in $opts echo $i end end end function _roscomplete_rostest set -l command (_ros_command_line) set -l arg $command[-1] if echo -- $arg | grep -qE -- "--.*" set -l opts --bare --bare-limit --bare-name --pkgdir --package for i in $opts echo -- $i end else set -l opts (_roscomplete_search_dir '( -type f -regex .*\.launch$ -o -type f -regex .*\.test$ )') if test (count $command) = 2 set opts $opts (__fish_complete_directories "$arg") set opts $opts (_rosfind "$arg" -mindepth 1 -maxdepth 1 -name "*.launch" -o -name "*.test" 2> /dev/null) end for i in $opts echo -- $i end end end function _roscomplete_rosbag set -l command (_ros_command_line) set -l arg $command[-1] if test (count $command) = 2 set -l opts check compress decompress filter fix help info play record reindex for i in $opts echo $i end else if echo -- $arg | grep -qE -- "--.*" set -l opts switch $command[2] case check set opts --genrules --append --noplugins --help case compress decompress set opts --output-dir --force --quiet --help case filter set opts --print --help case fix set opts --force --noplugins --help case info set opts --yaml --key --freq --help case play set opts --help --quiet --immediate --pause --queue --clock --hz --delay --rate --start --skip-empty --loop --keep-alive --try-future-version --topics --bags case record set opts --help --all --regex --exclude --quiet --output-prefix --output-name --split --size --duration --buffsize --limit --node --bz2 case reindex set opts --help --force --quiet --output-dir end for i in $opts echo -- $i end else set -l opts set -l arg (string replace --regex '^~/' "$HOME/" "$arg") set -l replaced_home $status if test -z "$arg" set arg ./ end set -l replaced_empty $status set opts $opts (_rosfind (string split --max 1 --right / "$arg")[1]/ -mindepth 1 -maxdepth 1 -name "*.bag" 2> /dev/null) set opts $opts (__fish_complete_directories "$arg") if test $replaced_home = 0 set -l fixed_opts for opt in $opts set fixed_opts $fixed_opts (string replace --regex "^$HOME/" "~/" "$opt") end set opts $fixed_opts end if test $replaced_empty = 0 set -l fixed_opts for opt in $opts set fixed_opts $fixed_opts (string replace --regex "^\./" "" "$opt") end set opts $fixed_opts end for i in $opts echo -- $i end end end end function _roscomplete_rospack set -l command (_ros_command_line) if test (count $command) = 2 set -l opts help find list list-names list-duplicates langs depends depends-manifests depends1 depends-indent depends-msgsrv depends-why rosdep rosdep0 vcs vcs0 depends-on depends-on1 export plugins cflags-only-I cflags-only-other libs-only-L libs-only-l libs-only-other profile for i in $opts echo $i end else for i in (rospack list-names) echo $i end end end function _roscomplete_rosnode set -l command (_ros_command_line) set -l arg $command[-1] if test (count $command) = 2 set -l opts ping list info machine kill cleanup for i in $opts echo $i end else if test (count $command) = 3 switch $command[2] case info for i in (rosnode list 2> /dev/null) echo $i end case ping list kill set -l opts if echo -- $arg | grep -qE -- "--.*" set opts --all --help else set opts (rosnode list 2> /dev/null) end for i in $opts echo $i end case machine # This takes more logic to determine which machines are present end else switch $command[2] case kill # complete on node name for i in (rosnode list 2> /dev/null) echo $i end end end end function _roscomplete_rosparam set -l command (_ros_command_line) if test (count $command) = 2 set -l opts set get load dump delete list for i in $opts echo $i end else if test (count $command) = 3 switch $command[2] case set get delete list for i in (rosparam list 2> /dev/null) echo $i end case load dump # complete on files set -l arg $command[-1] complete --do-complete="$arg" end else if test (count $command) = 4 switch $command[2] case load dump # complete on namespace for i in (rosparam list 2> /dev/null) echo $i end end end end function _roscomplete_rostopic set -l command (_ros_command_line) set -l arg $command[-1] set -l opts if test (count $command) = 2 set -l opts bw delay echo hz list pub type find info for i in $opts echo $i end else if test (count $command) -ge 3 if echo -- $arg | grep -qE -- '--.*' set -l opts switch $command[2] case pub set opts --rate --once --file --latch case bw set opts --window case delay set opts --window --tcpnodelay case echo set opts --bag --filter --nostr --noarr --clear --all offset case hz set opts --window --filter case list set opts --bag --verbose --host end for i in $opts echo -- "$i" end else switch $command[2] case bw delay echo hz list type info if test "$command[-2]" = '-b' -o "$command[-2]" = '--bag' __fish_complete_path "$arg" else for i in (rostopic list) echo $i end end case find for i in (_msg_opts $command[-1]) echo -- $i end case pub set -l topic_pos 3 set -l type_pos 4 set -l msg_pos 5 while test $topic_pos -le (count $command) if echo -- $command[$topic_pos] | grep -qE -- "-.*" # ignore any options starting with - if test $command[$topic_pos] = '-f' -o $command[$topic_pos] = '-r' # ignore additional argument of -f and -r set topic_pos (math $topic_pos + 1) set type_pos (math $type_pos + 1) set msg_pos (math $msg_pos + 1) end set topic_pos (math $topic_pos + 1) set type_pos (math $type_pos + 1) set msg_pos (math $msg_pos + 1) else break end end if test (count $command) = $topic_pos set -l opts (rostopic list 2> /dev/null) for i in $opts echo -- $i end else if test (count $command) = $type_pos set -l opts (rostopic info $command[-2] 2> /dev/null | awk '/Type:/{print $2}') if test -z $opts set opts (_msg_opts $command[-1]) end for i in $opts echo -- $i end else if test (count $command) = $msg_pos set -l opts (rosmsg-proto msg 2> /dev/null -s $command[-2]) if test $status = 0 for i in $opts echo -- $i end end end end end end end function _roscomplete_rosservice set -l command (_ros_command_line) if test (count $command) = 2 set -l opts args call find info list type uri for i in $opts echo -- $i end else if test (count $command) = 3 switch $command[2] case args call info list type uri set -l opts (rosservice list 2> /dev/null) for i in $opts echo -- $i end case find # Need a clever way to do message searching set -l opts (_srv_opts $command[-1]) for i in $opts echo -- $i end end else if test (count $command) = 4 switch $command[2] case call set -l type (rosservice type $command[3]) set -l opts (rosmsg-proto srv 2> /dev/null -s $type) # TODO: better formatting here echo -- (string unescape $opts) end end end function _roscomplete_rosmsg set -l command (_ros_command_line) set -l arg $command[-1] if test (count $command) = 2 set -l opts show list md5 package packages for i in $opts echo -- $i end else if test (count $command) = 3 switch $command[2] case show info users md5 for i in (_msg_opts $command[-1]) echo -- $i end case package for i in (rospack list-names) echo -- $i end case packages list # This shouldn't really have a completion rule end end end function _roscomplete_roscreate_pkg set -l command (_ros_command_line) if test (count $command) != 2 set -l opts (rospack list-names) for i in $opts echo $i end end end function _roscomplete_roswtf set -l command (_ros_command_line) set -l arg $command[-1] if echo -- $arg | grep -qE -- "--.*" set -l opts --all --noplugins --offline for i in $opts echo -- $i end else if test (count $command) = 2 __fish_complete_directories "$arg" _rosfind "$arg" -mindepth 1 -maxdepth 1 -name "*.launch" 2> /dev/null end end end function _roscomplete_rosconsole set -l command (_ros_command_line) set -l arg $command[-1] set -l opts if test (count $command) = 2 set opts get list set else if test (count $command) = 3 switch "$command[2]" case get set list set opts (rosnode list 2> /dev/null) end else if test (count $command) = 4 switch "$command[2]" case get set set opts (rosconsole list "$command[3]" 2> /dev/null) end else if test (count $command) = 5 switch "$command[2]" case set set opts debug info warn error fatal end end for i in $opts echo -- $i end end # TODO add options for filenames, default complete -x -c roscd -a '(_roscomplete_sub_dir)' complete -x -c rospd -a '(_roscomplete_sub_dir)' complete -x -c rosls -a '(_roscomplete_sub_dir)' complete -x -c rosmake -a '(_roscomplete_rosmake)' complete -x -c rosclean -a 'check purge' complete -x -c rosrun -a '(_roscomplete_rosrun)' complete -x -c rosed -a '(_roscomplete_file)' complete -x -c roscp -a '(_roscomplete_file)' complete -x -c roscat -a '(_roscomplete_file)' complete -x -c roslaunch -a '(_roscomplete_roslaunch)' complete -x -c rostest -a '(_roscomplete_rostest)' complete -x -c rospack -a '(_roscomplete_rospack)' complete -x -c rosbag -a '(_roscomplete_rosbag)' complete -x -c rosnode -a '(_roscomplete_rosnode)' complete -x -c rosparam -a '(_roscomplete_rosparam)' complete -x -c rostopic -a '(_roscomplete_rostopic)' complete -x -c rosservice -a '(_roscomplete_rosservice)' complete -x -c rosmsg -a '(_roscomplete_rosmsg)' complete -x -c rossrv -a '(_roscomplete_rossrv)' complete -x -c roscreate-pkg -a '(_roscomplete_roscreate_pkg)' complete -x -c roswtf -a '(_roscomplete_roswtf)' complete -x -c rosconsole -a '(_roscomplete_rosconsole)' complete -x -c rosmv -a '(_roscomplete_filemv)' ros-1.15.8/tools/rosbash/rostcsh000066400000000000000000000045751407615046500166450ustar00rootroot00000000000000alias roscd 'cd `rospack find \!*; if ($status) rosstack find \!*;`' alias rcd roscd alias rosls 'ls `rospack find \!*`' #alias rosd 'echo "unimplemented"' #alias rospd 'echo "unimplemented"' #alias rosed 'echo "unimplemented"' #alias roscat 'echo "unimplemented"' #alias roscmd 'echo "unimplemented"' #alias roscp 'echo "unimplemented"' #alias rosmv 'echo "unimplemented"' complete roscd 'p/1/`rospack list-names && rosstack list-names`/' complete rosmake 'p/*/`rospack list-names && rosstack list-names`/' complete rosupdate 'p/1/`rospack list-names && rosstack list-names`/' complete rosdeb 'p/*/`rospack list-names && rosstack list-names`/' complete rosdep \ 'p/1/(help generate_bash install depdb what_needs check satisfy)/' \ 'n/{generate_bash,install,depdb,check,satisfy}/`rospack list-names`/' complete rospack \ 'p/1/(help find list list-names langs deps deps-manifests deps1 deps-indent rosdeps rosdeps0 vcs vcs0 depends-on)/' \ 'n/{find,deps,deps-manifests,deps1,deps-indent,rosdeps,rosdeps0,vcs,vcs0,depends-on,depends-on1,export,cflags-only-I,cflags-only-other,libs-only-L,libs-only-l,libs-only-other}/`rospack list-names`/' complete rosstack \ 'p/1/(help find list list-names langs deps deps-manifests deps1 deps-indent rosdeps rosdeps0 vcs vcs0 depends-on)/' \ 'n/{find,deps,deps-manifests,deps1,deps-indent,rosdeps,rosdeps0,vcs,vcs0,depends-on,depends-on1,export,cflags-only-I,cflags-only-other,libs-only-L,libs-only-l,libs-only-other}/`rosstack list-names`/' complete rostopic \ 'p/1/(hz echo type list)/' \ 'n/{echo,hz,type}/`rostopic list | sort -u`/' complete rosmsg \ 'p/1/(show users package packages)/' \ 'n@{show,users}@`rostopic list -v | grep " \* " | cut -f 4 -d " " | grep -v unknown | sed -e "s/[\d93\d91]//g"`@' \ 'n/{package,packages}/`rospack list-names`/' complete rossrv \ 'p/1/(show users package packages)/' \ 'n@{show,users}@`rostopic list -v | grep " \* " | cut -f 4 -d " +" | grep -v unknown | sed -e "s/[\d93\d91]//g"`@' \ 'n/{package,packages}/`rospack list-names`/' complete rosrun \ 'p/1/`rospack list-names`/' \ 'p@2@`rospack find $:1 | xargs -I 1 find 1 -perm /a+x -type f -printf "%f\n"`@' complete roslaunch \ 'p/1/`rospack list-names && find . -maxdepth 3 -regex ".*[xl][am][ul]n*c*h*" -printf "%P\n" `/' \ 'p@2@`rospack find $:1 | xargs -I 1 find 1 -maxdepth 3 -regex ".*[xl][am][ul]n*c*h*" -type f -printf "%f\n"`@' ros-1.15.8/tools/rosbash/roszsh000066400000000000000000000664451407615046500165140ustar00rootroot00000000000000# roszsh - functions to support ROS users # Useful things to know: # 'local' variables get unset after function, all others stay forever # 'reply' is the var used by zsh compctl builtin function _rossed { if [[ `uname` == Darwin || `uname` == FreeBSD ]]; then sed -E "$@" else sed -r "$@" fi } function _rosfind { if [[ `uname` == Darwin || `uname` == FreeBSD ]]; then # BSD find needs -E for extended regexp find -E "$@" else find "$@" fi } # _ros_location_find # based on $ROS_LOCATIONS, which the user can set to any colon # separated of key=folder pairs also resolves keys 'log' and # 'test_results' to ROS defaults finally resolves to package, then # stack echoes its result function _ros_location_find { local ROS_LOCATION_KEYS_ARR ROS_LOCATIONS_ARR loc ROS_LOCATION_KEYS_ARR=(`echo $ROS_LOCATIONS | _rossed -e 's/([^:=]*)=([^:=]*)(:*[^=])*(:|$)/\1 /g'`) ROS_LOCATIONS_ARR=(`echo $ROS_LOCATIONS | _rossed -e 's/([^:=]*)=([^:=]*)(:*[^=])*(:|$)/\2 /g' -e "s|~|$HOME|g"`) for (( i = 1 ; i <= ${#ROS_LOCATION_KEYS_ARR[@]} ; i++ )); do if [[ $1 == ${ROS_LOCATION_KEYS_ARR[$i]} ]]; then echo ${ROS_LOCATIONS_ARR[i]} return 0 fi done if [[ $1 == log ]]; then echo `roslaunch-logs` return 0 elif [[ $1 == test_results ]]; then echo `rosrun rosunit test_results_dir.py` return 0 fi loc=`export ROS_CACHE_TIMEOUT=-1.0 && rospack find $1 2> /dev/null` if [[ $? != 0 ]]; then loc=`export ROS_CACHE_TIMEOUT=-1.0 && rosstack find $1 2> /dev/null` if [[ $? != 0 ]]; then return 1 fi echo $loc return 0 fi echo $loc return 0 } function _ros_list_locations { local ROS_LOCATION_KEYS packages stacks ROS_LOCATION_KEYS=`echo $ROS_LOCATIONS | _rossed -e 's/([^:=]*)=([^:=]*)(:*[^=])*(:|$)/\1 /g'` packages=`export ROS_CACHE_TIMEOUT=-1.0 && rospack list-names` stacks=`export ROS_CACHE_TIMEOUT=-1.0 && rosstack list-names` echo $packages $stacks log test_results $ROS_LOCATION_KEYS | tr ' ' '\n' return 0 } function _ros_decode_path { local rosname rosdir reldir last rospackdir rosstack_result rosstackdir rosvals=() if [[ -z $1 ]]; then return 0 fi echo $1 | grep -G '.\+/.*' > /dev/null if [[ $? == 0 ]]; then rosname=${1%%/*} reldir=/${1#*/} last=${reldir##*/} reldir=${reldir%/*}/ else rosname=$1 if [[ -z $2 || $2 != "forceeval" ]]; then rosvals=(${rosname}) return 1 fi fi if [[ $rosname == ros ]]; then rosdir=`rosstack find ros` elif [[ $rosname == pkg ]]; then rosdir=${ROS_PACKAGE_PATH%%:*} elif [[ $rosname == log ]]; then rosdir=`roslaunch-logs` elif [[ $rosname == test_results ]]; then rosdir=`rosrun rosunit test_results_dir.py` else rospackdir=`export ROS_CACHE_TIMEOUT=-1.0 && rospack find $rosname 2> /dev/null` rospack_result=$? rosstackdir=`export ROS_CACHE_TIMEOUT=-1.0 && rosstack find $rosname 2> /dev/null` rosstack_result=$? if [[ $rospack_result == 0 ]]; then rosdir=$rospackdir elif [[ $rosstack_result == 0 ]]; then rosdir=$rosstackdir else rosvals=(${rosname}) return 1 fi fi rosvals=(${rosname} ${rosdir} ${reldir} ${last}) } function rospython { if [[ $1 = "--help" ]]; then echo -e "usage: rospython [package] \n\nRun python loading package manifest first." return 0 fi if [[ -z $1 ]]; then if [[ -f ./manifest.xml ]]; then pkgname=`basename \`pwd\`` python -i -c "import roslib; roslib.load_manifest('$pkgname')" else python fi else python -i -c "import roslib; roslib.load_manifest('$1')" fi } function roscd { local rosvals if [[ $1 = "--help" ]] | [[ $# -gt 1 ]]; then echo -e "usage: roscd package\n\nJump to target package." return 0 fi if [ -z $1 ]; then if [ ! -z $ROS_WORKSPACE ]; then cd ${ROS_WORKSPACE} return 0 fi if [ ! -z $CMAKE_PREFIX_PATH ]; then workspaces=("${(s/:/)CMAKE_PREFIX_PATH}") for ws in "${workspaces[@]}"; do if [ -f $ws/.catkin ]; then cd ${ws} return 0 fi done fi echo -e "Neither ROS_WORKSPACE is set nor a catkin workspace is listed in CMAKE_PREFIX_PATH. Please set ROS_WORKSPACE or source a catkin workspace to use roscd with no arguments." return 1 fi _ros_decode_path $1 forceeval if [ $? != 0 ]; then echo "roscd: No such package '$1'" return 1 elif [ -z ${rosvals[1]} ]; then if [ -z $ROS_WORKSPACE ]; then echo -e "No ROS_WORKSPACE set. Please set ROS_WORKSPACE to use roscd with no arguments." return 1 fi cd ${ROS_WORKSPACE} return 0 else cd ${rosvals[2]}${rosvals[3]}${rosvals[4]} return 0 fi } function _is_integer { [ "$1" -eq "$1" ] > /dev/null 2>&1 return $? } function rosd { if [[ $1 = "--help" ]]; then echo -e "usage: rosd\n\nDisplays the list of currently remembered directories with indexes." return 0 fi let count=0; for items in `dirs`; do echo $count $items; let count=$((count+1)); done } function rospd { if [[ $1 = "--help" ]]; then echo -e "usage: rospd\n\nLike pushd, also accepts indexes from rosd." return 0 fi if _is_integer $1; then pushd +$1 > /dev/null ; else local rosvals _ros_decode_path $1 forceeval pushd ${rosvals[2]}${rosvals[3]}${rosvals[4]} > /dev/null ; fi rosd } function rosls { local rosvals if [[ $1 = "--help" ]]; then echo -e "usage: rosls [package]\n\nLists contents of a package directory." return 0 fi _ros_decode_path $1 forceeval ls ${rosvals[2]}${rosvals[3]}${rosvals[4]} $2 } # sets arg as return value function _roscmd { local pkgdir exepath opt pkgdir=`export ROS_CACHE_TIMEOUT=-1.0 && rospack find $1 2> /dev/null` if [[ $? != 0 ]] ; then echo "Couldn't find package [$1]" return 1 fi exepath=(`find $pkgdir -name $2 -type f`) if [[ ${#exepath[@]} == 0 ]] ; then echo "That file does not exist in that package." return 1 elif [[ ${#exepath[@]} -gt 1 ]] ; then echo "You have chosen a non-unique filename, please pick one of the following:" select opt in ${exepath[@]}; do echo $opt break done else opt=${exepath[1]} fi arg=${opt} } function rosed { local arg if [[ $1 = "--help" ]]; then echo -e "usage: rosed [package] [file]\n\nEdit a file within a package." return 0 fi _roscmd ${1} ${2} if [[ -z $EDITOR ]]; then vim ${arg} else eval $EDITOR ${arg} fi } function roscp { local arg if [[ $1 = "--help" ]] | [[ $# -ne 3 ]]; then echo -e "usage: roscp package filename target\n\nCopy a file from a package to target location." return 0 fi _roscmd ${1} ${2} cp ${arg} ${3} } function rosmv { local arg rosvals if [[ $1 = "--help" ]] || [[ $# -ne 3 && $# -ne 4 ]]; then echo -e "usage: rosmv [OPTION]... source... destination\n or: rosmv package... filename... destination" echo -e "\nMove a file from a package to target location\n-d Move package to target directory" return 0 fi if [[ $1 = "-d" ]]; then _ros_decode_path ${2} forceeval pic="${rosvals[1]}${rosvals[2]}${rosvals[3]}" mv -t ${3} ${pic} else _roscmd ${1} ${2} mv ${arg} ${3} fi } function roscat { local arg if [[ $1 = "--help" ]] | [[ $# -ne 2 ]]; then echo -e "usage: roscat [package] [file]\n\nDisplay a file content within a package." [[ $1 = "--help" ]] && return 0 || return 1 fi _roscmd ${1} ${2} [ $? -eq 1 ] && return 1 if [[ -z $CATTER ]]; then cat ${arg} else $CATTER ${arg} fi } function _roscomplete { local arg opts stack_opts reply=() opts=`export ROS_CACHE_TIMEOUT=-1.0 && rospack list-names` stack_opts=`export ROS_CACHE_TIMEOUT=-1.0 && rosstack list-names` _roszsh_roscomplete_IFS="$IFS" IFS=$'\n' reply=(${=opts} ${=stack_opts}) IFS="$_roszsh_roscomplete_IFS" unset _roszsh_roscomplete_IFS } function _roscomplete_rosmake { local param _roscomplete if [[ $PREFIX == "--"* ]]; then param="--test-only --all --mark-installed --unmark-installed --robust --build-everything --specified-only --buildtest --buildtest1 --output --pre-clean --bootstrap --disable-logging --target --pjobs --threads --profile --skip-blacklist --status-rate" reply=(${=reply} ${=param}) fi } function _roscomplete_sub_dir { local arg opts rosvals sedcmd stack_opts reply=() arg="$1" _ros_decode_path ${arg} if [[ -z ${rosvals[3]} ]]; then opts=`export ROS_CACHE_TIMEOUT=-1.0 && rospack list-names` stack_opts=`export ROS_CACHE_TIMEOUT=-1.0 && rosstack list-names` _roszsh_roscomplete_sub_dir_IFS="$IFS" IFS=$'\n' reply=(${=opts} ${=stack_opts}) IFS="$_roszsh_roscomplete_sub_dir_IFS" unset _roszsh_roscomplete_sub_dir_IFS else if [ -e ${rosvals[2]}${rosvals[3]} ]; then sedcmd="s:^${rosvals[2]}:${rosvals[1]}:"g opts=`find ${rosvals[2]}${rosvals[3]} -maxdepth 1 -mindepth 1 -type d ! -regex ".*/[.].*" -print0 | tr '\000' '\n' | sed -e "$sedcmd"` else opts='' fi _roszsh_roscomplete_sub_dir_IFS="$IFS" IFS=$'\n' reply=(${=opts}) IFS="$_roszsh_roscomplete_sub_dir_IFS" unset _roszsh_roscomplete_sub_dir_IFS fi } function _roscomplete_search_dir { local words arg opts pkg pkgdir pkgdir_result stack_result catkin_package_libexec_dir reply=() words=(${=BUFFER}) if [[ $BUFFER[-1] == ' ' ]] then pkg=${words[-1]} else pkg=${words[-2]} fi pkgdir=`export ROS_CACHE_TIMEOUT=-1.0 && rospack find ${pkg} 2> /dev/null` pkgdir_result=$? catkin_package_libexec_dir=`catkin_find --first-only --without-underlays --libexec ${pkg} 2> /dev/null` if [[ $? != 0 ]] then catkin_package_libexec_dir="" fi stackdir=`export ROS_CACHE_TIMEOUT=-1.0 && rosstack find ${pkg} 2> /dev/null` stack_result=$? if [[ $pkgdir_result == 0 ]]; then opts=`find -L $pkgdir $catkin_package_libexec_dir ${=1} -print0 | tr '\000' '\n' | sed -e "s/.*\/\(.*\)/\1/g"` elif [[ $stack_result == 0 ]] ; then opts=`find -L $stackdir ${=1} -print0 | tr '\000' '\n' | sed -e "s/.*\/\(.*\)/\1/g"` else opts="" fi _roszsh_roscomplete_search_dir_IFS="$IFS" IFS=$'\n' reply=(${=opts}) IFS="$_roszsh_roscomplete_search_dir_IFS" unset _roszsh_roscomplete_search_dir_IFS } function _roscomplete_exe { local perm if [[ `uname` == Darwin || `uname` == FreeBSD ]]; then perm="+111" else perm="/111" fi _roscomplete_search_dir "-type f -perm $perm -regex .*/.*$ ! -path */\.*" } function _roscomplete_file { _roscomplete_search_dir "-type f ! -regex .*/[.].* ! -regex .*[.][oa]$" } function _roscomplete_launchfile { _roscomplete_search_dir "( -type f -regex .*\.launch$ -o -type f -regex .*\.test$ )" } function _roscomplete_launchfile_args { local ROSLAUNCH_COMPLETE _roslaunch_args # complete roslaunch arguments for a launch file ROSLAUNCH_COMPLETE=$(which roslaunch-complete) if [[ -x ${ROSLAUNCH_COMPLETE} ]]; then # Call roslaunch-complete instead of roslaunch to get arg completion _roslaunch_args=$(${ROSLAUNCH_COMPLETE} ${=${(s: :)words}[2]} ${=${(s: :)words}[3]}) # roslaunch-complete should be very silent about # errors and return 0 if it produced usable completion. if [[ $? == 0 ]]; then reply=(${=_roslaunch_args}) fi fi # opts="check compress decompress filter fix help info play record reindex" # reply=(${=opts}) } function _roscomplete_rosbag { local opts reply=() if [[ ${CURRENT} == 2 ]]; then opts="check compress decompress filter fix help info play record reindex" reply=(${=opts}) else if [[ ${=${(s: :)words}[$(( ${CURRENT} ))]} =~ \-\- ]]; then opts="--all --help" case ${=${(s: :)words}[2]} in check) opts="--genrules --append --noplugins --help" ;; compress|decompress) opts="--output-dir --force --quiet --help" ;; filter) opts="--print --help" ;; fix) opts="--force --noplugins --help" ;; info) opts="--yaml --key --freq --help" ;; play) opts="--help --quiet --immediate --pause --queue --clock --hz --delay --rate --start --skip-empty --loop --keep-alive --try-future-version --topics --bags" ;; record) opts="--help --all --regex --exclude --quiet --output-prefix --output-name --split --size --duration --buffsize --limit --node --bz2" ;; reindex) opts="--help --force --quiet --output-dir" ;; esac reply=(${=opts}) else case ${=${(s: :)words}[2]} in record) opts=$(rostopic list 2>/dev/null) if [ -z "$opts" ]; then reply="" #Prevent execution of next rule return fi reply=(${=opts}) ;; esac fi fi } function _roscomplete_rospack { local opts reply=() if [[ ${CURRENT} == 2 ]]; then opts="help find list list-names list-duplicates langs depends depends-manifests depends1 depends-indent depends-msgsrv depends-why rosdep rosdep0 vcs vcs0 depends-on depends-on1 export plugins cflags-only-I cflags-only-other libs-only-L libs-only-l libs-only-other profile" reply=(${=opts}) else opts=`rospack list-names` reply=(${=opts}) fi } function _roscomplete_rosnode { local opts reply=() if [[ ${CURRENT} == 2 ]]; then opts="ping list info machine kill cleanup" reply=(${=opts}) elif [[ ${CURRENT} == 3 ]]; then case ${=${(s: :)words}[2]} in info) opts=`rosnode list 2> /dev/null` reply=(${=opts}) ;; ping|list|kill) if [[ ${=${(s: :)words}[$(( ${CURRENT} ))]} =~ \-\- ]]; then opts="--all --help" else opts=`rosnode list 2> /dev/null` fi reply=(${=opts}) ;; machine) # This takes more logic to determine which machines are present. ;; esac else case ${=${(s: :)words}[2]} in kill) # complete on node name opts=`rosnode list 2> /dev/null` reply=(${=opts}) ;; esac fi } function _roscomplete_rosparam { local opts reply=() if [[ ${CURRENT} == 2 ]]; then opts="set get load dump delete list" reply=(${=opts}) elif [[ ${CURRENT} == 3 ]]; then case ${=${(s: :)words}[2]} in set|get|delete|list) opts=`rosparam list 2> /dev/null` reply=(${=opts}) ;; load|dump) # complete on files reply=(${=opts}) ;; esac elif [[ ${CURRENT} == 4 ]]; then case ${=${(s: :)words}[2]} in load|dump) # complete on namespace opts=`rosparam list 2> /dev/null` reply=(${=opts}) ;; esac fi } function _roscomplete_rostopic { local opts word reply=() if [[ ${CURRENT} == 2 ]]; then opts="bw echo hz list pub type find info" reply=(${=opts}) elif [[ ${CURRENT} > 2 ]]; then if [[ ${=${(s: :)words}[$(( ${CURRENT} ))]} =~ \-\- ]]; then case ${=${(s: :)words}[2]} in pub) opts="--help --rate --once --file --latch" ;; bw) opts="--help --window" ;; echo) opts="--help --bag --filter --nostr --noarr --clear --all --offset" ;; hz) opts="--help --window --filter" ;; list) opts="--help --bag --verbose --host" ;; type|info) opts="--help" ;; esac reply=(${=opts}) else case ${=${(s: :)words}[2]} in bw|echo|hz|list|type|info) if [[ ${=${(s: :)words}[$(( ${CURRENT} -1 ))]} == "-b" ]]; then opts=`find . -maxdepth 1 -type f -not -name ".*" -not -name "*[~#]" | sed 's!.*/!!'` reply=(${=opts}) else opts=`rostopic list 2> /dev/null` reply=(${=opts}) fi ;; find) opts=`_msg_opts ${=${(s: :)words[-1]}}` reply=(${=opts}) ;; pub) if [[ ${CURRENT} == 3 ]]; then opts=`rostopic list 2> /dev/null` reply=(${=opts}) elif [[ ${CURRENT} == 4 ]]; then if [[ ${=${(s: :)words}[$(( ${CURRENT} ))]} =~ / ]]; then word=(${=words}) type=`rostopic info ${word[3]} 2> /dev/null` opts=${=${type[(w)2]}} else word=(${=words}) type=`rostopic info ${word[3]} 2> /dev/null` opts=${=${type[(w)2]}} fi reply=(${=opts}) elif [[ ${CURRENT} == 5 ]]; then w=(${=words}) opts=`rosmsg-proto msg 2> /dev/null -s ${=${w[-1]}}` reply=(${opts}) fi ;; esac fi fi } function _roscomplete_rosservice { local opts reply=() if [[ ${CURRENT} == 2 ]]; then opts="args call find info list type uri" reply=(${=opts}) elif [[ ${CURRENT} == 3 ]]; then case ${words[2]} in args|call|info|list|type|uri) opts=`rosservice list 2> /dev/null` _roszsh_roscomplete_rosservice_IFS="$IFS" IFS=$'\n' reply=(${=opts}) IFS="$_roszsh_roscomplete_rosservice_IFS" unset _roszsh_roscomplete_rosservice_IFS ;; find) opts=`_srv_opts ${words[3]}` reply=(${=opts}) ;; esac elif [[ ${CURRENT} == 4 ]]; then case ${words[2]} in call) type="$(rosservice type ${words[3]} 2>/dev/null)" reply=("$(rosmsg-proto srv -s ${type} 2> /dev/null)") ;; esac fi } function _msg_opts { local pkgname msgname searchmsg pkgs count pkgname2 opts result unset searchmsg if [[ $1 =~ .+/.* ]]; then pkgname=${1%%/*} msgname=${1#*/} searchmsg=1 else pkgname=${1} fi if [[ -z ${searchmsg} ]]; then pkgs=`command rospack list | grep "^${pkgname}"` count=0 opts="" for pkg in ${(f)pkgs}; do pkgdir=${=${(s: :)pkg}[2]} if [[ -d $pkgdir/msg ]]; then pkgname2=${=${(s: :)pkg}[1]} opts="$opts $pkgname2/" count=$((count+1)) fi done if [[ $count > 0 ]]; then echo $opts return 0 fi fi pkgpath=`rospack find ${pkgname} 2> /dev/null` if [[ $? == 0 ]] && [[ -d ${pkgpath}/msg ]]; then result=`find -L ${pkgpath}/msg -maxdepth 1 -mindepth 1 -name \*.msg ! -regex ".\*/[.].\*" -print0 | tr '\000' '\n' | sed -e "s/.*\/\(.*\)\.msg/${pkgname}\/\1/g"` echo $result fi } function _roscomplete_rosmsg { local opts reply=() if [[ ${CURRENT} == 2 ]]; then opts="show list md5 package packages" reply=(${=opts}) elif [[ ${CURRENT} == 3 ]]; then case ${=${(s: :)words}[2]} in show|users|md5) opts=`_msg_opts ${=${(s: :)words[-1]}}` reply=(${=opts}) ;; package) opts=`rospack list-names` reply=(${=opts}) ;; packages|list) # This shouldn't really have a completion rule ;; esac fi } function _srv_opts { local pkgname srvname searchsrv pkgs count opts pkgpath result unset searchsrv if [[ $1 =~ .+/.* ]]; then pkgname=${1%%/*} srvname=${1#*/} searchsrv=1 else pkgname=${1} fi if [[ -z ${searchsrv} ]]; then pkgs=`command rospack list | grep "^${pkgname}"` count=0 opts="" for pkg in ${(f)pkgs}; do pkgdir=${=${(s: :)pkg}[2]} if [[ -d $pkgdir/srv ]]; then pkgname2=${=${(s: :)pkg}[1]} opts="$opts $pkgname2/" count=$((count+1)) fi done if [[ $count > 0 ]]; then echo $opts return 0 fi fi pkgpath=`rospack find ${pkgname} 2> /dev/null` if [[ $? == 0 ]] && [[ -d ${pkgpath}/srv ]]; then result=`find -L ${pkgpath}/srv -maxdepth 1 -mindepth 1 -name \*.srv ! -regex ".\*/[.].\*" -print0 | tr '\000' '\n' | sed -e "s/.*\/\(.*\)\.srv/${pkgname}\/\1/g"` echo $result fi } function _roscomplete_rossrv { local opts reply=() if [[ ${CURRENT} == 2 ]]; then opts="show list md5 package packages" reply=(${=opts}) elif [[ ${CURRENT} == 3 ]]; then case ${=${(s: :)words}[2]} in show|users|md5) opts=`_srv_opts ${=${(s: :)words[-1]}}` reply=(${=opts}) ;; package) opts=`rospack list-names` reply=(${=opts}) ;; packages|list) # This shouldn't really have a completion rule ;; esac fi } function _roscomplete_roscreate_pkg { local opts reply=() if [[ ${CURRENT} > 2 ]]; then opts=`rospack list-names` reply=(${=opts}) fi } function _roscomplete_filemv { _roscompletemv_search_dir "-type f ! -regex .*[.][oa]$" } function _roscompletemv_search_dir { local arg opts rosvals COMPREPLY=() arg="${COMP_WORDS[COMP_CWORD]}" option="$(echo -e "${COMP_WORDS[1]}" | tr -d '[:space:]')" if [[ $COMP_CWORD == 2 && ( $option == "-d" ) ]] || [[ $COMP_CWORD == 1 ]]; then # complete packages _roscomplete_pkg "${arg}" elif [[ $COMP_CWORD == 2 && ( $option != "-d" ) ]]; then # complete files within package according to $1 _roscomplete_find "${1}" "${COMP_WORDS[1]}" "${arg}" else # complete filenames arg=$(echo ${arg} | sed -e "s|~|$HOME|g") if [[ $arg =~ ^/*.+/.* ]]; then path=${arg%/*} else path=. fi if [[ -e ${path} ]]; then opts=$(find -L $path -maxdepth 1 -type d ! -regex ".*/[.][^./].*" ! -regex "^[.]/" -print0 | tr '\000' '\n' | sed -e "s/$/\//g" -e "s/^[.]\///g" -e "s/'/\\\\\'/g" -e "s/ /\\\\\ /g")$'\n'$(find -L $path -maxdepth 1 -type f ! -regex ".*/[.][^.]*" ! -regex "^[.]/" -print0 | tr '\000' '\n' | sed -e "s/^[.]\///g" -e "s/'/\\\\\'/g" -e "s/ /\\\\\ /g") else opts="" fi _rosbash_roscomplete_search_dir_IFS="$IFS" IFS=$'\n' COMPREPLY=($(compgen -W "$opts" -- ${arg})) IFS="$_rosbash_roscomplete_search_dir_IFS" unset _rosbash_roscomplete_search_dir_IFS if [[ ${#COMPREPLY[*]} = 1 ]]; then newpath=${COMPREPLY[0]%/*} if [[ -d ${newpath} ]]; then opts=$(find -L $newpath -maxdepth 1 -type d ! -regex ".*/[.][^./].*" ! -regex "^[.]/" -print0 | tr '\000' '\n' | sed -e "s/$/\//g" -e "s/^[.]\///g" -e "s/'/\\\\\'/g" -e "s/ /\\\\\ /g")$'\n'$(find -L $newpath -maxdepth 1 -type f ! -regex ".*/[.][^.]*" ! -regex "^[.]/" -print0 | tr '\000' '\n' | sed -e "s/^[.]\///g" -e "s/'/\\\\\'/g" -e "s/ /\\\\\ /g") _rosbash_roscomplete_search_dir_IFS="$IFS" IFS=$'\n' COMPREPLY=($(compgen -W "$opts" -- ${arg})) IFS="$_rosbash_roscomplete_search_dir_IFS" unset _rosbash_roscomplete_search_dir_IFS fi fi fi } compctl -K "_roscomplete_sub_dir" -S / "roscd" "rospd" "rosls" compctl -K "_roscomplete_rosmake" "rosmake" compctl -x 'p[1]' -k "(check purge)" -- "rosclean" compctl -f -x 'p[1]' -K "_roscomplete" - 'p[2]' -K _roscomplete_file -- "rosed" "roscp" "roscat" compctl -f -x 'p[1]' -K "_roscomplete_filemv" -- "rosmv" compctl -f -x 'S[-]' -k '(--debug --prefix)' - 'c[-1,--prefix][-1,-p]' -h '' - 'p[1],c[-1,-d],c[-1,--debug],c[-2,-p],c[-2,--prefix]' -K "_roscomplete" - 'p[2],c[-2,-d],c[-2,--debug],c[-3,-p],c[-3,--prefix]' -K _roscomplete_exe -- "rosrun" compctl -/g '*.(launch|test)' -x 'p[1]' -K "_roscomplete" -tx - 'p[2]' -K _roscomplete_launchfile - 'p[3,20]' -K _roscomplete_launchfile_args -S ':=' -- + -x 'S[--]' -k "(--files --args --nodes --find-node --child --local --screen --server_uri --run_id --wait --port --core --pid --dump-params --disable-title --help --numworkers --ros-args --skip-log-check --timeout)" -- "roslaunch" compctl -/g '*.(launch|test)' -x 'p[1]' -K "_roscomplete" -tx - 'p[2]' -K _roscomplete_launchfile -- + -x 'S[--]' -k "(--bare --bare-limit --bare-name --pkgdir --package)" -- "rostest" compctl -K "_roscomplete_rospack" "rospack" compctl -K "_roscomplete_rosbag" + -g "*.bag *(/)" "rosbag" compctl -K "_roscomplete_rosnode" "rosnode" compctl -K "_roscomplete_rosparam" "rosparam" compctl -x 'p[0,2]' -K "_roscomplete_rostopic" - 'n[1,/] p[3]' -K "_roscomplete_rostopic" - 'p[3]' -S ' ' -K "_roscomplete_rostopic" - 'p[4]' -Q -K "_roscomplete_rostopic" -- "rostopic" compctl -Q -K "_roscomplete_rosservice" "rosservice" compctl -x 'p[1]' -k "(md5 package packages show users)" - 'p[2]' -S '' -K "_roscomplete_rosmsg" -- "rosmsg" compctl -x 'p[1]' -k "(md5 package packages show users)" - 'p[2]' -S '' -K "_roscomplete_rossrv" -- "rossrv" compctl -K "_roscomplete_roscreate_pkg" "roscreate-pkg" compctl -/g '*.(launch|test)' -x 'S[--]' -k "(--all --no-plugins --offline)" -- "roswtf" ros-1.15.8/tools/rosbash/scripts/000077500000000000000000000000001407615046500167115ustar00rootroot00000000000000ros-1.15.8/tools/rosbash/scripts/roscd.bat000066400000000000000000000021631407615046500205150ustar00rootroot00000000000000@echo off if "%1" equ "--help" goto :usage if not "%2" equ "" goto :usage if "%1" equ "" ( if not "%ROS_WORKSPACE%" equ "" ( cd /d %ROS_WORKSPACE% exit /b 0 ) if not "%CMAKE_PREFIX_PATH%" equ "" ( for %%a in ("%CMAKE_PREFIX_PATH:;=";"%") do ( if exist %%a\.catkin ( cd /d %%a exit /b 0 ) ) ) echo Neither ROS_WORKSPACE is set nor a catkin workspace is listed in CMAKE_PREFIX_PATH. Please set ROS_WORKSPACE or source a catkin workspace to use roscd with no arguments. exit /b 1 ) for /f "tokens=*" %%g in ('call python %~dp0\rosfindpath.py %1 forceeval') do ( set target_path=%%~g ) if /i "%target_path:~0,7%"=="Error: " ( echo roscd: %target_path:~7% exit /b 1 ) if "%target_path%" equ "" ( if not "%ROS_WORKSPACE%" equ "" ( cd /d %ROS_WORKSPACE% exit /b 0 ) echo No ROS_WORKSPACE set. Please set ROS_WORKSPACE to use roscd with no arguments. exit /b 1 ) cd /d "%target_path%" exit /b 0 :usage echo usage: roscd package echo. echo. echo Jump to target package. exit /b 0 ros-1.15.8/tools/rosbash/scripts/roscp.bat000066400000000000000000000050471407615046500205350ustar00rootroot00000000000000@echo off setlocal EnableDelayedExpansion set DEBUG=0 set roscp_args=%* set roscp_package= set roscp_filename= :handleargs if "%1" equ "--help" goto :usage if "%1" equ "-h" goto :usage if "%1" equ "--debug" ( set /A DEBUG=1 goto :nextarg ) if "%1" equ "-d" ( set DEBUG=1 goto :nextarg ) goto :find_roscp_parameters :nextarg shift /1 call :trim_first_arg result_args !roscp_args! set roscp_args=!result_args! if not "%1"=="" goto :handleargs :find_roscp_parameters if "%1"=="" goto :usage set roscp_package=%1 call :trim_first_arg result_args !roscp_args! set roscp_args=!result_args! shift /1 if "%1"=="" goto :usage set roscp_filename=%1 call :trim_first_arg result_args !roscp_args! set roscp_args=!result_args! shift /1 set catbin= set roscp_search_path= set catkin_find_search_path= set rospack_find_search_path= if NOT "%CMAKE_PREFIX_PATH%"=="" ( for /f "delims=" %%g in ('catkin_find --without-underlays --libexec --share !roscp_package!') do ( set "catkin_find_search_path=!catkin_find_search_path!;%%g" ) call :debug "Looking in catkin libexec dirs: !catkin_find_search_path!" ) for /f "delims=" %%a in ('rospack find !roscp_package!') do ( set "rospack_find_search_path=!rospack_find_search_path!;%%a" ) call :debug "Looking in rospack dir: %rospack_find_search_path%" if "%catkin_find_search_path%" == "" ( if "%rospack_find_search_path%" == "" ( exit /b 2 ) ) for /f "delims=" %%a in ('catkin_find --bin') do ( set "catbin=!catbin!;%%a" ) set catkin_find_search_path=%catkin_find_search_path:~1% set rospack_find_search_path=%rospack_find_search_path:~1% set catbin=%catbin:~1% :: on Windows, we will have a pecking order, libexec, pkgdir, global bin dir set "roscp_search_path=%catkin_find_search_path%;%rospack_find_search_path%;%catbin%" :: search in the catkin and rospack path call :debug "Searching for !roscp_filename! from !roscp_search_path!" for %%i in (!roscp_filename!) do ( set "src_filepath=%%~$roscp_search_path:i" if NOT "!src_filepath!" == "" ( goto :run_roscp_internal ) ) if "!src_filepath!" == "" ( echo [roscp] Couldn't find file named !roscp_filename! exit /b 3 ) :run_roscp_internal call :debug "copy %src_filepath% %roscp_args%" copy %src_filepath% %roscp_args% > NUL exit /b %ERRORLEVEL% :debug if %DEBUG% == 1 ( echo [roscp] %* ) goto :eof :usage echo usage: roscp package filename target echo. echo. echo Copy a file from a package to target location. exit /b 0 :trim_first_arg setlocal EnableDelayedExpansion set params=%* for /f "tokens=2*" %%a in ("!params!") do EndLocal & set %1=%%b exit /b ros-1.15.8/tools/rosbash/scripts/rosfindpath.py000066400000000000000000000055311407615046500216100ustar00rootroot00000000000000from __future__ import print_function import os import subprocess import sys ROS_CACHE_TIMEOUT_ENV_NAME = 'ROS_CACHE_TIMEOUT' ROS_LOCATIONS_ENV_NAME = 'ROS_LOCATIONS' ROS_LOCATION_SEP = ';' ERROR_PREFIX = 'Error: ' def ros_location_find(package_name): # process ROS_LOCATION and return if found ros_location = os.environ.get(ROS_LOCATIONS_ENV_NAME) if ros_location is not None: locations = ros_location.split(ROS_LOCATION_SEP) for loc in locations: index = loc.find('=') if index != -1: if package_name == loc[:index]: return 0, loc[index + 1:] if package_name == 'log': p = subprocess.Popen('roslaunch-logs', stdout=subprocess.PIPE) result_location = p.communicate()[0].decode().strip() result_code = p.returncode return result_code, result_location if result_code == 0 else '' if package_name == 'test_results': p = subprocess.Popen('rosrun.bat rosunit test_results_dir.py', stdout=subprocess.PIPE) result_location = p.communicate()[0].decode().strip() result_code = p.returncode return result_code, result_location if result_code == 0 else '' # process package_name and return env = os.environ env[ROS_CACHE_TIMEOUT_ENV_NAME] = '-1.0' p = subprocess.Popen(['rospack', 'find', package_name], stdout=subprocess.PIPE) result_location = p.communicate()[0].decode().strip() result_code = p.returncode if result_code == 0: return result_code, result_location p = subprocess.Popen(['rosstack', 'find', package_name], stdout=subprocess.PIPE) result_location = p.communicate()[0].decode().strip() result_code = p.returncode if result_code == 0: return result_code, result_location # package not found return result_code, '' # takes as argument either just a package-path or just a pkgname # returns 0 for no argument or if package (+ path) exist, 1 else # on success with arguments print result_path or Error: error message def findpathmain(argv): reldir = '' parameters = os.path.normpath(argv[0]).split(os.path.sep) package_name = parameters[0] if len(parameters) > 1: reldir = os.path.sep.join(parameters[1:]) else: if len(argv) < 2 or argv[1] != 'forceeval': print(ERROR_PREFIX + '[' + package_name + '] is not a valid argument!', file=sys.stderr) return 1 error_code, package_dir = ros_location_find(package_name) if error_code != 0: print(ERROR_PREFIX + '[' + package_name + '] not found!', file=sys.stderr) return error_code else: rosdir = os.path.normpath(os.path.sep.join([package_dir, reldir])) print(rosdir) return 0 if __name__ == '__main__': if len(sys.argv) < 2: sys.exit(1) sys.exit(findpathmain(sys.argv[1:])) ros-1.15.8/tools/rosbash/scripts/rosls.bat000066400000000000000000000005661407615046500205520ustar00rootroot00000000000000@echo off if "%1" equ "--help" goto :usage for /f "tokens=*" %%g in ('call python %~dp0\rosfindpath.py %1 forceeval') do ( set target_path=%%~g ) if /i "%target_path:~0,7%"=="Error: " ( echo rosls: %target_path:~7% exit /b 1 ) dir "%target_path%" exit /b 0 :usage echo usage: rosls [package] echo. echo. echo Lists contents of a package directory. exit /b 0 ros-1.15.8/tools/rosbash/scripts/rosrun000077500000000000000000000103301407615046500201640ustar00rootroot00000000000000#!/usr/bin/env bash function usage() { echo "Usage: rosrun [--prefix cmd] [--debug] PACKAGE EXECUTABLE [ARGS]" echo " rosrun will locate PACKAGE and try to find" echo " an executable named EXECUTABLE in the PACKAGE tree." echo " If it finds it, it will run it with ARGS." } args=1 rosrun_prefix="" function debug() { return } while [ $args == 1 ] do case "$1" in "--help" | "-h") usage exit 0 ;; "--prefix" | "-p") rosrun_prefix="$2" shift shift ;; "--debug" | "-d") shift function debug() { echo "[rosrun]" "$@" ; } ;; *) # default args=0 esac done if [ $# -lt 2 ]; then usage exit 0 fi # early check that filename does not end with '/' case $2 in */) echo "Invalid filename: " $2 exit 1 ;; esac pkg_name="$1" file_name="$2" function inonedir() { exe=$1 shift list_of_dirs=("$@") for location in "${list_of_dirs[@]}"; do if [[ "$exe" = "$location"* ]] ; then # exe path starts with $location echo "yes" return fi done echo "no" } if [[ -n $CMAKE_PREFIX_PATH ]]; then _rosrun_IFS="$IFS" IFS=$'\n' catkin_package_libexec_dirs=($(catkin_find --without-underlays --libexec --share "$pkg_name" 2> /dev/null)) debug "Looking in catkin libexec dirs: $IFS$(catkin_find --without-underlays --libexec --share "$pkg_name" 2>&1)" IFS="$_rosrun_IFS" unset _rosrun_IFS fi pkgdir=$(rospack find "$pkg_name") debug "Looking in rospack dir: $pkgdir" if [[ ${#catkin_package_libexec_dirs[@]} -eq 0 && -z $pkgdir ]]; then exit 2 fi if [[ ! $file_name == */* ]]; then # The -perm /mode usage is not available in find on the Mac or FreeBSD #exepathlist=(`find $pkgdir -name $file_name -type f -perm /u+x,g+x,o+x`) # -L: #3475 if [[ $(uname) == Darwin || $(uname) == FreeBSD ]]; then _perm="+111" else _perm="/111" fi debug "Searching for $file_name with permissions $_perm" exepathlist="$(find -L "${catkin_package_libexec_dirs[@]}" "$pkgdir" -name "$file_name" -type f -perm "$_perm" ! -regex ".*$pkgdir\/build\/.*" | uniq)" _rosrun_IFS="$IFS" IFS=$'\n' exepathlist=($exepathlist) IFS="$_rosrun_IFS" unset _rosrun_IFS unset _perm if [[ ${#exepathlist[@]} == 0 ]]; then echo "[rosrun] Couldn't find executable named $file_name below $pkgdir" nonexepathlist=($(find -H "$pkgdir" -name "$file_name")) if [[ ${#nonexepathlist[@]} != 0 ]]; then echo "[rosrun] Found the following, but they're either not files," echo "[rosrun] or not executable:" for p in "${nonexepathlist[@]}"; do echo "[rosrun] ${p}" done fi exit 3 elif [[ ${#exepathlist[@]} -eq 2 ]]; then # If one executable is from share and another from libexec then use one from libexec. # This assumes the one from libexec is a devel-space python relay script created by catkin. # Share dirs includes devel, install, or src space locations catkin_package_share_dirs=($(catkin_find --without-underlays --share "$pkg_name" 2> /dev/null)) debug "Looking in catkin share dirs: $IFS$(catkin_find --without-underlays --share "$pkg_name" 2>&1)" first_share=$(inonedir "${exepathlist[0]}" "${catkin_package_share_dirs[@]}") second_share=$(inonedir "${exepathlist[1]}" "${catkin_package_share_dirs[@]}") if [[ $first_share == "no" && $second_share == "yes" ]]; then debug "Assuming ${exepathlist[0]} is a devel-space relay for ${exepathlist[1]}" exepathlist=(${exepathlist[0]}) elif [[ $second_share == "no" && $first_share == "yes" ]]; then debug "Assuming ${exepathlist[1]} is a devel-space relay for ${exepathlist[0]}" exepathlist=(${exepathlist[1]}) fi fi if [[ ${#exepathlist[@]} -gt 1 ]]; then echo "[rosrun] You have chosen a non-unique executable, please pick one of the following:" select opt in "${exepathlist[@]}"; do exepath="$opt" break done else exepath="${exepathlist[0]}" fi else absname="$pkgdir/$file_name" debug "Path given. Looing for $absname" if [[ ! -f $absname || ! -x $absname ]]; then echo "[rosrun] Couldn't find executable named $absname" exit 3 fi exepath="$absname" fi shift shift debug "Running $rosrun_prefix $exepath" "$@" exec $rosrun_prefix "$exepath" "$@" ros-1.15.8/tools/rosbash/scripts/rosrun.bat000066400000000000000000000067101407615046500207350ustar00rootroot00000000000000@echo off setlocal EnableDelayedExpansion set DEBUG=0 set rosrun_args=%* set rosrun_prefix= set rosrun_package= set rosrun_executable= :handleargs if "%1" equ "--help" goto :usage if "%1" equ "-h" goto :usage if "%1" equ "--prefix" goto :prefix if "%1" equ "-p" goto :prefix if "%1" equ "--debug" ( set /A DEBUG=1 goto :nextarg ) if "%1" equ "-d" ( set DEBUG=1 goto :nextarg ) goto :find_rosrun_parameters :prefix set rosrun_prefix=%2 shift /1 call :trim_first_arg result_args !rosrun_args! set rosrun_args=!result_args! :nextarg shift /1 call :trim_first_arg result_args !rosrun_args! set rosrun_args=!result_args! if not "%1"=="" goto :handleargs :find_rosrun_parameters if "%1"=="" goto :usage set rosrun_package=%1 call :trim_first_arg result_args !rosrun_args! set rosrun_args=!result_args! shift /1 if "%1"=="" goto :usage set rosrun_executable=%1 set rosrun_executable_extension=%~x1 call :trim_first_arg result_args !rosrun_args! set rosrun_args=!result_args! shift /1 set catbin= set rosrun_search_path= set catkin_find_search_path= set rospack_find_search_path= if NOT "%CMAKE_PREFIX_PATH%"=="" ( for /f "delims=" %%g in ('catkin_find --without-underlays --libexec --share !rosrun_package!') do ( set "catkin_find_search_path=!catkin_find_search_path!;%%g" ) call :debug "Looking in catkin libexec dirs: !catkin_find_search_path!" ) for /f "delims=" %%a in ('rospack find !rosrun_package!') do ( set "rospack_find_search_path=!rospack_find_search_path!;%%a" ) call :debug "Looking in rospack dir: %rospack_find_search_path%" if "%catkin_find_search_path%" == "" ( if "%rospack_find_search_path%" == "" ( exit /b 2 ) ) for /f "delims=" %%a in ('catkin_find --bin') do ( set "catbin=!catbin!;%%a" ) REM on Windows, we will have a pecking order, libexec, pkgdir, global bin dir set "rosrun_search_path=%catkin_find_search_path%;%rospack_find_search_path%;%catbin%" if "!rosrun_executable_extension!"=="" ( REM iterate through PATHEXT if no file extension specified. for %%a in (%PATHEXT%) do ( call :debug "Searching for executable !rosrun_executable!%%a" for %%i in (!rosrun_executable!%%a) do ( set "exepath=%%~$rosrun_search_path:i" if NOT "!exepath!" == "" ( goto :run_rosrun_internal ) ) ) ) REM search in the catkin and rospack path call :debug "Searching for executable !rosrun_executable!" for %%i in (!rosrun_executable!) do ( set "exepath=%%~$rosrun_search_path:i" if NOT "!exepath!" == "" ( goto :run_rosrun_internal ) ) if "!exepath!" == "" ( echo [rosrun] Couldn't find executable named !rosrun_executable! exit /b 3 ) :run_rosrun_internal call :debug "Running %rosrun_prefix% %exepath% %rosrun_args%" for %%a in ("%exepath%") do ( set exepath_extension=%%~xa ) if "!exepath_extension!" == ".py" ( call %rosrun_prefix% "%PYTHONHOME%\python.exe" %exepath% %rosrun_args% ) else if "!exepath_extension!" == "" ( call %rosrun_prefix% "%PYTHONHOME%\python.exe" %exepath% %rosrun_args% ) else ( call %rosrun_prefix% %exepath% %rosrun_args% ) exit /b %ERRORLEVEL% :debug if %DEBUG% == 1 ( echo [rosrun] %* ) goto :eof :usage echo Usage: rosrun [--prefix cmd] [--debug] PACKAGE EXECUTABLE [ARGS] echo rosrun will locate PACKAGE and try to find echo an executable named EXECUTABLE in the PACKAGE tree. echo If it finds it, it will run it with ARGS. exit /b 0 :trim_first_arg setlocal EnableDelayedExpansion set params=%* for /f "tokens=2*" %%a in ("!params!") do EndLocal & set %1=%%b exit /b ros-1.15.8/tools/rosbash/test/000077500000000000000000000000001407615046500162015ustar00rootroot00000000000000ros-1.15.8/tools/rosbash/test/example.launch000066400000000000000000000001061407615046500210250ustar00rootroot00000000000000 ros-1.15.8/tools/rosbash/test/test_rosbash.bash000077500000000000000000000022631407615046500215460ustar00rootroot00000000000000#! /usr/bin/env bash # This script is supposed to be a unit test for rosbash, also used for manual checks against other operating systems. # TODO extend this script . ../rosbash echo Testing BASH . test_zshbash.sh # roslaunch completion export COMP_CWORD=1 _roscomplete_launch roslaunch if [[ ! ${COMPREPLY[@]} =~ rosbash ]]; then echo "rosbash package missing from" ${COMPREPLY[@]} ; exit 1 fi echo success roslaunch pkg export COMP_WORDS=("roslaunch" "--") export COMP_CWORD=1 _roscomplete_launch roslaunch "--" roslaunch if [[ ! ${COMPREPLY[@]} == "--files --args --nodes --find-node --child --local --screen --server_uri --run_id --wait --port --core --pid --dump-params" ]]; then echo "roslaunch --options missing" from ${COMPREPLY[@]} ; exit 1 fi echo success roslaunch --option export COMP_WORDS=("roslaunch" "roslaunch") export COMP_CWORD=2 _roscomplete_launch roslaunch roslaunch if [[ ! ${COMPREPLY[@]} =~ "example.launch" ]]; then echo "example.launch missing from " ${COMPREPLY[@]} ; exit 1 fi echo success roslaunch launchfiles # if [[ ! ${COMPREPLY[@]} =~ "example.launch" ]]; then # echo "example.launch missing from " ${COMPREPLY[@]} ; exit 1 # fi # echo success 4 ros-1.15.8/tools/rosbash/test/test_roszsh.zsh000077500000000000000000000006711407615046500213250ustar00rootroot00000000000000#! /usr/bin/env zsh # This script is supposed to be a unit test for rosbash, also used for manual checks against other operating systems. # TODO extend this script . ../roszsh echo "Testing ZSH" . ./test_zshbash.sh # roslaunch completion BUFFER=("foo roslaunch") _roscomplete_search_dir if [[ ! ${reply[@]} =~ "example.launch" ]]; then echo "rosbash package missing from" ${reply[@]} ; exit 1 fi echo success roslaunch launchfiles ros-1.15.8/tools/rosbash/test/test_scripts.py000066400000000000000000000044041407615046500213030ustar00rootroot00000000000000#!/usr/bin/env python import os import shutil import subprocess import tempfile import unittest PKG_PATH = os.getcwd() TEST_PATH = os.path.join(PKG_PATH, 'test') def make_bash_pre_command(strings, currentword): return "bash -c '. %s; export COMP_WORDS=(%s); export COMP_CWORD=%s;" % (os.path.join(PKG_PATH, 'rosbash'), ' '.join(['"%s"' % w for w in strings]), currentword) class TestRosBash(unittest.TestCase): def setUp(self): self.cmdbash = os.path.join(TEST_PATH, 'test_rosbash.bash') self.assertTrue(os.path.exists(self.cmdbash)) self.cmdzsh = os.path.join(TEST_PATH, 'test_roszsh.zsh') self.assertTrue(os.path.exists(self.cmdzsh)) def test_rosbash_completion(self): subprocess.check_call([self.cmdbash], cwd=TEST_PATH) def test_roszsh_completion(self): subprocess.check_call([self.cmdzsh], cwd=TEST_PATH) class TestWithFiles(unittest.TestCase): @classmethod def setUpClass(self): self.test_root_path = tempfile.mkdtemp() @classmethod def tearDownClass(self): shutil.rmtree(self.test_root_path) def test_make_precommand(self): self.assertEqual("bash -c '. %s; export COMP_WORDS=(\"foo\" \"bar\"); export COMP_CWORD=1;" % os.path.join(PKG_PATH, 'rosbash'), make_bash_pre_command(['foo', 'bar'], 1)) self.assertEqual("bash -c '. %s; export COMP_WORDS=(\"foo\"); export COMP_CWORD=2;" % os.path.join(PKG_PATH, 'rosbash'), make_bash_pre_command(['foo'], 2)) def test_roslaunch_completion(self): # regression test that roslaunch completion works even in the presence of launchfiles subprocess.check_call('touch foo.launch', shell=True, cwd=self.test_root_path) subprocess.check_call('touch bar.launch', shell=True, cwd=self.test_root_path) cmd = make_bash_pre_command(['rosbash', 'rosbash'], 2) cmd += "_roscomplete_launch rosbash rosbash; echo $COMPREPLY'" p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, cwd=self.test_root_path) output = p.communicate() self.assertEqual(0, p.returncode, (p.returncode, output, cmd)) self.assertTrue('example.launch' in output[0], (p.returncode, output[0], cmd)) ros-1.15.8/tools/rosbash/test/test_zshbash.sh000066400000000000000000000010201407615046500212270ustar00rootroot00000000000000# tests that can work against both bash and zsh # rossed (extended regular expressions) if [[ ! `echo abcde | _rossed 's,abc?,foo,'` = "foode" ]]; then echo "rosbash package missing from" ${reply[@]} ; exit 1 fi echo success rossed ROS_LOCATIONS=foohome=/work:share=/share if [[ ! `_ros_location_find foohome` = "/work" ]]; then echo "ros_location_find missed foohome"; exit 1 fi if [[ ! `_ros_location_find share` = "/share" ]]; then echo "ros_location_find missed share"; exit 1 fi echo success ros_location_find ros-1.15.8/tools/rosboost_cfg/000077500000000000000000000000001407615046500162525ustar00rootroot00000000000000ros-1.15.8/tools/rosboost_cfg/CHANGELOG.rst000066400000000000000000000056641407615046500203060ustar00rootroot00000000000000^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Changelog for package rosboost_cfg ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 1.15.8 (2021-07-21) ------------------- * Update maintainers (`#272 `_) * Contributors: Jacob Perron 1.15.7 (2020-09-28) ------------------- 1.15.6 (2020-07-20) ------------------- 1.15.5 (2020-07-06) ------------------- 1.15.4 (2020-05-28) ------------------- 1.15.3 (2020-05-14) ------------------- 1.15.2 (2020-04-07) ------------------- 1.15.1 (2020-03-17) ------------------- 1.15.0 (2020-02-11) ------------------- 1.14.8 (2020-02-11) ------------------- * update style to pass flake8 (`#240 `_) * Use setuptools instead of distutils (`#235 `_) * Bump CMake version to avoid CMP0048 warning (`#234 `_) 1.14.7 (2019-10-03) ------------------- 1.14.6 (2019-03-18) ------------------- 1.14.5 (2019-03-04) ------------------- * chmod -x on Python modules (`#183 `_) 1.14.4 (2018-05-01) ------------------- 1.14.3 (2018-01-30) ------------------- 1.14.2 (2017-10-26) ------------------- 1.14.1 (2017-07-27) ------------------- 1.14.0 (2017-02-22) ------------------- 1.13.6 (2017-10-31) ------------------- 1.13.5 (2017-02-14) ------------------- 1.13.4 (2016-09-19) ------------------- 1.13.3 (2016-09-16) ------------------- 1.13.2 (2016-09-02) ------------------- 1.13.1 (2016-03-13) ------------------- 1.13.0 (2016-03-10) ------------------- 1.12.6 (2016-03-10) ------------------- 1.12.5 (2015-10-13) ------------------- 1.12.4 (2015-10-12) ------------------- 1.12.3 (2015-09-19) ------------------- 1.12.2 (2015-04-27) ------------------- 1.12.1 (2015-04-16) ------------------- 1.12.0 (2014-12-26) ------------------- 1.11.6 (2014-12-22) ------------------- 1.11.5 (2014-08-18) ------------------- 1.11.4 (2014-07-23) ------------------- * fix dry rosboost_cfg to support finding boost in multiarch lib folder (`#62 `_) 1.11.3 (2014-07-18) ------------------- 1.11.2 (2014-06-16) ------------------- 1.11.1 (2014-05-07) ------------------- 1.11.0 (2014-01-31) ------------------- 1.10.9 (2014-01-07) ------------------- 1.10.8 (2013-10-15) ------------------- 1.10.7 (2013-10-04) ------------------- 1.10.6 (2013-08-22) ------------------- 1.10.5 (2013-08-21) ------------------- 1.10.4 (2013-07-05) ------------------- 1.10.3 (2013-07-03) ------------------- 1.10.2 (2013-06-18) ------------------- 1.10.1 (2013-06-06) ------------------- 1.10.0 (2013-03-22 09:23) ------------------------- 1.9 (Groovy) ============ 1.9.44 (2013-03-13) ------------------- 1.9.43 (2013-03-08) ------------------- 1.9.42 (2013-01-25) ------------------- 1.9.41 (2013-01-24) ------------------- 1.9.40 (2013-01-13) ------------------- 1.9.39 (2012-12-30) ------------------- * first public release for Groovy ros-1.15.8/tools/rosboost_cfg/CMakeLists.txt000066400000000000000000000002021407615046500210040ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.0.2) project(rosboost_cfg) find_package(catkin REQUIRED) catkin_package() catkin_python_setup() ros-1.15.8/tools/rosboost_cfg/package.xml000066400000000000000000000016331407615046500203720ustar00rootroot00000000000000 rosboost_cfg 1.15.8 Contains scripts used by the rosboost-cfg tool for determining cflags/lflags/etc. of boost on your system Michel Hidalgo Jacob Perron BSD http://ros.org/wiki/rosboost_cfg Josh Faust Dirk Thomas catkin python-setuptools python3-setuptools ros-1.15.8/tools/rosboost_cfg/scripts/000077500000000000000000000000001407615046500177415ustar00rootroot00000000000000ros-1.15.8/tools/rosboost_cfg/scripts/rosboost-cfg000077500000000000000000000032031407615046500222740ustar00rootroot00000000000000#!/usr/bin/env python # Software License Agreement (BSD License) # # Copyright (c) 2010, Willow Garage, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following # disclaimer in the documentation and/or other materials provided # with the distribution. # * Neither the name of Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. import rosboost_cfg rosboost_cfg.main() ros-1.15.8/tools/rosboost_cfg/setup.py000066400000000000000000000003501407615046500177620ustar00rootroot00000000000000from setuptools import setup from catkin_pkg.python_setup import generate_distutils_setup d = generate_distutils_setup( packages=['rosboost_cfg'], package_dir={'': 'src'}, scripts=['scripts/rosboost-cfg'] ) setup(**d) ros-1.15.8/tools/rosboost_cfg/src/000077500000000000000000000000001407615046500170415ustar00rootroot00000000000000ros-1.15.8/tools/rosboost_cfg/src/rosboost_cfg/000077500000000000000000000000001407615046500215325ustar00rootroot00000000000000ros-1.15.8/tools/rosboost_cfg/src/rosboost_cfg/__init__.py000066400000000000000000000031411407615046500236420ustar00rootroot00000000000000# Software License Agreement (BSD License) # # Copyright (c) 2010, Willow Garage, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following # disclaimer in the documentation and/or other materials provided # with the distribution. # * Neither the name of Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. from .rosboost_cfg import * ros-1.15.8/tools/rosboost_cfg/src/rosboost_cfg/rosboost_cfg.py000066400000000000000000000335001407615046500245760ustar00rootroot00000000000000#!/usr/bin/env python # Software License Agreement (BSD License) # # Copyright (c) 2010, Willow Garage, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following # disclaimer in the documentation and/or other materials provided # with the distribution. # * Neither the name of Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. from __future__ import print_function import os import platform import sys from glob import glob from optparse import OptionParser lib_suffix = 'so' if (sys.platform == 'darwin'): lib_suffix = 'dylib' link_static = 'ROS_BOOST_LINK' in os.environ and os.environ['ROS_BOOST_LINK'] == 'static' if (link_static): lib_suffix = 'a' no_L_or_I = 'ROS_BOOST_NO_L_OR_I' in os.environ boost_version = None if ('ROS_BOOST_VERSION' in os.environ and len(os.environ['ROS_BOOST_VERSION']) > 0): ver = os.environ['ROS_BOOST_VERSION'] ver = ver.split('.') boost_version = [int(v) for v in ver] if (len(boost_version) == 2): boost_version.append(0) def print_usage_and_exit(): print('Usage: rosboost-cfg --lflags [thread,regex,graph,...]') print(' rosboost-cfg --cflags') print(' rosboost-cfg --libs [thread,regex,graph,...]') print(' rosboost-cfg --include_dirs') print(' rosboost-cfg --lib_dirs') print(' rosboost-cfg --root') sys.exit(1) class BoostError(Exception): def __init__(self, value): self.value = value def __str__(self): return repr(self.value) class Version(object): def __init__(self, major, minor, patch, root, include_dir, lib_dir, is_default_search_location): self.major = major self.minor = minor self.patch = patch self.root = root self.include_dir = include_dir self.lib_dir = lib_dir self.is_default_search_location = is_default_search_location self.is_system_install = os.path.split(self.include_dir)[0] == self.root def __cmp__(self, other): if (self.major != other.major): if self.major < other.major: return -1 else: return 1 if (self.minor != other.minor): if self.minor < other.minor: return -1 else: return 1 if (self.patch != other.patch): if self.patch < other.patch: return -1 else: return 1 return 0 def __repr__(self): return repr((self.major, self.minor, self.patch, self.root, self.include_dir, self.is_default_search_location, self.is_system_install)) def find_lib_dir(root_dir, multiarch=''): # prefer lib64 unless explicitly specified in the environment if ('ROS_BOOST_LIB_DIR_NAME' in os.environ): possible_dirs = [os.path.join(root_dir, os.environ['ROS_BOOST_LIB_DIR_NAME'])] else: possible_dirs = [os.path.join(root_dir, 'lib64'), os.path.join(root_dir, 'lib')] if multiarch: possible_dirs = [os.path.join(root_dir, 'lib/%s' % multiarch)] + possible_dirs for p in possible_dirs: glob_files = glob('%s*' % (os.path.join(p, 'libboost*'))) if (len(glob_files) > 0): return p return None def extract_versions(dir, is_default_search_location, multiarch=''): version_paths = [os.path.join(dir, 'version.hpp'), os.path.join(dir, 'boost', 'version.hpp')] glob_dirs = glob('%s*' % (os.path.join(dir, 'boost-'))) [version_paths.append(os.path.join(gdir, 'boost', 'version.hpp')) for gdir in glob_dirs] versions = [] for p in version_paths: ver_string = '' if (os.path.isfile(p)): fh = open(p, 'r') lines = fh.readlines() fh.close() for line in lines: if line.find('#define BOOST_VERSION ') > -1: def_string = line.split() ver_string = def_string[2] ver_int = int(ver_string) patch = ver_int % 100 minor = ver_int / 100 % 1000 major = ver_int / 100000 include_dir = os.path.split(os.path.split(p)[0])[0] root_dir = os.path.split(dir)[0] lib_dir = find_lib_dir(root_dir, multiarch) versions.append(Version(major, minor, patch, root_dir, include_dir, lib_dir, is_default_search_location)) return versions def find_versions(search_paths, multiarch=''): vers = [] for path, system in search_paths: path = os.path.join(path, 'include') pvers = extract_versions(path, system, multiarch) [vers.append(ver) for ver in pvers] if (len(vers) == 0): return None if (boost_version is not None): for v in vers: if (v.major == boost_version[0] and v.minor == boost_version[1] and v.patch == boost_version[2]): return [v] raise BoostError('Could not find boost version %s required by ROS_BOOST_VERSION environment variable' % (boost_version)) vers.sort() return vers def find_boost(search_paths, multiarch=''): result = find_versions(search_paths, multiarch) if result is None: return None if len(result) > 1: sys.stderr.write("WARN, found multiple boost versions '%s', using latest" % result) return result[-1] def search_paths(sysroot): _search_paths = [(sysroot+'/usr', True), (sysroot+'/usr/local', True), (None if 'INCLUDE_DIRS' not in os.environ else os.environ['INCLUDE_DIRS'], True), (None if 'CPATH' not in os.environ else os.environ['CPATH'], True), (None if 'C_INCLUDE_PATH' not in os.environ else os.environ['C_INCLUDE_PATH'], True), (None if 'CPLUS_INCLUDE_PATH' not in os.environ else os.environ['CPLUS_INCLUDE_PATH'], True), (None if 'ROS_BOOST_ROOT' not in os.environ else os.environ['ROS_BOOST_ROOT'], False)] search_paths = [] for (str, system) in _search_paths: if (str is not None): dirs = str.split(':') for dir in dirs: if (len(dir) > 0): if (dir.endswith('/include')): dir = dir[:-len('/include')] search_paths.append((dir, system)) return search_paths def lib_dir(ver): return ver.lib_dir def find_lib(ver, name, full_lib=link_static): global lib_suffix global link_static dynamic_search_paths = [] static_search_paths = [] if (ver.is_system_install): dynamic_search_paths = ['libboost_%s-mt.%s' % (name, lib_suffix), 'libboost_%s.%s' % (name, lib_suffix)] static_search_paths = ['libboost_%s-mt.a' % (name), 'libboost_%s.a' % (name)] else: dynamic_search_paths = ['libboost_%s*%s_%s*.%s' % (name, ver.major, ver.minor, lib_suffix), 'libboost_%s-mt*.%s' % (name, lib_suffix), 'libboost_%s*.%s' % (name, lib_suffix)] static_search_paths = ['libboost_%s*%s_%s*.a' % (name, ver.major, ver.minor), 'libboost_%s-mt*.a' % (name), 'libboost_%s*.a' % (name)] # Boost.Python needs some special handling on some systems (Karmic), since it may have per-python-version libs if (name == 'python'): python_ver = platform.python_version().split('.') dynamic_search_paths = ['libboost_%s-mt-py%s%s.%s' % (name, python_ver[0], python_ver[1], lib_suffix), 'libboost_%s-py%s%s.%s' % (name, python_ver[0], python_ver[1], lib_suffix)] + dynamic_search_paths static_search_paths = ['libboost_%s-mt-py%s%s.a' % (name, python_ver[0], python_ver[1]), 'libboost_%s-py%s%s.a' % (name, python_ver[0], python_ver[1])] + static_search_paths search_paths = static_search_paths if link_static else dynamic_search_paths dir = lib_dir(ver) if dir is None: raise BoostError('Could not locate library [%s], version %s' % (name, ver)) for p in search_paths: globstr = os.path.join(dir, p) libs = glob(globstr) if (len(libs) > 0): if (full_lib): return libs[0] else: return os.path.basename(libs[0]) raise BoostError('Could not locate library [%s], version %s in lib directory [%s]' % (name, ver, dir)) def include_dirs(ver, prefix=''): if ver.is_system_install or no_L_or_I: return '' return ' %s%s' % (prefix, ver.include_dir) def cflags(ver): return include_dirs(ver, '-I') def lib_dir_flags(ver): if not ver.is_default_search_location: dir = lib_dir(ver) return ' -L%s -Wl,-rpath,%s' % (dir, dir) return '' def lib_flags(ver, name): lib = find_lib(ver, name) if (link_static): return ' %s' % (lib) else: # Cut off "lib" and extension (.so/.a/.dylib/etc.) return ' -l%s' % (os.path.splitext(lib)[0][len('lib'):]) def lflags(ver, libs): s = lib_dir_flags(ver) + ' ' for lib in libs: s += lib_flags(ver, lib) + ' ' return s def libs(ver, libs): s = '' for lib in libs: s += find_lib(ver, lib, True) + ' ' return s def lib_dirs(ver): if (ver.is_default_search_location or no_L_or_I): return '' return lib_dir(ver) OPTIONS = ['libs', 'include_dirs', 'lib_dirs', 'cflags', 'lflags', 'root', 'print_versions', 'version'] def check_one_option(options, key): for k in dir(options): if (k in OPTIONS): v = getattr(options, k) if (k != key and v): raise BoostError('Only one option (excepting sysroot) is allowed at a time') def main(): if (len(sys.argv) < 2): print_usage_and_exit() parser = OptionParser() parser.add_option('-l', '--libs', dest='libs', type='string', help='') parser.add_option('-i', '--include_dirs', dest='include_dirs', action='store_true', default=False, help='') parser.add_option('-d', '--lib_dirs', dest='lib_dirs', action='store_true', help='') parser.add_option('-c', '--cflags', dest='cflags', action='store_true', default=False, help='') parser.add_option('-f', '--lflags', dest='lflags', type='string', help='') parser.add_option('-r', '--root', dest='root', action='store_true', default=False, help='') parser.add_option('-p', '--print_versions', dest='print_versions', action='store_true', default=False, help='') parser.add_option('-v', '--version', dest='version', action='store_true', default=False, help='') parser.add_option('-s', '--sysroot', dest='sysroot', type='string', default='', help='Location of the system root (usually toolchain root).') parser.add_option('-m', '--multiarch', dest='multiarch', type='string', default='', help="Name of multiarch to search below 'lib' folder for libraries.") (options, args) = parser.parse_args() if (options.print_versions): check_one_option(options, 'print_versions') for ver in find_versions(search_paths(options.sysroot), options.multiarch): print('%s.%s.%s root=%s include_dir=%s' % (ver.major, ver.minor, ver.patch, ver.root, ver.include_dir)) return ver = find_boost(search_paths(options.sysroot), options.multiarch) if ver is None: raise BoostError('Cannot find boost in any of %s' % search_paths(options.sysroot)) sys.exit(0) if options.version: check_one_option(options, 'version') print('%s.%s.%s root=%s include_dir=%s' % (ver.major, ver.minor, ver.patch, ver.root, ver.include_dir)) return if ver.major < 1 or (ver.major == 1 and ver.minor < 37): raise BoostError('Boost version %s.%s.%s does not meet the minimum requirements of boost 1.37.0' % (ver.major, ver.minor, ver.patch)) output = '' if (options.root): check_one_option(options, 'root') output = ver.root elif (options.libs): check_one_option(options, 'libs') output = libs(ver, options.libs.split(',')) elif (options.include_dirs): check_one_option(options, 'include_dirs') output = include_dirs(ver) elif (options.lib_dirs): check_one_option(options, 'lib_dirs') output = lib_dirs(ver) elif (options.cflags): check_one_option(options, 'cflags') output = cflags(ver) elif (options.lflags): check_one_option(options, 'lflags') output = lflags(ver, options.lflags.split(',')) else: print_usage_and_exit() print(output.strip()) if __name__ == '__main__': main() ros-1.15.8/tools/rosclean/000077500000000000000000000000001407615046500153675ustar00rootroot00000000000000ros-1.15.8/tools/rosclean/CHANGELOG.rst000066400000000000000000000067011407615046500174140ustar00rootroot00000000000000^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Changelog for package rosclean ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 1.15.8 (2021-07-21) ------------------- * Update maintainers (`#272 `_) * Contributors: Jacob Perron 1.15.7 (2020-09-28) ------------------- 1.15.6 (2020-07-20) ------------------- 1.15.5 (2020-07-06) ------------------- * fix size output of 'rosclean check' (`#266 `_) * fix subparsers of rosclean (`#265 `_) 1.15.4 (2020-05-28) ------------------- 1.15.3 (2020-05-14) ------------------- 1.15.2 (2020-04-07) ------------------- * fix log purge on Windows (`#251 `_) 1.15.1 (2020-03-17) ------------------- 1.15.0 (2020-02-11) ------------------- 1.14.8 (2020-02-11) ------------------- * update style to pass flake8 (`#240 `_) * Use setuptools instead of distutils (`#235 `_) * Bump CMake version to avoid CMP0048 warning (`#234 `_) 1.14.7 (2019-10-03) ------------------- * use condition attributes to specify Python 2 and 3 dependencies (`#226 `_) * use rd on Windows (`#224 `_) 1.14.6 (2019-03-18) ------------------- 1.14.5 (2019-03-04) ------------------- * enable rosclean on Windows (`#198 `_) * support BusyBox du (`#185 `_) 1.14.4 (2018-05-01) ------------------- 1.14.3 (2018-01-30) ------------------- 1.14.2 (2017-10-26) ------------------- 1.14.1 (2017-07-27) ------------------- 1.14.0 (2017-02-22) ------------------- 1.13.6 (2017-10-31) ------------------- 1.13.5 (2017-02-14) ------------------- * add --size option to rosclean purge (`#126 `_) 1.13.4 (2016-09-19) ------------------- 1.13.3 (2016-09-16) ------------------- 1.13.2 (2016-09-02) ------------------- 1.13.1 (2016-03-13) ------------------- 1.13.0 (2016-03-10) ------------------- 1.12.6 (2016-03-10) ------------------- 1.12.5 (2015-10-13) ------------------- 1.12.4 (2015-10-12) ------------------- 1.12.3 (2015-09-19) ------------------- 1.12.2 (2015-04-27) ------------------- 1.12.1 (2015-04-16) ------------------- 1.12.0 (2014-12-26) ------------------- 1.11.6 (2014-12-22) ------------------- 1.11.5 (2014-08-18) ------------------- 1.11.4 (2014-07-23) ------------------- 1.11.3 (2014-07-18) ------------------- 1.11.2 (2014-06-16) ------------------- 1.11.1 (2014-05-07) ------------------- 1.11.0 (2014-01-31) ------------------- 1.10.9 (2014-01-07) ------------------- 1.10.8 (2013-10-15) ------------------- 1.10.7 (2013-10-04) ------------------- 1.10.6 (2013-08-22) ------------------- 1.10.5 (2013-08-21) ------------------- 1.10.4 (2013-07-05) ------------------- 1.10.3 (2013-07-03) ------------------- * check for CATKIN_ENABLE_TESTING to enable configure without tests 1.10.2 (2013-06-18) ------------------- 1.10.1 (2013-06-06) ------------------- 1.10.0 (2013-03-22 09:23) ------------------------- 1.9 (Groovy) ============ 1.9.44 (2013-03-13) ------------------- 1.9.43 (2013-03-08) ------------------- 1.9.42 (2013-01-25) ------------------- 1.9.41 (2013-01-24) ------------------- 1.9.40 (2013-01-13) ------------------- 1.9.39 (2012-12-30) ------------------- * first public release for Groovy ros-1.15.8/tools/rosclean/CMakeLists.txt000066400000000000000000000002761407615046500201340ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.0.2) project(rosclean) find_package(catkin REQUIRED) catkin_package() catkin_python_setup() if(CATKIN_ENABLE_TESTING) catkin_add_nosetests(test) endif() ros-1.15.8/tools/rosclean/package.xml000066400000000000000000000022431407615046500175050ustar00rootroot00000000000000 rosclean 1.15.8 rosclean: cleanup filesystem resources (e.g. log files). Michel Hidalgo Jacob Perron BSD http://wiki.ros.org/rosclean https://github.com/ros/ros/issues https://github.com/ros/ros Ken Conley Dirk Thomas catkin python-setuptools python3-setuptools python-rospkg python3-rospkg ros-1.15.8/tools/rosclean/scripts/000077500000000000000000000000001407615046500170565ustar00rootroot00000000000000ros-1.15.8/tools/rosclean/scripts/rosclean000077500000000000000000000032041407615046500206110ustar00rootroot00000000000000#!/usr/bin/env python # Software License Agreement (BSD License) # # Copyright (c) 2010, Willow Garage, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following # disclaimer in the documentation and/or other materials provided # with the distribution. # * Neither the name of Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. import rosclean rosclean.rosclean_main() ros-1.15.8/tools/rosclean/setup.py000066400000000000000000000003711407615046500171020ustar00rootroot00000000000000from setuptools import setup from catkin_pkg.python_setup import generate_distutils_setup d = generate_distutils_setup( packages=['rosclean'], package_dir={'': 'src'}, scripts=['scripts/rosclean'], requires=['rospkg'] ) setup(**d) ros-1.15.8/tools/rosclean/src/000077500000000000000000000000001407615046500161565ustar00rootroot00000000000000ros-1.15.8/tools/rosclean/src/rosclean/000077500000000000000000000000001407615046500177645ustar00rootroot00000000000000ros-1.15.8/tools/rosclean/src/rosclean/__init__.py000066400000000000000000000222611407615046500221000ustar00rootroot00000000000000# Software License Agreement (BSD License) # # Copyright (c) 2010, Willow Garage, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following # disclaimer in the documentation and/or other materials provided # with the distribution. # * Neither the name of Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. from __future__ import print_function import argparse import os import platform import subprocess import sys from distutils.spawn import find_executable import rospkg __version__ = '1.7.0' class CleanupException(Exception): pass def _ask_and_call(cmds, cwd=None): """ Pretty print cmds, ask if they should be run, and if so, runs them using _call(). :param cmds: a list of commands executed one after another, ``list`` :param cwd: (optional) set cwd of command that is executed, ``str`` :returns: ``True`` if cmds were run. """ # Pretty-print a string version of the commands def quote(s): return '"%s"' % s if ' ' in s else s accepted = _ask('\n'.join([' '.join([quote(s) for s in c]) for c in cmds])) if accepted: _call(cmds, cwd) return accepted def _ask(comment): """ ask user with provided comment. If user responds with y, return True :param comment: comment, ``str`` :return: ``True`` if user responds with y """ sys.stdout.write('Okay to perform:\n\n%s\n(y/n)?\n' % comment) while 1: input = sys.stdin.readline().strip().lower() if input in ['y', 'n']: break return input == 'y' def _call(cmds, cwd=None): """ Runs cmds using subprocess.check_call. :param cmds: a list of commands executed one after another, ``list`` :param cwd: (optional) set cwd of command that is executed, ``str`` """ for c in cmds: if cwd: subprocess.check_call(c, cwd=cwd) else: subprocess.check_call(c) def _usage(): print("""Usage: rosclean Commands: \trosclean check\tCheck usage of log files \trosclean purge\tRemove log files """) sys.exit(getattr(os, 'EX_USAGE', 1)) def _get_check_dirs(): home_dir = rospkg.get_ros_home() log_dir = rospkg.get_log_dir() dirs = [(log_dir, 'ROS node logs'), (os.path.join(home_dir, 'rosmake'), 'rosmake logs')] return [x for x in dirs if os.path.isdir(x[0])] def _rosclean_cmd_check(args): dirs = _get_check_dirs() for d, label in dirs: desc = get_human_readable_disk_usage(d) print('%s %s' % (desc, label)) def _get_disk_usage_by_walking_tree(d): total_size = 0 for dirpath, dirnames, filenames in os.walk(d): for f in filenames: fp = os.path.join(dirpath, f) total_size += os.path.getsize(fp) return total_size def get_human_readable_disk_usage(d): """ Get human-readable disk usage for directory :param d: directory path, ``str` :returns: human-readable disk usage (du -h), ``str`` """ # only implemented on Linux and FreeBSD for now. Should work on OS X but need to verify first (du is not identical) if platform.system() in ['Linux', 'FreeBSD']: try: return subprocess.Popen(['du', '-sh', d], stdout=subprocess.PIPE).communicate()[0].split()[0].decode() except Exception: raise CleanupException('rosclean is not supported on this platform') elif platform.system() == 'Windows': total_size = _get_disk_usage_by_walking_tree(d) return 'Total Size: ' + str(total_size) + ' ' + d else: raise CleanupException('rosclean is not supported on this platform') def get_disk_usage(d): """ Get disk usage in bytes for directory :param d: directory path, ``str`` :returns: disk usage in bytes (du -b) or (du -A) * 1024, ``int`` :raises: :exc:`CleanupException` If get_disk_usage() cannot be used on this platform """ if platform.system() == 'Windows': return _get_disk_usage_by_walking_tree(d) # only implemented on Linux and FreeBSD for now. Should work on OS X but need to verify first (du is not identical) cmd = None unit = 1 du = find_executable('du') if du is not None: if platform.system() == 'Linux': cmd = [du, '-sb', d] elif platform.system() == 'FreeBSD': cmd = [du, '-skA', d] unit = 1024 try: # detect BusyBox du command by following symlink if os.path.basename(os.readlink(du)) == 'busybox': cmd = [du, '-sk', d] unit = 1024 except OSError: # readlink raises OSError if the target is not symlink pass if cmd is None: raise CleanupException('rosclean is not supported on this platform') try: return int(subprocess.Popen(cmd, stdout=subprocess.PIPE).communicate()[0].split()[0]) * unit except Exception: raise CleanupException('rosclean is not supported on this platform') def _sort_file_by_oldest(d): """ Get files and directories in specified path sorted by last modified time :param d: directory path, ```str``` :return: a list of files and directories sorted by last modified time (old first), ```list``` """ files = os.listdir(d) files.sort(key=lambda f: os.path.getmtime(os.path.join(d, f))) return files def _rosclean_cmd_purge(args): dirs = _get_check_dirs() for d, label in dirs: if not args.size: print('Purging %s.' % label) if platform.system() == 'Windows': cmds = [['cmd', '/c', 'rd', '/s', '/q', d]] else: cmds = [['rm', '-rf', d]] try: if args.y: _call(cmds) else: print('PLEASE BE CAREFUL TO VERIFY THE COMMAND BELOW!') _ask_and_call(cmds) except Exception: print('FAILED to execute command', file=sys.stderr) else: files = _sort_file_by_oldest(d) log_size = get_disk_usage(d) if log_size <= args.size * 1024 * 1024: print('Directory size of %s is %d MB which is already below the requested threshold of %d MB.' % (label, log_size / 1024 / 1024, args.size)) continue print('Purging %s until directory size is at most %d MB (currently %d MB).' % (label, args.size, log_size / 1024 / 1024)) if not args.y: print('PLEASE BE CAREFUL TO VERIFY THE COMMAND BELOW!') if not _ask('Purge some of old logs in %s' % d): return for f in files: if log_size <= args.size * 1024 * 1024: break path = os.path.join(d, f) log_size -= get_disk_usage(path) if platform.system() == 'Windows': cmds = [['cmd', '/c', 'rd', '/s', '/q', path]] else: cmds = [['rm', '-rf', path]] try: _call(cmds) except Exception: print('FAILED to execute command', file=sys.stderr) def rosclean_main(argv=None): if argv is None: argv = sys.argv parser = argparse.ArgumentParser(prog='rosclean') subparsers = parser.add_subparsers(required=True, dest='{check,purge}') # help='sub-command help') parser_check = subparsers.add_parser('check', help='Check usage of log files') parser_check.set_defaults(func=_rosclean_cmd_check) parser_purge = subparsers.add_parser('purge', help='Remove log files') parser_purge.set_defaults(func=_rosclean_cmd_purge) parser_purge.add_argument('-y', action='store_true', default=False, help='CAUTION: automatically confirms all questions to delete files') parser_purge.add_argument('--size', action='store', default=None, type=int, help='Maximum total size in MB to keep when deleting old files') args = parser.parse_args(argv[1:]) args.func(args) if __name__ == '__main__': rosclean_main() ros-1.15.8/tools/rosclean/test/000077500000000000000000000000001407615046500163465ustar00rootroot00000000000000ros-1.15.8/tools/rosclean/test/__init__.py000066400000000000000000000000001407615046500204450ustar00rootroot00000000000000ros-1.15.8/tools/rosclean/test/test_rosclean.py000066400000000000000000000050551407615046500215720ustar00rootroot00000000000000# Software License Agreement (BSD License) # # Copyright (c) 2012, Willow Garage, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following # disclaimer in the documentation and/or other materials provided # with the distribution. # * Neither the name of Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. import os def test__get_check_dirs(): # just a tripwire, no way to assert the actual values w/o identical reimplementation from rosclean import _get_check_dirs vals = _get_check_dirs() for path, desc in vals: assert os.path.isdir(path) def test_get_human_readable_disk_usage(): from rosclean import get_human_readable_disk_usage val = get_human_readable_disk_usage(get_test_path()) assert val def get_test_path(): return os.path.abspath(os.path.join(os.path.dirname(__file__))) def test_get_disk_usage(): from rosclean import get_disk_usage val = get_disk_usage(get_test_path()) assert val > 0 def test_cmd(): from rosclean import rosclean_main try: rosclean_main(['rosclean', 'fake']) assert False, 'should have raised sys exit' except SystemExit: pass # should run cleanly try: rosclean_main(['rosclean', 'check']) except SystemExit: assert False, 'failed with sys exit' ros-1.15.8/tools/roscreate/000077500000000000000000000000001407615046500155505ustar00rootroot00000000000000ros-1.15.8/tools/roscreate/CHANGELOG.rst000066400000000000000000000062701407615046500175760ustar00rootroot00000000000000^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Changelog for package roscreate ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 1.15.8 (2021-07-21) ------------------- * Update maintainers (`#272 `_) * Contributors: Jacob Perron 1.15.7 (2020-09-28) ------------------- 1.15.6 (2020-07-20) ------------------- * fix string encoding in roscreate-pkg with Python 3 (`#267 `_) 1.15.5 (2020-07-06) ------------------- 1.15.4 (2020-05-28) ------------------- 1.15.3 (2020-05-14) ------------------- 1.15.2 (2020-04-07) ------------------- 1.15.1 (2020-03-17) ------------------- 1.15.0 (2020-02-11) ------------------- 1.14.8 (2020-02-11) ------------------- * update style to pass flake8 (`#240 `_) * Use setuptools instead of distutils (`#235 `_) * Bump CMake version to avoid CMP0048 warning (`#234 `_) 1.14.7 (2019-10-03) ------------------- * use condition attributes to specify Python 2 and 3 dependencies (`#226 `_) 1.14.6 (2019-03-18) ------------------- 1.14.5 (2019-03-04) ------------------- * chmod -x on Python modules (`#183 `_) * add missing dependencies (`#181 `_) 1.14.4 (2018-05-01) ------------------- 1.14.3 (2018-01-30) ------------------- 1.14.2 (2017-10-26) ------------------- 1.14.1 (2017-07-27) ------------------- 1.14.0 (2017-02-22) ------------------- 1.13.6 (2017-10-31) ------------------- 1.13.5 (2017-02-14) ------------------- 1.13.4 (2016-09-19) ------------------- 1.13.3 (2016-09-16) ------------------- 1.13.2 (2016-09-02) ------------------- 1.13.1 (2016-03-13) ------------------- 1.13.0 (2016-03-10) ------------------- 1.12.6 (2016-03-10) ------------------- 1.12.5 (2015-10-13) ------------------- 1.12.4 (2015-10-12) ------------------- 1.12.3 (2015-09-19) ------------------- 1.12.2 (2015-04-27) ------------------- 1.12.1 (2015-04-16) ------------------- 1.12.0 (2014-12-26) ------------------- 1.11.6 (2014-12-22) ------------------- 1.11.5 (2014-08-18) ------------------- 1.11.4 (2014-07-23) ------------------- 1.11.3 (2014-07-18) ------------------- 1.11.2 (2014-06-16) ------------------- 1.11.1 (2014-05-07) ------------------- * python 3 compatibility 1.11.0 (2014-01-31) ------------------- 1.10.9 (2014-01-07) ------------------- 1.10.8 (2013-10-15) ------------------- 1.10.7 (2013-10-04) ------------------- 1.10.6 (2013-08-22) ------------------- 1.10.5 (2013-08-21) ------------------- 1.10.4 (2013-07-05) ------------------- 1.10.3 (2013-07-03) ------------------- * check for CATKIN_ENABLE_TESTING to enable configure without tests 1.10.2 (2013-06-18) ------------------- 1.10.1 (2013-06-06) ------------------- 1.10.0 (2013-03-22 09:23) ------------------------- 1.9 (Groovy) ============ 1.9.44 (2013-03-13) ------------------- 1.9.43 (2013-03-08) ------------------- 1.9.42 (2013-01-25) ------------------- 1.9.41 (2013-01-24) ------------------- 1.9.40 (2013-01-13) ------------------- 1.9.39 (2012-12-30) ------------------- * first public release for Groovy ros-1.15.8/tools/roscreate/CMakeLists.txt000066400000000000000000000004631407615046500203130ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.0.2) project(roscreate) find_package(catkin REQUIRED) catkin_package() catkin_python_setup() install(DIRECTORY templates/ DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}/templates PATTERN ".svn" EXCLUDE) if(CATKIN_ENABLE_TESTING) catkin_add_nosetests(test) endif() ros-1.15.8/tools/roscreate/package.xml000066400000000000000000000026151407615046500176710ustar00rootroot00000000000000 roscreate 1.15.8 roscreate contains a tool that assists in the creation of ROS filesystem resources. It provides: roscreate-pkg, which creates a new package directory, including the appropriate build and manifest files. Michel Hidalgo Jacob Perron BSD http://wiki.ros.org/roscreate https://github.com/ros/ros/issues https://github.com/ros/ros Ken Conley Dirk Thomas catkin python-setuptools python3-setuptools python-rospkg python3-rospkg roslib ros-1.15.8/tools/roscreate/scripts/000077500000000000000000000000001407615046500172375ustar00rootroot00000000000000ros-1.15.8/tools/roscreate/scripts/roscreate-pkg000077500000000000000000000032271407615046500217370ustar00rootroot00000000000000#!/usr/bin/env python # Software License Agreement (BSD License) # # Copyright (c) 2008, Willow Garage, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following # disclaimer in the documentation and/or other materials provided # with the distribution. # * Neither the name of Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. import roscreate roscreate.roscreatepkg.roscreatepkg_main() ros-1.15.8/tools/roscreate/setup.py000066400000000000000000000004111407615046500172560ustar00rootroot00000000000000from setuptools import setup from catkin_pkg.python_setup import generate_distutils_setup d = generate_distutils_setup( packages=['roscreate'], package_dir={'': 'src'}, scripts=['scripts/roscreate-pkg'], requires=['roslib', 'rospkg'] ) setup(**d) ros-1.15.8/tools/roscreate/src/000077500000000000000000000000001407615046500163375ustar00rootroot00000000000000ros-1.15.8/tools/roscreate/src/roscreate/000077500000000000000000000000001407615046500203265ustar00rootroot00000000000000ros-1.15.8/tools/roscreate/src/roscreate/__init__.py000066400000000000000000000032411407615046500224370ustar00rootroot00000000000000#!/usr/bin/env python # Software License Agreement (BSD License) # # Copyright (c) 2008, Willow Garage, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following # disclaimer in the documentation and/or other materials provided # with the distribution. # * Neither the name of Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # # Revision $Id$ import roscreate.core import roscreate.roscreatepkg ros-1.15.8/tools/roscreate/src/roscreate/core.py000066400000000000000000000056401407615046500216350ustar00rootroot00000000000000#!/usr/bin/env python # Software License Agreement (BSD License) # # Copyright (c) 2009, Willow Garage, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following # disclaimer in the documentation and/or other materials provided # with the distribution. # * Neither the name of Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. from __future__ import print_function import os import sys import pkg_resources import rospkg def print_warning(msg): """print warning to screen (bold red)""" print('\033[31m%s\033[0m' % msg, file=sys.stderr) def author_name(): """ Utility to compute logged in user name :returns: name of current user, ``str`` """ import getpass name = getpass.getuser() try: import pwd login = name name = pwd.getpwnam(login)[4] name = ''.join(name.split(',')) # strip commas # in case pwnam is not set if not name: name = login except Exception: # pwd failed pass try: name = name.decode('utf-8') except AttributeError: pass return name def read_template(tmplf): """ Read resource template from egg installation, or fallback on rospkg otherwise. :returns: text of template file """ if pkg_resources.resource_exists('roscreate', tmplf): f = pkg_resources.resource_stream('roscreate', tmplf) t = f.read() else: # fallback on rospkg r = rospkg.RosPack() with open(os.path.join(r.get_path('roscreate'), 'templates', tmplf)) as f: t = f.read() try: t = t.decode('utf-8') except AttributeError: pass return t ros-1.15.8/tools/roscreate/src/roscreate/roscreatepkg.py000066400000000000000000000120361407615046500233730ustar00rootroot00000000000000# Software License Agreement (BSD License) # # Copyright (c) 2008, Willow Garage, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following # disclaimer in the documentation and/or other materials provided # with the distribution. # * Neither the name of Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # # Revision $Id$ from __future__ import print_function import os import sys from roscreate.core import author_name from roscreate.core import read_template import roslib.names from rospkg import ResourceNotFound from rospkg import RosPack from rospkg import on_ros_path NAME = 'roscreate-pkg' def get_templates(): templates = {} templates['CMakeLists.txt'] = read_template('CMakeLists.tmpl') templates['manifest.xml'] = read_template('manifest.tmpl') templates['mainpage.dox'] = read_template('mainpage.tmpl') templates['Makefile'] = read_template('Makefile.tmpl') return templates def instantiate_template(template, package, brief, description, author, depends): return template % locals() def create_package(package, author, depends, uses_roscpp=False, uses_rospy=False): p = os.path.abspath(package) if os.path.exists(p): print('%s already exists, aborting' % p, file=sys.stderr) sys.exit(1) os.makedirs(p) print('Created package directory', p) if uses_roscpp: # create package/include/package and package/src for roscpp code cpp_path = os.path.join(p, 'include', package) try: os.makedirs(cpp_path) print('Created include directory', cpp_path) cpp_path = os.path.join(p, 'src') os.makedirs(cpp_path) print('Created cpp source directory', cpp_path) except Exception: # file exists pass if uses_rospy: # create package/src/ for python files py_path = os.path.join(p, 'src') try: os.makedirs(py_path) print('Created python source directory', py_path) except Exception: # file exists pass templates = get_templates() for filename, template in templates.items(): contents = instantiate_template(template, package, package, package, author, depends) p = os.path.abspath(os.path.join(package, filename)) with open(p, 'wb') as f: f.write(contents.encode('utf-8')) print('Created package file', p) print('\nPlease edit %s/manifest.xml and mainpage.dox to finish creating your package' % package) def roscreatepkg_main(): from optparse import OptionParser parser = OptionParser(usage='usage: %prog [dependencies...]', prog=NAME) options, args = parser.parse_args() if not args: parser.error('you must specify a package name and optionally also list package dependencies') package = args[0] if not roslib.names.is_legal_resource_base_name(package): parser.error('illegal package name: %s\nNames must start with a letter and contain only alphanumeric characters\nand underscores.' % package) # validate dependencies and turn into XML depends = args[1:] uses_roscpp = 'roscpp' in depends uses_rospy = 'rospy' in depends rospack = RosPack() for d in depends: try: rospack.get_path(d) except ResourceNotFound: print('ERROR: dependency [%s] cannot be found' % d, file=sys.stderr) sys.exit(1) depends = u''.join([u' \n' % d for d in depends]) if not on_ros_path(os.getcwd()): print('!'*80+'\nWARNING: current working directory is not on ROS_PACKAGE_PATH!\nPlease update your ROS_PACKAGE_PATH environment variable.\n'+'!'*80, file=sys.stderr) create_package(package, author_name(), depends, uses_roscpp=uses_roscpp, uses_rospy=uses_rospy) ros-1.15.8/tools/roscreate/templates/000077500000000000000000000000001407615046500175465ustar00rootroot00000000000000ros-1.15.8/tools/roscreate/templates/CMakeLists.stack.tmpl000066400000000000000000000014571407615046500235560ustar00rootroot00000000000000cmake_minimum_required(VERSION 2.4.6) include($ENV{ROS_ROOT}/core/rosbuild/rosbuild.cmake) # Append to CPACK_SOURCE_IGNORE_FILES a semicolon-separated list of # directories (or patterns, but directories should suffice) that should # be excluded from the distro. This is not the place to put things that # should be ignored everywhere, like "build" directories; that happens in # rosbuild/rosbuild.cmake. Here should be listed packages that aren't # ready for inclusion in a distro. # # This list is combined with the list in rosbuild/rosbuild.cmake. Note # that CMake 2.6 may be required to ensure that the two lists are combined # properly. CMake 2.4 seems to have unpredictable scoping rules for such # variables. #list(APPEND CPACK_SOURCE_IGNORE_FILES /core/experimental) rosbuild_make_distribution(0.1.0) ros-1.15.8/tools/roscreate/templates/CMakeLists.tmpl000066400000000000000000000022631407615046500224460ustar00rootroot00000000000000cmake_minimum_required(VERSION 2.4.6) include($ENV{ROS_ROOT}/core/rosbuild/rosbuild.cmake) # Set the build type. Options are: # Coverage : w/ debug symbols, w/o optimization, w/ code-coverage # Debug : w/ debug symbols, w/o optimization # Release : w/o debug symbols, w/ optimization # RelWithDebInfo : w/ debug symbols, w/ optimization # MinSizeRel : w/o debug symbols, w/ optimization, stripped binaries #set(ROS_BUILD_TYPE RelWithDebInfo) rosbuild_init() #set the default path for built executables to the "bin" directory set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin) #set the default path for built libraries to the "lib" directory set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib) #uncomment if you have defined messages #rosbuild_genmsg() #uncomment if you have defined services #rosbuild_gensrv() #common commands for building c++ executables and libraries #rosbuild_add_library(${PROJECT_NAME} src/example.cpp) #target_link_libraries(${PROJECT_NAME} another_library) #rosbuild_add_boost_directories() #rosbuild_link_boost(${PROJECT_NAME} thread) #rosbuild_add_executable(example examples/example.cpp) #target_link_libraries(example ${PROJECT_NAME}) ros-1.15.8/tools/roscreate/templates/Makefile.stack.tmpl000066400000000000000000000000571407615046500232670ustar00rootroot00000000000000include $(shell rospack find mk)/cmake_stack.mkros-1.15.8/tools/roscreate/templates/Makefile.tmpl000066400000000000000000000000511407615046500221550ustar00rootroot00000000000000include $(shell rospack find mk)/cmake.mkros-1.15.8/tools/roscreate/templates/mainpage.tmpl000066400000000000000000000001621407615046500222240ustar00rootroot00000000000000/** \mainpage \htmlinclude manifest.html \b %(package)s --> */ ros-1.15.8/tools/roscreate/templates/manifest.tmpl000066400000000000000000000003701407615046500222520ustar00rootroot00000000000000 %(description)s %(author)s BSD http://ros.org/wiki/%(package)s %(depends)s ros-1.15.8/tools/roscreate/templates/stack.tmpl000066400000000000000000000003221407615046500215460ustar00rootroot00000000000000 %(description)s %(author)s %(licenses)s %(review)s http://ros.org/wiki/%(stack)s %(depends)s ros-1.15.8/tools/roscreate/test/000077500000000000000000000000001407615046500165275ustar00rootroot00000000000000ros-1.15.8/tools/roscreate/test/__init__.py000066400000000000000000000000001407615046500206260ustar00rootroot00000000000000ros-1.15.8/tools/roscreate/test/fake-pkg/000077500000000000000000000000001407615046500202145ustar00rootroot00000000000000ros-1.15.8/tools/roscreate/test/fake-pkg/stack1/000077500000000000000000000000001407615046500214025ustar00rootroot00000000000000ros-1.15.8/tools/roscreate/test/fake-pkg/stack1/depends_roslib/000077500000000000000000000000001407615046500243765ustar00rootroot00000000000000ros-1.15.8/tools/roscreate/test/fake-pkg/stack1/depends_roslib/manifest.xml000066400000000000000000000002741407615046500267310ustar00rootroot00000000000000 depends_roslib Kenneth Conley BSD ros-1.15.8/tools/roscreate/test/fake-pkg/stack1/stack.xml000066400000000000000000000002661407615046500232350ustar00rootroot00000000000000 stack1 Maintained by Kenneth Conley BSD ros-1.15.8/tools/roscreate/test/fake-pkg/stack2/000077500000000000000000000000001407615046500214035ustar00rootroot00000000000000ros-1.15.8/tools/roscreate/test/fake-pkg/stack2/depends_stack1/000077500000000000000000000000001407615046500242735ustar00rootroot00000000000000ros-1.15.8/tools/roscreate/test/fake-pkg/stack2/depends_stack1/CMakeLists.txt000066400000000000000000000022631407615046500270360ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.0.2) include($ENV{ROS_ROOT}/core/rosbuild/rosbuild.cmake) # Set the build type. Options are: # Coverage : w/ debug symbols, w/o optimization, w/ code-coverage # Debug : w/ debug symbols, w/o optimization # Release : w/o debug symbols, w/ optimization # RelWithDebInfo : w/ debug symbols, w/ optimization # MinSizeRel : w/o debug symbols, w/ optimization, stripped binaries #set(ROS_BUILD_TYPE RelWithDebInfo) rosbuild_init() #set the default path for built executables to the "bin" directory set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin) #set the default path for built libraries to the "lib" directory set(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib) #uncomment if you have defined messages #rosbuild_genmsg() #uncomment if you have defined services #rosbuild_gensrv() #common commands for building c++ executables and libraries #rosbuild_add_library(${PROJECT_NAME} src/example.cpp) #target_link_libraries(${PROJECT_NAME} another_library) #rosbuild_add_boost_directories() #rosbuild_link_boost(${PROJECT_NAME} thread) #rosbuild_add_executable(example examples/example.cpp) #target_link_libraries(example ${PROJECT_NAME}) ros-1.15.8/tools/roscreate/test/fake-pkg/stack2/depends_stack1/Makefile000066400000000000000000000000511407615046500257270ustar00rootroot00000000000000include $(shell rospack find mk)/cmake.mkros-1.15.8/tools/roscreate/test/fake-pkg/stack2/depends_stack1/mainpage.dox000066400000000000000000000015621407615046500265740ustar00rootroot00000000000000/** \mainpage \htmlinclude manifest.html \b depends_stack1 is ... \section codeapi Code API */ros-1.15.8/tools/roscreate/test/fake-pkg/stack2/depends_stack1/manifest.xml000066400000000000000000000003021407615046500266160ustar00rootroot00000000000000 depends_stack1 Kenneth Conley BSD ros-1.15.8/tools/roscreate/test/fake-pkg/stack2/stack.xml000066400000000000000000000003011407615046500232240ustar00rootroot00000000000000 stack2 Maintained by Kenneth Conley BSD ros-1.15.8/tools/roscreate/test/test_roscreate_core.py000066400000000000000000000043771407615046500231520ustar00rootroot00000000000000# Software License Agreement (BSD License) # # Copyright (c) 2012, Willow Garage, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following # disclaimer in the documentation and/or other materials provided # with the distribution. # * Neither the name of Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. def test_author_name(): from roscreate.core import author_name val = author_name() assert val, val def test_read_template(): from roscreate.core import read_template s = set() # this unit test will break if any of the templates get removed/renamed tests = ['Makefile.tmpl', 'stack.tmpl', 'mainpage.tmpl', 'CMakeLists.stack.tmpl'] for f in tests: text = read_template(f) s.add(text) # simple assert to make sure we didn't read the same thing from each template assert len(s) == len(tests) # hardcode test against a known template text = read_template('Makefile.tmpl') assert text == 'include $(shell rospack find mk)/cmake.mk' ros-1.15.8/tools/rosmake/000077500000000000000000000000001407615046500152225ustar00rootroot00000000000000ros-1.15.8/tools/rosmake/CHANGELOG.rst000066400000000000000000000071721407615046500172520ustar00rootroot00000000000000^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Changelog for package rosmake ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 1.15.8 (2021-07-21) ------------------- * Fix spelling (`#277 `_) * Update maintainers (`#272 `_) * Contributors: Jacob Perron, freddii 1.15.7 (2020-09-28) ------------------- 1.15.6 (2020-07-20) ------------------- 1.15.5 (2020-07-06) ------------------- 1.15.4 (2020-05-28) ------------------- 1.15.3 (2020-05-14) ------------------- 1.15.2 (2020-04-07) ------------------- 1.15.1 (2020-03-17) ------------------- 1.15.0 (2020-02-11) ------------------- 1.14.8 (2020-02-11) ------------------- * update style to pass flake8 (`#240 `_) * Use setuptools instead of distutils (`#235 `_) * Bump CMake version to avoid CMP0048 warning (`#234 `_) 1.14.7 (2019-10-03) ------------------- * use condition attributes to specify Python 2 and 3 dependencies (`#226 `_) 1.14.6 (2019-03-18) ------------------- 1.14.5 (2019-03-04) ------------------- * fall back to default value if modules are not available (`#199 `_) * chmod -x on Python modules (`#183 `_) 1.14.4 (2018-05-01) ------------------- 1.14.3 (2018-01-30) ------------------- 1.14.2 (2017-10-26) ------------------- 1.14.1 (2017-07-27) ------------------- 1.14.0 (2017-02-22) ------------------- 1.13.6 (2017-10-31) ------------------- 1.13.5 (2017-02-14) ------------------- 1.13.4 (2016-09-19) ------------------- 1.13.3 (2016-09-16) ------------------- 1.13.2 (2016-09-02) ------------------- 1.13.1 (2016-03-13) ------------------- 1.13.0 (2016-03-10) ------------------- 1.12.6 (2016-03-10) ------------------- 1.12.5 (2015-10-13) ------------------- 1.12.4 (2015-10-12) ------------------- 1.12.3 (2015-09-19) ------------------- 1.12.2 (2015-04-27) ------------------- 1.12.1 (2015-04-16) ------------------- 1.12.0 (2014-12-26) ------------------- 1.11.6 (2014-12-22) ------------------- 1.11.5 (2014-08-18) ------------------- 1.11.4 (2014-07-23) ------------------- 1.11.3 (2014-07-18) ------------------- * fix Python 3 regression in rosmake (`#54 `_) 1.11.2 (2014-06-16) ------------------- 1.11.1 (2014-05-07) ------------------- * python 3 compatibility 1.11.0 (2014-01-31) ------------------- 1.10.9 (2014-01-07) ------------------- 1.10.8 (2013-10-15) ------------------- 1.10.7 (2013-10-04) ------------------- 1.10.6 (2013-08-22) ------------------- 1.10.5 (2013-08-21) ------------------- 1.10.4 (2013-07-05) ------------------- 1.10.3 (2013-07-03) ------------------- * check for CATKIN_ENABLE_TESTING to enable configure without tests 1.10.2 (2013-06-18) ------------------- 1.10.1 (2013-06-06) ------------------- 1.10.0 (2013-03-22 09:23) ------------------------- 1.9 (Groovy) ============ 1.9.44 (2013-03-13) ------------------- 1.9.43 (2013-03-08) ------------------- * use -jN -lN in rosmake (`#4 `_) * fix inconsistent format for ROS_PARALLEL_JOBS (`#4 `_) 1.9.42 (2013-01-25) ------------------- 1.9.41 (2013-01-24) ------------------- * fix rosmake for non-empty stacks (`#4068 `_) 1.9.40 (2013-01-13) ------------------- * update rosmake to output more specific compiler warnings (`#1903 `_) 1.9.39 (2012-12-30) ------------------- * first public release for Groovy ros-1.15.8/tools/rosmake/CMakeLists.txt000066400000000000000000000002761407615046500177670ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.0.2) project(rosmake) find_package(catkin REQUIRED) catkin_package() catkin_python_setup() if(CATKIN_ENABLE_TESTING) catkin_add_nosetests(test) endif() ros-1.15.8/tools/rosmake/package.xml000066400000000000000000000025361407615046500173450ustar00rootroot00000000000000 rosmake 1.15.8 rosmake is a ros dependency aware build tool which can be used to build all dependencies in the correct order. Michel Hidalgo Jacob Perron BSD http://wiki.ros.org/rosmake https://github.com/ros/ros/issues https://github.com/ros/ros Tully Foote Dirk Thomas catkin python-setuptools python3-setuptools catkin python-rospkg python3-rospkg ros-1.15.8/tools/rosmake/rosdoc.yaml000066400000000000000000000000231407615046500173720ustar00rootroot00000000000000 - builder: epydoc ros-1.15.8/tools/rosmake/scripts/000077500000000000000000000000001407615046500167115ustar00rootroot00000000000000ros-1.15.8/tools/rosmake/scripts/rosmake000077500000000000000000000051611407615046500203030ustar00rootroot00000000000000#! /usr/bin/env python # Copyright (c) 2009, Willow Garage, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # * Neither the name of Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # Author Tully Foote/tfoote@willowgarage.com from __future__ import print_function import subprocess import sys import threading import rosmake import rospkg # make sure that rospack is built, it is a requirement for rosmake def assert_rospack_built(): p = subprocess.Popen(['rospack', 'help'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) output = p.communicate() if p.returncode != 0: print('rospack not available.\nPlease install rospack before using rosmake and make sure it is available on your path. %s %s' % (output[0], output[1]), file=sys.stderr) sys.exit(1) result = 1 with rosmake.Printer(): rma = rosmake.RosMakeAll() try: if rma.main(): result = 0 except rospkg.ResourceNotFound as e: print('cannot find required resource: %s' % (str(e))) # make sure the thread is done rosmake.Printer().join() for t in threading.enumerate(): if t != threading.currentThread(): # Join all threads before exiting print('Cleaning up thread', t) t.join() sys.exit(result) ros-1.15.8/tools/rosmake/setup.py000066400000000000000000000003671407615046500167420ustar00rootroot00000000000000from setuptools import setup from catkin_pkg.python_setup import generate_distutils_setup d = generate_distutils_setup( packages=['rosmake'], package_dir={'': 'src'}, scripts=['scripts/rosmake'], requires=['rospkg'] ) setup(**d) ros-1.15.8/tools/rosmake/src/000077500000000000000000000000001407615046500160115ustar00rootroot00000000000000ros-1.15.8/tools/rosmake/src/rosmake/000077500000000000000000000000001407615046500174525ustar00rootroot00000000000000ros-1.15.8/tools/rosmake/src/rosmake/__init__.py000066400000000000000000000035501407615046500215660ustar00rootroot00000000000000# Copyright (c) 2009, Willow Garage, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # * Neither the name of the Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. """ Implements the 'rosmake' command-line tool via the L{RosMakeAll} class. This class is for internal-use only within ROS tools. The API is very likely to change in future releases and is not stable. """ from .engine import Printer # noqa: F401 from .engine import RosMakeAll # noqa: F401 __version__ = '1.7.0' ros-1.15.8/tools/rosmake/src/rosmake/engine.py000066400000000000000000001133461407615046500213010ustar00rootroot00000000000000#! /usr/bin/env python # Copyright (c) 2009, Willow Garage, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # * Neither the name of Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # Author Tully Foote/tfoote@willowgarage.com from __future__ import print_function import os import re import signal import subprocess import sys import threading import time import traceback from operator import itemgetter from optparse import OptionParser import rospkg from rospkg import ResourceNotFound try: from exceptions import SystemExit # Python 2.x except ImportError: pass # Python 3.x (in Python 3, 'exceptions' is always imported) from . import package_stats from . import parallel_build from .gcc_output_parse import Warnings # #3883 _popen_lock = threading.Lock() def make_command(): """ @return: name of 'make' command @rtype: str """ return os.environ.get('MAKE', 'make') # this is a copy of the roslogging utility. it's been moved here as it is a common # routine for programs using accessing ROS directories def makedirs_with_parent_perms(p): """ Create the directory using the permissions of the nearest (existing) parent directory. This is useful for logging, where a root process sometimes has to log in the user's space. @param p: directory to create @type p: str """ p = os.path.abspath(p) parent = os.path.dirname(p) # recurse upwards, checking to make sure we haven't reached the # top if not os.path.exists(p) and p and parent != p: makedirs_with_parent_perms(parent) s = os.stat(parent) os.mkdir(p) # if perms of new dir don't match, set anew s2 = os.stat(p) if s.st_uid != s2.st_uid or s.st_gid != s2.st_gid: os.chown(p, s.st_uid, s.st_gid) if s.st_mode != s2.st_mode: os.chmod(p, s.st_mode) class Printer: # storage for the instance reference __instance = None def __init__(self): """Create singleton instance.""" # Check whether we already have an instance if Printer.__instance is None: # Create and remember instance Printer.__instance = Printer.__impl() # Store instance reference as the only member in the handle self.__dict__['_Printer__instance'] = Printer.__instance def __getattr__(self, attr): """Delegate access to implementation.""" return getattr(self.__instance, attr) def __setattr__(self, attr, value): """Delegate access to implementation.""" return setattr(self.__instance, attr, value) def __enter__(self): """Pass through for the __enter__ function for the __instance""" return self.__instance.__enter__() def __exit__(self, mtype, value, tb): """Pass through for the __exit__ function for the __instance""" return self.__instance.__exit__(mtype, value, tb) class __impl(threading.Thread): def __init__(self): threading.Thread.__init__(self) self.build_queue = None self.condition = threading.Condition() self.running = True self.done = False self.status = '' self.verbose = False self.full_verbose = False self.duration = 1./10. self._last_status = None # Rosmake specific data self.cache_argument = None self.cache_right = '' self.pkg_start_times = {} def shutdown(self): self.running = False cycles = 10 for i in range(0, cycles): # sleep for at least 2 cycles of the status testing 'cycles' times if self.done: # print "SUCCESSFULLY SHUTDOWN" return True # print "Sleeping for %f FOR SHUTDOWN. %d threads running"%(max(self.duration/cycles*2, 0.01), threading.activeCount()) time.sleep(max(self.duration, 0.1)/cycles*2) raise Exception('Failed to shutdown status thread in %.2f seconds' % (self.duration * 2)) def __enter__(self): self.start() def __exit__(self, mtype, value, tb): self.shutdown() if value: if isinstance(mtype, SystemExit): traceback.print_exception(mtype, value, tb) else: sys.exit(value) def run(self): while self.running: # shutdown if duration set to zero if self.duration <= 0: self.running = False break self.set_status_from_cache() if len(self.pkg_start_times.keys()) > 0: n = self.terminal_width() - len(self.status) status = self.status if n > 0: status = ' '*n + self.status if status != self._last_status: self._print_status('%s' % status) self._last_status = status time.sleep(self.duration) self.done = True # print "STATUS THREAD FINISHED" def rosmake_cache_info(self, argument, start_times, right): self.cache_argument = argument self.pkg_start_times = start_times self.cache_right = right def rosmake_pkg_times_to_string(self, start_times): threads = [] for p, t in sorted(start_times.items(), key=itemgetter(1)): # py3k threads.append('[ %s: %.1f sec ]' % (p, time.time() - t)) return ' '.join(threads) def set_status_from_cache(self): if self.cache_argument: self.set_status('[ make %s ] ' % self.cache_argument + self.rosmake_pkg_times_to_string(self.pkg_start_times), self.cache_right) else: self.set_status('[ make ] ' + self.rosmake_pkg_times_to_string(self.pkg_start_times), self.cache_right) def set_status(self, left, right=''): header = '[ rosmake ] ' h = len(header) l = len(left) r = len(right) w = self.terminal_width() if l + r < w - h: padding = w - h - l - r self.status = header + left + ' ' * padding + right else: self.status = header + left[:(w - h - r - 4)] + '... ' + right def print_all(self, s, thread_name=None): if thread_name is None: str = '[ rosmake ] %s' % s else: str = '[rosmake-%s] %s' % (thread_name, s) sys.stdout.write(self.pad_str_to_width(str, self.terminal_width()) + '\n') sys.stdout.flush() def print_verbose(self, s, thread_name=None): if self.verbose or self.full_verbose: self.print_all(s, thread_name=thread_name) def print_full_verbose(self, s): if self.full_verbose: print('[ rosmake ] %s' % (s)) def print_tail(self, s, tail_lines=40): lines = s.splitlines() if self.full_verbose: tail_lines = len(lines) num_lines = min(len(lines), tail_lines) if num_lines == tail_lines: print('[ rosmake ] Last %d lines' % (num_lines)) else: print('[ rosmake ] All %d lines' % (num_lines)) print("{' + '-" * 79) for l in range(-num_lines, -1): print(' %s' % (lines[l])) print('-' * 79 + '}') def _print_status(self, s): sys.stdout.write('%s\r' % (s)) sys.stdout.flush() @staticmethod def terminal_width(): """Estimate the width of the terminal""" width = 0 try: import fcntl import struct import termios s = struct.pack('HHHH', 0, 0, 0, 0) x = fcntl.ioctl(1, termios.TIOCGWINSZ, s) width = struct.unpack('HHHH', x)[1] except ImportError: pass except IOError: pass if width <= 0: try: width = int(os.environ['COLUMNS']) except Exception: pass if width <= 0: width = 80 return width @staticmethod def pad_str_to_width(str, width): """Pad the string to be terminal width.""" length = len(str) excess = 0 if length < width: excess = width - length return str + ' ' * excess class RosMakeAll: def __init__(self): self._result_lock = threading.Lock() self.rospack = rospkg.RosPack() self.rosstack = rospkg.RosStack() self.printer = Printer() self.result = {} self.paths = {} self.dependency_tracker = parallel_build.DependencyTracker(rospack=self.rospack) self.flag_tracker = package_stats.PackageFlagTracker(self.dependency_tracker) self.output = {} self.profile = {} self.ros_parallel_jobs = 0 self.build_list = [] self.start_time = time.time() self.log_dir = '' self.logging_enabled = True def num_packages_built(self): """ @return: number of packages that were built @rtype: int """ return len(list(self.result[argument].keys())) # py3k def update_status(self, argument, start_times, right): self.printer.rosmake_cache_info(argument, start_times, right) def build_or_recurse(self, p): if p in self.build_list: return for d in self.dependency_tracker.get_deps_1(p): self.build_or_recurse(d) try: # append it ot the list only if present self.rospack.get_path(p) self.build_list.append(p) except rospkg.ResourceNotFound as ex: if not self.robust_build: self.printer.print_all('Exiting due to missing package: %s' % ex) sys.exit(-1) else: self.printer.print_all('!' * 20 + ' Package %s does not exist. %s' % (p, ex) + '!' * 20) def parallel_build_pkgs(self, build_queue, argument=None, threads=1): self.profile[argument] = {} self.output[argument] = {} with self._result_lock: if argument not in self.result.keys(): self.result[argument] = {} cts = [] for i in range(0, threads): ct = parallel_build.CompileThread(str(i), build_queue, self, argument) # print "TTTH starting thread ", ct ct.start() cts.append(ct) for ct in cts: try: # print "TTTT Joining", ct ct.join() # print "TTTH naturally ended thread", ct except KeyboardInterrupt: self.printer.print_all('TTTH Caught KeyboardInterrupt. Stopping build.') build_queue.stop() ct.join() except Exception: # catch all self.printer.print_all('TTTH OTHER exception thrown!!!!!!!!!!!!!!!!!!!!!') ct.join() # print "All threads joined" all_pkgs_passed = True with self._result_lock: for v in self.result[argument].values(): all_pkgs_passed = v and all_pkgs_passed build_passed = build_queue.succeeded() and all_pkgs_passed return build_passed # This function taken from # http://www.chiark.greenend.org.uk/ucgi/~cjwatson/blosxom/2009-07-02-python-sigpipe.html def _subprocess_setup(self): # Python installs a SIGPIPE handler by default. This is usually not # what non-Python subprocesses expect. signal.signal(signal.SIGPIPE, signal.SIG_DFL) def _build_package(self, package, argument=None): """ Lower-level routine for building a package. Handles execution of actual build command. @param package: package name @type package: str """ local_env = os.environ.copy() if self.ros_parallel_jobs > 0: local_env['ROS_PARALLEL_JOBS'] = '-j%d -l%d' % (self.ros_parallel_jobs, self.ros_parallel_jobs) elif 'ROS_PARALLEL_JOBS' not in os.environ: # if no environment setup and no args fall back to # cpus # num_cpus check can (on OS X) trigger a Popen(), which has # the multithreading bug we wish to avoid on Py2.7. with _popen_lock: num_cpus = parallel_build.num_cpus() local_env['ROS_PARALLEL_JOBS'] = '-j%d -l%d' % (num_cpus, num_cpus) local_env['SVN_CMDLINE'] = 'svn --non-interactive' cmd = ['bash', '-c', 'cd %s && %s ' % (self.rospack.get_path(package), make_command())] # UNIXONLY if argument: cmd[-1] += argument self.printer.print_full_verbose(cmd) # #3883: make sure only one Popen command occurs at a time due to # http://bugs.python.org/issue13817 with _popen_lock: command_line = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env=local_env, preexec_fn=self._subprocess_setup) (pstd_out, pstd_err) = command_line.communicate() # pstd_err should be None due to pipe above if not isinstance(pstd_out, str): pstd_out = pstd_out.decode() return (command_line.returncode, pstd_out) def build(self, p, argument=None, robust_build=False): """ Build package @param p: package name @type p: str """ return_string = '' try: # warn if ROS_BUILD_BLACKLIST encountered if applicable # do not build packages for which the build has failed if argument == 'test': # Tests are not build dependent failed_packages = [] else: with self._result_lock: failed_packages = [j for j in self.result[argument] if not self.result[argument][j] is True] (buildable, error, why) = self.flag_tracker.can_build(p, self.skip_blacklist, failed_packages) if buildable or self.robust_build: start_time = time.time() (returncode, pstd_out) = self._build_package(p, argument) self.profile[argument][p] = time.time() - start_time self.output[argument][p] = pstd_out if argument: log_type = 'build_%s' % argument else: log_type = 'build' if not returncode: self.printer.print_full_verbose(pstd_out) with self._result_lock: self.result[argument][p] = True warnings = Warnings(pstd_out) num_warnings = len(warnings.warning_lines) if num_warnings > 0: return_string = '[PASS] [ %.2f seconds ] [ %d warnings ' % (self.profile[argument][p], num_warnings) warning_dict = warnings.analyze() for warntype, warnlines in warning_dict.items(): if len(warnlines) > 0: return_string = return_string + '[ {0:d} {1} ] '.format(len(warnlines), warntype) return_string = return_string + ' ]' else: return_string = ('[PASS] [ %.2f seconds ]' % (self.profile[argument][p])) self.output_to_file(p, log_type, pstd_out, num_warnings > 0) else: success = False no_target = len(re.findall('No rule to make target', pstd_out)) > 0 interrupt = len(re.findall('Interrupt', pstd_out)) > 0 if no_target: return_string = ('[SKIP] No rule to make target %s' % (argument)) success = True elif interrupt: return_string = ('[Interrupted]') else: return_string = ('[FAIL] [ %.2f seconds ]' % (self.profile[argument][p])) with self._result_lock: self.result[argument][p] = True if no_target else False if success is False: # don't print tail if [SKIP] target self.printer.print_tail(pstd_out) self.output_to_file(p, log_type, pstd_out, always_print=not (no_target or interrupt)) return (success, return_string) else: with self._result_lock: self.result[argument][p] = error return_string += why return(error, return_string) return (True, return_string) # this means that we didn't error in any case above except rospkg.ResourceNotFound as ex: with self._result_lock: self.result[argument][p] = False self.printer.print_verbose('[SKIP] Package %s not found\n' % p) self.output[argument][p] = 'Package not found %s' % ex return (False, return_string) def output_to_file(self, package, log_type, stdout, always_print=False): if not self.logging_enabled: return package_log_dir = os.path.join(self.log_dir, package) std_out_filename = os.path.join(package_log_dir, log_type + '_output.log') if not os.path.exists(package_log_dir): makedirs_with_parent_perms(package_log_dir) with open(std_out_filename, 'w') as stdout_file: stdout_file.write(stdout) print_string = 'Output from build of package %s written to:\n[ rosmake ] %s' % (package, std_out_filename) if always_print: self.printer.print_all(print_string) else: self.printer.print_full_verbose(print_string) def generate_summary_output(self, log_dir): if not self.logging_enabled: return self.printer.print_all('Results:') if 'clean' in self.result.keys(): self.printer.print_all('Cleaned %d packages.' % len(self.result['clean'])) if None in self.result.keys(): build_failure_count = len([p for p in self.result[None].keys() if self.result[None][p] is False]) self.printer.print_all('Built %d packages with %d failures.' % (len(self.result[None]), build_failure_count)) if 'test' in self.result.keys(): test_failure_count = len([p for p in self.result['test'].keys() if self.result['test'][p] is False]) self.printer.print_all('Tested %d packages with %d failures.' % (len(self.result['test']), test_failure_count)) self.printer.print_all('Summary output to directory') self.printer.print_all('%s' % self.log_dir) if self.rejected_packages: 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) if None in self.result.keys(): if len(self.result[None].keys()) > 0: buildfail_filename = os.path.join(log_dir, 'buildfailures.txt') with open(buildfail_filename, 'w') as bf: bf.write('Build failures:\n') for key in self.build_list: if key in self.result[None].keys() and self.result[None][key] is False: bf.write('%s\n' % key) if None in self.output.keys(): buildfail_context_filename = os.path.join(log_dir, 'buildfailures-with-context.txt') with open(buildfail_context_filename, 'w') as bfwc: bfwc.write('Build failures with context:\n') for key in self.build_list: if key in self.result[None].keys() and self.result[None][key] is False: bfwc.write('---------------------\n') bfwc.write('%s\n' % key) if key in self.output[None]: bfwc.write(self.output[None][key]) if 'test' in self.result.keys(): if len(self.result['test'].keys()) > 0: testfail_filename = os.path.join(log_dir, 'testfailures.txt') with open(testfail_filename, 'w') as btwc: btwc.write('Test failures:\n') for key in self.build_list: if key in self.result['test'].keys() and self.result['test'][key] is False: btwc.write('%s\n' % key) if 'test' in self.output.keys(): testfail_filename = os.path.join(log_dir, 'testfailures-with-context.txt') with open(testfail_filename, 'w') as btwc: btwc.write('Test failures with context:\n') for key in self.build_list: if key in self.result['test'].keys() and self.result['test'][key] is False: btwc.write('%s\n' % key) if key in self.output['test']: btwc.write(self.output['test'][key]) profile_filename = os.path.join(log_dir, 'profile.txt') with open(profile_filename, 'w') as pf: pf.write(self.get_profile_string()) def get_profile_string(self): output = '--------------\nProfile\n--------------\n' total = 0.0 count = 1 for key in self.build_list: build_results = ['[Not Built ]', '[ Built ]', '[Build Fail]'] test_results = ['[Untested ]', '[Test Pass]', '[Test Fail]'] build_result = 0 test_result = 0 test_time = 0.0 build_time = 0.0 if None in self.result.keys(): if key in self.result[None].keys(): if self.result[None][key] is True: build_result = 1 else: build_result = 2 if 'test' in self.profile.keys(): if key in self.result['test'].keys(): if self.result['test'][key] is True: test_result = 1 else: test_result = 2 if None in self.profile.keys(): if key in self.profile[None].keys(): build_time = self.profile[None][key] if 'test' in self.profile.keys(): if key in self.profile['test'].keys(): test_time = self.profile['test'][key] 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) total = total + build_time count = count + 1 elapsed_time = self.finish_time - self.start_time output = output + '----------------\n' + '%.2f Cumulative, %.2f Elapsed, %.2f Speedup \n' % (total, elapsed_time, float(total) / float(elapsed_time)) return output def main(self): """ main command-line entrypoint """ parser = OptionParser(usage='usage: %prog [options] [PACKAGE]...', description='rosmake recursively builds all dependencies before building a package', prog='rosmake') parser.add_option('--test-only', dest='test_only', default=False, action='store_true', help='only run tests') parser.add_option('-t', dest='test', default=False, action='store_true', help='build and test packages') parser.add_option('-a', '--all', dest='build_all', default=False, action='store_true', help='select all packages') parser.add_option('-i', '--mark-installed', dest='mark_installed', default=False, action='store_true', help='On successful build, mark specified packages as installed with ROS_NOBUILD') parser.add_option('-u', '--unmark-installed', dest='unmark_installed', default=False, action='store_true', help='Remove ROS_NOBUILD from the specified packages. This will not build anything.') parser.add_option('-v', dest='verbose', default=False, action='store_true', help='display errored builds') parser.add_option('-r', '-k', '--robust', dest='best_effort', default=False, action='store_true', help='do not stop build on error') parser.add_option('--build-everything', dest='robust', default=False, action='store_true', help='build all packages regardless of errors') parser.add_option('-V', dest='full_verbose', default=False, action='store_true', help='display all builds') parser.add_option('-s', '--specified-only', dest='specified_only', default=False, action='store_true', help='only build packages specified on the command line') parser.add_option('--buildtest', dest='buildtest', action='append', help='package to buildtest') parser.add_option('--buildtest1', dest='buildtest1', action='append', help='package to buildtest1') parser.add_option('--output', dest='output_dir', action='store', help='where to output results') parser.add_option('--pre-clean', dest='pre_clean', action='store_true', help='run make clean first') parser.add_option('--bootstrap', dest='bootstrap', default=False, action='store_true', help='DEPRECATED, UNUSED') parser.add_option('--disable-logging', dest='logging_enabled', default=True, action='store_false', help='turn off all logs') parser.add_option('--target', dest='target', action='store', help='run make with this target') parser.add_option('--pjobs', dest='ros_parallel_jobs', type='int', action='store', help='Override ROS_PARALLEL_JOBS environment variable with this number of jobs.') parser.add_option('--threads', dest='threads', type='int', default=os.environ.get('ROSMAKE_THREADS', parallel_build.num_cpus()), action='store', help='Build up to N packages in parallel') parser.add_option('--profile', dest='print_profile', default=False, action='store_true', help='print time profile after build') parser.add_option('--skip-blacklist', dest='skip_blacklist', default=False, action='store_true', help='skip packages containing a file called ROS_BUILD_BLACKLIST (Default behavior will ignore the presence of ROS_BUILD_BLACKLIST)') parser.add_option('--skip-blacklist-osx', dest='skip_blacklist_osx', default=False, action='store_true', help='deprecated option. it will do nothing, please use platform declarations and --require-platform instead') parser.add_option('--status-rate', dest='status_update_rate', action='store', help='How fast to update the status bar in Hz. Default: 5Hz') options, args = parser.parse_args() self.printer.print_all('rosmake starting...') rospack = self.rospack rosstack = self.rosstack testing = False building = True if options.test_only: testing = True building = False elif options.test: testing = True if options.ros_parallel_jobs: self.ros_parallel_jobs = options.ros_parallel_jobs self.robust_build = options.robust self.best_effort = options.best_effort self.threads = options.threads self.skip_blacklist = options.skip_blacklist if options.skip_blacklist_osx: self.printer.print_all('Option --skip-blacklist-osx is deprecated. It will do nothing, please use platform declarations and --require-platform instead') self.logging_enabled = options.logging_enabled # pass through verbosity options self.printer.full_verbose = options.full_verbose self.printer.verbose = options.verbose if options.status_update_rate: if float(options.status_update_rate) > 0: self.printer.duration = 1.0/float(options.status_update_rate) else: self.printer.duration = 0 packages = [] # load packages from arguments if options.build_all: packages = [x for x in rospack.list() if not self.rospack.get_manifest(x).is_catkin] self.printer.print_all('Building all packages') else: # no need to extend if all already selected if options.buildtest: for p in options.buildtest: packages.extend(self.rospack.get_depends_on(p)) self.printer.print_all('buildtest requested for package %s adding it and all dependent packages: ' % p) if options.buildtest1: for p in options.buildtest1: packages.extend(self.rospack.get_depends_on(p, implicit=False)) self.printer.print_all('buildtest1 requested for package %s adding it and all depends-on1 packages: ' % p) if len(packages) == 0 and len(args) == 0: p = os.path.basename(os.path.abspath('.')) try: if os.path.samefile(rospack.get_path(p), '.'): packages = [p] self.printer.print_all('No package specified. Building %s' % packages) else: self.printer.print_all("No package selected and the current directory is not the correct path for package '%s'." % p) except rospkg.ResourceNotFound: try: stack_dir = rosstack.get_path(p) if os.path.samefile(stack_dir, '.'): packages = [p] self.printer.print_all('No package specified. Building stack %s' % packages) else: 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))) except Exception: self.printer.print_all("No package or stack specified. And current directory '%s' is not a package name or stack name." % p) else: packages.extend(args) self.printer.print_all('Packages requested are: %s' % packages) # Setup logging if self.logging_enabled: date_time_stamp = 'rosmake_output-' + time.strftime('%Y%m%d-%H%M%S') if options.output_dir: # self.log_dir = os.path.join(os.getcwd(), options.output_dir, date_time_stamp); self.log_dir = os.path.abspath(options.output_dir) else: self.log_dir = os.path.join(rospkg.get_ros_home(), 'rosmake', date_time_stamp) self.printer.print_all('Logging to directory %s' % self.log_dir) if os.path.exists(self.log_dir) and not os.path.isdir(self.log_dir): self.printer.print_all('Log destination %s is a file; please remove it or choose a new destination' % self.log_dir) sys.exit(1) if not os.path.exists(self.log_dir): self.printer.print_verbose("%s doesn't exist: creating" % self.log_dir) makedirs_with_parent_perms(self.log_dir) self.printer.print_verbose('Finished setting up logging') stacks_arguments = [s for s in packages if s in rosstack.list()] (self.specified_packages, self.rejected_packages) = rospkg.expand_to_packages(packages, rospack, rosstack) self.printer.print_all('Expanded args %s to:\n%s' % (packages, self.specified_packages)) if self.rejected_packages: self.printer.print_all('WARNING: The following args could not be parsed as stacks or packages: %s' % self.rejected_packages) if len(self.specified_packages) + len(stacks_arguments) == 0: self.printer.print_all('ERROR: No arguments could be parsed into valid package or stack names.') self.printer.running = False return False if options.unmark_installed: for p in self.specified_packages: if self.flag_tracker.remove_nobuild(p): self.printer.print_all('Removed ROS_NOBUILD from %s' % p) self.printer.running = False return True required_packages = self.specified_packages[:] # catch packages of dependent stacks when specified stack is zero-sized #3528 # add them to required list but not the specified list. for s in stacks_arguments: if not rosstack.packages_of(s): for d in rosstack.get_depends(s, implicit=False): try: required_packages.extend(rosstack.packages_of(d)) except ResourceNotFound: 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) # deduplicate required_packages required_packages = list(set(required_packages)) # make sure all dependencies are satisfied and if not warn buildable_packages = [] for p in required_packages: (buildable, error, str) = self.flag_tracker.can_build(p, self.skip_blacklist, [], False) if buildable: buildable_packages.append(p) # generate the list of packages necessary to build(in order of dependencies) counter = 0 for p in required_packages: counter = counter + 1 self.printer.print_verbose('Processing %s and all dependencies(%d of %d requested)' % (p, counter, len(packages))) self.build_or_recurse(p) # remove extra packages if specified-only flag is set if options.specified_only: new_list = [] for pkg in self.build_list: if pkg in self.specified_packages: new_list.append(pkg) self.dependency_tracker = parallel_build.DependencyTracker(self.specified_packages, rospack=self.rospack) # this will make the tracker only respond to packages in the list self.printer.print_all('specified-only option was used, only building packages %s' % new_list) self.build_list = new_list if options.pre_clean: build_queue = parallel_build.BuildQueue(self.build_list, parallel_build.DependencyTracker([], rospack=self.rospack), robust_build=True) self.parallel_build_pkgs(build_queue, 'clean', threads=options.threads) build_passed = True if building: self.printer.print_verbose('Building packages %s' % self.build_list) build_queue = parallel_build.BuildQueue(self.build_list, self.dependency_tracker, robust_build=options.robust or options.best_effort) if None not in self.result.keys(): self.result[None] = {} build_passed = self.parallel_build_pkgs(build_queue, options.target, threads=options.threads) tests_passed = True if build_passed and testing: self.printer.print_verbose('Testing packages %s' % packages) build_queue = parallel_build.BuildQueue(self.specified_packages, parallel_build.DependencyTracker(self.specified_packages, rospack=self.rospack), robust_build=True) tests_passed = self.parallel_build_pkgs(build_queue, 'test', threads=1) if options.mark_installed: if build_passed and tests_passed: for p in self.specified_packages: if self.flag_tracker.add_nobuild(p): self.printer.print_all('Marking %s as installed with a ROS_NOBUILD file' % p) else: self.printer.print_all('All builds and tests did not pass cannot mark packages as installed.') self.finish_time = time.time() # note: before profiling self.generate_summary_output(self.log_dir) if options.print_profile: self.printer.print_all(self.get_profile_string()) self.printer.running = False return build_passed and tests_passed ros-1.15.8/tools/rosmake/src/rosmake/gcc_output_parse.py000066400000000000000000000025211407615046500233720ustar00rootroot00000000000000#! /usr/bin/env python import re class Warnings: """Extract warnings from GCC's output Analyzes compiler output and classifies warnings. """ _warning_pattern_map = { 'antiquated': ' antiquated', 'deprecated': ' deprecated', 'unused_func': ' defined but not used', 'isoc': ' ISO C', 'missing_init': ' missing initializer', 'out_of_bounds': ' subscript .*? bounds', 'unused_var': ' unused variable' } def __init__(self, console_output): self.warning_lines = [x for x in console_output.splitlines() if x.find(' warning:') > 0] def byType(self, warntype): """Extract warning messages corresponding to warntype. The warntypes can be all keys of the _warning_pattern_map dictionary. @param warntype: The type of warning message that should be extracted. @type warntype: str @return a list of warning messages @rtype list """ return [x for x in self.warning_lines if re.search(self._warning_pattern_map[warntype], x)] def analyze(self): """Get dictionary of classified warnings. @return A dictionary of lists of warning messages indexed by the warning type @rtype {str:[str]} """ return {(t, self.byType(t)) for t, p in self._warning_pattern_map.items()} ros-1.15.8/tools/rosmake/src/rosmake/package_stats.py000066400000000000000000000207431407615046500226430ustar00rootroot00000000000000#! /usr/bin/env python # Copyright (c) 2009, Willow Garage, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # * Neither the name of Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # Author Tully Foote/tfoote@willowgarage.com import os import sys import rospkg import rospkg.os_detect def _platform_supported(m, os, version): for p in m.platforms: if os == p.os and version == p.version: return True return False def platform_supported(rospack, pkg, os, version): """ Return whether the platform defined by os and version is marked as supported in the package @param pkg The package to test for support @param os The os name to test for support @param version The os version to test for support """ return _platform_supported(rospack.get_manifest(pkg), os, version) class PackageFlagTracker: """This will use the dependency tracker to test if packages are blacklisted and all their dependents.""" def __init__(self, dependency_tracker, os_name=None, os_version=None): if not os_name and not os_version: try: osd = rospkg.os_detect.OsDetect() self.os_name = osd.get_codename() self.os_version = osd.get_version() except rospkg.os_detect.OsNotDetected: sys.stderr.write('Could not detect OS. platform detection will not work\n') else: self.os_name = os_name self.os_version = os_version self.rospack = rospkg.RosPack() self.blacklisted = {} self.blacklisted_osx = {} self.nobuild = set() self.nomakefile = set() self.packages_tested = set() self.dependency_tracker = dependency_tracker self.build_failed = set() def register_blacklisted(self, blacklisted_package, dependent_package): if dependent_package in self.blacklisted.keys(): self.blacklisted[dependent_package].append(blacklisted_package) else: self.blacklisted[dependent_package] = [blacklisted_package] def register_blacklisted_osx(self, blacklisted_package, dependent_package): if dependent_package in self.blacklisted_osx: self.blacklisted_osx[dependent_package].append(blacklisted_package) else: self.blacklisted_osx[dependent_package] = [blacklisted_package] def _check_package_flags(self, package): if package in self.packages_tested: return rospack = self.rospack path = rospack.get_path(package) if os.path.exists(os.path.join(path, 'ROS_BUILD_BLACKLIST')): self.register_blacklisted(package, package) for p in rospack.get_depends_on(package, implicit=True): self.register_blacklisted(package, p) if os.path.exists(os.path.join(path, 'ROS_BUILD_BLACKLIST_OSX')): self.register_blacklisted_osx(package, package) for p in rospack.get_depends_on(package, implicit=True): self.register_blacklisted_osx(package, p) # NO_BUILD if marker file or catkin attribute in manifest if os.path.exists(os.path.join(path, 'ROS_NOBUILD')): self.nobuild.add(package) if self.rospack.get_manifest(package).is_catkin: self.nobuild.add(package) if not os.path.exists(os.path.join(path, 'Makefile')): self.nomakefile.add(package) self.packages_tested.add(package) def is_blacklisted(self, package): # this will noop if already run self._check_package_flags(package) # make sure it's not dependent on a blacklisted package for p in self.dependency_tracker.get_deps(package): if p not in self.packages_tested: self._check_package_flags(p) # test result after checking all dependents. if package in self.blacklisted: return self.blacklisted[package] return [] def is_blacklisted_osx(self, package): # this will noop if already run self._check_package_flags(package) # make sure it's not dependent on a blacklisted_osx package for p in self.dependency_tracker.get_deps(package): if p not in self.packages_tested: self._check_package_flags(p) # test result after checking all dependents. if package in self.blacklisted_osx: return self.blacklisted_osx[package] return [] def has_nobuild(self, package): # this will noop if already run self._check_package_flags(package) # Short circuit if known result if package in self.nobuild: return True return False def has_makefile(self, package): # this will noop if already run self._check_package_flags(package) # Short circuit if known result if package in self.nomakefile: return False return True def add_nobuild(self, package): if self.has_nobuild(package): return True with open(os.path.join(self.rospack.get_path(package), 'ROS_NOBUILD'), 'w') as f: f.write('created by rosmake to mark as installed') self.nobuild.add(package) return True return False def remove_nobuild(self, package): if not self.has_nobuild(package): return True try: os.remove(os.path.join(self.rospack.get_path(package), 'ROS_NOBUILD')) self.nobuild.remove(package) return True except Exception: return False def mark_build_failed(self, package): self.build_failed.add(package) def build_failed(self, package): return package in self.build_failed def can_build(self, pkg, use_blacklist=False, failed_packages=[], use_makefile=True): """ Return (buildable, error, "reason why not") """ output_str = '' output_state = True buildable = True previously_failed_pkgs = [pk for pk in failed_packages if pk in self.dependency_tracker.get_deps(pkg)] if len(previously_failed_pkgs) > 0: buildable = False output_state = False output_str += ' Package %s cannot be built for dependent package(s) %s failed. \n' % (pkg, previously_failed_pkgs) if use_blacklist: black_listed_dependents = self.is_blacklisted(pkg) if len(black_listed_dependents) > 0: buildable = False output_str += 'Cannot build %s ROS_BUILD_BLACKLIST found in packages %s' % (pkg, black_listed_dependents) if self.has_nobuild(pkg): buildable = False output_state = True # dependents are ok, it should already be built output_str += 'ROS_NOBUILD in package %s\n' % pkg if use_makefile and not self.has_makefile(pkg): output_state = True # dependents are ok no need to build buildable = False output_str += ' No Makefile in package %s\n' % pkg if output_str and output_str[-1] == '\n': output_str = output_str[:-1] return (buildable, output_state, output_str) ros-1.15.8/tools/rosmake/src/rosmake/parallel_build.py000066400000000000000000000276241407615046500230120ustar00rootroot00000000000000#! /usr/bin/env python # Copyright (c) 2009, Willow Garage, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # * Neither the name of Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # Author Tully Foote/tfoote@willowgarage.com import os import subprocess import sys import threading import time import rospkg if sys.hexversion > 0x03000000: # Python3 python3 = True else: python3 = False def _read_stdout(cmd): p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) std_out, std_err = p.communicate() if python3: return std_out.decode() else: return std_out def num_cpus(): """ Detects the number of CPUs on a system. Cribbed from pp. """ # Linux, Unix and MacOS: if hasattr(os, 'sysconf'): if 'SC_NPROCESSORS_ONLN' in os.sysconf_names: # Linux & Unix: ncpus = os.sysconf('SC_NPROCESSORS_ONLN') if isinstance(ncpus, int) and ncpus > 0: return ncpus else: # OSX: return int(_read_stdout(['sysctl', '-n', 'hw.ncpu'])) or 1 # Windows: if 'NUMBER_OF_PROCESSORS' in os.environ: ncpus = int(os.environ['NUMBER_OF_PROCESSORS']) if ncpus > 0: return ncpus return 1 # Default # TODO: may no longer need this now that we've ported to rospkg class DependencyTracker: """Track dependencies between packages. This is basically a caching way to call rospkg. It also will allow you to specify a range of packages over which to track dependencies. This is useful if you are only building a subset of the tree. For example with the --specified-only option.""" def __init__(self, valid_packages=None, rospack=None): """ @param valid_packages: defaults to rospack list """ if rospack is None: self.rospack = rospkg.RosPack() else: self.rospack = rospack if valid_packages is None: valid_packages = self.rospack.list() self.valid_packages = valid_packages self.deps_1 = {} self.deps = {} def get_deps_1(self, package): if package not in self.deps_1: self.deps_1[package] = [] try: potential_dependencies = self.rospack.get_depends(package, implicit=False) except rospkg.ResourceNotFound: potential_dependencies = [] for p in potential_dependencies: if p in self.valid_packages: self.deps_1[package].append(p) return self.deps_1[package] def get_deps(self, package): if package not in self.deps: self.deps[package] = [] try: potential_dependencies = self.rospack.get_depends(package) except rospkg.ResourceNotFound: potential_dependencies = [] for p in potential_dependencies: if p in self.valid_packages: self.deps[package].append(p) return self.deps[package] def load_fake_deps(self, deps, deps1): self.deps = deps self.deps_1 = deps1 return class CompileThread(threading.Thread): """This is the class which is used as the thread for parallel builds. This class will query the build queue object for new commands and block on its calls until the build queue says that building is done.""" def __init__(self, name, build_queue, rosmakeall, argument=None): threading.Thread.__init__(self) self.build_queue = build_queue self.rosmakeall = rosmakeall self.argument = argument self.name = name self.logging_enabled = True def run(self): while not self.build_queue.is_done(): pkg = self.build_queue.get_valid_package() if not pkg: if self.build_queue.succeeded(): self.rosmakeall.printer.print_verbose('[ Build Completed Thread Exiting ]', thread_name=self.name) else: self.rosmakeall.printer.print_verbose('[ Build Terminated Thread Exiting ]', thread_name=self.name) break # no more packages must be done # update status after accepting build self.rosmakeall.update_status(self.argument, self.build_queue.get_started_threads(), self.build_queue.progress_str()) if self.argument: self.rosmakeall.printer.print_all('Starting >>> %s [ make %s ]' % (pkg, self.argument), thread_name=self.name) else: self.rosmakeall.printer.print_all('Starting >>> %s [ make ] ' % pkg, thread_name=self.name) (result, result_string) = self.rosmakeall.build(pkg, self.argument, self.build_queue.robust_build) self.rosmakeall.printer.print_all('Finished <<< %s %s' % (pkg, result_string), thread_name=self.name) # print "Finished2" self.build_queue.return_built(pkg, result) # print "returned" if result or self.build_queue.robust_build: pass # print "result", result, "robust", self.build_queue.robust_build else: if result_string.find('[Interrupted]') != -1: self.rosmakeall.printer.print_all('Caught Interruption', thread_name=self.name) self.build_queue.stop() # todo move this logic into BuildQueue itself break # unnecessary since build_queue is done now while will quit self.rosmakeall.printer.print_all('Halting due to failure in package %s. \n[ rosmake ] Waiting for other threads to complete.' % pkg) self.build_queue.stop() break # unnecessary since build_queue is done now, while will quit # update status after at end of build # print "updating status" self.rosmakeall.update_status(self.argument, self.build_queue.get_started_threads(), self.build_queue.progress_str()) # print "done built", len(self.build_queue.built), self.build_queue.built # print "failed", len(self.build_queue.failed), self.build_queue.failed # print "to_build", len(self.build_queue.to_build), self.build_queue.to_build # print "in progress", len(self.build_queue._started), self.build_queue._started # print "last update" # update status before ending thread self.rosmakeall.update_status(self.argument, self.build_queue.get_started_threads(), self.build_queue.progress_str()) # print "thread finished" class BuildQueue: """This class provides a thread safe build queue. Which will do the sequencing for many CompileThreads.""" def __init__(self, package_list, dependency_tracker, robust_build=False): self._total_pkgs = len(package_list) self.dependency_tracker = dependency_tracker self.to_build = package_list[:] # do a copy not a reference self.built = [] self.failed = [] self.condition = threading.Condition() self._done = False self.robust_build = robust_build self._started = {} self._hack_end_counter = 0 def progress_str(self): return '[ %d Active %d/%d Complete ]' % (len(self._started), len(self.built), self._total_pkgs) def get_started_threads(self): # TODO sort this other than hash order return self._started.copy() def is_completed(self): """Return if the build queue has been completed.""" return len(self.built) + len(self.failed) == self._total_pkgs def is_done(self): """Return if the build queue has been completed.""" return self.is_completed() or self._done # finished or halted def succeeded(self): """Return whether the build queue has completed all packages successfully.""" return len(self.built) == self._total_pkgs # flag that we're finished def stop(self): """Stop the build queue, including waking all blocking threads. It will not stop in flight builds.""" self._done = True with self.condition: self.condition.notifyAll() # wake any blocking threads def return_built(self, package, successful=True): # mark that a package is built """The thread which completes a package marks it as done with this method.""" with self.condition: if successful: self.built.append(package) else: self.failed.append(package) if package in self._started.keys(): self._started.pop(package) else: pass # used early on print "\n\n\nERROR THIS SHOULDN't RETURN %s\n\n\n"%package if self.is_completed(): self._done = True self.condition.notifyAll() # wake up any waiting threads def get_valid_package(self): # blocking call to get a package to build returns none if done """This is a blocking call which will return a package which has all dependencies met. If interrupted or done it will return None""" with self.condition: while (not self.is_done() and len(self.to_build) > 0): for p in self.to_build: dependencies_met = True for d in self.dependency_tracker.get_deps(p): if d not in self.built and not (self.robust_build and d in self.failed): dependencies_met = False # print "Dependency %s not met for %s"%(d, p) break if dependencies_met: # all dependencies met self.to_build.remove(p) self._started[p] = time.time() self._hack_end_counter = 0 # reset end counter if success return p # break out and return package if found elif len(self._started) == 0 and self._hack_end_counter > 2: # we're hung with broken dependencies return None # print "TTGTTTTHTHT Waiting on condition" self.condition.wait(1.0) # failed to find a package wait for a notify before looping self._hack_end_counter += 1 # if we're here too often we will quit if self.is_done(): break return None ros-1.15.8/tools/rosmake/test/000077500000000000000000000000001407615046500162015ustar00rootroot00000000000000ros-1.15.8/tools/rosmake/test/__init__.py000066400000000000000000000000001407615046500203000ustar00rootroot00000000000000ros-1.15.8/tools/rosmake/test/test_parallel_build.py000066400000000000000000000206101407615046500225640ustar00rootroot00000000000000#!/usr/bin/env python # Copyright (c) 2009, Willow Garage, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # * Neither the name of the Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. import unittest from rosmake import parallel_build class TestDependencyTracker(unittest.TestCase): def setUp(self): self.deps = {} self.deps1 = {} self.deps['a'] = ['b', 'c', 'd', 'e'] self.deps1['a'] = ['b'] self.deps['b'] = ['c'] self.deps1['b'] = ['c'] self.deps['d'] = ['c', 'e'] self.deps1['d'] = ['c', 'e'] self.dt = parallel_build.DependencyTracker() self.dt.load_fake_deps(self.deps, self.deps1) def test_deps_1(self): self.assertEquals(self.deps1['a'], self.dt.get_deps_1('a')) self.assertEquals(self.deps1['b'], self.dt.get_deps_1('b')) self.assertEquals(self.deps1['d'], self.dt.get_deps_1('d')) def test_deps(self): self.assertEquals(self.deps['a'], self.dt.get_deps('a')) self.assertEquals(self.deps['b'], self.dt.get_deps('b')) self.assertEquals(self.deps['d'], self.dt.get_deps('d')) def test_not_package(self): self.assertEquals([], self.dt.get_deps('This is not a valid package name')) self.assertEquals([], self.dt.get_deps_1('This is not a valid package name')) class TestBuildQueue(unittest.TestCase): def setUp(self): deps = {} deps1 = {} deps1['a'] = ['b'] deps['a'] = ['b', 'c', 'd', 'e', 'f'] deps1['b'] = ['c'] deps['b'] = ['c', 'd', 'e', 'f'] deps1['c'] = ['d'] deps['c'] = ['d', 'e', 'f'] deps1['d'] = ['e'] deps['d'] = ['e', 'f'] deps['e'] = ['f'] deps1['e'] = ['f'] deps['f'] = [] deps1['f'] = [] self.serial_tracker = parallel_build.DependencyTracker() self.serial_tracker.load_fake_deps(deps, deps1) deps = {} deps1 = {} deps['a'] = ['b', 'c', 'd', 'e', 'f'] deps1['a'] = ['b', 'c', 'd', 'e', 'f'] deps['b'] = [] deps1['b'] = [] deps['c'] = [] deps1['c'] = [] deps['d'] = [] deps1['d'] = [] deps['e'] = [] deps1['e'] = [] deps['f'] = [] deps1['f'] = [] self.parallel_tracker = parallel_build.DependencyTracker() self.parallel_tracker.load_fake_deps(deps, deps1) # full queue def test_full_build(self): bq = parallel_build.BuildQueue(['a', 'b', 'c', 'd', 'e', 'f'], self.serial_tracker) self.assertFalse(bq.is_done()) self.assertFalse(bq.succeeded()) self.assertEqual('f', bq.get_valid_package()) self.assertEqual(0, len(bq.built)) bq.return_built('f') self.assertEqual(1, len(bq.built)) self.assertFalse(bq.is_done()) self.assertFalse(bq.succeeded()) self.assertEqual('e', bq.get_valid_package()) bq.return_built('e') self.assertEqual(2, len(bq.built)) self.assertFalse(bq.is_done()) self.assertFalse(bq.succeeded()) self.assertEqual('d', bq.get_valid_package()) bq.return_built('d') self.assertEqual(3, len(bq.built)) self.assertFalse(bq.is_done()) self.assertFalse(bq.succeeded()) self.assertEqual('c', bq.get_valid_package()) bq.return_built('c') self.assertEqual(4, len(bq.built)) self.assertFalse(bq.is_done()) self.assertFalse(bq.succeeded()) self.assertEqual('b', bq.get_valid_package()) bq.return_built('b') self.assertEqual(5, len(bq.built)) self.assertFalse(bq.is_done()) self.assertFalse(bq.succeeded()) self.assertEqual('a', bq.get_valid_package()) self.assertFalse(bq.is_done()) self.assertFalse(bq.succeeded()) bq.return_built('a') self.assertEqual(6, len(bq.built)) self.assertTrue(bq.is_done()) self.assertTrue(bq.succeeded()) # partial build def test_partial_build(self): bq = parallel_build.BuildQueue(['d', 'e', 'f'], self.serial_tracker) self.assertFalse(bq.is_done()) self.assertFalse(bq.succeeded()) self.assertEqual('f', bq.get_valid_package()) self.assertEqual(0, len(bq.built)) bq.return_built('f') self.assertEqual(1, len(bq.built)) self.assertFalse(bq.is_done()) self.assertFalse(bq.succeeded()) self.assertEqual('e', bq.get_valid_package()) bq.return_built('e') self.assertEqual(2, len(bq.built)) self.assertFalse(bq.is_done()) self.assertFalse(bq.succeeded()) self.assertEqual('d', bq.get_valid_package()) self.assertFalse(bq.is_done()) self.assertFalse(bq.succeeded()) bq.return_built('d') self.assertEqual(3, len(bq.built)) self.assertTrue(bq.is_done()) self.assertTrue(bq.succeeded()) # abort early def test_abort_early(self): bq = parallel_build.BuildQueue(['a', 'b', 'c', 'd', 'e', 'f'], self.serial_tracker) self.assertFalse(bq.is_done()) self.assertFalse(bq.succeeded()) self.assertEqual(0, len(bq.built)) self.assertEqual('f', bq.get_valid_package()) bq.return_built('f') self.assertEqual(1, len(bq.built)) self.assertFalse(bq.is_done()) self.assertFalse(bq.succeeded()) self.assertEqual('e', bq.get_valid_package()) bq.return_built('e') self.assertEqual(2, len(bq.built)) self.assertFalse(bq.is_done()) self.assertFalse(bq.succeeded()) self.assertEqual('d', bq.get_valid_package()) bq.return_built('d') self.assertEqual(3, len(bq.built)) self.assertFalse(bq.is_done()) self.assertFalse(bq.succeeded()) bq.stop() self.assertTrue(bq.is_done()) self.assertFalse(bq.succeeded()) self.assertEqual(None, bq.get_valid_package()) # many parallel def test_parallel_build(self): bq = parallel_build.BuildQueue(['a', 'b', 'c', 'd', 'e', 'f'], self.parallel_tracker) self.assertFalse(bq.is_done()) self.assertFalse(bq.succeeded()) dependents = ['b', 'c', 'd', 'e', 'f'] count = 0 total = 6 while len(dependents) > 0: result = bq.get_valid_package() done = len(bq.built) pkgs = bq._total_pkgs self.assertTrue(result in dependents) # print result, done, pkgs dependents.remove(result) self.assertEqual(count, done) self.assertEqual(total, pkgs) self.assertFalse(bq.is_done()) self.assertFalse(bq.succeeded()) bq.return_built(result) count = count + 1 self.assertFalse(bq.is_done()) self.assertFalse(bq.succeeded()) self.assertEqual('a', bq.get_valid_package()) self.assertFalse(bq.is_done()) self.assertFalse(bq.succeeded()) bq.return_built('a') self.assertTrue(bq.is_done()) self.assertTrue(bq.succeeded()) # stalled(future) ros-1.15.8/tools/rosmake/test/test_rosmake_commandline.py000066400000000000000000000032621407615046500236240ustar00rootroot00000000000000# Software License Agreement (BSD License) # # Copyright (c) 2009, Willow Garage, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following # disclaimer in the documentation and/or other materials provided # with the distribution. # * Neither the name of Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. import subprocess def test_Rosmake_commandline_usage(): assert 0 == subprocess.call(['rosmake', '-h']) ros-1.15.8/tools/rosunit/000077500000000000000000000000001407615046500152645ustar00rootroot00000000000000ros-1.15.8/tools/rosunit/CHANGELOG.rst000066400000000000000000000136201407615046500173070ustar00rootroot00000000000000^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Changelog for package rosunit ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 1.15.8 (2021-07-21) ------------------- * Gracefully handle missing time attribute in testcase XML element (`#283 `_) * Fix spelling (`#277 `_) * Update maintainers (`#272 `_) * Contributors: Jacob Perron, Romain Reignier, freddii 1.15.7 (2020-09-28) ------------------- 1.15.6 (2020-07-20) ------------------- 1.15.5 (2020-07-06) ------------------- 1.15.4 (2020-05-28) ------------------- 1.15.3 (2020-05-14) ------------------- 1.15.2 (2020-04-07) ------------------- 1.15.1 (2020-03-17) ------------------- * fix missing rosunit results in Python 3 (`#244 `_) 1.15.0 (2020-02-11) ------------------- 1.14.8 (2020-02-11) ------------------- * fix various issues discovered by flake8 (`#241 `_) * update style to pass flake8 (`#240 `_) * Use setuptools instead of distutils (`#235 `_) * Bump CMake version to avoid CMP0048 warning (`#234 `_) 1.14.7 (2019-10-03) ------------------- * use condition attributes to specify Python 2 and 3 dependencies (`#226 `_) * Python 3 support (`#212 `_) 1.14.6 (2019-03-18) ------------------- 1.14.5 (2019-03-04) ------------------- * add Python executable to ROSUNIT_EXE so it runs correctly on Windows (`#200 `_) * rosunit Python 3 support (`#190 `_) 1.14.4 (2018-05-01) ------------------- 1.14.3 (2018-01-30) ------------------- 1.14.2 (2017-10-26) ------------------- * use python constants rather than hardcoded integers for error codes (`#153 `_) 1.14.1 (2017-07-27) ------------------- * fix syntax of unicode raw string in Python 3 (`#150 `_) * ensure cwd exists (`#143 `_) * more searchable testcase result message (`#139 `_) 1.14.0 (2017-02-22) ------------------- 1.13.6 (2017-10-31) ------------------- * use python constants rather than hardcoded integers for error codes (`#153 `_) * fix syntax of unicode raw string in Python 3 (`#150 `_) * ensure cwd exists (`#143 `_) * more searchable testcase result message (`#139 `_) 1.13.5 (2017-02-14) ------------------- * improve error message when creating test directory fails (`#134 `_) * fix race condition creating folder (`#130 `_) 1.13.4 (2016-09-19) ------------------- * fix test type handling (`#123 `_) 1.13.3 (2016-09-16) ------------------- * allow custom class_name, testcase_name in test_xx_junit_xml (`#119 `_) * fix check of test type (`#121 `_) 1.13.2 (2016-09-02) ------------------- 1.13.1 (2016-03-13) ------------------- * fix a regression in XML reports introduced in 1.12.6 (`#109 `_) 1.13.0 (2016-03-10) ------------------- 1.12.6 (2016-03-10) ------------------- * remove invalid characters from XML unit test results (`#89 `_, `#108 `_) * add ability to load tests using dotnames in rosunit (`#101 `_) 1.12.5 (2015-10-13) ------------------- 1.12.4 (2015-10-12) ------------------- 1.12.3 (2015-09-19) ------------------- 1.12.2 (2015-04-27) ------------------- * allow custom environment when determining test results location (`#82 `_) 1.12.1 (2015-04-16) ------------------- 1.12.0 (2014-12-26) ------------------- 1.11.6 (2014-12-22) ------------------- * fix OSError handling (`#69 `_, regression since 1.11.1) 1.11.5 (2014-08-18) ------------------- 1.11.4 (2014-07-23) ------------------- 1.11.3 (2014-07-18) ------------------- 1.11.2 (2014-06-16) ------------------- 1.11.1 (2014-05-07) ------------------- * use catkin_install_python() to install Python scripts (`#46 `_) * python 3 compatibility 1.11.0 (2014-01-31) ------------------- 1.10.9 (2014-01-07) ------------------- * python 3 compatibility * fix repo urls in manifest 1.10.8 (2013-10-15) ------------------- 1.10.7 (2013-10-04) ------------------- * fix sanitizing rosunit xml files on the lowest level possible 1.10.6 (2013-08-22) ------------------- 1.10.5 (2013-08-21) ------------------- * make rosunit relocatable (`ros/catkin#490 `_) 1.10.4 (2013-07-05) ------------------- 1.10.3 (2013-07-03) ------------------- * check for CATKIN_ENABLE_TESTING to enable configure without tests 1.10.2 (2013-06-18) ------------------- 1.10.1 (2013-06-06) ------------------- * make rosunit use print function for Python 2 and 3 compatibility (`#11 `_) * remove unnecessary usage of unicode strings (`#12 `_) 1.10.0 (2013-03-22 09:23) ------------------------- 1.9 (Groovy) ============ 1.9.44 (2013-03-13) ------------------- 1.9.43 (2013-03-08) ------------------- * fix handling spaces in folder names (`ros/catkin#375 `_) 1.9.42 (2013-01-25) ------------------- 1.9.41 (2013-01-24) ------------------- 1.9.40 (2013-01-13) ------------------- 1.9.39 (2012-12-30) ------------------- * first public release for Groovy ros-1.15.8/tools/rosunit/CMakeLists.txt000066400000000000000000000007251407615046500200300ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.0.2) project(rosunit) find_package(catkin REQUIRED) catkin_package(CFG_EXTRAS ${PROJECT_NAME}-extras.cmake) catkin_python_setup() catkin_install_python(PROGRAMS scripts/check_test_ran.py scripts/clean_junit_xml.py scripts/pycoverage_to_html.py scripts/summarize_results.py scripts/test_results_dir.py DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}/scripts) if(CATKIN_ENABLE_TESTING) catkin_add_nosetests(test) endif() ros-1.15.8/tools/rosunit/cmake/000077500000000000000000000000001407615046500163445ustar00rootroot00000000000000ros-1.15.8/tools/rosunit/cmake/rosunit-extras.cmake.em000066400000000000000000000036401407615046500227600ustar00rootroot00000000000000include(CMakeParseArguments) macro(rosunit_initialize_tests) @[if DEVELSPACE]@ # binary and script in develspace set(ROSUNIT_SCRIPTS_DIR "@(CMAKE_CURRENT_SOURCE_DIR)/scripts") set(ROSUNIT_EXE "${PYTHON_EXECUTABLE} ${ROSUNIT_SCRIPTS_DIR}/rosunit") @[else]@ # binary and script in installspace set(ROSUNIT_SCRIPTS_DIR "${rosunit_DIR}/../scripts") set(ROSUNIT_EXE "${PYTHON_EXECUTABLE} ${rosunit_DIR}/../../../@(CATKIN_GLOBAL_BIN_DESTINATION)/rosunit") @[end if]@ endmacro() rosunit_initialize_tests() function(add_pyunit file) message(WARNING "add_pyunit() is deprecated. For Python tests, use catkin_add_nosetests() instead.") # Look for optional TIMEOUT argument, #2645 cmake_parse_arguments(_pyunit "" "TIMEOUT;WORKING_DIRECTORY" "" ${ARGN}) if(NOT _pyunit_TIMEOUT) set(_pyunit_TIMEOUT 60.0) endif() # Check that the file exists, #1621 set(_file_name _file_name-NOTFOUND) if(IS_ABSOLUTE ${file}) set(_file_name ${file}) else() find_file(_file_name ${file} PATHS ${CMAKE_CURRENT_SOURCE_DIR} NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH) # for cross-compilation. thanks jeremy. if(NOT _file_name) message(FATAL_ERROR "Can't find pyunit file \"${file}\"") endif() endif() # We look for ROS_TEST_COVERAGE=1 # to indicate that coverage reports are being requested. if("$ENV{ROS_TEST_COVERAGE}" STREQUAL "1") set(_covarg "--cov") else() set(_covarg) endif() # Create a legal test name, in case the target name has slashes in it string(REPLACE "/" "_" _testname ${file}) # We use rostest to call the executable to get process control, #1629 set(cmd "${ROSUNIT_EXE} --name=${_testname} --time-limit=${_pyunit_TIMEOUT} --package=${PROJECT_NAME} -- ${_file_name} ${_covarg}") catkin_run_tests_target("rosunit" ${_testname} "rosunit-${_testname}.xml" COMMAND ${cmd} WORKING_DIRECTORY ${_pyunit_WORKING_DIRECTORY}) endfunction() ros-1.15.8/tools/rosunit/package.xml000066400000000000000000000025241407615046500174040ustar00rootroot00000000000000 rosunit 1.15.8 Unit-testing package for ROS. This is a lower-level library for rostest and handles unit tests, whereas rostest handles integration tests. Michel Hidalgo Jacob Perron BSD http://wiki.ros.org/rosunit https://github.com/ros/ros/issues https://github.com/ros/ros Ken Conley Dirk Thomas catkin python-setuptools python3-setuptools python-rospkg python3-rospkg roslib ros-1.15.8/tools/rosunit/rosdoc.yaml000066400000000000000000000000221407615046500174330ustar00rootroot00000000000000 - builder: epydocros-1.15.8/tools/rosunit/scripts/000077500000000000000000000000001407615046500167535ustar00rootroot00000000000000ros-1.15.8/tools/rosunit/scripts/check_test_ran.py000077500000000000000000000070061407615046500223070ustar00rootroot00000000000000#!/usr/bin/env python # Software License Agreement (BSD License) # # Copyright (c) 2008, Willow Garage, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following # disclaimer in the documentation and/or other materials provided # with the distribution. # * Neither the name of Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # # Revision $Id$ """ Writes a test failure out to test file if it doesn't exist. """ from __future__ import print_function import os import sys import rospkg import rosunit NAME = 'check_test_ran.py' def usage(): print("""Usage: \t%s test-file.xml or \t%s --rostest pkg-name test-file.xml """ % (NAME, NAME), file=sys.stderr) print(sys.argv) sys.exit(getattr(os, 'EX_USAGE', 1)) def check_main(): if len(sys.argv) < 2: usage() if '--rostest' in sys.argv[1:]: if len(sys.argv) != 4: usage() test_pkg, test_file = [a for a in sys.argv[1:] if a != '--rostest'] # this logic derives the output filename that rostest uses r = rospkg.RosPack() pkg_name = rospkg.get_package_name(test_file) pkg_dir = r.get_path(pkg_name) # compute test name for friendlier reporting outname = rosunit.rostest_name_from_path(pkg_dir, test_file) test_file = rosunit.xml_results_file(test_pkg, outname, is_rostest=True) else: if len(sys.argv) != 2: usage() test_file = sys.argv[1] print('Checking for test results in %s' % test_file) if not os.path.exists(test_file): if not os.path.exists(os.path.dirname(test_file)): os.makedirs(os.path.dirname(test_file)) print('Cannot find results, writing failure results to', test_file) with open(test_file, 'w') as f: test_name = os.path.basename(test_file) d = {'test': test_name, 'test_file': test_file} f.write(""" """ % d) if __name__ == '__main__': check_main() ros-1.15.8/tools/rosunit/scripts/clean_junit_xml.py000077500000000000000000000077361407615046500225200ustar00rootroot00000000000000#!/usr/bin/env python # Software License Agreement (BSD License) # # Copyright (c) 2009, Willow Garage, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following # disclaimer in the documentation and/or other materials provided # with the distribution. # * Neither the name of Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # # Revision $Id$ from __future__ import print_function """ clean_junit_xml.py is a simple script that takes all the xml-formatted Ant JUnit XML test output in test_results and aggregates them into test_results/_hudson. In this process, it strips any characters that tend to cause Hudson trouble. """ import os import sys import rospkg import rosunit.junitxml as junitxml PKG = 'rosunit' def prepare_dirs(output_dir_name): test_results_dir = rospkg.get_test_results_dir() print('will read test results from', test_results_dir) output_dir = os.path.join(test_results_dir, output_dir_name) if not os.path.exists(output_dir): print('creating directory', output_dir) os.makedirs(output_dir) return test_results_dir, output_dir def clean_results(test_results_dir, output_dir, filter): """ Read results from test_results_dir and write them into output_dir. """ for d in os.listdir(test_results_dir): if filter and d in filter: continue print('looking at', d) test_dir = os.path.join(test_results_dir, d) if not os.path.isdir(test_dir): continue base_test_name = os.path.basename(test_dir) # for each test result that a package generated, read it, then # rewrite it to our output directory. This will invoke our # cleaning rules on the XML that protect the result from Hudson # issues. for file in os.listdir(test_dir): if file.endswith('.xml'): test_name = base_test_name + '.' + file[:-4] file = os.path.join(test_dir, file) try: result = junitxml.read(file, test_name) output_path = os.path.join(output_dir, '%s.xml' % test_name) with open(output_path, 'w') as f: print('re-writing', output_path) f.write(result.xml().encode('utf-8')) except Exception as e: sys.stderr.write('ignoring [%s]: %s\n' % (file, e)) def main(): print('[clean_junit_xml]: STARTING') output_dir_name = '_hudson' test_results_dir, output_dir = prepare_dirs(output_dir_name) print('[clean_junit_xml]: writing aggregated test results to %s' % output_dir) clean_results(test_results_dir, output_dir, [output_dir_name, '.svn']) print('[clean_junit_xml]: FINISHED') if __name__ == '__main__': main() ros-1.15.8/tools/rosunit/scripts/pycoverage_to_html.py000077500000000000000000000060331407615046500232240ustar00rootroot00000000000000#!/usr/bin/env python # Software License Agreement (BSD License) # # Copyright (c) 2008, Willow Garage, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following # disclaimer in the documentation and/or other materials provided # with the distribution. # * Neither the name of Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # # Revision $Id$ """ Generate HTML reports from coverage.py (aka python-coverage). This is currently a no-frills backend tool. """ import sys import roslib try: import coverage except ImportError: sys.stderr.write("ERROR: cannot import python-coverage, coverage report will not run.\nTo install coverage, run 'easy_install coverage'\n") sys.exit(1) def coverage_html(): import os.path if not os.path.isfile('.coverage-modules'): sys.stderr.write('No .coverage-modules file; nothing to do\n') return with open('.coverage-modules', 'r') as f: modules = [x for x in f.read().split('\n') if x.strip()] cov = coverage.coverage() cov.load() # import everything for m in modules: try: base = m.split('.')[0] roslib.load_manifest(base) __import__(m) except Exception: sys.stderr.write('WARN: cannot import %s\n' % (base)) modlist = '\n'.join([' * %s' % m for m in modules]) sys.stdout.write('Generating for\n%s\n' % (modlist)) # load the module instances to pass to coverage so it can generate annotation html reports mods = [] # TODO: rewrite, buggy for m in modules: mods.extend([v for v in sys.modules.values() if v and v.__name__.startswith(m) and v not in mods]) # dump the output to covhtml directory cov.html_report(mods, directory='covhtml') if __name__ == '__main__': coverage_html() ros-1.15.8/tools/rosunit/scripts/rosunit000077500000000000000000000032321407615046500204040ustar00rootroot00000000000000#!/usr/bin/env python # Software License Agreement (BSD License) # # Copyright (c) 2010, Willow Garage, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following # disclaimer in the documentation and/or other materials provided # with the distribution. # * Neither the name of Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. import rosunit.rosunit_main rosunit.rosunit_main.rosunitmain() ros-1.15.8/tools/rosunit/scripts/summarize_results.py000077500000000000000000000100571407615046500231300ustar00rootroot00000000000000#!/usr/bin/env python # Software License Agreement (BSD License) # # Copyright (c) 2008, Willow Garage, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following # disclaimer in the documentation and/or other materials provided # with the distribution. # * Neither the name of Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # # Revision $Id$ """ Prints summary of aggregated test results to stdout. This is useful when running several tests across a package. """ from __future__ import print_function import sys try: from cStringIO import StringIO except ImportError: from io import StringIO import rospkg import rosunit.junitxml as junitxml def create_summary(result, packages): buff = StringIO() buff.write('-' * 80 + '\n') buff.write('\033[1m[AGGREGATED TEST RESULTS SUMMARY]\033[0m\n\n') errors_failures = [r for r in result.test_case_results if r.errors or r.failures] if errors_failures: buff.write('ERRORS/FAILURES:\n') for tc_result in errors_failures: buff.write(tc_result.description) buff.write('PACKAGES: \n%s\n\n' % '\n'.join([' * %s' % p for p in packages])) buff.write('\nSUMMARY\n') if (result.num_errors + result.num_failures) == 0: buff.write('\033[32m * RESULT: SUCCESS\033[0m\n') else: buff.write('\033[1;31m * RESULT: FAIL\033[0m\n') # TODO: still some issues with the numbers adding up if tests fail to launch # number of errors from the inner tests, plus add in count for tests # that didn't run properly ('result' object). buff.write(' * TESTS: %s\n' % result.num_tests) if result.num_errors: buff.write('\033[1;31m * ERRORS: %s\033[0m\n' % result.num_errors) else: buff.write(' * ERRORS: 0\n') if result.num_failures: buff.write('\033[1;31m * FAILURES: %s\033[0m\n' % result.num_failures) else: buff.write(' * FAILURES: 0\n') return buff.getvalue() def main(): from optparse import OptionParser parser = OptionParser(usage='usage: summarize_results.py [options] package') parser.add_option('--nodeps', dest='no_deps', default=False, action='store_true', help="don't compute test results for the specified package only") (options, args) = parser.parse_args() if len(args) != 1: parser.error('Only one package may be specified') package = args[0] r = rospkg.RosPack() if options.no_deps: packages = [package] else: packages = [package] + r.get_depends_on(package, implicit=True) packages = [p for p in packages if p] result = junitxml.read_all(packages) print(create_summary(result, packages)) if result.num_errors or result.num_failures: sys.exit(1) if __name__ == '__main__': main() ros-1.15.8/tools/rosunit/scripts/test_results_dir.py000077500000000000000000000034551407615046500227350ustar00rootroot00000000000000#!/usr/bin/env python # Software License Agreement (BSD License) # # Copyright (c) 2009, Willow Garage, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following # disclaimer in the documentation and/or other materials provided # with the distribution. # * Neither the name of Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # # Revision $Id$ """ test_results_dir.py simply prints the directory that rosunit/rostest results are stored in. """ from __future__ import print_function import rospkg print(rospkg.get_test_results_dir()) ros-1.15.8/tools/rosunit/setup.py000066400000000000000000000003671407615046500170040ustar00rootroot00000000000000from setuptools import setup from catkin_pkg.python_setup import generate_distutils_setup d = generate_distutils_setup( packages=['rosunit'], package_dir={'': 'src'}, scripts=['scripts/rosunit'], requires=['rospkg'] ) setup(**d) ros-1.15.8/tools/rosunit/src/000077500000000000000000000000001407615046500160535ustar00rootroot00000000000000ros-1.15.8/tools/rosunit/src/rosunit/000077500000000000000000000000001407615046500175565ustar00rootroot00000000000000ros-1.15.8/tools/rosunit/src/rosunit/__init__.py000066400000000000000000000042471407615046500216760ustar00rootroot00000000000000# Software License Agreement (BSD License) # # Copyright (c) 2008, Willow Garage, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following # disclaimer in the documentation and/or other materials provided # with the distribution. # * Neither the name of Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # # Revision $Id$ """ Library and tools support unit testing in ROS. """ # NOTE: while this makes some forward references to conventions used # in rostest, it does not use rostest itself. from . import junitxml # noqa: F401 from .baretest import print_runner_summary # noqa: F401 from .baretest import print_unittest_summary # noqa: F401 from .core import XML_OUTPUT_FLAG # noqa: F401 from .core import create_xml_runner # noqa: F401 from .core import rostest_name_from_path # noqa: F401 from .core import xml_results_file # noqa: F401 from .pyunit import unitrun # noqa: F401 __version__ = '1.7.0' ros-1.15.8/tools/rosunit/src/rosunit/baretest.py000066400000000000000000000524141407615046500217470ustar00rootroot00000000000000# Software License Agreement (BSD License) # # Copyright (c) 2010, Willow Garage, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following # disclaimer in the documentation and/or other materials provided # with the distribution. # * Neither the name of Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # # Revision $Id$ """ rostest implementation of running bare (gtest-compatible) unit test executables. These do not run in a ROS environment. """ from __future__ import print_function import errno import os try: from cStringIO import StringIO except ImportError: from io import StringIO import signal import subprocess import time import traceback import unittest import rospkg from . import junitxml from . import pmon from .core import create_xml_runner # noqa: F401 from .core import printerrlog from .core import printlog from .core import printlog_bold from .core import rostest_name_from_path # noqa: F401 from .core import xml_results_file BARE_TIME_LIMIT = 60. TIMEOUT_SIGINT = 15.0 # seconds TIMEOUT_SIGTERM = 2.0 # seconds class TestTimeoutException(Exception): pass class BareTestCase(unittest.TestCase): def __init__(self, exe, args, retry=0, time_limit=None, test_name=None, text_mode=False, package_name=None): """ @param exe: path to executable to run @type exe: str @param args: arguments to exe @type args: [str] @type retry: int @param time_limit: (optional) time limit for test. Defaults to BARE_TIME_LIMIT. @type time_limit: float @param test_name: (optional) override automatically generated test name @type test_name: str @param package_name: (optional) override automatically inferred package name @type package_name: str """ super(BareTestCase, self).__init__() self.text_mode = text_mode if package_name: self.package = package_name else: self.package = rospkg.get_package_name(exe) self.exe = os.path.abspath(exe) if test_name is None: self.test_name = os.path.basename(exe) else: self.test_name = test_name # invoke pyunit tests with python executable if self.exe.endswith('.py'): self.args = ['python', self.exe] + args else: self.args = [self.exe] + args if text_mode: self.args = self.args + ['--text'] self.retry = retry self.time_limit = time_limit or BARE_TIME_LIMIT self.pmon = None self.results = junitxml.Result(self.test_name) def setUp(self): self.pmon = pmon.start_process_monitor() def tearDown(self): if self.pmon is not None: pmon.shutdown_process_monitor(self.pmon) self.pmon = None def runTest(self): self.failIf(self.package is None, 'unable to determine package of executable') done = False while not done: test_name = self.test_name printlog('Running test [%s]', test_name) # setup the test # - we pass in the output test_file name so we can scrape it test_file = xml_results_file(self.package, test_name, False) if os.path.exists(test_file): printlog('removing previous test results file [%s]', test_file) os.remove(test_file) self.args.append('--gtest_output=xml:%s' % test_file) # run the test, blocks until completion printlog('running test %s' % test_name) timeout_failure = False run_id = None # TODO: really need different, non-node version of LocalProcess instead of these extra args process = LocalProcess(run_id, self.package, self.test_name, self.args, os.environ, False, cwd='cwd', is_node=False) pm = self.pmon pm.register(process) success = process.start() self.assert_(success, 'test failed to start') # poll until test terminates or allotted time exceed timeout_t = time.time() + self.time_limit try: while process.is_alive(): # test fails on timeout if time.time() > timeout_t: raise TestTimeoutException('test max time allotted') time.sleep(0.1) except TestTimeoutException: if self.retry: timeout_failure = True else: raise if not timeout_failure: printlog('test [%s] finished' % test_name) else: printerrlog('test [%s] timed out' % test_name) if self.text_mode: results = self.results elif not self.text_mode: # load in test_file if not timeout_failure: self.assert_(os.path.isfile(test_file), 'test [%s] did not generate test results' % test_name) printlog('test [%s] results are in [%s]', test_name, test_file) results = junitxml.read(test_file, test_name) test_fail = results.num_errors or results.num_failures else: test_fail = True if self.retry > 0 and test_fail: self.retry -= 1 printlog('test [%s] failed, retrying. Retries left: %s' % (test_name, self.retry)) else: done = True self.results = results printlog('test [%s] results summary: %s errors, %s failures, %s tests', test_name, results.num_errors, results.num_failures, results.num_tests) printlog('[ROSTEST] test [%s] done', test_name) # TODO: this is a straight copy from roslaunch. Need to reduce, refactor class LocalProcess(pmon.Process): """ Process launched on local machine """ def __init__(self, run_id, package, name, args, env, log_output, respawn=False, required=False, cwd=None, is_node=True): """ @param run_id: unique run ID for this roslaunch. Used to generate log directory location. run_id may be None if this feature is not being used. @type run_id: str @param package: name of package process is part of @type package: str @param name: name of process @type name: str @param args: list of arguments to process @type args: [str] @param env: environment dictionary for process @type env: {str : str} @param log_output: if True, log output streams of process @type log_output: bool @param respawn: respawn process if it dies (default is False) @type respawn: bool @param cwd: working directory of process, or None @type cwd: str @param is_node: (optional) if True, process is ROS node and accepts ROS node command-line arguments. Default: True @type is_node: False """ super(LocalProcess, self).__init__(package, name, args, env, respawn, required) self.run_id = run_id self.popen = None self.log_output = log_output self.started = False self.stopped = False self.cwd = cwd self.log_dir = None self.pid = -1 self.is_node = is_node # NOTE: in the future, info() is going to have to be sufficient for relaunching a process def get_info(self): """ Get all data about this process in dictionary form """ info = super(LocalProcess, self).get_info() info['pid'] = self.pid if self.run_id: info['run_id'] = self.run_id info['log_output'] = self.log_output if self.cwd is not None: info['cwd'] = self.cwd return info def _configure_logging(self): """ Configure logging of node's log file and stdout/stderr @return: stdout log file name, stderr log file name. Values are None if stdout/stderr are not logged. @rtype: str, str """ log_dir = rospkg.get_log_dir(env=os.environ) if self.run_id: log_dir = os.path.join(log_dir, self.run_id) if not os.path.exists(log_dir): try: os.makedirs(log_dir) except OSError as e: if e.errno == errno.EACCES: raise RLException('unable to create directory for log file [%s].\nPlease check permissions.' % log_dir) else: raise RLException('unable to create directory for log file [%s]: %s' % (log_dir, e.strerror)) # #973: save log dir for error messages self.log_dir = log_dir # send stdout/stderr to file. in the case of respawning, we have to # open in append mode # note: logfileerr: disabling in favor of stderr appearing in the console. # will likely reinstate once roserr/rosout is more properly used. logfileout = logfileerr = None if self.log_output: outf, errf = [os.path.join(log_dir, '%s-%s.log' % (self.name, n)) for n in ['stdout', 'stderr']] if self.respawn: mode = 'a' else: mode = 'w' logfileout = open(outf, mode) if is_child_mode(): logfileerr = open(errf, mode) # #986: pass in logfile name to node if self.is_node: # #1595: on respawn, these keep appending self.args = _cleanup_remappings(self.args, '__log:=') self.args.append('__log:=%s' % os.path.join(log_dir, '%s.log' % self.name)) return logfileout, logfileerr def start(self): """ Start the process. @raise pmon.FatalProcessLaunch: if process cannot be started and it is not likely to ever succeed """ super(LocalProcess, self).start() try: self.lock.acquire() self.started = self.stopped = False full_env = self.env # _configure_logging() can mutate self.args try: logfileout, logfileerr = self._configure_logging() except Exception as e: printerrlog('[%s] ERROR: unable to configure logging [%s]' % (self.name, str(e))) # it's not safe to inherit from this process as # rostest changes stdout to a StringIO, which is not a # proper file. logfileout, logfileerr = subprocess.PIPE, subprocess.PIPE if self.cwd == 'node': cwd = os.path.dirname(self.args[0]) elif self.cwd == 'cwd': cwd = os.getcwd() elif self.cwd == 'ros-root': from roslib.rosenv import get_ros_root cwd = get_ros_root() else: cwd = rospkg.get_ros_home() if not os.path.exists(cwd): try: os.makedirs(cwd) except OSError: # exist_ok=True pass try: self.popen = subprocess.Popen(self.args, cwd=cwd, stdout=logfileout, stderr=logfileerr, env=full_env, close_fds=True, preexec_fn=os.setsid) except OSError as e: self.started = True # must set so is_alive state is correct if e.errno == errno.ENOEXEC: # Exec format error raise pmon.FatalProcessLaunch("Unable to launch [%s]. \nIf it is a script, you may be missing a '#!' declaration at the top." % self.name) elif e.errno == errno.ENOENT: # no such file or directory raise pmon.FatalProcessLaunch("""Roslaunch got a '%s' error while attempting to run: %s Please make sure that all the executables in this command exist and have executable permission. This is often caused by a bad launch-prefix.""" % (msg, ' '.join(self.args))) else: raise pmon.FatalProcessLaunch('unable to launch [%s]: %s' % (' '.join(self.args), msg)) self.started = True # Check that the process is either still running (poll returns # None) or that it completed successfully since when we # launched it above (poll returns the return code, 0). poll_result = self.popen.poll() if poll_result is None or poll_result == 0: self.pid = self.popen.pid printlog_bold('process[%s]: started with pid [%s]' % (self.name, self.pid)) return True else: printerrlog('failed to start local process: %s' % (' '.join(self.args))) return False finally: self.lock.release() def is_alive(self): """ @return: True if process is still running @rtype: bool """ if not self.started: # not started yet return True if self.stopped or self.popen is None: return False self.exit_code = self.popen.poll() if self.exit_code is not None: return False return True def get_exit_description(self): """ @return: human-readable description of exit state @rtype: str """ # #973: include location of output location in message if self.exit_code is not None: if self.exit_code: if self.log_dir: return 'process has died [pid %s, exit code %s].\nlog files: %s*.log' % (self.pid, self.exit_code, os.path.join(self.log_dir, self.name)) else: return 'process has died [pid %s, exit code %s]' % (self.pid, self.exit_code) else: if self.log_dir: return 'process has finished cleanly.\nlog file: %s*.log' % (os.path.join(self.log_dir, self.name)) else: return 'process has finished cleanly' else: return 'process has died' def _stop_unix(self, errors): """ UNIX implementation of process killing @param errors: error messages. stop() will record messages into this list. @type errors: [str] """ self.exit_code = self.popen.poll() if self.exit_code is not None: # print "process[%s].stop(): process has already returned %s"%(self.name, self.exit_code) self.popen = None self.stopped = True return pid = self.popen.pid pgid = os.getpgid(pid) try: # Start with SIGINT and escalate from there. os.killpg(pgid, signal.SIGINT) timeout_t = time.time() + TIMEOUT_SIGINT retcode = self.popen.poll() while time.time() < timeout_t and retcode is None: time.sleep(0.1) retcode = self.popen.poll() # Escalate non-responsive process if retcode is None: printerrlog('[%s] escalating to SIGTERM' % self.name) timeout_t = time.time() + TIMEOUT_SIGTERM os.killpg(pgid, signal.SIGTERM) retcode = self.popen.poll() while time.time() < timeout_t and retcode is None: time.sleep(0.2) retcode = self.popen.poll() if retcode is None: printerrlog('[%s] escalating to SIGKILL' % self.name) errors.append('process[%s, pid %s]: required SIGKILL. May still be running.' % (self.name, pid)) try: os.killpg(pgid, signal.SIGKILL) # #2096: don't block on SIGKILL, because this results in more orphaned processes overall except OSError as e: if e.args[0] == 3: printerrlog('no [%s] process with pid [%s]' % (self.name, pid)) else: printerrlog('errors shutting down [%s]: %s' % (self.name, e)) finally: self.popen = None def stop(self, errors=[]): """ Stop the process. Record any significant error messages in the errors parameter @param errors: error messages. stop() will record messages into this list. @type errors: [str] """ super(LocalProcess, self).stop(errors) self.lock.acquire() try: try: if self.popen is None: return # NOTE: currently POSIX-only. Need to add in Windows code once I have a test environment: # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/347462 self._stop_unix(errors) except Exception: printerrlog('[%s] EXCEPTION %s' % (self.name, traceback.format_exc())) finally: self.stopped = True self.lock.release() def print_runner_summary(runner_results, junit_results, runner_name='ROSUNIT'): """ Print summary of runner results and actual test results to stdout. For rosunit and rostest, the test is wrapped in an external runner. The results from this runner are important if the runner itself has a failure. @param runner_result: unittest runner result object @type runner_result: _XMLTestResult @param junit_results: Parsed JUnit test results @type junit_results: rosunit.junitxml.Result """ # we have two separate result objects, which can be a bit # confusing. 'result' counts successful _running_ of tests # (i.e. doesn't check for actual test success). The 'r' result # object contains results of the actual tests. buff = StringIO() buff.write('[%s]' % (runner_name) + '-' * 71 + '\n\n') for tc_result in junit_results.test_case_results: buff.write(tc_result.description) for tc_result in runner_results.failures: buff.write('[%s][failed]\n' % tc_result[0]._testMethodName) buff.write('\nSUMMARY\n') if runner_results.wasSuccessful() and (junit_results.num_errors + junit_results.num_failures) == 0: buff.write('\033[32m * RESULT: SUCCESS\033[0m\n') else: buff.write('\033[1;31m * RESULT: FAIL\033[0m\n') # TODO: still some issues with the numbers adding up if tests fail to launch # number of errors from the inner tests, plus add in count for tests # that didn't run properly ('result' object). buff.write(' * TESTS: %s\n' % junit_results.num_tests) num_errors = junit_results.num_errors+len(runner_results.errors) if num_errors: buff.write('\033[1;31m * ERRORS: %s\033[0m\n' % num_errors) else: buff.write(' * ERRORS: 0\n') num_failures = junit_results.num_failures+len(runner_results.failures) if num_failures: buff.write('\033[1;31m * FAILURES: %s\033[0m\n' % num_failures) else: buff.write(' * FAILURES: 0\n') if runner_results.failures: buff.write('\nERROR: The following tests failed to run:\n') for tc_result in runner_results.failures: buff.write(' * ' + tc_result[0]._testMethodName + '\n') print(buff.getvalue()) def _format_errors(errors): formatted = [] for e in errors: if '_testMethodName' in e[0].__dict__: formatted.append(e[0]._testMethodName) elif 'description' in e[0].__dict__: formatted.append('%s: %s\n' % (str(e[0].description), str(e[1]))) else: formatted.append(str(e[0].__dict__)) return formatted def print_unittest_summary(result): """ Print summary of python unittest result to stdout @param result: test results """ buff = StringIO() buff.write('-------------------------------------------------------------\nSUMMARY:\n') if result.wasSuccessful(): buff.write('\033[32m * RESULT: SUCCESS\033[0m\n') else: buff.write(' * RESULT: FAIL\n') buff.write(' * TESTS: %s\n' % result.testsRun) buff.write(' * ERRORS: %s [%s]\n' % (len(result.errors), ', '.join(_format_errors(result.errors)))) buff.write(' * FAILURES: %s [%s]\n' % (len(result.failures), ', '.join(_format_errors(result.failures)))) print(buff.getvalue()) ros-1.15.8/tools/rosunit/src/rosunit/core.py000066400000000000000000000141321407615046500210610ustar00rootroot00000000000000# Software License Agreement (BSD License) # # Copyright (c) 2008, Willow Garage, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following # disclaimer in the documentation and/or other materials provided # with the distribution. # * Neither the name of Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. from __future__ import print_function import errno import os import sys import rospkg from .xmlrunner import XMLTestRunner XML_OUTPUT_FLAG = '--gtest_output=xml:' # use gtest-compatible flag def printlog(msg, *args): if args: msg = msg % args print('[ROSUNIT]' + msg) def printlog_bold(msg, *args): if args: msg = msg % args print('\033[1m[ROSUNIT]' + msg + '\033[0m') def printerrlog(msg, *args): if args: msg = msg % args print('[ROSUNIT]' + msg, file=sys.stderr) # this is a copy of the roslogging utility. it's been moved here as it is a common # routine for programs using accessing ROS directories def makedirs_with_parent_perms(p): """ Create the directory using the permissions of the nearest (existing) parent directory. This is useful for logging, where a root process sometimes has to log in the user's space. @param p: directory to create @type p: str """ p = os.path.abspath(p) parent = os.path.dirname(p) # recurse upwards, checking to make sure we haven't reached the # top if not os.path.exists(p) and p and parent != p: makedirs_with_parent_perms(parent) s = os.stat(parent) try: os.mkdir(p) except OSError as e: if e.errno != errno.EEXIST: raise # if perms of new dir don't match, set anew s2 = os.stat(p) if s.st_uid != s2.st_uid or s.st_gid != s2.st_gid: os.chown(p, s.st_uid, s.st_gid) if s.st_mode != s2.st_mode: os.chmod(p, s.st_mode) def xml_results_file(test_pkg, test_name, is_rostest=False, env=None): """ @param test_pkg: name of test's package @type test_pkg: str @param test_name str: name of test @type test_name: str @param is_rostest: True if the results file is for a rostest-generated unit instance @type is_rostest: bool @return: name of xml results file for specified test @rtype: str """ test_dir = os.path.join(rospkg.get_test_results_dir(env=env), test_pkg) if not os.path.exists(test_dir): try: makedirs_with_parent_perms(test_dir) except OSError as error: raise IOError('cannot create test results directory [%s]: %s' % (test_dir, str(error))) # #576: strip out chars that would bork the filename # this is fairly primitive, but for now just trying to catch some common cases for c in ' "\'&$!`/\\': if c in test_name: test_name = test_name.replace(c, '_') if is_rostest: return os.path.join(test_dir, 'rostest-%s.xml' % test_name) else: return os.path.join(test_dir, 'rosunit-%s.xml' % test_name) def rostest_name_from_path(pkg_dir, test_file): """ Derive name of rostest based on file name/path. rostest follows a certain convention defined above. @return: name of test @rtype: str """ test_file_abs = os.path.abspath(test_file) if test_file_abs.startswith(pkg_dir): # compute package-relative path test_file = test_file_abs[len(pkg_dir):] if test_file[0] == os.sep: test_file = test_file[1:] outname = test_file.replace(os.sep, '_') if '.' in outname: outname = outname[:outname.rfind('.')] return outname def create_xml_runner(test_pkg, test_name, results_file=None, is_rostest=False): """ Create the unittest test runner with XML output @param test_pkg: package name @type test_pkg: str @param test_name: test name @type test_name: str @param is_rostest: if True, use naming scheme for rostest itself instead of individual unit test naming @type is_rostest: bool """ test_name = os.path.basename(test_name) # determine output xml file name if not results_file: results_file = xml_results_file(test_pkg, test_name, is_rostest) test_dir = os.path.abspath(os.path.dirname(results_file)) if not os.path.exists(test_dir): try: makedirs_with_parent_perms(test_dir) # NOTE: this will pass up an error exception if it fails except OSError as error: raise IOError('cannot create test results directory [%s]: %s' % (test_dir, str(error))) elif os.path.isfile(test_dir): raise Exception('ERROR: cannot run test suite, file is preventing creation of test dir: %s' % test_dir) print('[ROSUNIT] Outputting test results to ' + results_file) outstream = open(results_file, 'w') outstream.write('\n') return XMLTestRunner(stream=outstream) ros-1.15.8/tools/rosunit/src/rosunit/junitxml.py000066400000000000000000000470161407615046500220120ustar00rootroot00000000000000#!/usr/bin/env python # Software License Agreement (BSD License) # # Copyright (c) 2008, Willow Garage, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following # disclaimer in the documentation and/or other materials provided # with the distribution. # * Neither the name of Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # # Revision $Id$ """ Library for reading and manipulating Ant JUnit XML result files. """ from __future__ import print_function import codecs import os try: from cStringIO import StringIO python2 = True except ImportError: from io import StringIO python2 = False import re import xml.etree.ElementTree as ET from functools import reduce from xml.dom import Node as DomNode from xml.dom.minidom import parseString import rospkg pattern = r'[^\x09\x0A\x0D\x20-\x7E\x85\xA0-\xFF\u0100-\uD7FF\uE000-\uFDCF\uFDE0-\uFFFD]' if python2: pattern = pattern.decode('unicode_escape') else: pattern = codecs.decode(pattern, 'unicode_escape') invalid_chars = re.compile(pattern) def invalid_char_replacer(m): return '&#x' + ('%04X' % ord(m.group(0))) + ';' def filter_nonprintable_text(text): return re.sub(invalid_chars, invalid_char_replacer, text) def cdata(cdata_text): return ''.format(cdata_text) class TestInfo(object): """ Common container for 'error' and 'failure' results """ def __init__(self, type_, text): """ @param type_: type attribute from xml @type type_: str @param text: text property from xml @type text: str """ self.type = type_ self.text = text class TestError(TestInfo): """ 'error' result container """ def xml(self): """ @return XML tag representing the object, with non-XML text filtered out @rtype: str """ return ET.tostring(self.xml_element(), encoding='utf-8', method='xml') def xml_element(self): """ @return XML tag representing the object, with non-XML text filtered out @rtype: xml.etree.ElementTree.Element """ error = ET.Element('error') error.set('type', self.type) error.text = cdata(filter_nonprintable_text(self.text)) return error class TestFailure(TestInfo): """ 'failure' result container """ def xml(self): """ @return XML tag representing the object, with non-XML text filtered out @rtype: str """ return ET.tostring(self.xml_element(), encoding='utf-8', method='xml') def xml_element(self): """ @return XML tag representing the object, with non-XML text filtered out @rtype: xml.etree.ElementTree.Element """ error = ET.Element('failure') error.set('type', self.type) error.text = cdata(filter_nonprintable_text(self.text)) return error class TestCaseResult(object): """ 'testcase' result container """ def __init__(self, name): """ @param name: name of testcase @type name: str """ self.name = name self.failures = [] self.errors = [] self.time = 0.0 self.classname = '' def _passed(self): """ @return: True if test passed @rtype: bool """ return not self.errors and not self.failures # bool: True if test passed without errors or failures passed = property(_passed) def _failure_description(self): """ @return: description of testcase failure @rtype: str """ if self.failures: tmpl = '[%s][FAILURE]' % self.name tmpl = tmpl + '-'*(80 - len(tmpl)) tmpl = tmpl+'\n%s\n' + '-' * 80 + '\n\n' return '\n'.join(tmpl % x.text for x in self.failures) return '' def _error_description(self): """ @return: description of testcase error @rtype: str """ if self.errors: tmpl = '[%s][ERROR]' % self.name tmpl = tmpl + '-' * (80 - len(tmpl)) tmpl = tmpl+'\n%s\n' + '-' * 80 + '\n\n' return '\n'.join(tmpl % x.text for x in self.errors) return '' def _description(self): """ @return: description of testcase result @rtype: str """ if self.passed: return '[%s][passed]\n' % self.name else: return self._failure_description() + \ self._error_description() # str: printable description of testcase result description = property(_description) def add_failure(self, failure): """ @param failure TestFailure """ self.failures.append(failure) def add_error(self, error): """ @param failure TestError """ self.errors.append(error) def xml(self): """ @return XML tag representing the object, with non-XML text filtered out @rtype: str """ return ET.tostring(self.xml_element(), encoding='utf-8', method='xml') def xml_element(self): """ @return XML tag representing the object, with non-XML text filtered out @rtype: xml.etree.ElementTree.Element """ testcase = ET.Element('testcase') testcase.set('classname', self.classname) testcase.set('name', self.name) testcase.set('time', str(self.time)) for f in self.failures: testcase.append(f.xml_element()) for e in self.errors: testcase.append(e.xml_element()) return testcase class Result(object): __slots__ = ['name', 'num_errors', 'num_failures', 'num_tests', 'test_case_results', 'system_out', 'system_err', 'time'] def __init__(self, name, num_errors=0, num_failures=0, num_tests=0): self.name = name self.num_errors = num_errors self.num_failures = num_failures self.num_tests = num_tests self.test_case_results = [] self.system_out = '' self.system_err = '' self.time = 0.0 def accumulate(self, r): """ Add results from r to this result @param r: results to aggregate with this result @type r: Result """ self.num_errors += r.num_errors self.num_failures += r.num_failures self.num_tests += r.num_tests self.time += r.time self.test_case_results.extend(r.test_case_results) if r.system_out: self.system_out += '\n'+r.system_out if r.system_err: self.system_err += '\n'+r.system_err def add_test_case_result(self, r): """ Add results from a testcase to this result container @param r: TestCaseResult @type r: TestCaseResult """ self.test_case_results.append(r) def xml_element(self): """ @return: document as unicode (UTF-8 declared) XML according to Ant JUnit spec """ testsuite = ET.Element('testsuite') testsuite.set('tests', str(self.num_tests)) testsuite.set('failures', str(self.num_failures)) testsuite.set('time', str(self.time)) testsuite.set('errors', str(self.num_errors)) testsuite.set('name', self.name) for tc in self.test_case_results: tc.xml(testsuite) system_out = ET.SubElement(testsuite, 'system-out') system_out.text = cdata(filter_nonprintable_text(self.system_out)) system_err = ET.SubElement(testsuite, 'system-err') system_err.text = cdata(filter_nonprintable_text(self.system_err)) return ET.tostring(testsuite, encoding='utf-8', method='xml') def _text(tag): return reduce(lambda x, y: x + y, [c.data for c in tag.childNodes if c.nodeType in [DomNode.TEXT_NODE, DomNode.CDATA_SECTION_NODE]], '').strip() def _load_suite_results(test_suite_name, test_suite, result): nodes = [n for n in test_suite.childNodes if n.nodeType == DomNode.ELEMENT_NODE] for node in nodes: name = node.tagName if name == 'testsuite': # for now we flatten this hierarchy _load_suite_results(test_suite_name, node, result) elif name == 'system-out': if _text(node): system_out = '[%s] stdout' % test_suite_name + '-' * (71 - len(test_suite_name)) system_out += '\n'+_text(node) result.system_out += system_out elif name == 'system-err': if _text(node): system_err = '[%s] stderr' % test_suite_name + '-' * (71 - len(test_suite_name)) system_err += '\n'+_text(node) result.system_err += system_err elif name == 'testcase': name = node.getAttribute('name') or 'unknown' classname = node.getAttribute('classname') or 'unknown' # mangle the classname for some sense of uniformity # between rostest/unittest/gtest if '__main__.' in classname: classname = classname[classname.find('__main__.') + 9:] if classname == 'rostest.rostest.RosTest': classname = 'rostest' elif not classname.startswith(result.name): classname = '%s.%s' % (result.name, classname) try: time = float(node.getAttribute('time')) except ValueError: time = 0.0 tc_result = TestCaseResult('%s/%s' % (test_suite_name, name)) tc_result.classname = classname tc_result.time = time result.add_test_case_result(tc_result) for d in [n for n in node.childNodes if n.nodeType == DomNode.ELEMENT_NODE]: # convert 'message' attributes to text elements to keep # python unittest and gtest consistent if d.tagName == 'failure': message = d.getAttribute('message') or '' text = _text(d) or message x = TestFailure(d.getAttribute('type') or '', text) tc_result.add_failure(x) elif d.tagName == 'error': message = d.getAttribute('message') or '' text = _text(d) or message x = TestError(d.getAttribute('type') or '', text) tc_result.add_error(x) # #603: unit test suites are not good about screening out illegal # unicode characters. This little recipe I from http://boodebr.org/main/python/all-about-python-and-unicode#UNI_XML # screens these out try: char = unichr except NameError: char = chr RE_XML_ILLEGAL = '([%s-%s%s-%s%s-%s%s-%s])' + \ '|' + \ '([%s-%s][^%s-%s])|([^%s-%s][%s-%s])|([%s-%s]$)|(^[%s-%s])' try: RE_XML_ILLEGAL = unicode(RE_XML_ILLEGAL) except NameError: pass RE_XML_ILLEGAL = RE_XML_ILLEGAL % \ (char(0x0000), char(0x0008), char(0x000b), char(0x000c), char(0x000e), char(0x001f), char(0xfffe), char(0xffff), char(0xd800), char(0xdbff), char(0xdc00), char(0xdfff), char(0xd800), char(0xdbff), char(0xdc00), char(0xdfff), char(0xd800), char(0xdbff), char(0xdc00), char(0xdfff)) _safe_xml_regex = re.compile(RE_XML_ILLEGAL) def _read_file_safe_xml(test_file, write_back_sanitized=True): """ read in file, screen out unsafe unicode characters """ f = None try: # this is ugly, but the files in question that are problematic # do not declare unicode type. if not os.path.isfile(test_file): raise Exception('test file does not exist') try: f = codecs.open(test_file, 'r', 'utf-8') x = f.read() except Exception: if f is not None: f.close() f = codecs.open(test_file, 'r', 'iso8859-1') x = f.read() for match in _safe_xml_regex.finditer(x): x = x[:match.start()] + '?' + x[match.end():] x = x.encode('utf-8') if write_back_sanitized: with open(test_file, 'wb') as h: h.write(x) return x finally: if f is not None: f.close() def read(test_file, test_name): """ Read in the test_result file @param test_file: test file path @type test_file: str @param test_name: name of test @type test_name: str @return: test results @rtype: Result """ try: xml_str = _read_file_safe_xml(test_file) if not xml_str.strip(): print('WARN: test result file is empty [%s]' % (test_file)) return Result(test_name, 0, 0, 0) test_suites = parseString(xml_str).getElementsByTagName('testsuite') except Exception as e: print('WARN: cannot read test result file [%s]: %s' % (test_file, str(e))) return Result(test_name, 0, 0, 0) if not test_suites: print('WARN: test result file [%s] contains no results' % (test_file)) return Result(test_name, 0, 0, 0) results = Result(test_name, 0, 0, 0) for index, test_suite in enumerate(test_suites): # skip test suites which are already covered by a parent test suite if index > 0 and test_suite.parentNode in test_suites[0:index]: continue # test_suite = test_suite[0] vals = [test_suite.getAttribute(attr) for attr in ['errors', 'failures', 'tests']] vals = [v or 0 for v in vals] err, fail, tests = [int(val) for val in vals] result = Result(test_name, err, fail, tests) result.time = 0.0 if not len(test_suite.getAttribute('time')) else float(test_suite.getAttribute('time')) # Create a prefix based on the test result filename. The idea is to # disambiguate the case when tests of the same name are provided in # different .xml files. We use the name of the parent directory test_file_base = os.path.basename(os.path.dirname(os.path.abspath(test_file))) fname = os.path.basename(test_file) if fname.startswith('TEST-'): fname = fname[5:] if fname.endswith('.xml'): fname = fname[:-4] test_file_base = '%s.%s' % (test_file_base, fname) _load_suite_results(test_file_base, test_suite, result) results.accumulate(result) return results def read_all(filter_=[]): """ Read in the test_results and aggregate into a single Result object @param filter_: list of packages that should be processed @type filter_: [str] @return: aggregated result @rtype: L{Result} """ dir_ = rospkg.get_test_results_dir() root_result = Result('ros', 0, 0, 0) if not os.path.exists(dir_): return root_result for d in os.listdir(dir_): if filter_ and d not in filter_: continue subdir = os.path.join(dir_, d) if os.path.isdir(subdir): for filename in os.listdir(subdir): if filename.endswith('.xml'): filename = os.path.join(subdir, filename) result = read(filename, os.path.basename(subdir)) root_result.accumulate(result) return root_result def test_failure_junit_xml(test_name, message, stdout=None, class_name='Results', testcase_name='test_ran'): """ Generate JUnit XML file for a unary test suite where the test failed @param test_name: Name of test that failed @type test_name: str @param message: failure message @type message: str @param stdout: stdout data to include in report @type stdout: str """ testsuite = ET.Element('testsuite') testsuite.set('tests', '1') testsuite.set('failures', '1') testsuite.set('time', '1') testsuite.set('errors', '0') testsuite.set('name', test_name) testcase = ET.SubElement(testsuite, 'testcase') testcase.set('name', testcase_name) testcase.set('status', 'run') testcase.set('time', '1') testcase.set('classname', class_name) failure = ET.SubElement(testcase, 'failure') failure.set('message', message) failure.set('type', '') if stdout: system_out = ET.SubElement(testsuite, 'system-out') system_out.text = cdata(filter_nonprintable_text(stdout)) return ET.tostring(testsuite, encoding='utf-8', method='xml') def test_success_junit_xml(test_name, class_name='Results', testcase_name='test_ran'): """ Generate JUnit XML file for a unary test suite where the test succeeded. @param test_name: Name of test that passed @type test_name: str """ testsuite = ET.Element('testsuite') testsuite.set('tests', '1') testsuite.set('failures', '0') testsuite.set('time', '1') testsuite.set('errors', '0') testsuite.set('name', test_name) testcase = ET.SubElement(testsuite, 'testcase') testcase.set('name', testcase_name) testcase.set('status', 'run') testcase.set('time', '1') testcase.set('classname', class_name) return ET.tostring(testsuite, encoding='utf-8', method='xml') def print_summary(junit_results, runner_name='ROSUNIT'): """ Print summary of junitxml results to stdout. """ # we have two separate result objects, which can be a bit # confusing. 'result' counts successful _running_ of tests # (i.e. doesn't check for actual test success). The 'r' result # object contains results of the actual tests. buff = StringIO() buff.write('[%s]' % runner_name + '-' * 71 + '\n\n') for tc_result in junit_results.test_case_results: buff.write(tc_result.description) buff.write('\nSUMMARY\n') if (junit_results.num_errors + junit_results.num_failures) == 0: buff.write('\033[32m * RESULT: SUCCESS\033[0m\n') else: buff.write('\033[1;31m * RESULT: FAIL\033[0m\n') # TODO: still some issues with the numbers adding up if tests fail to launch # number of errors from the inner tests, plus add in count for tests # that didn't run properly ('result' object). buff.write(' * TESTS: %s\n' % junit_results.num_tests) num_errors = junit_results.num_errors if num_errors: buff.write('\033[1;31m * ERRORS: %s\033[0m\n' % num_errors) else: buff.write(' * ERRORS: 0\n') num_failures = junit_results.num_failures if num_failures: buff.write('\033[1;31m * FAILURES: %s\033[0m\n' % num_failures) else: buff.write(' * FAILURES: 0\n') print(buff.getvalue()) ros-1.15.8/tools/rosunit/src/rosunit/pmon.py000066400000000000000000000431601407615046500211050ustar00rootroot00000000000000# Software License Agreement (BSD License) # # Copyright (c) 2008, Willow Garage, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following # disclaimer in the documentation and/or other materials provided # with the distribution. # * Neither the name of Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # # Revision $Id$ """ Process monitor """ from __future__ import with_statement import atexit import time import traceback from threading import Lock from threading import RLock from threading import Thread try: from queue import Empty, Queue except ImportError: from Queue import Empty, Queue from .core import printerrlog from .core import printlog from .core import printlog_bold class PmonException(Exception): pass class FatalProcessLaunch(PmonException): """ Exception to indicate that a process launch has failed in a fatal manner (i.e. relaunch is unlikely to succeed) """ pass # start/shutdown ################################################ _pmons = [] _pmon_counter = 0 _shutting_down = False def start_process_monitor(): global _pmon_counter if _shutting_down: return None _pmon_counter += 1 name = 'ProcessMonitor-%s' % _pmon_counter process_monitor = ProcessMonitor(name) with _shutdown_lock: # prevent race condition with pmon_shutdown() being triggered # as we are starting a ProcessMonitor (i.e. user hits ctrl-C # during startup) _pmons.append(process_monitor) process_monitor.start() return process_monitor def shutdown_process_monitor(process_monitor): """ @param process_monitor: process monitor to kill @type process_monitor: L{ProcessMonitor} @return: True if process_monitor was successfully shutdown. False if it could not be shutdown cleanly or if there is a problem with process_monitor parameter. shutdown_process_monitor() does not throw any exceptions as this is shutdown-critical code. @rtype: bool """ try: if process_monitor is None or process_monitor.is_shutdown: return False process_monitor.shutdown() process_monitor.join(20.0) if process_monitor.isAlive(): return False else: return True except Exception: return False _shutdown_lock = Lock() def pmon_shutdown(): global _pmons with _shutdown_lock: if not _pmons: return for p in _pmons: shutdown_process_monitor(p) del _pmons[:] atexit.register(pmon_shutdown) # ############################################################## class Process(object): """ Basic process representation for L{ProcessMonitor}. Must be subclassed to provide actual start()/stop() implementations. """ def __init__(self, package, name, args, env, respawn=False, required=False): self.package = package self.name = name self.args = args self.env = env self.respawn = respawn self.required = required self.lock = Lock() self.exit_code = None # for keeping track of respawning self.spawn_count = 0 def __str__(self): return 'Process<%s>' % (self.name) # NOTE: get_info() is going to have to be sufficient for # generating respawn requests, so we must be complete about it def get_info(self): """ Get all data about this process in dictionary form @return: dictionary of all relevant process properties @rtype: dict { str: val } """ info = { 'spawn_count': self.spawn_count, 'args': self.args, 'env': self.env, 'package': self.package, 'name': self.name, 'alive': self.is_alive(), 'respawn': self.respawn, 'required': self.required, } if self.exit_code is not None: info['exit_code'] = self.exit_code return info def start(self): self.spawn_count += 1 def is_alive(self): return False def stop(self, errors=[]): """ Stop the process. Record any significant error messages in the errors parameter @param errors: error messages. stop() will record messages into this list. @type errors: [str] """ pass def get_exit_description(self): if self.exit_code is not None: if self.exit_code: return 'process has died [exit code %s]' % self.exit_code else: # try not to scare users about process exit return 'process has finished cleanly' else: return 'process has died' class DeadProcess(Process): """ Container class to maintain information about a process that has died. This container allows us to delete the actual Process but still maintain the metadata """ def __init__(self, p): super(DeadProcess, self).__init__(p.package, p.name, p.args, p.env, p.respawn) self.exit_code = p.exit_code self.lock = None self.spawn_count = p.spawn_count self.info = p.get_info() def get_info(self): return self.info def start(self): raise Exception('cannot call start on a dead process!') def is_alive(self): return False class ProcessListener(object): """ Listener class for L{ProcessMonitor} """ def process_died(self, process_name, exit_code): """ Notifies listener that process has died. This callback only occurs for processes that die during normal process monitor execution -- processes that are forcibly killed during ProcessMonitor shutdown are not reported. @param process_name: name of process @type process_name: str @param exit_code: exit code of process. If None, it means that ProcessMonitor was unable to determine an exit code. @type exit_code: int """ pass class ProcessMonitor(Thread): def __init__(self, name='ProcessMonitor'): Thread.__init__(self, name=name) self.procs = [] self.plock = RLock() self.is_shutdown = False self.done = False self.setDaemon(True) self.listeners = [] self.dead_list = [] # #885: ensure core procs self.core_procs = [] # #642: flag to prevent process monitor exiting prematurely self._registrations_complete = False def add_process_listener(self, l): """ Listener for process events. MUST be called before ProcessMonitor is running.See ProcessListener class. @param l: listener instance @type l: L{ProcessListener} """ self.listeners.append(l) def register(self, p): """ Register process with L{ProcessMonitor} @param p: Process @type p: L{Process} @raise PmonException: if process with same name is already registered """ e = None with self.plock: if self.has_process(p.name): e = PmonException("cannot add process with duplicate name '%s'" % p.name) elif self.is_shutdown: e = PmonException('cannot add process [%s] after process monitor has been shut down' % p.name) else: self.procs.append(p) if e: raise e def register_core_proc(self, p): """ Register core process with ProcessMonitor. Coreprocesses have special shutdown semantics. They are killed after all other processes, in reverse order in which they are added. @param p Process @type p: L{Process} @raise PmonException: if process with same name is already registered """ self.register(p) self.core_procs.append(p) def registrations_complete(self): """ Inform the process monitor that registrations are complete. After the registrations_complete flag is set, process monitor will exit if there are no processes left to monitor. """ self._registrations_complete = True def unregister(self, p): with self.plock: self.procs.remove(p) def has_process(self, name): """ @return: True if process is still be monitored. If False, process has died or was never registered with process @rtype: bool """ return len([p for p in self.procs if p.name == name]) > 0 def get_process(self, name): """ @return: process registered under \a name, or None @rtype: L{Process} """ with self.plock: v = [p for p in self.procs if p.name == name] if v: return v[0] def kill_process(self, name): """ Kill process that matches name. NOTE: a killed process will continue to show up as active until the process monitor thread has caught that it has died. @param name: Process name @type name: str @return: True if a process named name was removed from process monitor. A process is considered killed if its stop() method was called. @rtype: bool """ def is_string_type(obj): try: return isinstance(obj, basestring) except NameError: return isinstance(obj, str) if not is_string_type(name): raise PmonException('kill_process takes in a process name but was given: %s' % name) printlog('[%s] kill requested' % name) with self.plock: p = self.get_process(name) if p: try: # no need to accumulate errors, so pass in [] p.stop([]) except Exception as e: printerrlog('Exception: %s' % (str(e))) return True else: return False def shutdown(self): """ Shutdown the process monitor thread """ self.is_shutdown = True def get_active_names(self): """ @return [str]: list of active process names """ with self.plock: retval = [p.name for p in self.procs] return retval def get_process_names_with_spawn_count(self): """ @return: Two lists, where first list of active process names along with the number of times that process has been spawned. Second list contains dead process names and their spawn count. @rtype: [[(str, int),], [(str,int),]] """ with self.plock: actives = [(p.name, p.spawn_count) for p in self.procs] deads = [(p.name, p.spawn_count) for p in self.dead_list] retval = [actives, deads] return retval def run(self): """ thread routine of the process monitor. """ try: # don't let exceptions bomb thread, interferes with exit try: self._run() except Exception: traceback.print_exc() finally: self._post_run() def _run(self): """ Internal run loop of ProcessMonitor """ plock = self.plock dead = [] respawn = [] while not self.is_shutdown: with plock: # copy self.procs procs = self.procs[:] if self.is_shutdown: break for p in procs: try: if not p.is_alive(): exit_code_str = p.get_exit_description() if p.respawn: printlog_bold('[%s] %s\nrespawning...' % (p.name, exit_code_str)) respawn.append(p) elif p.required: printerrlog('=' * 80 + 'REQUIRED process [%s] has died!\n%s\nInitiating shutdown!\n' % (p.name, exit_code_str) + '=' * 80) self.is_shutdown = True else: if p.exit_code: printerrlog('[%s] %s' % (p.name, exit_code_str)) else: printlog_bold('[%s] %s' % (p.name, exit_code_str)) dead.append(p) # no need for lock as we require listeners be # added before process monitor is launched for l in self.listeners: l.process_died(p.name, p.exit_code) except Exception: traceback.print_exc() # don't respawn as this is an internal error dead.append(p) if self.is_shutdown: break # stop polling for d in dead: try: self.unregister(d) # stop process, don't accumulate errors d.stop([]) # save process data to dead list with plock: self.dead_list.append(DeadProcess(d)) except Exception as e: printerrlog('Exception: %s' % (str(e))) # dead check is to make sure that ProcessMonitor at least # waits until its had at least one process before exiting if self._registrations_complete and dead and not self.procs and not respawn: printlog('all processes on machine have died, roslaunch will exit') self.is_shutdown = True del dead[:] for r in respawn: try: if self.is_shutdown: break printlog('[%s] restarting process' % r.name) # stop process, don't accumulate errors r.stop([]) r.start() except Exception: traceback.print_exc() del respawn[:] time.sleep(0.1) # yield thread # moved this to finally block of _post_run # self._post_run() #kill all processes def _post_run(self): # this is already true entering, but go ahead and make sure self.is_shutdown = True # killall processes on run exit q = Queue() q.join() with self.plock: # make copy of core_procs for threadsafe usage core_procs = self.core_procs[:] # enqueue all non-core procs in reverse order for parallel kill # #526/885: ignore core procs [q.put(p) for p in reversed(self.procs) if p not in core_procs] # use 10 workers killers = [] for i in range(10): t = _ProcessKiller(q, i) killers.append(t) t.start() # wait for workers to finish q.join() shutdown_errors = [] # accumulate all the shutdown errors for t in killers: shutdown_errors.extend(t.errors) del killers[:] # #526/885: kill core procs last # we don't want to parallelize this as the master has to be last for p in reversed(core_procs): _kill_process(p, shutdown_errors) # delete everything except dead_list with self.plock: del core_procs[:] del self.procs[:] del self.core_procs[:] self.done = True if shutdown_errors: printerrlog('Shutdown errors:\n' + '\n'.join([' * %s' % e for e in shutdown_errors])) def _kill_process(p, errors): """ Routine for kill Process p with appropriate logging to screen and logfile @param p: process to kill @type p: Process @param errors: list of error messages from killed process @type errors: [str] """ try: printlog('[%s] killing on exit' % p.name) # we accumulate errors from each process so that we can print these at the end p.stop(errors) except Exception as e: printerrlog('Exception: %s' % (str(e))) class _ProcessKiller(Thread): def __init__(self, q, i): Thread.__init__(self, name='ProcessKiller-%s' % i) self.q = q self.errors = [] def run(self): q = self.q while not q.empty(): try: p = q.get(False) _kill_process(p, self.errors) q.task_done() except Empty: pass ros-1.15.8/tools/rosunit/src/rosunit/pyunit.py000066400000000000000000000156311407615046500214660ustar00rootroot00000000000000# Software License Agreement (BSD License) # # Copyright (c) 2008, Willow Garage, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following # disclaimer in the documentation and/or other materials provided # with the distribution. # * Neither the name of Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # # Revision $Id$ """ Wrapper for running Python unittest within rosunit/rostest framework. """ from __future__ import print_function from __future__ import with_statement import sys from .baretest import print_unittest_summary from .core import XML_OUTPUT_FLAG from .core import create_xml_runner def unitrun(package, test_name, test, sysargs=None, coverage_packages=None): """ Wrapper routine from running python unitttests with JUnit-compatible XML output. This is meant for unittests that do not not need a running ROS graph (i.e. offline tests only). This enables JUnit-compatible test reporting so that test results can be reported to higher-level tools. WARNING: unitrun() will trigger a sys.exit() on test failure in order to properly exit with an error code. This routine is meant to be used as a main() routine, not as a library. @param package: name of ROS package that is running the test @type package: str @param test: a test case instance or a name resolving to a test case or suite @type test: unittest.TestCase, or string @param coverage_packages: list of Python package to compute coverage results for. Defaults to package @type coverage_packages: [str] @param sysargs: (optional) alternate sys.argv @type sysargs: [str] """ if sysargs is None: # lazy-init sys args import sys sysargs = sys.argv import unittest if coverage_packages is None: coverage_packages = [package] # parse sysargs result_file = None for arg in sysargs: if arg.startswith(XML_OUTPUT_FLAG): result_file = arg[len(XML_OUTPUT_FLAG):] text_mode = '--text' in sysargs coverage_mode = '--cov' in sysargs or '--covhtml' in sysargs if coverage_mode: start_coverage(coverage_packages) # create and run unittest suite with our xmllrunner wrapper suite = None if isinstance(test, str): suite = unittest.TestLoader().loadTestsFromName(test) else: # some callers pass a TestCase type (instead of an instance) suite = unittest.TestLoader().loadTestsFromTestCase(test) if text_mode: result = unittest.TextTestRunner(verbosity=2).run(suite) else: result = create_xml_runner(package, test_name, result_file).run(suite) if coverage_mode: cov_html_dir = 'covhtml' if '--covhtml' in sysargs else None stop_coverage(coverage_packages, html=cov_html_dir) # test over, summarize results and exit appropriately print_unittest_summary(result) if not result.wasSuccessful(): import sys sys.exit(1) # coverage instance _cov = None def start_coverage(packages): global _cov try: import coverage try: _cov = coverage.coverage() # load previous results as we need to accumulate _cov.load() _cov.start() except coverage.CoverageException: print("WARNING: you have an older version of python-coverage that is not support. Please update to the version provided by 'easy_install coverage'", file=sys.stderr) except ImportError: print("""WARNING: cannot import python-coverage, coverage tests will not run. To install coverage, run 'easy_install coverage'""", file=sys.stderr) def stop_coverage(packages, html=None): """ @param packages: list of packages to generate coverage reports for @type packages: [str] @param html: (optional) if not None, directory to generate html report to @type html: str """ if _cov is None: return import os import sys try: _cov.stop() # accumulate results _cov.save() # - update our own .coverage-modules file list for # coverage-html tool. The reason we read and rewrite instead # of append is that this does a uniqueness check to keep the # file from growing unbounded if os.path.exists('.coverage-modules'): with open('.coverage-modules', 'r') as f: all_packages = set([x for x in f.read().split('\n') if x.strip()] + packages) else: all_packages = set(packages) with open('.coverage-modules', 'w') as f: f.write('\n'.join(all_packages)+'\n') try: # list of all modules for html report all_mods = [] # iterate over packages to generate per-package console reports for package in packages: __import__(package) m = [v for v in sys.modules.values() if v and v.__name__.startswith(package)] all_mods.extend(m) # generate overall report and per module analysis _cov.report(m, show_missing=0) for mod in m: res = _cov.analysis(mod) print('\n%s:\nMissing lines: %s' % (res[0], res[3])) if html: print('=' * 80 + '\ngenerating html coverage report to %s\n' % html + '=' * 80) _cov.html_report(all_mods, directory=html) except ImportError: print("WARNING: cannot import '%s', will not generate coverage report" % package, file=sys.stderr) except ImportError: print("""WARNING: cannot import python-coverage, coverage tests will not run. To install coverage, run 'easy_install coverage'""", file=sys.stderr) ros-1.15.8/tools/rosunit/src/rosunit/rosunit_main.py000066400000000000000000000117561407615046500226510ustar00rootroot00000000000000# Software License Agreement (BSD License) # # Copyright (c) 2008, Willow Garage, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following # disclaimer in the documentation and/or other materials provided # with the distribution. # * Neither the name of Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # # Revision $Id$ from __future__ import print_function from __future__ import with_statement import os import sys import unittest import rospkg from . import pmon from .baretest import BareTestCase from .baretest import print_runner_summary from . core import create_xml_runner from . core import xml_results_file from .junitxml import Result from .junitxml import print_summary # noqa: F401 _NAME = 'rosunit' def rosunitmain(): from optparse import OptionParser parser = OptionParser(usage='usage: %prog [options] [test args...]', prog=_NAME) parser.add_option('-t', '--text', action='store_true', dest='text_mode', default=False, help='Run with stdout output instead of XML output') parser.add_option('--time-limit', metavar='TIME_LIMIT', dest='time_limit', default=60, help='Set time limit for test') parser.add_option('--name', metavar='TEST_NAME', dest='test_name', default=None, help='Test name') parser.add_option('--package', metavar='PACKAGE_NAME', dest='pkg', default=None, help='Package name (optional)') (options, args) = parser.parse_args() if len(args) < 1: parser.error('You must supply a test file.') test_file = args[0] if options.test_name: test_name = options.test_name else: test_name = os.path.basename(test_file) if '.' in test_name: test_name = test_name[:test_name.rfind('.')] time_limit = float(options.time_limit) if options.time_limit else None # If the caller didn't tell us the package name, we'll try to infer it. # compute some common names we'll be using to generate test names and files pkg = options.pkg if not pkg: pkg = rospkg.get_package_name(test_file) if not pkg: print("Error: failed to determine package name for file '%s'; maybe you should supply the --package argument to rosunit?" % (test_file)) sys.exit(1) try: runner_result = None results = Result('rosunit', 0, 0, 0) test_case = BareTestCase(test_file, args[1:], retry=0, time_limit=time_limit, test_name=test_name, text_mode=options.text_mode, package_name=pkg) suite = unittest.TestSuite() suite.addTest(test_case) if options.text_mode: result = unittest.TextTestRunner(stream=sys.stdout, verbosity=2).run(suite) else: results_file = xml_results_file(pkg, test_name, True) # the is_rostest really just means "wrapper" xml_runner = create_xml_runner(pkg, test_name, results_file=results_file, is_rostest=True) runner_result = xml_runner.run(suite) finally: pmon.pmon_shutdown() # summary is worthless if textMode is on as we cannot scrape .xml results results = test_case.results if not options.text_mode: print_runner_summary(runner_result, results) else: print('WARNING: overall test result is not accurate when --text is enabled') if runner_result is not None and not runner_result.wasSuccessful(): sys.exit(1) elif results.num_errors or results.num_failures: sys.exit(2) if __name__ == '__main__': rosunitmain() ros-1.15.8/tools/rosunit/src/rosunit/xmlrunner.py000066400000000000000000000225271407615046500221720ustar00rootroot00000000000000""" XML Test Runner for PyUnit """ # Written by Sebastian Rittau and placed in # the Public Domain. With contributions by Paolo Borelli. from __future__ import print_function import codecs import os.path import re import sys import time import traceback import unittest try: from cStringIO import StringIO python2 = True except ImportError: from io import StringIO python2 = False import xml.etree.ElementTree as ET from xml.sax.saxutils import escape def cdata(cdata_text): return ''.format(cdata_text) class _TestInfo(object): """Information about a particular test. Used by _XMLTestResult.""" def __init__(self, test, time): (self._class, self._method) = test.id().rsplit('.', 1) self._time = time self._error = None self._failure = None @staticmethod def create_success(test, time): """Create a _TestInfo instance for a successful test.""" return _TestInfo(test, time) @staticmethod def create_failure(test, time, failure): """Create a _TestInfo instance for a failed test.""" info = _TestInfo(test, time) info._failure = failure return info @staticmethod def create_error(test, time, error): """Create a _TestInfo instance for an erroneous test.""" info = _TestInfo(test, time) info._error = error return info def xml(self): """Create an XML tag with information about this test case. """ testcase = ET.Element('testcase') testcase.set('classname', self._class) testcase.set('name', self._method) testcase.set('time', '%.4f' % self._time) if self._failure is not None: self._print_error(testcase, 'failure', self._failure) if self._error is not None: self._print_error(testcase, 'error', self._error) return testcase def print_report(self, stream): """Print information about this test case in XML format to the supplied stream. """ stream.write(ET.tostring(self.xml())) def print_report_text(self, stream): # stream.write(' ' % \ # { # "class": self._class, # "method": self._method, # "time": self._time, # }) stream.write('[Testcase: ' + self._method + ']') if self._failure is not None: stream.write(' ... FAILURE!\n') self._print_error_text(stream, 'failure', self._failure) if self._error is not None: stream.write(' ... ERROR!\n') self._print_error_text(stream, 'error', self._error) if self._failure is None and self._error is None: stream.write(' ... ok\n') def _print_error(self, testcase, tagname, error): """ Append an XML tag with information from a failure or error to the supplied testcase. """ tag = ET.SubElement(testcase, tagname) tag.set('type', str(error[0].__name__)) tb_stream = StringIO() traceback.print_tb(error[2], None, tb_stream) tag.text = '%s\n%s' % (str(error[1]), tb_stream.getvalue()) def _print_error_text(self, stream, tagname, error): """Print information from a failure or error to the supplied stream.""" text = escape(str(error[1])) stream.write('%s: %s\n' % (tagname.upper(), text)) tb_stream = StringIO() traceback.print_tb(error[2], None, tb_stream) stream.write(escape(tb_stream.getvalue())) stream.write('-' * 80 + '\n') class _XMLTestResult(unittest.TestResult): """A test result class that stores result as XML. Used by XMLTestRunner.""" def __init__(self, classname): unittest.TestResult.__init__(self) self._test_name = classname self._start_time = None self._tests = [] self._error = None self._failure = None def startTest(self, test): unittest.TestResult.startTest(self, test) self._error = None self._failure = None self._start_time = time.time() def stopTest(self, test): time_taken = time.time() - self._start_time unittest.TestResult.stopTest(self, test) if self._error: info = _TestInfo.create_error(test, time_taken, self._error) elif self._failure: info = _TestInfo.create_failure(test, time_taken, self._failure) else: info = _TestInfo.create_success(test, time_taken) self._tests.append(info) def addError(self, test, err): unittest.TestResult.addError(self, test, err) self._error = err def addFailure(self, test, err): unittest.TestResult.addFailure(self, test, err) self._failure = err def filter_nonprintable_text(self, text): pattern = r'[^\x09\x0A\x0D\x20-\x7E\x85\xA0-\xFF\u0100-\uD7FF\uE000-\uFDCF\uFDE0-\uFFFD]' if python2: pattern = pattern.decode('unicode_escape') else: pattern = codecs.decode(pattern, 'unicode_escape') invalid_chars = re.compile(pattern) def invalid_char_replacer(m): return '&#x' + ('%04X' % ord(m.group(0))) + ';' return re.sub(invalid_chars, invalid_char_replacer, str(text)) def xml(self, time_taken, out, err): """ @return XML tag representing the object @rtype: xml.etree.ElementTree.Element """ test_suite = ET.Element('testsuite') test_suite.set('errors', str(len(self.errors))) test_suite.set('failures', str(len(self.failures))) test_suite.set('name', self._test_name) test_suite.set('tests', str(self.testsRun)) test_suite.set('time', '%.3f' % time_taken) for info in self._tests: test_suite.append(info.xml()) system_out = ET.SubElement(test_suite, 'system-out') system_out.text = cdata(self.filter_nonprintable_text(out)) system_err = ET.SubElement(test_suite, 'system-err') system_err.text = cdata(self.filter_nonprintable_text(err)) return ET.ElementTree(test_suite) def print_report(self, stream, time_taken, out, err): """Prints the XML report to the supplied stream. The time the tests took to perform as well as the captured standard output and standard error streams must be passed in.a """ root = self.xml(time_taken, out, err).getroot() stream.write(ET.tostring(root, encoding='utf-8', method='xml').decode('utf-8')) def print_report_text(self, stream, time_taken, out, err): """Prints the text report to the supplied stream. The time the tests took to perform as well as the captured standard output and standard error streams must be passed in.a """ # stream.write('\n' % \ # { # "n": self._test_name, # "t": self.testsRun, # "time": time_taken, # }) for info in self._tests: info.print_report_text(stream) class XMLTestRunner(object): """A test runner that stores results in XML format compatible with JUnit. XMLTestRunner(stream=None) -> XML test runner The XML file is written to the supplied stream. If stream is None, the results are stored in a file called TEST-..xml in the current working directory (if not overridden with the path property), where and are the module and class name of the test class.""" def __init__(self, stream=None): self._stream = stream self._path = '.' def run(self, test): """Run the given test case or test suite.""" class_ = test.__class__ classname = class_.__module__ + '.' + class_.__name__ if self._stream is None: filename = 'TEST-%s.xml' % classname stream = open(os.path.join(self._path, filename), 'w') stream.write('\n') else: stream = self._stream result = _XMLTestResult(classname) start_time = time.time() # TODO: Python 2.5: Use the with statement old_stdout = sys.stdout old_stderr = sys.stderr sys.stdout = StringIO() sys.stderr = StringIO() try: test(result) try: out_s = sys.stdout.getvalue() except AttributeError: out_s = '' try: err_s = sys.stderr.getvalue() except AttributeError: err_s = '' finally: sys.stdout = old_stdout sys.stderr = old_stderr time_taken = time.time() - start_time result.print_report(stream, time_taken, out_s, err_s) stream.flush() result.print_report_text(sys.stdout, time_taken, out_s, err_s) return result def _set_path(self, path): self._path = path path = property( lambda self: self._path, _set_path, None, """The path where the XML files are stored. This property is ignored when the XML file is written to a file stream.""") ros-1.15.8/tools/rosunit/test/000077500000000000000000000000001407615046500162435ustar00rootroot00000000000000ros-1.15.8/tools/rosunit/test/__init__.py000066400000000000000000000000001407615046500203420ustar00rootroot00000000000000ros-1.15.8/tools/rosunit/test/dotname_cases.py000077500000000000000000000011201407615046500214170ustar00rootroot00000000000000import unittest class CaseA(unittest.TestCase): def runTest(self): self.assertTrue(True) class CaseB(unittest.TestCase): def runTest(self): self.assertTrue(True) class DotnameLoadingSuite(unittest.TestSuite): def __init__(self): super(DotnameLoadingSuite, self).__init__() self.addTest(CaseA()) self.addTest(CaseB()) class DotnameLoadingTest(unittest.TestCase): def test_a(self): self.assertTrue(True) def test_b(self): self.assertTrue(True) class NotTestCase(): def not_test(self): pass ros-1.15.8/tools/rosunit/test/test_dotname.py000077500000000000000000000036361407615046500213160ustar00rootroot00000000000000#!/usr/bin/env python # This file should be run using a non-ros unit test framework such as nose using # nosetests test_dotname.py. Alternatively, just run with python test_dotname.py. # You will get the output from rostest as well. import unittest from dotname_cases import DotnameLoadingTest, NotTestCase import rosunit class TestDotnameLoading(unittest.TestCase): def test_class_basic(self): rosunit.unitrun('test_rosunit', 'test_class_basic', DotnameLoadingTest) def test_class_dotname(self): rosunit.unitrun('test_rosunit', 'test_class_dotname', 'test.dotname_cases.DotnameLoadingTest') def test_method_dotname(self): rosunit.unitrun('test_rosunit', 'test_method_dotname', 'test.dotname_cases.DotnameLoadingTest.test_a') def test_suite_dotname(self): rosunit.unitrun('test_rosunit', 'test_suite_dotname', 'test.dotname_cases.DotnameLoadingSuite') def test_class_basic_nottest(self): # class which exists but is not a TestCase with self.assertRaises(SystemExit): rosunit.unitrun('test_rosunit', 'test_class_basic_nottest', NotTestCase) def test_class_dotname_nottest(self): # class which exists but is not a valid test with self.assertRaises(TypeError): rosunit.unitrun('test_rosunit', 'test_class_dotname_nottest', 'test.dotname_cases.NotTestCase') def test_class_dotname_noexist(self): # class which does not exist in the module with self.assertRaises(AttributeError): rosunit.unitrun('test_rosunit', 'test_class_dotname_noexist', 'test.dotname_cases.DotnameLoading') def test_method_dotname_noexist(self): # method which does not exist in the class with self.assertRaises(AttributeError): rosunit.unitrun('test_rosunit', 'test_method_dotname_noexist', 'test.dotname_cases.DotnameLoadingTest.not_method') if __name__ == '__main__': unittest.main() ros-1.15.8/tools/rosunit/test/test_junitxml.py000066400000000000000000000226321407615046500215330ustar00rootroot00000000000000#!/usr/bin/env python # Software License Agreement (BSD License) # # Copyright (c) 2008, Willow Garage, Inc. # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # * Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following # disclaimer in the documentation and/or other materials provided # with the distribution. # * Neither the name of Willow Garage, Inc. nor the names of its # contributors may be used to endorse or promote products derived # from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # # Revision $Id: $ import os import shutil import tempfile import unittest junitxml = None # Basic test of xmlresult functionality of reading gtest xml files and # summarizing their results into a new file. class MockResult(): def __init__(self, directory, filename, suites=[], noSuitesRoot=False): self.filename = os.path.join(directory, filename) self.suites = suites # whether to suppress root node self.noSuitesRoot = noSuitesRoot class MockSuite(): def __init__(self, cases, name, tests=0, errors=0, fail=0, time=1): self.cases = cases self.tests = tests self.time = time self.fail = fail self.errors = errors self.name = name class MockCase(): def __init__(self, name, errorList=[], classname='', time=1): self.classname = classname self.name = name self.time = time self.errorList = errorList class MockErrorType(Exception): def __init__(self, value, etype=''): self.value = value self.__name__ = value self.type = etype def _writeMockResultFile(result): """writes a test result as a gtest compatible test runner would do""" with open(result.filename, 'w') as f: f.write('\n') if len(result.suites) > 1 or result.noSuitesRoot is False: f.write('\n') for suite in result.suites: f.write('\n') for case in suite.cases: f.write('\n') for error in case.errorList: f.write('\n') f.write('\n') f.write('\n') if len(result.suites) > 1 or result.noSuitesRoot is False: f.write('\n') class XmlResultTestGeneration(unittest.TestCase): def setUp(self): global junitxml if junitxml is None: import rosunit.junitxml junitxml = rosunit.junitxml def tearDown(self): pass def testGenerateError(self): error = junitxml.TestError('error_type', 'error_text') error_str = error.xml() self.assertEquals(b"""<![CDATA[ error_text ]]>""", error_str) def testGenerateFailure(self): failure = junitxml.TestFailure('failure_type', 'failure_text') failure_str = failure.xml() self.assertEquals(b"""<![CDATA[ failure_text ]]>""", failure_str) def testGenerateTestCaseResult(self): testcase = junitxml.TestCaseResult('test_case') error = junitxml.TestError('error_type', 'error_text') error_str = error.xml() failure = junitxml.TestFailure('failure_type', 'failure_text') failure_str = failure.xml() testcase.add_error(error) testcase.add_failure(failure) testcase_str = testcase.xml() self.assertEquals(b"""<![CDATA[ failure_text ]]><![CDATA[ error_text ]]>""", testcase_str) class XmlResultTestRead(unittest.TestCase): def setUp(self): # lazy-import to get coverage global junitxml if junitxml is None: import rosunit.junitxml junitxml = rosunit.junitxml self.directory = tempfile.mkdtemp() # setting up mock results as dict so results can be checked individually self.mockresults = { 'empty': MockResult(self.directory, 'empty.xml', []), 'emptysuite': MockResult(self.directory, 'emptysuite.xml', [MockSuite([], 'emptySuite', 0, 0, 0, 0)]), 'succ1': MockResult(self.directory, 'succ1.xml', [MockSuite([MockCase('succCase')], 'succ1suite', 1, 0, 0, 1)]), 'err1': MockResult(self.directory, 'err1.xml', [MockSuite([MockCase('errCase')], 'err1suite', 1, 1, 0, 1)]), 'fail1': MockResult(self.directory, 'fail1.xml', [MockSuite([MockCase('failCase')], 'fail1suite', 1, 0, 1, 1)]), 'noroot': MockResult(self.directory, 'succ1.xml', [MockSuite([MockCase('succCase')], 'succ1suite', 1, 0, 0, 1)], noSuitesRoot=True), 'multicase': MockResult(self.directory, 'multicase.xml', [MockSuite([MockCase('succCase'), MockCase('errCase'), MockCase('failCase')], 'succ1suite', 3, 1, 1, time=3)]), 'multisuite': MockResult(self.directory, 'multisuite.xml', [MockSuite([MockCase('succCase')], 'succ1suite', 1, 0, 0, 1), MockSuite([MockCase('errCase')], 'err1suite', 1, 1, 0, 1), MockSuite([MockCase('failCase')], 'fail1suite', 1, 0, 1, 1)]) } for name, result in self.mockresults.items(): _writeMockResultFile(result) def tearDown(self): shutil.rmtree(self.directory) # pass def testReadNoSuites(self): result = junitxml.read(self.mockresults['empty'].filename, 'fooname') self.assert_(result is not None) self.assertEquals(0.0, result.time) self.assertEquals(0, result.num_tests) self.assertEquals(0, result.num_errors) self.assertEquals(0, result.num_failures) def testReadEmptySuite(self): result = junitxml.read(self.mockresults['emptysuite'].filename, 'fooname') self.assert_(result is not None) self.assertEquals(0.0, result.time) self.assertEquals(0, result.num_tests) self.assertEquals(0, result.num_errors) self.assertEquals(0, result.num_failures) def testReadSuccess(self): result = junitxml.read(self.mockresults['succ1'].filename, 'fooname') self.assert_(result is not None) self.assertEquals(1.0, result.time) self.assertEquals(1, result.num_tests) self.assertEquals(0, result.num_errors) self.assertEquals(0, result.num_failures) def testReadError(self): result = junitxml.read(self.mockresults['err1'].filename, 'fooname') self.assert_(result is not None) self.assertEquals(1.0, result.time) self.assertEquals(1, result.num_tests) self.assertEquals(1, result.num_errors) self.assertEquals(0, result.num_failures) def testReadFail(self): result = junitxml.read(self.mockresults['fail1'].filename, 'fooname') self.assert_(result is not None) self.assertEquals(1.0, result.time) self.assertEquals(1, result.num_tests) self.assertEquals(0, result.num_errors) self.assertEquals(1, result.num_failures) def testReadMulticase(self): result = junitxml.read(self.mockresults['multicase'].filename, 'fooname') self.assert_(result is not None) self.assertEquals(3.0, result.time) self.assertEquals(3, result.num_tests) self.assertEquals(1, result.num_errors) self.assertEquals(1, result.num_failures) def testReadMultisuite(self): result = junitxml.read(self.mockresults['multisuite'].filename, 'fooname') self.assert_(result is not None) self.assertEquals(3.0, result.time) self.assertEquals(3, result.num_tests) self.assertEquals(1, result.num_errors) self.assertEquals(1, result.num_failures) ros-1.15.8/tools/rosunit/test/test_xmlrunner.py000066400000000000000000000164311407615046500217130ustar00rootroot00000000000000#!/usr/bin/env python # This file should be run using a non-ros unit test framework such as nose using # nosetests test_dotname.py. Alternatively, just run with python test_dotname.py. # You will get the output from rostest as well. # Original code for xmlrunner written by Sebastian Rittau # and placed in the Public Domain. # With contributions by Paolo Borelli. # These tests refactored into a separate package by Edward Venator. from __future__ import print_function import re import sys import unittest try: from cStringIO import StringIO except ImportError: from io import StringIO from rosunit.xmlrunner import XMLTestRunner class XMLTestRunnerTest(unittest.TestCase): def setUp(self): self._stream = StringIO() def _try_test_run(self, test_class, expected): """Run the test suite against the supplied test class and compare the XML result against the expected XML string. Fail if the expected string doesn't match the actual string. All time attribute in the expected string should have the value "0.000". All error and failure messages are reduced to "Foobar".""" runner = XMLTestRunner(self._stream) runner.run(unittest.makeSuite(test_class)) got = self._stream.getvalue() # Replace all time="X.YYY" attributes by time="0.000" to enable a # simple string comparison. got = re.sub(r'time="\d+\.\d+"', 'time="0.000"', got) # Likewise, replace all failure and error messages by a simple "Foobar" # string. got = re.sub(r'(?s).*?', r'Foobar', got) got = re.sub(r'(?s).*?', r'Foobar', got) self.assertIn(got, expected) def test_no_tests(self): """Regression test: Check whether a test run without any tests matches a previous run. """ class TestTest(unittest.TestCase): pass self._try_test_run(TestTest, ["""<![CDATA[\n\n]]><![CDATA[\n\n]]>"""]) def test_success(self): """Regression test: Check whether a test run with a successful test matches a previous run. """ class TestTest(unittest.TestCase): def test_foo(self): pass py2_expected = """<![CDATA[\n\n]]><![CDATA[\n\n]]>""" py3_expected = py2_expected.replace('TestTest', 'XMLTestRunnerTest.test_success.<locals>.TestTest') self._try_test_run(TestTest, [py2_expected, py3_expected]) def test_failure(self): """Regression test: Check whether a test run with a failing test matches a previous run. """ class TestTest(unittest.TestCase): def test_foo(self): self.assert_(False) py2_expected = """Foobar<![CDATA[\n\n]]><![CDATA[\n\n]]>""" py3_expected = py2_expected.replace('TestTest', 'XMLTestRunnerTest.test_failure.<locals>.TestTest') self._try_test_run(TestTest, [py2_expected, py3_expected]) def test_error(self): """Regression test: Check whether a test run with a erroneous test matches a previous run. """ class TestTest(unittest.TestCase): def test_foo(self): raise IndexError() py2_expected = """Foobar<![CDATA[\n\n]]><![CDATA[\n\n]]>""" py3_expected = py2_expected.replace('TestTest', 'XMLTestRunnerTest.test_error.<locals>.TestTest') self._try_test_run(TestTest, [py2_expected, py3_expected]) def test_stdout_capture(self): """Regression test: Check whether a test run with output to stdout matches a previous run. """ class TestTest(unittest.TestCase): def test_foo(self): print('Foo > Bar') py2_expected = """<![CDATA[\nFoo > Bar\n\n]]><![CDATA[\n\n]]>""" py3_expected = py2_expected.replace('TestTest', 'XMLTestRunnerTest.test_stdout_capture.<locals>.TestTest') self._try_test_run(TestTest, [py2_expected, py3_expected]) def test_stderr_capture(self): """Regression test: Check whether a test run with output to stderr matches a previous run. """ class TestTest(unittest.TestCase): def test_foo(self): print('Foo > Bar', file=sys.stderr) py2_expected = """<![CDATA[\n\n]]><![CDATA[\nFoo > Bar\n\n]]>""" py3_expected = py2_expected.replace('TestTest', 'XMLTestRunnerTest.test_stderr_capture.<locals>.TestTest') self._try_test_run(TestTest, [py2_expected, py3_expected]) class NullStream(object): """A file-like object that discards everything written to it.""" def write(self, buffer): pass def test_unittests_changing_stdout(self): """Check whether the XMLTestRunner recovers gracefully from unit tests that change stdout, but don't change it back properly. """ class TestTest(unittest.TestCase): def test_foo(self): sys.stdout = XMLTestRunnerTest.NullStream() runner = XMLTestRunner(self._stream) runner.run(unittest.makeSuite(TestTest)) def test_unittests_changing_stderr(self): """Check whether the XMLTestRunner recovers gracefully from unit tests that change stderr, but don't change it back properly. """ class TestTest(unittest.TestCase): def test_foo(self): sys.stderr = XMLTestRunnerTest.NullStream() runner = XMLTestRunner(self._stream) runner.run(unittest.makeSuite(TestTest)) class XMLTestProgram(unittest.TestProgram): def runTests(self): if self.testRunner is None: self.testRunner = XMLTestRunner() unittest.TestProgram.runTests(self) main = XMLTestProgram if __name__ == '__main__': main(module=None)