compat15.py 12 KB

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