Package roswtf :: Module packages
[frames] | no frames]

Source Code for Module roswtf.packages

  1  # Software License Agreement (BSD License) 
  2  # 
  3  # Copyright (c) 2009, Willow Garage, Inc. 
  4  # All rights reserved. 
  5  # 
  6  # Redistribution and use in source and binary forms, with or without 
  7  # modification, are permitted provided that the following conditions 
  8  # are met: 
  9  # 
 10  #  * Redistributions of source code must retain the above copyright 
 11  #    notice, this list of conditions and the following disclaimer. 
 12  #  * Redistributions in binary form must reproduce the above 
 13  #    copyright notice, this list of conditions and the following 
 14  #    disclaimer in the documentation and/or other materials provided 
 15  #    with the distribution. 
 16  #  * Neither the name of Willow Garage, Inc. nor the names of its 
 17  #    contributors may be used to endorse or promote products derived 
 18  #    from this software without specific prior written permission. 
 19  # 
 20  # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
 21  # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
 22  # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
 23  # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
 24  # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
 25  # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
 26  # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
 27  # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
 28  # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
 29  # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
 30  # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
 31  # POSSIBILITY OF SUCH DAMAGE. 
 32  # 
 33  # Revision $Id: packages.py 14270 2011-07-12 21:36:39Z kwc $ 
 34   
 35  import os 
 36  import time 
 37   
 38  from roswtf.environment import paths, is_executable 
 39  from roswtf.rules import warning_rule, error_rule 
 40   
 41  import roslib.msgs 
 42  import roslib.packages 
 43  import roslib.srvs 
 44   
 45  ## look for unknown tags in manifest 
