1#! /usr/bin/env python 2# encoding: utf-8 3# Thomas Nagy, 2010 (ita) 4 5""" 6This file is provided to enable compatibility with waf 1.5 7It was enabled by default in waf 1.6, but it is not used in waf 1.7 8""" 9 10import sys 11from waflib import ConfigSet, Logs, Options, Scripting, Task, Build, Configure, Node, Runner, TaskGen, Utils, Errors, Context 12 13# the following is to bring some compatibility with waf 1.5 "import waflib.Configure → import Configure" 14sys.modules['Environment'] = ConfigSet 15ConfigSet.Environment = ConfigSet.ConfigSet 16 17sys.modules['Logs'] = Logs 18sys.modules['Options'] = Options 19sys.modules['Scripting'] = Scripting 20sys.modules['Task'] = Task 21sys.modules['Build'] = Build 22sys.modules['Configure'] = Configure 23sys.modules['Node'] = Node 24sys.modules['Runner'] = Runner 25sys.modules['TaskGen'] = TaskGen 26sys.modules['Utils'] = Utils 27sys.modules['Constants'] = Context 28Context.SRCDIR = '' 29Context.BLDDIR = '' 30 31from waflib.Tools import c_preproc 32sys.modules['preproc'] = c_preproc 33 34from waflib.Tools import c_config 35sys.modules['config_c'] = c_config 36 37ConfigSet.ConfigSet.copy = ConfigSet.ConfigSet.derive 38ConfigSet.ConfigSet.set_variant = Utils.nada 39 40Utils.pproc = Utils.subprocess 41 42Build.BuildContext.add_subdirs = Build.BuildContext.recurse 43Build.BuildContext.new_task_gen = Build.BuildContext.__call__ 44Build.BuildContext.is_install = 0 45Node.Node.relpath_gen = Node.Node.path_from 46 47Utils.pproc = Utils.subprocess 48Utils.get_term_cols = Logs.get_term_cols 49 50def cmd_output(cmd, **kw): 51 52 silent = False 53 if 'silent' in kw: 54 silent = kw['silent'] 55 del(kw['silent']) 56 57 if 'e' in kw: 58 tmp = kw['e'] 59 del(kw['e']) 60 kw['env'] = tmp 61 62 kw['shell'] = isinstance(cmd, str) 63 kw['stdout'] = Utils.subprocess.PIPE 64 if silent: 65 kw['stderr'] = Utils.subprocess.PIPE 66 67 try: 68 p = Utils.subprocess.Popen(cmd, **kw) 69 output = p.communicate()[0] 70 except OSError as e: 71 raise ValueError(str(e)) 72 73 if p.returncode: 74 if not silent: 75 msg = "command execution failed: %s -> %r" % (cmd, str(output)) 76 raise ValueError(msg) 77 output = '' 78 return output 79Utils.cmd_output = cmd_output 80 81def name_to_obj(self, s, env=None): 82 if Logs.verbose: 83 Logs.warn('compat: change "name_to_obj(name, env)" by "get_tgen_by_name(name)"') 84 return self.get_tgen_by_name(s) 85Build.BuildContext.name_to_obj = name_to_obj 86 87def env_of_name(self, name): 88 try: 89 return self.all_envs[name] 90 except KeyError: 91 Logs.error('no such environment: '+name) 92 return None 93Build.BuildContext.env_of_name = env_of_name 94 95 96def set_env_name(self, name, env): 97 self.all_envs[name] = env 98 return env 99Configure.ConfigurationContext.set_env_name = set_env_name 100 101def retrieve(self, name, fromenv=None): 102 try: 103 env = self.all_envs[name] 104 except KeyError: 105 env = ConfigSet.ConfigSet() 106 self.prepare_env(env) 107 self.all_envs[name] = env 108 else: 109 if fromenv: 110 Logs.warn('The environment %s may have been configured already', name) 111 return env 112Configure.ConfigurationContext.retrieve = retrieve 113 114Configure.ConfigurationContext.sub_config = Configure.ConfigurationContext.recurse 115Configure.ConfigurationContext.check_tool = Configure.ConfigurationContext.load 116Configure.conftest = Configure.conf 117Configure.ConfigurationError = Errors.ConfigurationError 118Utils.WafError = Errors.WafError 119 120Options.OptionsContext.sub_options = Options.OptionsContext.recurse 121Options.OptionsContext.tool_options = Context.Context.load 122Options.Handler = Options.OptionsContext 123 124Task.simple_task_type = Task.task_type_from_func = Task.task_factory 125Task.Task.classes = Task.classes 126 127def setitem(self, key, value): 128 if key.startswith('CCFLAGS'): 129 key = key[1:] 130 self.table[key] = value 131ConfigSet.ConfigSet.__setitem__ = setitem 132 133@TaskGen.feature('d') 134@TaskGen.before('apply_incpaths') 135def old_importpaths(self): 136 if getattr(self, 'importpaths', []): 137 self.includes = self.importpaths 138 139from waflib import Context 140eld = Context.load_tool 141def load_tool(*k, **kw): 142 ret = eld(*k, **kw) 143 if 'set_options' in ret.__dict__: 144 if Logs.verbose: 145 Logs.warn('compat: rename "set_options" to options') 146 ret.options = ret.set_options 147 if 'detect' in ret.__dict__: 148 if Logs.verbose: 149 Logs.warn('compat: rename "detect" to "configure"') 150 ret.configure = ret.detect 151 return ret 152Context.load_tool = load_tool 153 154def get_curdir(self): 155 return self.path.abspath() 156Context.Context.curdir = property(get_curdir, Utils.nada) 157 158def get_srcdir(self): 159 return self.srcnode.abspath() 160Configure.ConfigurationContext.srcdir = property(get_srcdir, Utils.nada) 161 162def get_blddir(self): 163 return self.bldnode.abspath() 164Configure.ConfigurationContext.blddir = property(get_blddir, Utils.nada) 165 166Configure.ConfigurationContext.check_message_1 = Configure.ConfigurationContext.start_msg 167Configure.ConfigurationContext.check_message_2 = Configure.ConfigurationContext.end_msg 168 169rev = Context.load_module 170def load_module(path, encoding=None): 171 ret = rev(path, encoding) 172 if 'set_options' in ret.__dict__: 173 if Logs.verbose: 174 Logs.warn('compat: rename "set_options" to "options" (%r)', path) 175 ret.options = ret.set_options 176 if 'srcdir' in ret.__dict__: 177 if Logs.verbose: 178 Logs.warn('compat: rename "srcdir" to "top" (%r)', path) 179 ret.top = ret.srcdir 180 if 'blddir' in ret.__dict__: 181 if Logs.verbose: 182 Logs.warn('compat: rename "blddir" to "out" (%r)', path) 183 ret.out = ret.blddir 184 Utils.g_module = Context.g_module 185 Options.launch_dir = Context.launch_dir 186 return ret 187Context.load_module = load_module 188 189old_post = TaskGen.task_gen.post 190def post(self): 191 self.features = self.to_list(self.features) 192 if 'cc' in self.features: 193 if Logs.verbose: 194 Logs.warn('compat: the feature cc does not exist anymore (use "c")') 195 self.features.remove('cc') 196 self.features.append('c') 197 if 'cstaticlib' in self.features: 198 if Logs.verbose: 199 Logs.warn('compat: the feature cstaticlib does not exist anymore (use "cstlib" or "cxxstlib")') 200 self.features.remove('cstaticlib') 201 self.features.append(('cxx' in self.features) and 'cxxstlib' or 'cstlib') 202 if getattr(self, 'ccflags', None): 203 if Logs.verbose: 204 Logs.warn('compat: "ccflags" was renamed to "cflags"') 205 self.cflags = self.ccflags 206 return old_post(self) 207TaskGen.task_gen.post = post 208 209def waf_version(*k, **kw): 210 Logs.warn('wrong version (waf_version was removed in waf 1.6)') 211Utils.waf_version = waf_version 212 213 214import os 215@TaskGen.feature('c', 'cxx', 'd') 216@TaskGen.before('apply_incpaths', 'propagate_uselib_vars') 217@TaskGen.after('apply_link', 'process_source') 218def apply_uselib_local(self): 219 """ 220 process the uselib_local attribute 221 execute after apply_link because of the execution order set on 'link_task' 222 """ 223 env = self.env 224 from waflib.Tools.ccroot import stlink_task 225 226 # 1. the case of the libs defined in the project (visit ancestors first) 227 # the ancestors external libraries (uselib) will be prepended 228 self.uselib = self.to_list(getattr(self, 'uselib', [])) 229 self.includes = self.to_list(getattr(self, 'includes', [])) 230 names = self.to_list(getattr(self, 'uselib_local', [])) 231 get = self.bld.get_tgen_by_name 232 seen = set() 233 seen_uselib = set() 234 tmp = Utils.deque(names) # consume a copy of the list of names 235 if tmp: 236 if Logs.verbose: 237 Logs.warn('compat: "uselib_local" is deprecated, replace by "use"') 238 while tmp: 239 lib_name = tmp.popleft() 240 # visit dependencies only once 241 if lib_name in seen: 242 continue 243 244 y = get(lib_name) 245 y.post() 246 seen.add(lib_name) 247 248 # object has ancestors to process (shared libraries): add them to the end of the list 249 if getattr(y, 'uselib_local', None): 250 for x in self.to_list(getattr(y, 'uselib_local', [])): 251 obj = get(x) 252 obj.post() 253 if getattr(obj, 'link_task', None): 254 if not isinstance(obj.link_task, stlink_task): 255 tmp.append(x) 256 257 # link task and flags 258 if getattr(y, 'link_task', None): 259 260 link_name = y.target[y.target.rfind(os.sep) + 1:] 261 if isinstance(y.link_task, stlink_task): 262 env.append_value('STLIB', [link_name]) 263 else: 264 # some linkers can link against programs 265 env.append_value('LIB', [link_name]) 266 267 # the order 268 self.link_task.set_run_after(y.link_task) 269 270 # for the recompilation 271 self.link_task.dep_nodes += y.link_task.outputs 272 273 # add the link path too 274 tmp_path = y.link_task.outputs[0].parent.bldpath() 275 if not tmp_path in env['LIBPATH']: 276 env.prepend_value('LIBPATH', [tmp_path]) 277 278 # add ancestors uselib too - but only propagate those that have no staticlib defined 279 for v in self.to_list(getattr(y, 'uselib', [])): 280 if v not in seen_uselib: 281 seen_uselib.add(v) 282 if not env['STLIB_' + v]: 283 if not v in self.uselib: 284 self.uselib.insert(0, v) 285 286 # if the library task generator provides 'export_includes', add to the include path 287 # the export_includes must be a list of paths relative to the other library 288 if getattr(y, 'export_includes', None): 289 self.includes.extend(y.to_incnodes(y.export_includes)) 290 291@TaskGen.feature('cprogram', 'cxxprogram', 'cstlib', 'cxxstlib', 'cshlib', 'cxxshlib', 'dprogram', 'dstlib', 'dshlib') 292@TaskGen.after('apply_link') 293def apply_objdeps(self): 294 "add the .o files produced by some other object files in the same manner as uselib_local" 295 names = getattr(self, 'add_objects', []) 296 if not names: 297 return 298 names = self.to_list(names) 299 300 get = self.bld.get_tgen_by_name 301 seen = [] 302 while names: 303 x = names[0] 304 305 # visit dependencies only once 306 if x in seen: 307 names = names[1:] 308 continue 309 310 # object does not exist ? 311 y = get(x) 312 313 # object has ancestors to process first ? update the list of names 314 if getattr(y, 'add_objects', None): 315 added = 0 316 lst = y.to_list(y.add_objects) 317 lst.reverse() 318 for u in lst: 319 if u in seen: 320 continue 321 added = 1 322 names = [u]+names 323 if added: 324 continue # list of names modified, loop 325 326 # safe to process the current object 327 y.post() 328 seen.append(x) 329 330 for t in getattr(y, 'compiled_tasks', []): 331 self.link_task.inputs.extend(t.outputs) 332 333@TaskGen.after('apply_link') 334def process_obj_files(self): 335 if not hasattr(self, 'obj_files'): 336 return 337 for x in self.obj_files: 338 node = self.path.find_resource(x) 339 self.link_task.inputs.append(node) 340 341@TaskGen.taskgen_method 342def add_obj_file(self, file): 343 """Small example on how to link object files as if they were source 344 obj = bld.create_obj('cc') 345 obj.add_obj_file('foo.o')""" 346 if not hasattr(self, 'obj_files'): 347 self.obj_files = [] 348 if not 'process_obj_files' in self.meths: 349 self.meths.append('process_obj_files') 350 self.obj_files.append(file) 351 352 353old_define = Configure.ConfigurationContext.__dict__['define'] 354 355@Configure.conf 356def define(self, key, val, quote=True, comment=''): 357 old_define(self, key, val, quote, comment) 358 if key.startswith('HAVE_'): 359 self.env[key] = 1 360 361old_undefine = Configure.ConfigurationContext.__dict__['undefine'] 362 363@Configure.conf 364def undefine(self, key, comment=''): 365 old_undefine(self, key, comment) 366 if key.startswith('HAVE_'): 367 self.env[key] = 0 368 369# some people might want to use export_incdirs, but it was renamed 370def set_incdirs(self, val): 371 Logs.warn('compat: change "export_incdirs" by "export_includes"') 372 self.export_includes = val 373TaskGen.task_gen.export_incdirs = property(None, set_incdirs) 374 375def install_dir(self, path): 376 if not path: 377 return [] 378 379 destpath = Utils.subst_vars(path, self.env) 380 381 if self.is_install > 0: 382 Logs.info('* creating %s', destpath) 383 Utils.check_dir(destpath) 384 elif self.is_install < 0: 385 Logs.info('* removing %s', destpath) 386 try: 387 os.remove(destpath) 388 except OSError: 389 pass 390Build.BuildContext.install_dir = install_dir 391 392# before/after names 393repl = {'apply_core': 'process_source', 394 'apply_lib_vars': 'process_source', 395 'apply_obj_vars': 'propagate_uselib_vars', 396 'exec_rule': 'process_rule' 397} 398def after(*k): 399 k = [repl.get(key, key) for key in k] 400 return TaskGen.after_method(*k) 401 402def before(*k): 403 k = [repl.get(key, key) for key in k] 404 return TaskGen.before_method(*k) 405TaskGen.before = before 406 407