waf

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

eclipse.py (19719B)


      1 #! /usr/bin/env python
      2 # encoding: utf-8
      3 # Eclipse CDT 5.0 generator for Waf
      4 # Richard Quirk 2009-1011 (New BSD License)
      5 # Thomas Nagy 2011 (ported to Waf 1.6)
      6 
      7 """
      8 Usage:
      9 
     10 def options(opt):
     11 	opt.load('eclipse')
     12 
     13 To add additional targets beside standard ones (configure, dist, install, check)
     14 the environment ECLIPSE_EXTRA_TARGETS can be set (ie. to ['test', 'lint', 'docs'])
     15 
     16 $ waf configure eclipse
     17 """
     18 
     19 import sys, os
     20 from waflib import Utils, Logs, Context, Build, TaskGen, Scripting, Errors, Node
     21 from xml.dom.minidom import Document
     22 
     23 STANDARD_INCLUDES = [ '/usr/local/include', '/usr/include' ]
     24 
     25 oe_cdt = 'org.eclipse.cdt'
     26 cdt_mk = oe_cdt + '.make.core'
     27 cdt_core = oe_cdt + '.core'
     28 cdt_bld = oe_cdt + '.build.core'
     29 extbuilder_dir = '.externalToolBuilders'
     30 extbuilder_name = 'Waf_Builder.launch'
     31 settings_dir = '.settings'
     32 settings_name = 'language.settings.xml'
     33 
     34 class eclipse(Build.BuildContext):
     35 	cmd = 'eclipse'
     36 	fun = Scripting.default_cmd
     37 
     38 	def execute(self):
     39 		"""
     40 		Entry point
     41 		"""
     42 		self.restore()
     43 		if not self.all_envs:
     44 			self.load_envs()
     45 		self.recurse([self.run_dir])
     46 
     47 		appname = getattr(Context.g_module, Context.APPNAME, os.path.basename(self.srcnode.abspath()))
     48 		self.create_cproject(appname, pythonpath=self.env['ECLIPSE_PYTHON_PATH'])
     49 
     50 	# Helper to dump the XML document content to XML with UTF-8 encoding
     51 	def write_conf_to_xml(self, filename, document):
     52 		self.srcnode.make_node(filename).write(document.toprettyxml(encoding='UTF-8'), flags='wb')
     53 
     54 	def create_cproject(self, appname, workspace_includes=[], pythonpath=[]):
     55 		"""
     56 		Create the Eclipse CDT .project and .cproject files
     57 		@param appname The name that will appear in the Project Explorer
     58 		@param build The BuildContext object to extract includes from
     59 		@param workspace_includes Optional project includes to prevent
     60 			  "Unresolved Inclusion" errors in the Eclipse editor
     61 		@param pythonpath Optional project specific python paths
     62 		"""
     63 		hasc = hasjava = haspython = False
     64 		source_dirs = []
     65 		cpppath = self.env['CPPPATH']
     66 		javasrcpath = []
     67 		javalibpath = []
     68 		includes = STANDARD_INCLUDES
     69 		if sys.platform != 'win32':
     70 			cc = self.env.CC or self.env.CXX
     71 			if cc:
     72 				cmd = cc + ['-xc++', '-E', '-Wp,-v', '-']
     73 				try:
     74 					gccout = self.cmd_and_log(cmd, output=Context.STDERR, quiet=Context.BOTH, input='\n'.encode()).splitlines()
     75 				except Errors.WafError:
     76 					pass
     77 				else:
     78 					includes = []
     79 					for ipath in gccout:
     80 						if ipath.startswith(' /'):
     81 							includes.append(ipath[1:])
     82 			cpppath += includes
     83 		Logs.warn('Generating Eclipse CDT project files')
     84 
     85 		for g in self.groups:
     86 			for tg in g:
     87 				if not isinstance(tg, TaskGen.task_gen):
     88 					continue
     89 
     90 				tg.post()
     91 
     92 				# Add local Python modules paths to configuration so object resolving will work in IDE
     93 				# This may also contain generated files (ie. pyqt5 or protoc) that get picked from build
     94 				if 'py' in tg.features:
     95 					pypath = tg.path.relpath()
     96 					py_installfrom = getattr(tg, 'install_from', None)
     97 					if isinstance(py_installfrom, Node.Node):
     98 						pypath = py_installfrom.path_from(self.root.make_node(self.top_dir))
     99 					if pypath not in pythonpath:
    100 						pythonpath.append(pypath)
    101 					haspython = True
    102 
    103 				# Add Java source directories so object resolving works in IDE
    104 				# This may also contain generated files (ie. protoc) that get picked from build
    105 				if 'javac' in tg.features:
    106 					java_src = tg.path.relpath()
    107 					java_srcdir = getattr(tg.javac_task, 'srcdir', None)
    108 					if java_srcdir:
    109 						if isinstance(java_srcdir, Node.Node):
    110 							java_srcdir = [java_srcdir]
    111 						for x in Utils.to_list(java_srcdir):
    112 							x = x.path_from(self.root.make_node(self.top_dir))
    113 							if x not in javasrcpath:
    114 								javasrcpath.append(x)
    115 					else:
    116 						if java_src not in javasrcpath:
    117 							javasrcpath.append(java_src)
    118 					hasjava = True
    119 
    120 					# Check if there are external dependencies and add them as external jar so they will be resolved by Eclipse
    121 					usedlibs=getattr(tg, 'use', [])
    122 					for x in Utils.to_list(usedlibs):
    123 						for cl in Utils.to_list(tg.env['CLASSPATH_'+x]):
    124 							if cl not in javalibpath:
    125 								javalibpath.append(cl)
    126 
    127 				if not getattr(tg, 'link_task', None):
    128 					continue
    129 
    130 				features = Utils.to_list(getattr(tg, 'features', ''))
    131 
    132 				is_cc = 'c' in features or 'cxx' in features
    133 
    134 				incnodes = tg.to_incnodes(tg.to_list(getattr(tg, 'includes', [])) + tg.env['INCLUDES'])
    135 				for p in incnodes:
    136 					path = p.path_from(self.srcnode)
    137 
    138 					if (path.startswith("/")):
    139 						if path not in cpppath:
    140 							cpppath.append(path)
    141 					else:
    142 						if path not in workspace_includes:
    143 							workspace_includes.append(path)
    144 
    145 					if is_cc and path not in source_dirs:
    146 						source_dirs.append(path)
    147 
    148 					hasc = True
    149 
    150 		waf_executable = os.path.abspath(sys.argv[0])
    151 		project = self.impl_create_project(sys.executable, appname, hasc, hasjava, haspython, waf_executable)
    152 		self.write_conf_to_xml('.project', project)
    153 
    154 		if hasc:
    155 			project = self.impl_create_cproject(sys.executable, waf_executable, appname, workspace_includes, cpppath, source_dirs)
    156 			self.write_conf_to_xml('.cproject', project)
    157 
    158 		if haspython:
    159 			project = self.impl_create_pydevproject(sys.path, pythonpath)
    160 			self.write_conf_to_xml('.pydevproject', project)
    161 
    162 		if hasjava:
    163 			project = self.impl_create_javaproject(javasrcpath, javalibpath)
    164 			self.write_conf_to_xml('.classpath', project)
    165 
    166 		# Create editor language settings to have correct standards applied in IDE, as per project configuration
    167 		try:
    168 			os.mkdir(settings_dir)
    169 		except OSError:
    170 			pass	# Ignore if dir already exists
    171 
    172 		lang_settings = Document()
    173 		project = lang_settings.createElement('project')
    174 
    175 		# Language configurations for C and C++ via cdt
    176 		if hasc:
    177 			configuration = self.add(lang_settings, project, 'configuration',
    178 							{'id' : 'org.eclipse.cdt.core.default.config.1', 'name': 'Default'})
    179 
    180 			extension = self.add(lang_settings, configuration, 'extension', {'point': 'org.eclipse.cdt.core.LanguageSettingsProvider'})
    181 
    182 			provider = self.add(lang_settings, extension, 'provider',
    183 							{ 'copy-of': 'extension',
    184 							  'id': 'org.eclipse.cdt.ui.UserLanguageSettingsProvider'})
    185 
    186 			provider = self.add(lang_settings, extension, 'provider-reference',
    187 							{ 'id': 'org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider',
    188 							  'ref': 'shared-provider'})
    189 
    190 			provider = self.add(lang_settings, extension, 'provider-reference',
    191 							{ 'id': 'org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider',
    192 							  'ref': 'shared-provider'})
    193 
    194 			# C and C++ are kept as separated providers so appropriate flags are used also in mixed projects
    195 			if self.env.CC:
    196 				provider = self.add(lang_settings, extension, 'provider',
    197 							{ 'class': 'org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuiltinSpecsDetector',
    198 							  'console': 'false',
    199 							  'id': 'org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuiltinSpecsDetector.1',
    200 							  'keep-relative-paths' : 'false',
    201 							  'name': 'CDT GCC Built-in Compiler Settings',
    202 							  'parameter': '%s %s ${FLAGS} -E -P -v -dD "${INPUTS}"'%(self.env.CC[0],' '.join(self.env['CFLAGS'])),
    203 							  'prefer-non-shared': 'true' })
    204 
    205 				self.add(lang_settings, provider, 'language-scope', { 'id': 'org.eclipse.cdt.core.gcc'})
    206 
    207 			if self.env.CXX:
    208 				provider = self.add(lang_settings, extension, 'provider',
    209 							{ 'class': 'org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuiltinSpecsDetector',
    210 							  'console': 'false',
    211 							  'id': 'org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuiltinSpecsDetector.2',
    212 							  'keep-relative-paths' : 'false',
    213 							  'name': 'CDT GCC Built-in Compiler Settings',
    214 							  'parameter': '%s %s ${FLAGS} -E -P -v -dD "${INPUTS}"'%(self.env.CXX[0],' '.join(self.env['CXXFLAGS'])),
    215 							  'prefer-non-shared': 'true' })
    216 				self.add(lang_settings, provider, 'language-scope', { 'id': 'org.eclipse.cdt.core.g++'})
    217 
    218 		lang_settings.appendChild(project)
    219 		self.write_conf_to_xml('%s%s%s'%(settings_dir, os.path.sep, settings_name), lang_settings)
    220 
    221 	def impl_create_project(self, executable, appname, hasc, hasjava, haspython, waf_executable):
    222 		doc = Document()
    223 		projectDescription = doc.createElement('projectDescription')
    224 		self.add(doc, projectDescription, 'name', appname)
    225 		self.add(doc, projectDescription, 'comment')
    226 		self.add(doc, projectDescription, 'projects')
    227 		buildSpec = self.add(doc, projectDescription, 'buildSpec')
    228 		buildCommand = self.add(doc, buildSpec, 'buildCommand')
    229 		self.add(doc, buildCommand, 'triggers', 'clean,full,incremental,')
    230 		arguments = self.add(doc, buildCommand, 'arguments')
    231 		dictionaries = {}
    232 
    233 		# If CDT is present, instruct this one to call waf as it is more flexible (separate build/clean ...)
    234 		if hasc:
    235 			self.add(doc, buildCommand, 'name', oe_cdt + '.managedbuilder.core.genmakebuilder')
    236 			# the default make-style targets are overwritten by the .cproject values
    237 			dictionaries = {
    238 					cdt_mk + '.contents': cdt_mk + '.activeConfigSettings',
    239 					cdt_mk + '.enableAutoBuild': 'false',
    240 					cdt_mk + '.enableCleanBuild': 'true',
    241 					cdt_mk + '.enableFullBuild': 'true',
    242 					}
    243 		else:
    244 			# Otherwise for Java/Python an external builder tool is created that will call waf build
    245 			self.add(doc, buildCommand, 'name', 'org.eclipse.ui.externaltools.ExternalToolBuilder')
    246 			dictionaries = {
    247 					'LaunchConfigHandle': '<project>/%s/%s'%(extbuilder_dir, extbuilder_name),
    248 					}
    249 			# The definition is in a separate directory XML file
    250 			try:
    251 				os.mkdir(extbuilder_dir)
    252 			except OSError:
    253 				pass	# Ignore error if already exists
    254 
    255 			# Populate here the external builder XML calling waf
    256 			builder = Document()
    257 			launchConfiguration = doc.createElement('launchConfiguration')
    258 			launchConfiguration.setAttribute('type', 'org.eclipse.ui.externaltools.ProgramBuilderLaunchConfigurationType')
    259 			self.add(doc, launchConfiguration, 'booleanAttribute', {'key': 'org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND', 'value': 'false'})
    260 			self.add(doc, launchConfiguration, 'booleanAttribute', {'key': 'org.eclipse.ui.externaltools.ATTR_TRIGGERS_CONFIGURED', 'value': 'true'})
    261 			self.add(doc, launchConfiguration, 'stringAttribute', {'key': 'org.eclipse.ui.externaltools.ATTR_LOCATION', 'value': waf_executable})
    262 			self.add(doc, launchConfiguration, 'stringAttribute', {'key': 'org.eclipse.ui.externaltools.ATTR_RUN_BUILD_KINDS', 'value': 'full,incremental,'})
    263 			self.add(doc, launchConfiguration, 'stringAttribute', {'key': 'org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS', 'value': 'build'})
    264 			self.add(doc, launchConfiguration, 'stringAttribute', {'key': 'org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY', 'value': '${project_loc}'})
    265 			builder.appendChild(launchConfiguration)
    266 			# And write the XML to the file references before
    267 			self.write_conf_to_xml('%s%s%s'%(extbuilder_dir, os.path.sep, extbuilder_name), builder)
    268 
    269 
    270 		for k, v in dictionaries.items():
    271 			self.addDictionary(doc, arguments, k, v)
    272 
    273 		natures = self.add(doc, projectDescription, 'natures')
    274 
    275 		if hasc:
    276 			nature_list = """
    277 				core.ccnature
    278 				managedbuilder.core.ScannerConfigNature
    279 				managedbuilder.core.managedBuildNature
    280 				core.cnature
    281 			""".split()
    282 			for n in nature_list:
    283 				self.add(doc, natures, 'nature', oe_cdt + '.' + n)
    284 
    285 		if haspython:
    286 			self.add(doc, natures, 'nature', 'org.python.pydev.pythonNature')
    287 		if hasjava:
    288 			self.add(doc, natures, 'nature', 'org.eclipse.jdt.core.javanature')
    289 
    290 		doc.appendChild(projectDescription)
    291 		return doc
    292 
    293 	def impl_create_cproject(self, executable, waf_executable, appname, workspace_includes, cpppath, source_dirs=[]):
    294 		doc = Document()
    295 		doc.appendChild(doc.createProcessingInstruction('fileVersion', '4.0.0'))
    296 		cconf_id = cdt_core + '.default.config.1'
    297 		cproject = doc.createElement('cproject')
    298 		storageModule = self.add(doc, cproject, 'storageModule',
    299 				{'moduleId': cdt_core + '.settings'})
    300 		cconf = self.add(doc, storageModule, 'cconfiguration', {'id':cconf_id})
    301 
    302 		storageModule = self.add(doc, cconf, 'storageModule',
    303 				{'buildSystemId': oe_cdt + '.managedbuilder.core.configurationDataProvider',
    304 				 'id': cconf_id,
    305 				 'moduleId': cdt_core + '.settings',
    306 				 'name': 'Default'})
    307 
    308 		self.add(doc, storageModule, 'externalSettings')
    309 
    310 		extensions = self.add(doc, storageModule, 'extensions')
    311 		extension_list = """
    312 			VCErrorParser
    313 			MakeErrorParser
    314 			GCCErrorParser
    315 			GASErrorParser
    316 			GLDErrorParser
    317 		""".split()
    318 		self.add(doc, extensions, 'extension', {'id': cdt_core + '.ELF', 'point':cdt_core + '.BinaryParser'})
    319 		for e in extension_list:
    320 			self.add(doc, extensions, 'extension', {'id': cdt_core + '.' + e, 'point':cdt_core + '.ErrorParser'})
    321 
    322 		storageModule = self.add(doc, cconf, 'storageModule',
    323 				{'moduleId': 'cdtBuildSystem', 'version': '4.0.0'})
    324 		config = self.add(doc, storageModule, 'configuration',
    325 					{'artifactName': appname,
    326 					 'id': cconf_id,
    327 					 'name': 'Default',
    328 					 'parent': cdt_bld + '.prefbase.cfg'})
    329 		folderInfo = self.add(doc, config, 'folderInfo',
    330 							{'id': cconf_id+'.', 'name': '/', 'resourcePath': ''})
    331 
    332 		toolChain = self.add(doc, folderInfo, 'toolChain',
    333 				{'id': cdt_bld + '.prefbase.toolchain.1',
    334 				 'name': 'No ToolChain',
    335 				 'resourceTypeBasedDiscovery': 'false',
    336 				 'superClass': cdt_bld + '.prefbase.toolchain'})
    337 
    338 		self.add(doc, toolChain, 'targetPlatform', {'binaryParser': 'org.eclipse.cdt.core.ELF', 'id': cdt_bld + '.prefbase.toolchain.1', 'name': ''})
    339 
    340 		waf_build = '"%s" %s'%(waf_executable, eclipse.fun)
    341 		waf_clean = '"%s" clean'%(waf_executable)
    342 		self.add(doc, toolChain, 'builder',
    343 					{'autoBuildTarget': waf_build,
    344 					 'command': executable,
    345 					 'enableAutoBuild': 'false',
    346 					 'cleanBuildTarget': waf_clean,
    347 					 'enableIncrementalBuild': 'true',
    348 					 'id': cdt_bld + '.settings.default.builder.1',
    349 					 'incrementalBuildTarget': waf_build,
    350 					 'managedBuildOn': 'false',
    351 					 'name': 'Gnu Make Builder',
    352 					 'superClass': cdt_bld + '.settings.default.builder'})
    353 
    354 		tool_index = 1;
    355 		for tool_name in ("Assembly", "GNU C++", "GNU C"):
    356 			tool = self.add(doc, toolChain, 'tool',
    357 					{'id': cdt_bld + '.settings.holder.' + str(tool_index),
    358 					 'name': tool_name,
    359 					 'superClass': cdt_bld + '.settings.holder'})
    360 			if cpppath or workspace_includes:
    361 				incpaths = cdt_bld + '.settings.holder.incpaths'
    362 				option = self.add(doc, tool, 'option',
    363 						{'id': incpaths + '.' +  str(tool_index),
    364 						 'name': 'Include Paths',
    365 						 'superClass': incpaths,
    366 						 'valueType': 'includePath'})
    367 				for i in workspace_includes:
    368 					self.add(doc, option, 'listOptionValue',
    369 								{'builtIn': 'false',
    370 								'value': '"${workspace_loc:/%s/%s}"'%(appname, i)})
    371 				for i in cpppath:
    372 					self.add(doc, option, 'listOptionValue',
    373 								{'builtIn': 'false',
    374 								'value': '"%s"'%(i)})
    375 			if tool_name == "GNU C++" or tool_name == "GNU C":
    376 				self.add(doc,tool,'inputType',{ 'id':'org.eclipse.cdt.build.core.settings.holder.inType.' + str(tool_index), \
    377 					'languageId':'org.eclipse.cdt.core.gcc' if tool_name == "GNU C" else 'org.eclipse.cdt.core.g++','languageName':tool_name, \
    378 					'sourceContentType':'org.eclipse.cdt.core.cSource,org.eclipse.cdt.core.cHeader', \
    379 					'superClass':'org.eclipse.cdt.build.core.settings.holder.inType' })
    380 			tool_index += 1
    381 
    382 		if source_dirs:
    383 			sourceEntries = self.add(doc, config, 'sourceEntries')
    384 			for i in source_dirs:
    385 				 self.add(doc, sourceEntries, 'entry',
    386 							{'excluding': i,
    387 							'flags': 'VALUE_WORKSPACE_PATH|RESOLVED',
    388 							'kind': 'sourcePath',
    389 							'name': ''})
    390 				 self.add(doc, sourceEntries, 'entry',
    391 							{
    392 							'flags': 'VALUE_WORKSPACE_PATH|RESOLVED',
    393 							'kind': 'sourcePath',
    394 							'name': i})
    395 
    396 		storageModule = self.add(doc, cconf, 'storageModule',
    397 							{'moduleId': cdt_mk + '.buildtargets'})
    398 		buildTargets = self.add(doc, storageModule, 'buildTargets')
    399 		def addTargetWrap(name, runAll):
    400 			return self.addTarget(doc, buildTargets, executable, name,
    401 								'"%s" %s'%(waf_executable, name), runAll)
    402 		addTargetWrap('configure', True)
    403 		addTargetWrap('dist', False)
    404 		addTargetWrap('install', False)
    405 		addTargetWrap('check', False)
    406 		for addTgt in self.env.ECLIPSE_EXTRA_TARGETS or []:
    407 			addTargetWrap(addTgt, False)
    408 
    409 		storageModule = self.add(doc, cproject, 'storageModule',
    410 							{'moduleId': 'cdtBuildSystem',
    411 							 'version': '4.0.0'})
    412 
    413 		self.add(doc, storageModule, 'project', {'id': '%s.null.1'%appname, 'name': appname})
    414 
    415 		storageModule = self.add(doc, cproject, 'storageModule',
    416 							{'moduleId': 'org.eclipse.cdt.core.LanguageSettingsProviders'})
    417 
    418 		storageModule = self.add(doc, cproject, 'storageModule',
    419 							{'moduleId': 'scannerConfiguration'})
    420 
    421 		doc.appendChild(cproject)
    422 		return doc
    423 
    424 	def impl_create_pydevproject(self, system_path, user_path):
    425 		# create a pydevproject file
    426 		doc = Document()
    427 		doc.appendChild(doc.createProcessingInstruction('eclipse-pydev', 'version="1.0"'))
    428 		pydevproject = doc.createElement('pydev_project')
    429 		prop = self.add(doc, pydevproject,
    430 					   'pydev_property',
    431 					   'python %d.%d'%(sys.version_info[0], sys.version_info[1]))
    432 		prop.setAttribute('name', 'org.python.pydev.PYTHON_PROJECT_VERSION')
    433 		prop = self.add(doc, pydevproject, 'pydev_property', 'Default')
    434 		prop.setAttribute('name', 'org.python.pydev.PYTHON_PROJECT_INTERPRETER')
    435 		# add waf's paths
    436 		wafadmin = [p for p in system_path if p.find('wafadmin') != -1]
    437 		if wafadmin:
    438 			prop = self.add(doc, pydevproject, 'pydev_pathproperty',
    439 					{'name':'org.python.pydev.PROJECT_EXTERNAL_SOURCE_PATH'})
    440 			for i in wafadmin:
    441 				self.add(doc, prop, 'path', i)
    442 		if user_path:
    443 			prop = self.add(doc, pydevproject, 'pydev_pathproperty',
    444 					{'name':'org.python.pydev.PROJECT_SOURCE_PATH'})
    445 			for i in user_path:
    446 				self.add(doc, prop, 'path', '/${PROJECT_DIR_NAME}/'+i)
    447 
    448 		doc.appendChild(pydevproject)
    449 		return doc
    450 
    451 	def impl_create_javaproject(self, javasrcpath, javalibpath):
    452 		# create a .classpath file for java usage
    453 		doc = Document()
    454 		javaproject = doc.createElement('classpath')
    455 		if javasrcpath:
    456 			for i in javasrcpath:
    457 				self.add(doc, javaproject, 'classpathentry',
    458 					{'kind': 'src', 'path': i})
    459 
    460 		if javalibpath:
    461 			for i in javalibpath:
    462 				self.add(doc, javaproject, 'classpathentry',
    463 					{'kind': 'lib', 'path': i})
    464 
    465 		self.add(doc, javaproject, 'classpathentry', {'kind': 'con', 'path': 'org.eclipse.jdt.launching.JRE_CONTAINER'})
    466 		self.add(doc, javaproject, 'classpathentry', {'kind': 'output', 'path': self.bldnode.name })
    467 		doc.appendChild(javaproject)
    468 		return doc
    469 
    470 	def addDictionary(self, doc, parent, k, v):
    471 		dictionary = self.add(doc, parent, 'dictionary')
    472 		self.add(doc, dictionary, 'key', k)
    473 		self.add(doc, dictionary, 'value', v)
    474 		return dictionary
    475 
    476 	def addTarget(self, doc, buildTargets, executable, name, buildTarget, runAllBuilders=True):
    477 		target = self.add(doc, buildTargets, 'target',
    478 						{'name': name,
    479 						 'path': '',
    480 						 'targetID': oe_cdt + '.build.MakeTargetBuilder'})
    481 		self.add(doc, target, 'buildCommand', executable)
    482 		self.add(doc, target, 'buildArguments', None)
    483 		self.add(doc, target, 'buildTarget', buildTarget)
    484 		self.add(doc, target, 'stopOnError', 'true')
    485 		self.add(doc, target, 'useDefaultCommand', 'false')
    486 		self.add(doc, target, 'runAllBuilders', str(runAllBuilders).lower())
    487 
    488 	def add(self, doc, parent, tag, value = None):
    489 		el = doc.createElement(tag)
    490 		if (value):
    491 			if type(value) == type(str()):
    492 				el.appendChild(doc.createTextNode(value))
    493 			elif type(value) == type(dict()):
    494 				self.setAttributes(el, value)
    495 		parent.appendChild(el)
    496 		return el
    497 
    498 	def setAttributes(self, node, attrs):
    499 		for k, v in attrs.items():
    500 			node.setAttribute(k, v)
    501