thirdparty:waf: New files for waf 1.9.10
[Samba.git] / third_party / waf / waflib / extras / codelite.py
blobc12ae4b9796753b8c7e1b1f8a7d872ceb00df8f9
1 #! /usr/bin/env python
2 # encoding: utf-8
3 # CodeLite Project
4 # Christian Klein (chrikle@berlios.de)
5 # Created: Jan 2012
6 # As templete for this file I used the msvs.py
7 # I hope this template will work proper
9 """
10 Redistribution and use in source and binary forms, with or without
11 modification, are permitted provided that the following conditions
12 are met:
14 1. Redistributions of source code must retain the above copyright
15 notice, this list of conditions and the following disclaimer.
17 2. Redistributions in binary form must reproduce the above copyright
18 notice, this list of conditions and the following disclaimer in the
19 documentation and/or other materials provided with the distribution.
21 3. The name of the author may not be used to endorse or promote products
22 derived from this software without specific prior written permission.
24 THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
25 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27 DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
28 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
32 STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
33 IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 POSSIBILITY OF SUCH DAMAGE.
35 """
37 """
40 To add this tool to your project:
41 def options(conf):
42 opt.load('codelite')
44 It can be a good idea to add the sync_exec tool too.
46 To generate solution files:
47 $ waf configure codelite
49 To customize the outputs, provide subclasses in your wscript files:
51 from waflib.extras import codelite
52 class vsnode_target(codelite.vsnode_target):
53 def get_build_command(self, props):
54 # likely to be required
55 return "waf.bat build"
56 def collect_source(self):
57 # likely to be required
58 ...
59 class codelite_bar(codelite.codelite_generator):
60 def init(self):
61 codelite.codelite_generator.init(self)
62 self.vsnode_target = vsnode_target
64 The codelite class re-uses the same build() function for reading the targets (task generators),
65 you may therefore specify codelite settings on the context object:
67 def build(bld):
68 bld.codelite_solution_name = 'foo.workspace'
69 bld.waf_command = 'waf.bat'
70 bld.projects_dir = bld.srcnode.make_node('')
71 bld.projects_dir.mkdir()
74 ASSUMPTIONS:
75 * a project can be either a directory or a target, project files are written only for targets that have source files
76 * each project is a vcxproj file, therefore the project uuid needs only to be a hash of the absolute path
77 """
79 import os, re, sys
80 import uuid # requires python 2.5
81 from waflib.Build import BuildContext
82 from waflib import Utils, TaskGen, Logs, Task, Context, Node, Options
84 HEADERS_GLOB = '**/(*.h|*.hpp|*.H|*.inl)'
86 PROJECT_TEMPLATE = r'''<?xml version="1.0" encoding="utf-8"?>
87 <CodeLite_Project Name="${project.name}" InternalType="Library">
88 <Plugins>
89 <Plugin Name="qmake">
90 <![CDATA[00010001N0005Release000000000000]]>
91 </Plugin>
92 </Plugins>
93 <Description/>
94 <Dependencies/>
95 <VirtualDirectory Name="src">
96 ${for x in project.source}
97 ${if (project.get_key(x)=="sourcefile")}
98 <File Name="${x.abspath()}"/>
99 ${endif}
100 ${endfor}
101 </VirtualDirectory>
102 <VirtualDirectory Name="include">
103 ${for x in project.source}
104 ${if (project.get_key(x)=="headerfile")}
105 <File Name="${x.abspath()}"/>
106 ${endif}
107 ${endfor}
108 </VirtualDirectory>
109 <Settings Type="Dynamic Library">
110 <GlobalSettings>
111 <Compiler Options="" C_Options="">
112 <IncludePath Value="."/>
113 </Compiler>
114 <Linker Options="">
115 <LibraryPath Value="."/>
116 </Linker>
117 <ResourceCompiler Options=""/>
118 </GlobalSettings>
119 <Configuration Name="Release" CompilerType="gnu gcc" ReleasegerType="GNU gdb Releaseger" Type="Dynamic Library" BuildCmpWithGlobalSettings="append" BuildLnkWithGlobalSettings="append" BuildResWithGlobalSettings="append">
120 <Compiler Options="" C_Options="" Required="yes" PreCompiledHeader="" PCHInCommandLine="no" UseDifferentPCHFlags="no" PCHFlags="">
121 <IncludePath Value="."/>
122 <IncludePath Value="."/>
123 </Compiler>
124 <Linker Options="" Required="yes">
125 <LibraryPath Value=""/>
126 </Linker>
127 <ResourceCompiler Options="" Required="no"/>
128 <General OutputFile="${xml:project.build_properties[0].output_file}" IntermediateDirectory="" Command="" CommandArguments="" PauseExecWhenProcTerminates="yes"/>
129 <Environment EnvVarSetName="&lt;Use Defaults&gt;" DbgSetName="&lt;Use Defaults&gt;">
130 <![CDATA[]]>
131 </Environment>
132 <Releaseger IsRemote="no" RemoteHostName="" RemoteHostPort="" ReleasegerPath="">
133 <PostConnectCommands/>
134 <StartupCommands/>
135 </Releaseger>
136 <PreBuild/>
137 <PostBuild/>
138 <CustomBuild Enabled="yes">
139 $b = project.build_properties[0]}
140 <RebuildCommand>${xml:project.get_rebuild_command(project.build_properties[0])}</RebuildCommand>
141 <CleanCommand>${xml:project.get_clean_command(project.build_properties[0])}</CleanCommand>
142 <BuildCommand>${xml:project.get_build_command(project.build_properties[0])}</BuildCommand>
143 <Target Name="Install">${xml:project.get_install_command(project.build_properties[0])}</Target>
144 <Target Name="Build and Install">${xml:project.get_build_and_install_command(project.build_properties[0])}</Target>
145 <Target Name="Build All">${xml:project.get_build_all_command(project.build_properties[0])}</Target>
146 <Target Name="Rebuild All">${xml:project.get_rebuild_all_command(project.build_properties[0])}</Target>
147 <Target Name="Clean All">${xml:project.get_clean_all_command(project.build_properties[0])}</Target>
148 <Target Name="Build and Install All">${xml:project.get_build_and_install_all_command(project.build_properties[0])}</Target>
149 <PreprocessFileCommand/>
150 <SingleFileCommand/>
151 <MakefileGenerationCommand/>
152 <ThirdPartyToolName>None</ThirdPartyToolName>
153 <WorkingDirectory/>
154 </CustomBuild>
155 <AdditionalRules>
156 <CustomPostBuild/>
157 <CustomPreBuild/>
158 </AdditionalRules>
159 <Completion>
160 <ClangCmpFlags/>
161 <ClangPP/>
162 <SearchPaths/>
163 </Completion>
164 </Configuration>
165 <Configuration Name="Release" CompilerType="gnu gcc" ReleasegerType="GNU gdb Releaseger" Type="" BuildCmpWithGlobalSettings="append" BuildLnkWithGlobalSettings="append" BuildResWithGlobalSettings="append">
166 <Compiler Options="" C_Options="" Required="yes" PreCompiledHeader="" PCHInCommandLine="no" UseDifferentPCHFlags="no" PCHFlags="">
167 <IncludePath Value="."/>
168 </Compiler>
169 <Linker Options="" Required="yes"/>
170 <ResourceCompiler Options="" Required="no"/>
171 <General OutputFile="" IntermediateDirectory="./Release" Command="" CommandArguments="" UseSeparateReleaseArgs="no" ReleaseArguments="" WorkingDirectory="$(IntermediateDirectory)" PauseExecWhenProcTerminates="yes"/>
172 <Environment EnvVarSetName="&lt;Use Defaults&gt;" DbgSetName="&lt;Use Defaults&gt;">
173 <![CDATA[
178 </Environment>
179 <Releaseger IsRemote="no" RemoteHostName="" RemoteHostPort="" ReleasegerPath="">
180 <PostConnectCommands/>
181 <StartupCommands/>
182 </Releaseger>
183 <PreBuild/>
184 <PostBuild/>
185 <CustomBuild Enabled="no">
186 <RebuildCommand/>
187 <CleanCommand/>
188 <BuildCommand/>
189 <PreprocessFileCommand/>
190 <SingleFileCommand/>
191 <MakefileGenerationCommand/>
192 <ThirdPartyToolName/>
193 <WorkingDirectory/>
194 </CustomBuild>
195 <AdditionalRules>
196 <CustomPostBuild/>
197 <CustomPreBuild/>
198 </AdditionalRules>
199 <Completion>
200 <ClangCmpFlags/>
201 <ClangPP/>
202 <SearchPaths/>
203 </Completion>
204 </Configuration>
205 </Settings>
206 </CodeLite_Project>'''
211 SOLUTION_TEMPLATE = '''<?xml version="1.0" encoding="utf-8"?>
212 <CodeLite_Workspace Name="${getattr(project, 'codelite_solution_name', None)[:-10]}" Database="./${getattr(project, 'codelite_solution_name', None)[:-10]}.tags">
213 ${for p in project.all_projects}
214 <Project Name = "${p.name}" Path = "${p.title}" Active="No"/>
215 ${endfor}
216 <BuildMatrix>
217 <WorkspaceConfiguration Name="Release" Selected="yes">
218 ${for p in project.all_projects}
219 <Project Name="${p.name}" ConfigName="Release"/>
220 ${endfor}
221 </WorkspaceConfiguration>
222 </BuildMatrix>
223 </CodeLite_Workspace>'''
227 COMPILE_TEMPLATE = '''def f(project):
228 lst = []
229 def xml_escape(value):
230 return value.replace("&", "&amp;").replace('"', "&quot;").replace("'", "&apos;").replace("<", "&lt;").replace(">", "&gt;")
234 #f = open('cmd.txt', 'w')
235 #f.write(str(lst))
236 #f.close()
237 return ''.join(lst)
239 reg_act = re.compile(r"(?P<backslash>\\)|(?P<dollar>\$\$)|(?P<subst>\$\{(?P<code>[^}]*?)\})", re.M)
240 def compile_template(line):
242 Compile a template expression into a python function (like jsps, but way shorter)
244 extr = []
245 def repl(match):
246 g = match.group
247 if g('dollar'): return "$"
248 elif g('backslash'):
249 return "\\"
250 elif g('subst'):
251 extr.append(g('code'))
252 return "<<|@|>>"
253 return None
255 line2 = reg_act.sub(repl, line)
256 params = line2.split('<<|@|>>')
257 assert(extr)
260 indent = 0
261 buf = []
262 app = buf.append
264 def app(txt):
265 buf.append(indent * '\t' + txt)
267 for x in range(len(extr)):
268 if params[x]:
269 app("lst.append(%r)" % params[x])
271 f = extr[x]
272 if f.startswith('if') or f.startswith('for'):
273 app(f + ':')
274 indent += 1
275 elif f.startswith('py:'):
276 app(f[3:])
277 elif f.startswith('endif') or f.startswith('endfor'):
278 indent -= 1
279 elif f.startswith('else') or f.startswith('elif'):
280 indent -= 1
281 app(f + ':')
282 indent += 1
283 elif f.startswith('xml:'):
284 app('lst.append(xml_escape(%s))' % f[4:])
285 else:
286 #app('lst.append((%s) or "cannot find %s")' % (f, f))
287 app('lst.append(%s)' % f)
289 if extr:
290 if params[-1]:
291 app("lst.append(%r)" % params[-1])
293 fun = COMPILE_TEMPLATE % "\n\t".join(buf)
294 #print(fun)
295 return Task.funex(fun)
298 re_blank = re.compile('(\n|\r|\\s)*\n', re.M)
299 def rm_blank_lines(txt):
300 txt = re_blank.sub('\r\n', txt)
301 return txt
303 BOM = '\xef\xbb\xbf'
304 try:
305 BOM = bytes(BOM, 'iso8859-1') # python 3
306 except NameError:
307 pass
309 def stealth_write(self, data, flags='wb'):
310 try:
311 unicode
312 except NameError:
313 data = data.encode('utf-8') # python 3
314 else:
315 data = data.decode(sys.getfilesystemencoding(), 'replace')
316 data = data.encode('utf-8')
318 if self.name.endswith('.project') or self.name.endswith('.project'):
319 data = BOM + data
321 try:
322 txt = self.read(flags='rb')
323 if txt != data:
324 raise ValueError('must write')
325 except (IOError, ValueError):
326 self.write(data, flags=flags)
327 else:
328 Logs.debug('codelite: skipping %s' % self.abspath())
329 Node.Node.stealth_write = stealth_write
331 re_quote = re.compile("[^a-zA-Z0-9-]")
332 def quote(s):
333 return re_quote.sub("_", s)
335 def xml_escape(value):
336 return value.replace("&", "&amp;").replace('"', "&quot;").replace("'", "&apos;").replace("<", "&lt;").replace(">", "&gt;")
338 def make_uuid(v, prefix = None):
340 simple utility function
342 if isinstance(v, dict):
343 keys = list(v.keys())
344 keys.sort()
345 tmp = str([(k, v[k]) for k in keys])
346 else:
347 tmp = str(v)
348 d = Utils.md5(tmp.encode()).hexdigest().upper()
349 if prefix:
350 d = '%s%s' % (prefix, d[8:])
351 gid = uuid.UUID(d, version = 4)
352 return str(gid).upper()
354 def diff(node, fromnode):
355 # difference between two nodes, but with "(..)" instead of ".."
356 c1 = node
357 c2 = fromnode
359 c1h = c1.height()
360 c2h = c2.height()
362 lst = []
363 up = 0
365 while c1h > c2h:
366 lst.append(c1.name)
367 c1 = c1.parent
368 c1h -= 1
370 while c2h > c1h:
371 up += 1
372 c2 = c2.parent
373 c2h -= 1
375 while id(c1) != id(c2):
376 lst.append(c1.name)
377 up += 1
379 c1 = c1.parent
380 c2 = c2.parent
382 for i in range(up):
383 lst.append('(..)')
384 lst.reverse()
385 return tuple(lst)
387 class build_property(object):
388 pass
390 class vsnode(object):
392 Abstract class representing visual studio elements
393 We assume that all visual studio nodes have a uuid and a parent
395 def __init__(self, ctx):
396 self.ctx = ctx # codelite context
397 self.name = '' # string, mandatory
398 self.vspath = '' # path in visual studio (name for dirs, absolute path for projects)
399 self.uuid = '' # string, mandatory
400 self.parent = None # parent node for visual studio nesting
402 def get_waf(self):
404 Override in subclasses...
406 return '%s/%s' % (self.ctx.srcnode.abspath(), getattr(self.ctx, 'waf_command', 'waf'))
408 def ptype(self):
410 Return a special uuid for projects written in the solution file
412 pass
414 def write(self):
416 Write the project file, by default, do nothing
418 pass
420 def make_uuid(self, val):
422 Alias for creating uuid values easily (the templates cannot access global variables)
424 return make_uuid(val)
426 class vsnode_vsdir(vsnode):
428 Nodes representing visual studio folders (which do not match the filesystem tree!)
430 VS_GUID_SOLUTIONFOLDER = "2150E333-8FDC-42A3-9474-1A3956D46DE8"
431 def __init__(self, ctx, uuid, name, vspath=''):
432 vsnode.__init__(self, ctx)
433 self.title = self.name = name
434 self.uuid = uuid
435 self.vspath = vspath or name
437 def ptype(self):
438 return self.VS_GUID_SOLUTIONFOLDER
440 class vsnode_project(vsnode):
442 Abstract class representing visual studio project elements
443 A project is assumed to be writable, and has a node representing the file to write to
445 VS_GUID_VCPROJ = "8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942"
446 def ptype(self):
447 return self.VS_GUID_VCPROJ
449 def __init__(self, ctx, node):
450 vsnode.__init__(self, ctx)
451 self.path = node
452 self.uuid = make_uuid(node.abspath())
453 self.name = node.name
454 self.title = self.path.abspath()
455 self.source = [] # list of node objects
456 self.build_properties = [] # list of properties (nmake commands, output dir, etc)
458 def dirs(self):
460 Get the list of parent folders of the source files (header files included)
461 for writing the filters
463 lst = []
464 def add(x):
465 if x.height() > self.tg.path.height() and x not in lst:
466 lst.append(x)
467 add(x.parent)
468 for x in self.source:
469 add(x.parent)
470 return lst
472 def write(self):
473 Logs.debug('codelite: creating %r' % self.path)
474 #print "self.name:",self.name
476 # first write the project file
477 template1 = compile_template(PROJECT_TEMPLATE)
478 proj_str = template1(self)
479 proj_str = rm_blank_lines(proj_str)
480 self.path.stealth_write(proj_str)
482 # then write the filter
483 #template2 = compile_template(FILTER_TEMPLATE)
484 #filter_str = template2(self)
485 #filter_str = rm_blank_lines(filter_str)
486 #tmp = self.path.parent.make_node(self.path.name + '.filters')
487 #tmp.stealth_write(filter_str)
489 def get_key(self, node):
491 required for writing the source files
493 name = node.name
494 if name.endswith('.cpp') or name.endswith('.c'):
495 return 'sourcefile'
496 return 'headerfile'
498 def collect_properties(self):
500 Returns a list of triplet (configuration, platform, output_directory)
502 ret = []
503 for c in self.ctx.configurations:
504 for p in self.ctx.platforms:
505 x = build_property()
506 x.outdir = ''
508 x.configuration = c
509 x.platform = p
511 x.preprocessor_definitions = ''
512 x.includes_search_path = ''
514 # can specify "deploy_dir" too
515 ret.append(x)
516 self.build_properties = ret
518 def get_build_params(self, props):
519 opt = ''
520 return (self.get_waf(), opt)
522 def get_build_command(self, props):
523 return "%s build %s" % self.get_build_params(props)
525 def get_clean_command(self, props):
526 return "%s clean %s" % self.get_build_params(props)
528 def get_rebuild_command(self, props):
529 return "%s clean build %s" % self.get_build_params(props)
531 def get_install_command(self, props):
532 return "%s install %s" % self.get_build_params(props)
533 def get_build_and_install_command(self, props):
534 return "%s build install %s" % self.get_build_params(props)
536 def get_build_and_install_all_command(self, props):
537 return "%s build install" % self.get_build_params(props)[0]
539 def get_clean_all_command(self, props):
540 return "%s clean" % self.get_build_params(props)[0]
542 def get_build_all_command(self, props):
543 return "%s build" % self.get_build_params(props)[0]
545 def get_rebuild_all_command(self, props):
546 return "%s clean build" % self.get_build_params(props)[0]
548 def get_filter_name(self, node):
549 lst = diff(node, self.tg.path)
550 return '\\'.join(lst) or '.'
552 class vsnode_alias(vsnode_project):
553 def __init__(self, ctx, node, name):
554 vsnode_project.__init__(self, ctx, node)
555 self.name = name
556 self.output_file = ''
558 class vsnode_build_all(vsnode_alias):
560 Fake target used to emulate the behaviour of "make all" (starting one process by target is slow)
561 This is the only alias enabled by default
563 def __init__(self, ctx, node, name='build_all_projects'):
564 vsnode_alias.__init__(self, ctx, node, name)
565 self.is_active = True
567 class vsnode_install_all(vsnode_alias):
569 Fake target used to emulate the behaviour of "make install"
571 def __init__(self, ctx, node, name='install_all_projects'):
572 vsnode_alias.__init__(self, ctx, node, name)
574 def get_build_command(self, props):
575 return "%s build install %s" % self.get_build_params(props)
577 def get_clean_command(self, props):
578 return "%s clean %s" % self.get_build_params(props)
580 def get_rebuild_command(self, props):
581 return "%s clean build install %s" % self.get_build_params(props)
583 class vsnode_project_view(vsnode_alias):
585 Fake target used to emulate a file system view
587 def __init__(self, ctx, node, name='project_view'):
588 vsnode_alias.__init__(self, ctx, node, name)
589 self.tg = self.ctx() # fake one, cannot remove
590 self.exclude_files = Node.exclude_regs + '''
591 waf-1.8.*
592 waf3-1.8.*/**
593 .waf-1.8.*
594 .waf3-1.8.*/**
595 **/*.sdf
596 **/*.suo
597 **/*.ncb
598 **/%s
599 ''' % Options.lockfile
601 def collect_source(self):
602 # this is likely to be slow
603 self.source = self.ctx.srcnode.ant_glob('**', excl=self.exclude_files)
605 def get_build_command(self, props):
606 params = self.get_build_params(props) + (self.ctx.cmd,)
607 return "%s %s %s" % params
609 def get_clean_command(self, props):
610 return ""
612 def get_rebuild_command(self, props):
613 return self.get_build_command(props)
615 class vsnode_target(vsnode_project):
617 CodeLite project representing a targets (programs, libraries, etc) and bound
618 to a task generator
620 def __init__(self, ctx, tg):
622 A project is more or less equivalent to a file/folder
624 base = getattr(ctx, 'projects_dir', None) or tg.path
625 node = base.make_node(quote(tg.name) + ctx.project_extension) # the project file as a Node
626 vsnode_project.__init__(self, ctx, node)
627 self.name = quote(tg.name)
628 self.tg = tg # task generator
630 def get_build_params(self, props):
632 Override the default to add the target name
634 opt = ''
635 if getattr(self, 'tg', None):
636 opt += " --targets=%s" % self.tg.name
637 return (self.get_waf(), opt)
639 def collect_source(self):
640 tg = self.tg
641 source_files = tg.to_nodes(getattr(tg, 'source', []))
642 include_dirs = Utils.to_list(getattr(tg, 'codelite_includes', []))
643 include_files = []
644 for x in include_dirs:
645 if isinstance(x, str):
646 x = tg.path.find_node(x)
647 if x:
648 lst = [y for y in x.ant_glob(HEADERS_GLOB, flat=False)]
649 include_files.extend(lst)
651 # remove duplicates
652 self.source.extend(list(set(source_files + include_files)))
653 self.source.sort(key=lambda x: x.abspath())
655 def collect_properties(self):
657 CodeLite projects are associated with platforms and configurations (for building especially)
659 super(vsnode_target, self).collect_properties()
660 for x in self.build_properties:
661 x.outdir = self.path.parent.abspath()
662 x.preprocessor_definitions = ''
663 x.includes_search_path = ''
665 try:
666 tsk = self.tg.link_task
667 except AttributeError:
668 pass
669 else:
670 x.output_file = tsk.outputs[0].abspath()
671 x.preprocessor_definitions = ';'.join(tsk.env.DEFINES)
672 x.includes_search_path = ';'.join(self.tg.env.INCPATHS)
674 class codelite_generator(BuildContext):
675 '''generates a CodeLite workspace'''
676 cmd = 'codelite'
677 fun = 'build'
679 def init(self):
681 Some data that needs to be present
683 if not getattr(self, 'configurations', None):
684 self.configurations = ['Release'] # LocalRelease, RemoteDebug, etc
685 if not getattr(self, 'platforms', None):
686 self.platforms = ['Win32']
687 if not getattr(self, 'all_projects', None):
688 self.all_projects = []
689 if not getattr(self, 'project_extension', None):
690 self.project_extension = '.project'
691 if not getattr(self, 'projects_dir', None):
692 self.projects_dir = self.srcnode.make_node('')
693 self.projects_dir.mkdir()
695 # bind the classes to the object, so that subclass can provide custom generators
696 if not getattr(self, 'vsnode_vsdir', None):
697 self.vsnode_vsdir = vsnode_vsdir
698 if not getattr(self, 'vsnode_target', None):
699 self.vsnode_target = vsnode_target
700 if not getattr(self, 'vsnode_build_all', None):
701 self.vsnode_build_all = vsnode_build_all
702 if not getattr(self, 'vsnode_install_all', None):
703 self.vsnode_install_all = vsnode_install_all
704 if not getattr(self, 'vsnode_project_view', None):
705 self.vsnode_project_view = vsnode_project_view
707 self.numver = '11.00'
708 self.vsver = '2010'
710 def execute(self):
712 Entry point
714 self.restore()
715 if not self.all_envs:
716 self.load_envs()
717 self.recurse([self.run_dir])
719 # user initialization
720 self.init()
722 # two phases for creating the solution
723 self.collect_projects() # add project objects into "self.all_projects"
724 self.write_files() # write the corresponding project and solution files
726 def collect_projects(self):
728 Fill the list self.all_projects with project objects
729 Fill the list of build targets
731 self.collect_targets()
732 #self.add_aliases()
733 #self.collect_dirs()
734 default_project = getattr(self, 'default_project', None)
735 def sortfun(x):
736 if x.name == default_project:
737 return ''
738 return getattr(x, 'path', None) and x.path.abspath() or x.name
739 self.all_projects.sort(key=sortfun)
742 def write_files(self):
745 Write the project and solution files from the data collected
746 so far. It is unlikely that you will want to change this
748 for p in self.all_projects:
749 p.write()
751 # and finally write the solution file
752 node = self.get_solution_node()
753 node.parent.mkdir()
754 Logs.warn('Creating %r' % node)
755 #a = dir(self.root)
756 #for b in a:
757 # print b
758 #print self.group_names
759 #print "Hallo2: ",self.root.listdir()
760 #print getattr(self, 'codelite_solution_name', None)
761 template1 = compile_template(SOLUTION_TEMPLATE)
762 sln_str = template1(self)
763 sln_str = rm_blank_lines(sln_str)
764 node.stealth_write(sln_str)
766 def get_solution_node(self):
768 The solution filename is required when writing the .vcproj files
769 return self.solution_node and if it does not exist, make one
771 try:
772 return self.solution_node
773 except:
774 pass
776 codelite_solution_name = getattr(self, 'codelite_solution_name', None)
777 if not codelite_solution_name:
778 codelite_solution_name = getattr(Context.g_module, Context.APPNAME, 'project') + '.workspace'
779 setattr(self, 'codelite_solution_name', codelite_solution_name)
780 if os.path.isabs(codelite_solution_name):
781 self.solution_node = self.root.make_node(codelite_solution_name)
782 else:
783 self.solution_node = self.srcnode.make_node(codelite_solution_name)
784 return self.solution_node
786 def project_configurations(self):
788 Helper that returns all the pairs (config,platform)
790 ret = []
791 for c in self.configurations:
792 for p in self.platforms:
793 ret.append((c, p))
794 return ret
796 def collect_targets(self):
798 Process the list of task generators
800 for g in self.groups:
801 for tg in g:
802 if not isinstance(tg, TaskGen.task_gen):
803 continue
805 if not hasattr(tg, 'codelite_includes'):
806 tg.codelite_includes = tg.to_list(getattr(tg, 'includes', [])) + tg.to_list(getattr(tg, 'export_includes', []))
807 tg.post()
808 if not getattr(tg, 'link_task', None):
809 continue
811 p = self.vsnode_target(self, tg)
812 p.collect_source() # delegate this processing
813 p.collect_properties()
814 self.all_projects.append(p)
816 def add_aliases(self):
818 Add a specific target that emulates the "make all" necessary for Visual studio when pressing F7
819 We also add an alias for "make install" (disabled by default)
821 base = getattr(self, 'projects_dir', None) or self.tg.path
823 node_project = base.make_node('build_all_projects' + self.project_extension) # Node
824 p_build = self.vsnode_build_all(self, node_project)
825 p_build.collect_properties()
826 self.all_projects.append(p_build)
828 node_project = base.make_node('install_all_projects' + self.project_extension) # Node
829 p_install = self.vsnode_install_all(self, node_project)
830 p_install.collect_properties()
831 self.all_projects.append(p_install)
833 node_project = base.make_node('project_view' + self.project_extension) # Node
834 p_view = self.vsnode_project_view(self, node_project)
835 p_view.collect_source()
836 p_view.collect_properties()
837 self.all_projects.append(p_view)
839 n = self.vsnode_vsdir(self, make_uuid(self.srcnode.abspath() + 'build_aliases'), "build_aliases")
840 p_build.parent = p_install.parent = p_view.parent = n
841 self.all_projects.append(n)
843 def collect_dirs(self):
845 Create the folder structure in the CodeLite project view
847 seen = {}
848 def make_parents(proj):
849 # look at a project, try to make a parent
850 if getattr(proj, 'parent', None):
851 # aliases already have parents
852 return
853 x = proj.iter_path
854 if x in seen:
855 proj.parent = seen[x]
856 return
858 # There is not vsnode_vsdir for x.
859 # So create a project representing the folder "x"
860 n = proj.parent = seen[x] = self.vsnode_vsdir(self, make_uuid(x.abspath()), x.name)
861 n.iter_path = x.parent
862 self.all_projects.append(n)
864 # recurse up to the project directory
865 if x.height() > self.srcnode.height() + 1:
866 make_parents(n)
868 for p in self.all_projects[:]: # iterate over a copy of all projects
869 if not getattr(p, 'tg', None):
870 # but only projects that have a task generator
871 continue
873 # make a folder for each task generator
874 p.iter_path = p.tg.path
875 make_parents(p)
879 def options(ctx):
880 pass