waf

FORK: waf with some random patches
git clone https://git.neptards.moe/neptards/waf.git
Log | Files | Refs | README

compat15.py (11813B)


      1 #! /usr/bin/env python
      2 # encoding: utf-8
      3 # Thomas Nagy, 2010 (ita)
      4 
      5 """
      6 This file is provided to enable compatibility with waf 1.5
      7 It was enabled by default in waf 1.6, but it is not used in waf 1.7
      8 """
      9 
     10 import sys
     11 from 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"
     14 sys.modules['Environment'] = ConfigSet
     15 ConfigSet.Environment = ConfigSet.ConfigSet
     16 
     17 sys.modules['Logs'] = Logs
     18 sys.modules['Options'] = Options
     19 sys.modules['Scripting'] = Scripting
     20 sys.modules['Task'] = Task
     21 sys.modules['Build'] = Build
     22 sys.modules['Configure'] = Configure
     23 sys.modules['Node'] = Node
     24 sys.modules['Runner'] = Runner
     25 sys.modules['TaskGen'] = TaskGen
     26 sys.modules['Utils'] = Utils
     27 sys.modules['Constants'] = Context
     28 Context.SRCDIR = ''
     29 Context.BLDDIR = ''
     30 
     31 from waflib.Tools import c_preproc
     32 sys.modules['preproc'] = c_preproc
     33 
     34 from waflib.Tools import c_config
     35 sys.modules['config_c'] = c_config
     36 
     37 ConfigSet.ConfigSet.copy = ConfigSet.ConfigSet.derive
     38 ConfigSet.ConfigSet.set_variant = Utils.nada
     39 
     40 Utils.pproc = Utils.subprocess
     41 
     42 Build.BuildContext.add_subdirs = Build.BuildContext.recurse
     43 Build.BuildContext.new_task_gen = Build.BuildContext.__call__
     44 Build.BuildContext.is_install = 0
     45 Node.Node.relpath_gen = Node.Node.path_from
     46 
     47 Utils.pproc = Utils.subprocess
     48 Utils.get_term_cols = Logs.get_term_cols
     49 
     50 def 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
     79 Utils.cmd_output = cmd_output
     80 
     81 def 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)
     85 Build.BuildContext.name_to_obj = name_to_obj
     86 
     87 def 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
     93 Build.BuildContext.env_of_name = env_of_name
     94 
     95 
     96 def set_env_name(self, name, env):
     97 	self.all_envs[name] = env
     98 	return env
     99 Configure.ConfigurationContext.set_env_name = set_env_name
    100 
    101 def 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
    112 Configure.ConfigurationContext.retrieve = retrieve
    113 
    114 Configure.ConfigurationContext.sub_config = Configure.ConfigurationContext.recurse
    115 Configure.ConfigurationContext.check_tool = Configure.ConfigurationContext.load
    116 Configure.conftest = Configure.conf
    117 Configure.ConfigurationError = Errors.ConfigurationError
    118 Utils.WafError = Errors.WafError
    119 
    120 Options.OptionsContext.sub_options = Options.OptionsContext.recurse
    121 Options.OptionsContext.tool_options = Context.Context.load
    122 Options.Handler = Options.OptionsContext
    123 
    124 Task.simple_task_type = Task.task_type_from_func = Task.task_factory
    125 Task.Task.classes = Task.classes
    126 
    127 def setitem(self, key, value):
    128 	if key.startswith('CCFLAGS'):
    129 		key = key[1:]
    130 	self.table[key] = value
    131 ConfigSet.ConfigSet.__setitem__ = setitem
    132 
    133 @TaskGen.feature('d')
    134 @TaskGen.before('apply_incpaths')
    135 def old_importpaths(self):
    136 	if getattr(self, 'importpaths', []):
    137 		self.includes = self.importpaths
    138 
    139 from waflib import Context
    140 eld = Context.load_tool
    141 def 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
    152 Context.load_tool = load_tool
    153 
    154 def get_curdir(self):
    155 	return self.path.abspath()
    156 Context.Context.curdir = property(get_curdir, Utils.nada)
    157 
    158 def get_srcdir(self):
    159 	return self.srcnode.abspath()
    160 Configure.ConfigurationContext.srcdir = property(get_srcdir, Utils.nada)
    161 
    162 def get_blddir(self):
    163 	return self.bldnode.abspath()
    164 Configure.ConfigurationContext.blddir = property(get_blddir, Utils.nada)
    165 
    166 Configure.ConfigurationContext.check_message_1 = Configure.ConfigurationContext.start_msg
    167 Configure.ConfigurationContext.check_message_2 = Configure.ConfigurationContext.end_msg
    168 
    169 rev = Context.load_module
    170 def 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
    187 Context.load_module = load_module
    188 
    189 old_post = TaskGen.task_gen.post
    190 def 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)
    207 TaskGen.task_gen.post = post
    208 
    209 def waf_version(*k, **kw):
    210 	Logs.warn('wrong version (waf_version was removed in waf 1.6)')
    211 Utils.waf_version = waf_version
    212 
    213 
    214 import os
    215 @TaskGen.feature('c', 'cxx', 'd')
    216 @TaskGen.before('apply_incpaths', 'propagate_uselib_vars')
    217 @TaskGen.after('apply_link', 'process_source')
    218 def 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')
    293 def 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')
    334 def 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
    342 def 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 
    353 old_define = Configure.ConfigurationContext.__dict__['define']
    354 
    355 @Configure.conf
    356 def 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 
    361 old_undefine = Configure.ConfigurationContext.__dict__['undefine']
    362 
    363 @Configure.conf
    364 def 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
    370 def set_incdirs(self, val):
    371 	Logs.warn('compat: change "export_incdirs" by "export_includes"')
    372 	self.export_includes = val
    373 TaskGen.task_gen.export_incdirs = property(None, set_incdirs)
    374 
    375 def 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
    390 Build.BuildContext.install_dir = install_dir
    391 
    392 # before/after names
    393 repl = {'apply_core': 'process_source',
    394 	'apply_lib_vars': 'process_source',
    395 	'apply_obj_vars': 'propagate_uselib_vars',
    396 	'exec_rule': 'process_rule'
    397 }
    398 def after(*k):
    399 	k = [repl.get(key, key) for key in k]
    400 	return TaskGen.after_method(*k)
    401 
    402 def before(*k):
    403 	k = [repl.get(key, key) for key in k]
    404 	return TaskGen.before_method(*k)
    405 TaskGen.before = before
    406