46 -def manifest_valid(ctx):
47 errors = [] 48 if ctx.manifest is not None: 49 errors = ["<%s>"%t.tagName for t in ctx.manifest.unknown_tags] 50 return errors
51 52 ## look for unbuilt .msg files
53 -def msgs_built(ctx):
54 unbuilt = set([]) 55 for pkg in ctx.pkgs: 56 pkg_dir = roslib.packages.get_pkg_dir(pkg) 57 mtypes = roslib.msgs.list_msg_types(pkg, False) 58 for t in mtypes: 59 expected = [os.path.join('msg_gen', 'cpp', 'include', pkg, '%s.h'%t), 60 # roslisp is no longer builtin 61 #os.path.join('msg', 'lisp', pkg, '%s.lisp'%t), 62 os.path.join('src', pkg, 'msg', '_%s.py'%t)] 63 for e in expected: 64 if not os.path.isfile(os.path.join(pkg_dir, e)): 65 unbuilt.add(pkg) 66 if 'roslib' in unbuilt: 67 unbuilt.remove('roslib') 68 return list(unbuilt)
69 70 ## look for unbuilt .srv files
71 -def srvs_built(ctx):
72 unbuilt = set([]) 73 for pkg in ctx.pkgs: 74 pkg_dir = roslib.packages.get_pkg_dir(pkg) 75 mtypes = roslib.srvs.list_srv_types(pkg, False) 76 for t in mtypes: 77 expected = [os.path.join('srv_gen', 'cpp', 'include', pkg, '%s.h'%t), 78 # roslisp is no longer builtin 79 #os.path.join('srv', 'lisp', pkg, '%s.lisp'%t), 80 os.path.join('src', pkg, 'srv', '_%s.py'%t)] 81 for e in expected: 82 if not os.path.isfile(os.path.join(pkg_dir, e)): 83 unbuilt.add(pkg) 84 return list(unbuilt)
85
86 -def _manifest_msg_srv_export(ctx, type_):
87 exist = [] 88 for pkg in ctx.pkgs: 89 pkg_dir = roslib.packages.get_pkg_dir(pkg) 90 d = os.path.join(pkg_dir, type_) 91 if os.path.isdir(d): 92 files = os.listdir(d) 93 if filter(lambda x: x.endswith('.'+type_), files): 94 m_file = roslib.manifest.manifest_file(pkg, True) 95 m = roslib.manifest.parse_file(m_file) 96 cflags = m.get_export('cpp', 'cflags') 97 include = '-I${prefix}/%s/cpp'%type_ 98 if filter(lambda x: include in x, cflags): 99 exist.append(pkg) 100 return exist
101
102 -def manifest_msg_srv_export(ctx):
103 msgs = set(_manifest_msg_srv_export(ctx, 'msg')) 104 srvs = set(_manifest_msg_srv_export(ctx, 'srv')) 105 errors = [] 106 107 for pkg in msgs & srvs: 108 errors.append('%s: -I${prefix}/msg/cpp -I${prefix}/srv/cpp'%pkg) 109 for pkg in msgs - srvs: 110 errors.append('%s: -I${prefix}/msg/cpp'%pkg) 111 for pkg in srvs - msgs: 112 errors.append('%s: -I${prefix}/srv/cpp'%pkg) 113 return errors
114 115
116 -def _check_for_rpath_flags(pkg, lflags):
117 if not lflags: 118 return 119 L_arg = '-L' 120 Wl_arg = '-Wl' 121 rpath_arg = '-rpath' 122 lflags_args = lflags.split() 123 # Collect the args we care about 124 L_args = [] 125 rpath_args = [] 126 i = 0 127 while i < len(lflags_args): 128 f = lflags_args[i] 129 if f.startswith(L_arg) and len(f) > len(L_arg): 130 # normpath avoids problems with trailing slash vs. no trailing 131 # slash, #2284 132 L_args.append(os.path.normpath(f[len(L_arg):])) 133 elif f == L_arg and (i+1) < len(lflags_args): 134 i += 1 135 # normpath avoids problems with trailing slash vs. no trailing 136 # slash, #2284 137 L_args.append(os.path.normpath(lflags_args[i])) 138 elif f.startswith(Wl_arg) and len(f) > len(Wl_arg): 139 # -Wl can be followed by multiple, comma-separated arguments, 140 # #2284. 141 args = f.split(',') 142 j = 1 143 while j < (len(args) - 1): 144 if args[j] == rpath_arg: 145 # normpath avoids problems with trailing slash vs. no trailing 146 # slash, #2284 147 rpath_args.append(os.path.normpath(args[j+1])) 148 j += 2 149 else: 150 j += 1 151 i += 1 152 # Check for parallelism; not efficient, but these strings are short 153 for f in L_args: 154 if f not in rpath_args: 155 return '%s: found flag "-L%s", but no matching "-Wl,-rpath,%s"'%(pkg, f,f) 156 for f in rpath_args: 157 if f not in L_args: 158 return '%s: found flag "-Wl,-rpath,%s", but no matching "-L%s"'%(pkg, f,f)
159
160 -def manifest_rpath_flags(ctx):
161 warn = [] 162 for pkg in ctx.pkgs: 163 # Use rospack to get lflags, so that they can be bash-expanded 164 # first, #2286. 165 import subprocess 166 lflags = subprocess.Popen(['rospack', 'export', '--lang=cpp', '--attrib=lflags', pkg], stdout=subprocess.PIPE).communicate()[0] 167 err_msg = _check_for_rpath_flags(pkg, lflags) 168 if err_msg: 169 warn.append(err_msg) 170 return warn
171 172 #CMake missing genmsg/gensrv
173 -def _cmake_genmsg_gensrv(ctx, type_):
174 missing = [] 175 cmds = ['rosbuild_gen%s()'%type_, 'gen%s()'%type_] 176 for pkg in ctx.pkgs: 177 pkg_dir = roslib.packages.get_pkg_dir(pkg) 178 d = os.path.join(pkg_dir, type_) 179 if os.path.isdir(d): 180 files = os.listdir(d) 181 if filter(lambda x: x.endswith('.'+type_), files): 182 c_file = os.path.join(pkg_dir, 'CMakeLists.txt') 183 if os.path.isfile(c_file): 184 f = open(c_file, 'r') 185 try: 186 for l in f: 187 # ignore all whitespace 188 l = l.strip().replace(' ', '') 189 found_cmd = False 190 for cmd in cmds: 191 if l.startswith(cmd): 192 found_cmd = True 193 if found_cmd: 194 break 195 else: 196 missing.append(pkg) 197 finally: 198 f.close() 199 200 if 'roslib' in missing: 201 missing.remove('roslib') 202 203 return missing
204
205 -def cmake_genmsg(ctx):
206 return _cmake_genmsg_gensrv(ctx, 'msg')
207 -def cmake_gensrv(ctx):
208 return _cmake_genmsg_gensrv(ctx, 'srv')
209 210 #TODO: not sure if we should have this rule or not as it _does_ fail on ros-pkg
211 -def makefile_exists(ctx):
212 missing = [] 213 for pkg in ctx.pkgs: 214 pkg_dir = roslib.packages.get_pkg_dir(pkg) 215 p = os.path.join(pkg_dir, 'Makefile') 216 if not os.path.isfile(p): 217 missing.append(pkg) 218 return missing
219
220 -def rospack_time(ctx):
221 start = time.time() 222 roslib.rospack.rospackexec(['deps', 'roslib']) 223 # arbitrarily tuned 224 return (time.time() - start) > 0.5
225
226 -def cmakelists_package_valid(ctx):
227 missing = [] 228 for pkg in ctx.pkgs: 229 found = False 230 pkg_dir = roslib.packages.get_pkg_dir(pkg) 231 p = os.path.join(pkg_dir, 'CMakeLists.txt') 232 if not os.path.isfile(p): 233 continue #covered by cmakelists_exists 234 f = open(p) 235 try: 236 for l in f: 237 # ignore all whitespace 238 l = l.strip().replace(' ', '') 239 240 if l.startswith('rospack('): 241 found = True 242 if not l.startswith('rospack(%s)'%pkg): 243 missing.append(pkg) 244 break 245 # there may be more than 1 rospack() declaration, so scan through entire 246 # CMakeLists 247 elif l.startswith("rosbuild_init()"): 248 found = True 249 if not found: 250 missing.append(pkg) 251 finally: 252 f.close() 253 # rospack exists outside our build system 254 if 'rospack' in missing: 255 missing.remove('rospack') 256 return missing
257 258 warnings = [ 259 # disabling as it is too common and regular 260 #(makefile_exists, 261 # "The following packages have no Makefile:"), 262 (cmakelists_package_valid, 263 "The following packages have incorrect rospack() declarations in CMakeLists.txt.\nPlease switch to using rosbuild_init():"), 264 (rospack_time, 265 "rospack is running very slowly. Consider running 'rospack profile' to find slow areas of your code tree."), 266 267 (manifest_msg_srv_export, 268 'The following packages have msg/srv-related cflags exports that are no longer necessary\n\t<export>\n\t\t<cpp cflags="..."\n\t</export>:'), 269 (cmake_genmsg, 270 'The following packages need rosbuild_genmsg() in CMakeLists.txt:'), 271 (cmake_gensrv, 272 'The following packages need rosbuild_gensrv() in CMakeLists.txt:'), 273 (manifest_valid, "%(pkg)s/manifest.xml has unrecognized tags:"), 274 275 ] 276 errors = [ 277 (msgs_built, "Messages have not been built in the following package(s).\nYou can fix this by typing 'rosmake <package-name>':"), 278 (srvs_built, "Services have not been built in the following package(s).\nYou can fix this by typing 'rosmake <package-name>':"), 279 (manifest_rpath_flags, "The following packages have rpath issues in manifest.xml:"), 280 ] 281
282 -def wtf_check(ctx):
283 # no package in context to verify 284 if not ctx.pkgs: 285 return 286 287 for r in warnings: 288 warning_rule(r, r[0](ctx), ctx) 289 for r in errors: 290 error_rule(r, r[0](ctx), ctx)
291