1 #! /usr/bin/env python3
2 # -*- Mode: python; tab-width: 4; indent-tabs-mode: t -*-
4 # This file is part of the LibreOffice project.
6 # This Source Code Form is subject to the terms of the Mozilla Public
7 # License, v. 2.0. If a copy of the MPL was not distributed with this
8 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
20 import xml.etree.ElementTree as ET
21 import xml.dom.minidom as minidom
24 from sys import platform
27 class GbuildLinkTarget:
28 def __init__(self, name, location, include, include_sys, defs, cxxobjects, cxxflags, linked_libs):
29 (self.name, self.location, self.include, self.include_sys, self.defs, self.cxxobjects, self.cxxflags, self.linked_libs) = (
30 name, location, include, include_sys, defs, cxxobjects, cxxflags, linked_libs)
36 return not self.include and not self.defs and not self.cxxobjects and not self.linked_libs
39 return '%s at %s with include path: %s, isystem includes: %s, defines: %s, objects: %s, cxxflags: %s and linked libs: %s' % (
40 self.short_name(), self.location, self.include, self.include_sys, self.defs, self.cxxobjects,
41 self.cxxflags, self.linked_libs)
44 class GbuildLib(GbuildLinkTarget):
45 def __init__(self, name, location, include, include_sys, defs, cxxobjects, cxxflags, linked_libs):
46 GbuildLinkTarget.__init__(self, name, location, include, include_sys, defs, cxxobjects, cxxflags, linked_libs)
49 """Return the short name of target based on the Library_* makefile name"""
50 return 'Library %s' % self.name
52 def target_name(self):
53 return 'Library_%s' % self.name
55 def library_name(self):
58 class GbuildTest(GbuildLinkTarget):
59 def __init__(self, name, location, include, include_sys, defs, cxxobjects, cxxflags, linked_libs):
60 GbuildLinkTarget.__init__(self, name, location, include, include_sys, defs, cxxobjects, cxxflags, linked_libs)
63 """Return the short name of target based n the CppunitTest_* makefile names"""
64 return 'CppunitTest %s' % self.name
66 def target_name(self):
67 return 'CppunitTest_%s' % self.name
69 class GbuildExe(GbuildLinkTarget):
70 def __init__(self, name, location, include, include_sys, defs, cxxobjects, cxxflags, linked_libs):
71 GbuildLinkTarget.__init__(self, name, location, include, include_sys, defs, cxxobjects, cxxflags, linked_libs)
74 """Return the short name of target based on the Executable_* makefile name"""
75 return 'Executable %s' % self.name
77 def target_name(self):
78 return 'Executable_%s' % self.name
82 """Main data model object.
85 target_by_path : dict[path:string, set(target)]
86 where target is one of the GbuildLinkTarget subclasses
87 target_by_location : dict[path:string, set(target)]
88 where target is one of the GbuildLinkTarget subclasses
90 def __init__(self, makecmd):
91 self.makecmd = makecmd
92 self.binpath = os.path.dirname(os.environ['GPERF']) # woha, this is quite a hack
93 (self.srcdir, self.builddir, self.instdir, self.workdir) = (os.environ['SRCDIR'], os.environ['BUILDDIR'], os.environ['INSTDIR'], os.environ['WORKDIR'])
94 (self.libs, self.exes, self.tests, self.modulenamelist) = ([], [], [], [])
95 (self.target_by_path, self.target_by_location) = ({}, {})
97 includepattern = re.compile('-I(\S+)')
98 isystempattern = re.compile('-isystem\s*(\S+)')
99 warningpattern = re.compile('-W\S+')
100 libpattern = re.compile('Library_(.*)\.mk')
101 exepattern = re.compile('Executable_(.*)\.mk')
102 testpattern = re.compile('CppunitTest_(.*)\.mk')
105 def __split_includes(includes):
106 foundisystem = GbuildParser.isystempattern.findall(includes)
107 foundincludes = [includeswitch.strip() for includeswitch in GbuildParser.includepattern.findall(includes) if
108 len(includeswitch) > 2]
109 return (foundincludes, foundisystem)
112 def __split_objs(objsline):
113 return [obj for obj in objsline.strip().split(' ') if len(obj) > 0 and obj != 'CXXOBJECTS' and obj != '+=']
116 def __split_defs(defsline):
118 alldefs = [defswitch.strip() for defswitch in defsline.strip().lstrip('-D').split(' -D') if len(defswitch) > 2]
120 dparts = d.split(' -U')
121 """after dparts.pop(0), dparts will contain only undefs"""
122 defparts = dparts.pop(0).strip().split('=')
123 if len(defparts) == 1:
124 defparts.append(None)
125 defs[defparts[0]] = defparts[1]
126 """Drop undefed items (if any) from previous defs"""
128 defs.pop(u.strip(), '')
129 defs["LIBO_INTERNAL_ONLY"] = None
133 def __split_flags(flagsline, flagslineappend):
134 return [cxxflag.strip() for cxxflag in GbuildParser.warningpattern.sub('', '%s %s' % (flagsline, flagslineappend)).split(' ') if len(cxxflag) > 1]
137 def __lib_from_json(json):
138 (foundincludes, foundisystem) = GbuildParser.__split_includes(json['INCLUDE'])
140 GbuildParser.libpattern.match(os.path.basename(json['MAKEFILE'])).group(1),
141 os.path.dirname(json['MAKEFILE']),
144 GbuildParser.__split_defs(json['DEFS']),
145 GbuildParser.__split_objs(json['CXXOBJECTS']),
146 GbuildParser.__split_flags(json['CXXFLAGS'], json['CXXFLAGSAPPEND']),
147 json['LINKED_LIBS'].strip().split(' '))
150 def __test_from_json(json):
151 (foundincludes, foundisystem) = GbuildParser.__split_includes(json['INCLUDE'])
152 testname_match = GbuildParser.testpattern.match(os.path.basename(json['MAKEFILE']))
154 # Workaround strange writer test makefile setup
155 if testname_match is None:
156 testname = "StrangeWriterMakefiles"
158 testname = testname_match.group(1)
162 os.path.dirname(json['MAKEFILE']),
165 GbuildParser.__split_defs(json['DEFS']),
166 GbuildParser.__split_objs(json['CXXOBJECTS']),
167 GbuildParser.__split_flags(json['CXXFLAGS'], json['CXXFLAGSAPPEND']),
168 json['LINKED_LIBS'].strip().split(' '))
171 def __exe_from_json(json):
172 (foundincludes, foundisystem) = GbuildParser.__split_includes(json['INCLUDE'])
174 GbuildParser.exepattern.match(os.path.basename(json['MAKEFILE'])).group(1),
175 os.path.dirname(json['MAKEFILE']),
178 GbuildParser.__split_defs(json['DEFS']),
179 GbuildParser.__split_objs(json['CXXOBJECTS']),
180 GbuildParser.__split_flags(json['CXXFLAGS'], json['CXXFLAGSAPPEND']),
181 json['LINKED_LIBS'].strip().split(' '))
184 for jsonfilename in os.listdir(os.path.join(self.workdir, 'GbuildToJson', 'Library')):
185 with open(os.path.join(self.workdir, 'GbuildToJson', 'Library', jsonfilename), 'r') as f:
186 lib = self.__lib_from_json(json.load(f))
187 self.libs.append(lib)
188 for jsonfilename in os.listdir(os.path.join(self.workdir, 'GbuildToJson', 'Executable')):
189 with open(os.path.join(self.workdir, 'GbuildToJson', 'Executable', jsonfilename), 'r') as f:
190 exe = self.__exe_from_json(json.load(f))
191 self.exes.append(exe)
192 for jsonfilename in os.listdir(os.path.join(self.workdir, 'GbuildToJson', 'CppunitTest')):
193 with open(os.path.join(self.workdir, 'GbuildToJson', 'CppunitTest', jsonfilename), 'r') as f:
194 test = self.__test_from_json(json.load(f))
195 self.tests.append(test)
196 for target in set(self.libs) | set(self.exes) | set(self.tests):
197 if target.location not in self.target_by_location:
198 self.target_by_location[target.location] = set()
199 self.target_by_location[target.location] |= set([target])
200 for cxx in target.cxxobjects:
201 path = '/'.join(cxx.split('/')[:-1])
202 if path not in self.target_by_path:
203 self.target_by_path[path] = set()
204 self.target_by_path[path] |= set([target])
205 for location in self.target_by_location:
206 self.modulenamelist.append(os.path.split(location)[1])
210 class IdeIntegrationGenerator:
212 def __init__(self, gbuildparser, ide):
213 self.gbuildparser = gbuildparser
219 class EclipseCDTIntegrationGenerator(IdeIntegrationGenerator):
221 def __init__(self, gbuildparser, ide):
222 IdeIntegrationGenerator.__init__(self, gbuildparser, ide)
224 def create_include_paths(self):
225 for module in self.gbuildparser.modulenamelist:
226 modulepath = os.path.join(self.gbuildparser.builddir, module)
227 includedirfile = open(os.path.join(modulepath, '.eclipsesettingfile'), 'w')
229 for lib in self.gbuildparser.target_by_path.keys():
230 if lib.startswith(module+'/'):
231 modulelibs.append(lib)
233 for lib in modulelibs:
234 for target in self.gbuildparser.target_by_path[lib]:
235 include |= set(target.include)
236 includedirfile.write('\n'.join(include))
237 includedirfile.close()
240 def create_macros(self):
241 for module in self.gbuildparser.modulenamelist:
242 modulepath = os.path.join(self.gbuildparser.builddir, module)
243 macrofile = open(os.path.join(modulepath, '.macros'), 'w')
245 for lib in self.gbuildparser.target_by_path.keys():
246 if lib.startswith(module+'/'):
247 modulelibs.append(lib)
250 for lib in modulelibs:
251 for target in self.gbuildparser.target_by_path[lib]:
252 for i in target.defs.keys():
253 tmp = str(i) +','+str(target.defs[i])
254 if tmp not in defineset:
256 macrofile.write('\n'.join(defineset))
260 def create_settings_file(self):
262 settingsfiletemplate = """\
263 <?xml version="1.0" encoding="UTF-8"?>
264 <cdtprojectproperties>
265 <section name="org.eclipse.cdt.internal.ui.wizards.settingswizards.IncludePaths">
266 <language name="C++ Source File">
270 <language name="C Source File">
273 <language name="Object File">
276 <language name="Assembly Source File">
280 <section name="org.eclipse.cdt.internal.ui.wizards.settingswizards.Macros">
281 <language name="C++ Source File">
284 <language name="C Source File">
287 <language name="Object File">
290 <language name="Assembly Source File">
294 </cdtprojectproperties>
297 for module in self.gbuildparser.modulenamelist:
299 modulepath = os.path.join(self.gbuildparser.builddir, module)
301 settingsfile = open(os.path.join(modulepath, 'eclipsesettingfile.xml'), 'w')
302 settingsfile.write(settingsfiletemplate)
305 settingsfile = open(os.path.join(modulepath, 'eclipsesettingfile.xml'), 'r')
306 tempxml = settingsfile.readlines()
307 tempinclude = open(os.path.join(modulepath, '.eclipsesettingfile'), 'r')
308 tempmacro = open(os.path.join(modulepath, '.macros'), 'r')
309 for includepath in tempinclude:
310 if includepath[-1:] == "\n":
311 includepath = includepath[:-1]
312 templine = "<includepath>%s</includepath>\n" % includepath
313 tempxml.insert(5, templine)
315 for line in tempmacro:
316 macroskeyvalue = line.split(',')
317 macrokey = macroskeyvalue[0]
318 macrovalue = macroskeyvalue[1]
319 if macrovalue[-1:] == "\n":
320 macrovalue = macrovalue[:-1]
321 templine = "<macro><name>%s</name><value>%s</value></macro>\n" %(macrokey, macrovalue)
322 tempxml.insert(-13, templine)
323 tempxml="".join(tempxml)
326 settingsfile = open(os.path.join(modulepath, 'eclipsesettingfile.xml'), 'w')
327 settingsfile.write(tempxml)
329 os.remove(os.path.join(modulepath, '.eclipsesettingfile'))
330 os.remove(os.path.join(modulepath, '.macros'))
333 self.create_include_paths()
335 self.create_settings_file()
337 class CodeliteIntegrationGenerator(IdeIntegrationGenerator):
339 def __init__(self, gbuildparser, ide):
340 IdeIntegrationGenerator.__init__(self, gbuildparser, ide)
343 self.create_workspace_file()
344 for module in self.gbuildparser.modulenamelist:
345 self.create_project_file(module)
346 #self.create_project_file('vcl')
348 def create_workspace_file(self):
349 root_node = ET.Element('CodeLite_Workspace', Name='libo2', Database='./libo2.tags', Version='10.0.0')
350 for module in self.gbuildparser.modulenamelist:
351 ET.SubElement(root_node, 'Project', Name=module, Path='%s/%s.project' % (module, module), Active='No')
352 build_matrix_node = ET.SubElement(root_node, 'BuildMatrix')
353 workspace_config_node = ET.SubElement(build_matrix_node, 'WorkspaceConfiguration', Name='Debug', Selected='yes')
354 ET.SubElement(workspace_config_node, 'Environment')
355 for module in self.gbuildparser.modulenamelist:
356 ET.SubElement(workspace_config_node, 'Project', Name=module, ConfigName='Debug')
357 workspace_config_node = ET.SubElement(build_matrix_node, 'WorkspaceConfiguration', Name='Release', Selected='yes')
358 ET.SubElement(workspace_config_node, 'Environment')
359 for module in self.gbuildparser.modulenamelist:
360 ET.SubElement(workspace_config_node, 'Project', Name=module, ConfigName='Release')
362 self.write_pretty_xml(root_node, os.path.join(self.gbuildparser.builddir, 'libo2.workspace'))
364 def create_project_file(self, module_name):
365 root_node = ET.Element('CodeLite_Project', Name=module_name, InternalType='')
366 ET.SubElement(root_node, 'Plugins')
369 virtual_dirs = collections.defaultdict(set)
370 for target_path in self.gbuildparser.target_by_path.keys():
371 if target_path.startswith(module_name+'/'):
372 for target in self.gbuildparser.target_by_path[target_path]:
373 for file in target.cxxobjects:
374 relative_file = '/'.join(file.split('/')[1:])
375 path = '/'.join(file.split('/')[1:-1])
376 virtual_dirs[path].add(relative_file + '.cxx')
378 all_libs = set(self.gbuildparser.libs) | set(self.gbuildparser.exes)
380 if lib.name == module_name:
381 for hdir in lib.include:
382 # only want the module-internal ones
383 if hdir.startswith(module_name+'/'):
384 for hf in os.listdir(hdir):
385 if hf.endswith(('.h', '.hxx', '.hpp', '.hrc')):
386 path = '/'.join(hf.split('/')[1:-1])
387 virtual_dirs[path].add(hf)
388 # add HXX files from the root/include/** folders
389 module_include = os.path.join(self.gbuildparser.builddir, 'include', module_name)
390 if os.path.exists(module_include):
391 for hf in os.listdir(module_include):
392 if hf.endswith(('.h', '.hxx', '.hpp', '.hrc')):
393 path = '../include/' + ('/'.join(hf.split('/')[1:-1]))
394 virtual_dirs['include/' + module_name].add('../include/' + module_name + '/' + hf)
396 for vd_name in sorted(virtual_dirs.keys()):
397 vd_files = sorted(virtual_dirs[vd_name])
398 parent_node = root_node
399 for subname in vd_name.split('/'):
400 parent_node = ET.SubElement(parent_node, 'VirtualDirectory', Name=subname)
401 for file in vd_files:
402 ET.SubElement(parent_node, 'File', Name=file)
404 ET.SubElement(root_node, 'Description')
405 ET.SubElement(root_node, 'Dependencies')
406 ET.SubElement(root_node, 'Dependencies', Name='Debug')
407 ET.SubElement(root_node, 'Dependencies', Name='Release')
409 settingstemplate = """\
410 <Settings Type="Dynamic Library">
412 <Compiler Options="" C_Options="" Assembler="">
413 <IncludePath Value="."/>
416 <LibraryPath Value="."/>
418 <ResourceCompiler Options=""/>
420 <Configuration Name="Debug" CompilerType="clang( based on LLVM 3.5.0 )" DebuggerType="GNU gdb debugger" Type="Dynamic Library" BuildCmpWithGlobalSettings="append" BuildLnkWithGlobalSettings="append" BuildResWithGlobalSettings="append">
421 <Compiler Options="-g" C_Options="-g" Assembler="" Required="yes" PreCompiledHeader="" PCHInCommandLine="no" PCHFlags="" PCHFlagsPolicy="0">
422 <IncludePath Value="."/>
424 <Linker Options="" Required="yes"/>
425 <ResourceCompiler Options="" Required="no"/>
426 <General OutputFile="" IntermediateDirectory="./Debug" Command="" CommandArguments="" UseSeparateDebugArgs="no" DebugArguments="" WorkingDirectory="$(IntermediateDirectory)" PauseExecWhenProcTerminates="yes" IsGUIProgram="no" IsEnabled="yes"/>
427 <BuildSystem Name="Default"/>
428 <Environment EnvVarSetName="<Use Defaults>" DbgSetName="<Use Defaults>">
431 <Debugger IsRemote="no" RemoteHostName="" RemoteHostPort="" DebuggerPath="" IsExtended="no">
432 <DebuggerSearchPaths/>
433 <PostConnectCommands/>
438 <CustomBuild Enabled="yes">
440 <CleanCommand>make %s.clean</CleanCommand>
441 <BuildCommand>make %s.build</BuildCommand>
442 <PreprocessFileCommand/>
444 <MakefileGenerationCommand/>
445 <ThirdPartyToolName>None</ThirdPartyToolName>
446 <WorkingDirectory>$(WorkspacePath)</WorkingDirectory>
452 <Completion EnableCpp11="no" EnableCpp14="no">
459 <Configuration Name="Release" CompilerType="clang( based on LLVM 3.5.0 )" DebuggerType="GNU gdb debugger" Type="Dynamic Library" BuildCmpWithGlobalSettings="append" BuildLnkWithGlobalSettings="append" BuildResWithGlobalSettings="append">
460 <Compiler Options="" C_Options="" Assembler="" Required="yes" PreCompiledHeader="" PCHInCommandLine="no" PCHFlags="" PCHFlagsPolicy="0">
461 <IncludePath Value="."/>
463 <Linker Options="-O2" Required="yes"/>
464 <ResourceCompiler Options="" Required="no"/>
465 <General OutputFile="" IntermediateDirectory="./Release" Command="" CommandArguments="" UseSeparateDebugArgs="no" DebugArguments="" WorkingDirectory="$(IntermediateDirectory)" PauseExecWhenProcTerminates="yes" IsGUIProgram="no" IsEnabled="yes"/>
466 <BuildSystem Name="Default"/>
467 <Environment EnvVarSetName="<Use Defaults>" DbgSetName="<Use Defaults>">
470 <Debugger IsRemote="no" RemoteHostName="" RemoteHostPort="" DebuggerPath="" IsExtended="no">
471 <DebuggerSearchPaths/>
472 <PostConnectCommands/>
477 <CustomBuild Enabled="yes">
479 <CleanCommand>make %s.clean</CleanCommand>
480 <BuildCommand>make %s.build</BuildCommand>
481 <PreprocessFileCommand/>
483 <MakefileGenerationCommand/>
484 <ThirdPartyToolName>None</ThirdPartyToolName>
485 <WorkingDirectory>$(WorkspacePath)</WorkingDirectory>
491 <Completion EnableCpp11="no" EnableCpp14="no">
500 root_node.append(ET.fromstring(settingstemplate % (module_name, module_name, module_name, module_name)))
502 self.write_pretty_xml(root_node, os.path.join(self.gbuildparser.builddir, module_name, '%s.project' % module_name))
504 def write_pretty_xml(self, node, file_path):
505 xml_str = ET.tostring(node, encoding='unicode')
506 pretty_str = minidom.parseString(xml_str).toprettyxml(encoding='utf-8')
507 with open(file_path, 'w') as f:
508 f.write(pretty_str.decode())
510 class DebugIntegrationGenerator(IdeIntegrationGenerator):
512 def __init__(self, gbuildparser, ide):
513 IdeIntegrationGenerator.__init__(self, gbuildparser, ide)
516 print(self.gbuildparser.srcdir)
517 print(self.gbuildparser.builddir)
518 for lib in self.gbuildparser.libs:
520 for exe in self.gbuildparser.exes:
522 for test in self.gbuildparser.tests:
526 class VimIntegrationGenerator(IdeIntegrationGenerator):
528 def __init__(self, gbuildparser, ide):
529 IdeIntegrationGenerator.__init__(self, gbuildparser, ide)
533 for lib in set(self.gbuildparser.libs) | set(self.gbuildparser.tests) | set(self.gbuildparser.exes):
535 for file in lib.cxxobjects:
536 filePath = os.path.join(self.gbuildparser.srcdir, file) + ".cxx"
537 entry = {'directory': lib.location, 'file': filePath, 'command': self.generateCommand(lib, filePath)}
538 entries.append(entry)
539 global_list.extend(entries)
540 export_file = open('compile_commands.json', 'w')
541 json.dump(global_list, export_file)
543 def generateCommand(self, lib, file):
544 command = 'clang++ -Wall'
545 for key, value in lib.defs.items():
548 if value is not None:
552 for include in lib.include:
555 for isystem in lib.include_sys:
556 command += ' -isystem '
558 for cxxflag in lib.cxxflags:
566 class KdevelopIntegrationGenerator(IdeIntegrationGenerator):
568 def encode_int(self, i):
570 return '\\x%s\\x%s\\x%s\\x%s' % (temp[0:2], temp[2:4], temp[4:6], temp[6:8])
572 def encode_string(self, string):
573 result = self.encode_int(len(string) * 2)
574 for c in string.encode('utf-16-be'):
575 if c in range(32, 126):
578 result += '\\x%02x' % c
581 def generate_buildsystemconfigtool(self, configid, tool, args, exe, typenr):
582 return KdevelopIntegrationGenerator.buildsystemconfigtooltemplate % {'configid': configid, 'tool': tool,
583 'args': args, 'exe': exe, 'typenr': typenr}
585 buildsystemconfigtooltemplate = """
586 [CustomBuildSystem][BuildConfig%(configid)d][Tool%(tool)s]
595 def generate_buildsystemconfig(self, configid, moduledir, builddir, title, buildparms=''):
596 result = KdevelopIntegrationGenerator.buildsystemconfigtemplate % {'configid': configid, 'builddir': builddir,
598 result += self.generate_buildsystemconfigtool(configid, 'Clean', 'clean %s' % buildparms,
599 self.gbuildparser.makecmd, 3)
600 result += self.generate_buildsystemconfigtool(configid, 'Build', 'all %s' % buildparms,
601 self.gbuildparser.makecmd, 0)
604 buildsystemconfigtemplate = """
605 [CustomBuildSystem][BuildConfig%(configid)d]
606 BuildDir=file://%(builddir)s
611 def generate_buildsystem(self, moduledir):
612 result = KdevelopIntegrationGenerator.buildsystemtemplate % {'defaultconfigid': 0}
613 result += self.generate_buildsystemconfig(0, moduledir, moduledir, 'Module Build -- Release')
614 result += self.generate_buildsystemconfig(1, moduledir, self.gbuildparser.builddir, 'Full Build -- Release')
615 result += self.generate_buildsystemconfig(2, moduledir, moduledir, 'Module Build -- Debug', 'debug=T')
616 result += self.generate_buildsystemconfig(3, moduledir, self.gbuildparser.builddir, 'Full Build -- Debug',
620 buildsystemtemplate = """
622 CurrentConfiguration=BuildConfig%(defaultconfigid)d
626 def generate_launch(self, launchid, launchname, executablepath, args, workdir):
627 return KdevelopIntegrationGenerator.launchtemplate % {'launchid': launchid, 'launchname': launchname,
628 'executablepath': executablepath, 'args': args,
632 [Launch][Launch Configuration %(launchid)d]
633 Configured Launch Modes=execute
634 Configured Launchers=nativeAppLauncher
636 Type=Native Application
638 [Launch][Launch Configuration %(launchid)d][Data]
640 Dependencies=@Variant(\\x00\\x00\\x00\\t\\x00\\x00\\x00\\x00\\x00)
641 Dependency Action=Nothing
642 EnvironmentGroup=default
643 Executable=file://%(executablepath)s
644 External Terminal=konsole --noclose --workdir %%workdir -e %%exe
646 Use External Terminal=false
647 Working Directory=file://%(workdir)s
652 def generate_launches(self, moduledir):
653 launches = ','.join(['Launch Configuration %d' % i for i in range(7)])
654 result = KdevelopIntegrationGenerator.launchestemplate % {'launches': launches}
655 result += self.generate_launch(0, 'Local tests -- quick tests (unitcheck)', self.gbuildparser.makecmd,
656 'unitcheck', moduledir)
657 result += self.generate_launch(1, 'Local tests -- slow tests (unitcheck, slowcheck, screenshot)', self.gbuildparser.makecmd,
658 'unitcheck slowcheck screenshot', moduledir)
659 result += self.generate_launch(2, 'Local tests -- integration tests (unitcheck, slowcheck, screenshot, subsequentcheck)',
660 self.gbuildparser.makecmd, 'unitcheck slowcheck screenshot subsequentcheck', moduledir)
661 result += self.generate_launch(3, 'Global tests -- quick tests (unitcheck)', self.gbuildparser.makecmd,
662 'unitcheck', self.gbuildparser.builddir)
663 result += self.generate_launch(4, 'Global tests -- slow tests (unitcheck, slowcheck, screenshot)',
664 self.gbuildparser.makecmd, 'unitcheck slowcheck screenshot', self.gbuildparser.builddir)
665 result += self.generate_launch(5, 'Global tests -- integration tests (unitcheck, slowcheck, screenshot, subsequentcheck)',
666 self.gbuildparser.makecmd, 'unitcheck slowcheck screenshot subsequentcheck',
667 self.gbuildparser.builddir)
668 result += self.generate_launch(6, 'Run LibreOffice',
669 os.path.join(self.gbuildparser.instdir, 'program/soffice.bin'), '',
670 self.gbuildparser.instdir)
673 launchestemplate = """
675 Launch Configurations=%(launches)s
679 def write_modulebeef(self, moduledir, modulename):
680 beefdir = os.path.join(moduledir, '.kdev4')
682 beeffile = open(os.path.join(beefdir, 'Module_%s.kdev4' % modulename), 'w')
683 beeffile.write(self.generate_buildsystem(moduledir))
684 beeffile.write(self.generate_launches(moduledir))
687 def write_modulestub(self, moduledir, modulename):
688 stubfile = open(os.path.join(moduledir, 'Module_%s.kdev4' % modulename), 'w')
689 stubfile.write(KdevelopIntegrationGenerator.modulestubtemplate % {'modulename': modulename,
690 'builditem': self.encode_string(
691 'Module_%s' % modulename)})
694 modulestubtemplate = """
696 BuildItems=@Variant(\\x00\\x00\\x00\\t\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x0b\\x00\\x00\\x00\\x00\\x01%(builditem)s)
699 Name=Module_%(modulename)s
700 Manager=KDevCustomBuildSystem
701 VersionControl=kdevgit
704 def write_includepaths(self, path):
705 includedirfile = open(os.path.join(path, '.kdev_include_paths'), 'w')
707 for target in self.gbuildparser.target_by_path[path]:
708 include |= set(target.include)
709 includedirfile.write('\n'.join(include))
710 includedirfile.close()
712 def __init__(self, gbuildparser, ide):
713 IdeIntegrationGenerator.__init__(self, gbuildparser, ide)
716 for path in self.gbuildparser.target_by_path:
717 self.write_includepaths(path)
718 for location in self.gbuildparser.target_by_location:
719 for f in os.listdir(location):
720 if f.endswith('.kdev4'):
722 os.remove(os.path.join(location, f))
724 shutil.rmtree(os.path.join(location, f))
725 for location in self.gbuildparser.target_by_location:
726 modulename = os.path.split(location)[1]
727 self.write_modulestub(location, modulename)
728 self.write_modulebeef(location, modulename)
731 class XcodeIntegrationGenerator(IdeIntegrationGenerator):
733 def indent(self, file, level):
736 for i in range(0, level):
739 def write_object(self, object, file, indent):
740 if isinstance(object, int):
741 file.write('%d' % object)
742 elif isinstance(object, str) and not re.search('[^A-Za-z0-9_]', object):
743 file.write('%s' % object)
744 elif isinstance(object, str):
745 file.write('"%s"' % object)
746 elif isinstance(object, dict):
747 self.write_dict(object, file, indent)
749 # Write a dictionary out as an "old-style (NeXT) ASCII plist"
750 def write_dict(self, dict, file, indent):
753 for key in sorted(dict.keys()):
754 self.indent(file, indent + 1)
755 file.write('%s = ' % key)
756 self.write_object(dict[key], file, indent + 1)
758 self.indent(file, indent)
761 def write_dict_to_plist(self, dict, file):
762 file.write('// !$*UTF8*$!\n')
763 self.write_dict(dict, file, 0)
765 def get_product_type(self, modulename):
766 if modulename in self.gbuildparser.libs:
767 return 'com.apple.product-type.library.dynamic'
768 elif modulename in self.gbuildparser.exes:
769 return 'com.apple.product-type.something'
773 def generate_id(self):
774 XcodeIntegrationGenerator.counter = XcodeIntegrationGenerator.counter + 1
775 return str('X%07x' % XcodeIntegrationGenerator.counter)
777 def generate_build_phases(self, modulename):
778 result = [self.sourcesBuildPhaseId]
781 def generate_root_object(self, modulename):
782 result = {'isa': 'PBXProject',
783 'attributes': {'LastUpgradeCheck': '0500',
784 'ORGANIZATIONNAME': 'LibreOffice'},
785 'buildConfigurationList': self.generate_id(),
786 'compatibilityVersion': 'Xcode 3.2',
787 'hasScannedForEncodings': 0,
788 'knownRegions': ['en'],
789 'mainGroup': self.mainGroupId,
790 'productRefGroup': self.productRefGroupId,
791 'projectDirPath': '',
793 'targets': self.targetId}
796 def generate_target(self, modulename):
797 result = {'isa': 'PBXNativeTarget',
798 'buildConfigurationList': self.generate_id(),
799 'buildPhases': self.generate_build_phases(modulename),
803 'productName': modulename,
804 'productReference': self.productReferenceId,
805 'productType': self.get_product_type(modulename)}
808 def generate_main_group(self, modulename):
809 result = {'isa': 'PBXGroup',
810 'children': [self.subMainGroupId, self.productGroupId],
811 'sourceTree': '<group>'}
814 def generate_sub_main_children(self, modulename):
817 def generate_sub_main_group(self, modulename):
818 result = {'isa': 'PBXGroup',
819 'children': self.generate_sub_main_children(modulename),
821 'sourceTree': '<group>'}
824 def generate_product_group(self, modulename):
825 result = {'isa': 'PBXGroup',
826 'children': [self.productReferenceId],
828 'sourceTree': '<group>'}
831 def build_source_list(self, module):
832 self.sourceRefList = {}
835 for i in module.cxxobjects:
836 ref = self.generate_id()
837 self.sourceList[self.generate_id()] = ref
838 self.sourceRefList[ref] = {'lastKnownFileType': 'sourcecode.cpp.cpp',
840 'sourceTree': '<group>'}
842 def generate_sources_build_phase(self, modulename):
843 result = {'isa': 'PBXSourcesBuildPhase',
844 'buildActionMask': 2147483647,
845 'files': self.sourceList.keys(),
846 'runOnlyForDeploymentPostprocessing': 0}
849 def generate_project(self, target):
850 self.rootObjectId = self.generate_id()
851 self.mainGroupId = self.generate_id()
852 self.subMainGroupId = self.generate_id()
853 self.productReferenceId = self.generate_id()
854 self.productRefGroupId = self.generate_id()
855 self.productGroupId = self.generate_id()
856 self.targetId = self.generate_id()
857 self.build_source_list(target)
858 self.sourcesBuildPhaseId = self.generate_id()
859 objects = {self.rootObjectId: self.generate_root_object(target),
860 self.targetId: self.generate_target(target),
861 self.mainGroupId: self.generate_main_group(target),
862 self.subMainGroupId: self.generate_sub_main_group(target),
863 self.productGroupId: self.generate_product_group(target),
864 self.sourcesBuildPhaseId: self.generate_sources_build_phase(target)
866 for i in self.sourceList.keys():
867 ref = self.sourceList[i]
868 objects[i] = {'isa': 'PBXBuildFile',
870 objects[ref] = {'isa': 'PBXFileReference',
871 'lastKnownFileType': self.sourceRefList[ref]['lastKnownFileType'],
872 'path': self.sourceRefList[ref]['path']}
873 project = {'archiveVersion': 1,
877 'rootObject': self.rootObjectId}
880 # For some reverse-engineered documentation on the project.pbxproj format,
881 # see http://www.monobjc.net/xcode-project-file-format.html .
882 def write_xcodeproj(self, moduledir, target):
883 xcodeprojdir = os.path.join(moduledir, '%s.xcodeproj' % target.target_name())
885 os.mkdir(xcodeprojdir)
888 self.write_dict_to_plist(self.generate_project(target),
889 open(os.path.join(xcodeprojdir, 'project.pbxproj'), 'w'))
891 def __init__(self, gbuildparser, ide):
892 IdeIntegrationGenerator.__init__(self, gbuildparser, ide)
895 self.rootlocation = './'
896 for location in self.gbuildparser.target_by_location:
897 # module = location.split('/')[-1]
898 # module_directory = os.path.join(self.rootlocation, module)
899 for target in self.gbuildparser.target_by_location[location]:
900 # project_path = os.path.join(module_directory, '%s.pbxroj' % target.target_name())
901 self.write_xcodeproj(location, target)
904 class VisualStudioIntegrationGenerator(IdeIntegrationGenerator):
906 def __init__(self, gbuildparser, ide):
907 IdeIntegrationGenerator.__init__(self, gbuildparser, ide)
908 self.toolset = self.retrieve_toolset(ide)
909 self.solution_directory = './'
910 self.configurations = {
912 'build': self.module_make_command('%(target)s'),
913 'clean': self.module_make_command('%(target)s.clean'),
914 'rebuild': self.module_make_command('%(target)s.clean %(target)s')
917 'build': self.module_make_command('unitcheck'),
918 'clean': self.module_make_command('clean'),
919 'rebuild': self.module_make_command('clean unitcheck'),
921 'Integration tests': {
922 'build': self.module_make_command('unitcheck slowcheck screenshot subsequentcheck'),
923 'clean': self.module_make_command('clean'),
924 'rebuild': self.module_make_command('clean unitcheck slowcheck screenshot subsequentcheck')
928 def retrieve_toolset(self, ide):
929 ide_toolset_map = {'vs2017': 'v141', 'vs2019': 'v142'}
930 return ide_toolset_map[ide]
932 def module_make_command(self, targets):
933 return '%(sh)s -c "PATH=\\"/bin:$PATH\\";BUILDDIR=\\"%(builddir)s\\" %(makecmd)s -rsC %(location)s ' + targets + '"'
937 def __init__(self, guid, target, project_path):
940 self.path = project_path
944 for location in self.gbuildparser.target_by_location:
946 module = location.split('/')[-1]
947 module_directory = os.path.join(self.solution_directory, module)
948 for target in self.gbuildparser.target_by_location[location]:
949 project_path = os.path.join(module_directory, '%s.vcxproj' % target.target_name())
950 project_guid = self.write_project(project_path, target)
951 p = VisualStudioIntegrationGenerator.Project(project_guid, target, project_path)
953 self.write_solution(os.path.join(module_directory, '%s.sln' % module), projects)
954 all_projects += projects
956 self.write_solution(os.path.join(self.solution_directory, 'LibreOffice.sln'), all_projects)
958 nmake_project_guid = '8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942'
960 def get_dependency_libs(self, linked_libs, library_projects):
962 for linked_lib in linked_libs:
963 for library_project in library_projects:
964 if library_project.target.library_name() == linked_lib:
965 dependency_libs[library_project.guid] = library_project
966 return dependency_libs
968 def write_solution(self, solution_path, projects):
969 print('Solution %s:' % os.path.splitext(os.path.basename(solution_path))[0], end='')
970 library_projects = [project for project in projects if project.target in self.gbuildparser.libs]
971 with open(solution_path, 'w') as f:
972 f.write('Microsoft Visual Studio Solution File, Format Version 12.00\n')
973 for project in projects:
974 target = project.target
975 print(' %s' % target.target_name(), end='')
976 proj_path = os.path.relpath(project.path, os.path.abspath(os.path.dirname(solution_path)))
977 f.write('Project("{%s}") = "%s", "%s", "{%s}"\n' %
978 (VisualStudioIntegrationGenerator.nmake_project_guid,
979 target.short_name(), proj_path, project.guid))
980 libs_in_solution = self.get_dependency_libs(target.linked_libs,
983 f.write('\tProjectSection(ProjectDependencies) = postProject\n')
984 for lib_guid in libs_in_solution.keys():
985 f.write('\t\t{%(guid)s} = {%(guid)s}\n' % {'guid': lib_guid})
986 f.write('\tEndProjectSection\n')
987 f.write('EndProject\n')
988 f.write('Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{B9292527-A979-4D13-A598-C75A33222174}"\n')
989 f.write('\tProjectSection(SolutionItems) = preProject\n')
990 f.write('\t\tsolenv/vs/LibreOffice.natvis = solenv/vs/LibreOffice.natvis\n')
991 f.write('\tEndProjectSection\n')
992 f.write('EndProject\n')
995 f.write('\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n')
996 for cfg in self.configurations:
997 f.write('\t\t%(cfg)s|%(platform)s = %(cfg)s|%(platform)s\n' % {'cfg': cfg, 'platform': platform})
998 f.write('\tEndGlobalSection\n')
999 f.write('\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\n')
1000 # Specifies project configurations for solution configuration
1001 for project in projects:
1002 for cfg in self.configurations:
1003 params = {'guid': project.guid, 'sol_cfg': cfg, 'proj_cfg': cfg, 'platform': platform}
1004 f.write('\t\t{%(guid)s}.%(sol_cfg)s|%(platform)s.ActiveCfg = %(proj_cfg)s|%(platform)s\n' % params)
1005 # Build.0 is basically 'Build checkbox' in configuration manager
1006 f.write('\t\t{%(guid)s}.%(sol_cfg)s|%(platform)s.Build.0 = %(proj_cfg)s|%(platform)s\n' % params)
1007 f.write('\tEndGlobalSection\n')
1008 f.write('EndGlobal\n')
1012 def to_long_names(shortnames):
1013 if platform == "cygwin":
1014 return (subprocess.check_output(["cygpath", "-wal"] + shortnames).decode("utf-8", "strict").rstrip()).split("\n")
1019 def defs_list(defs):
1022 for key, value in defs.items():
1024 if value is not None:
1025 define += '=' + value
1026 defines_list.append(define)
1029 def write_project(self, project_path, target):
1030 # See info at http://blogs.msdn.com/b/visualstudio/archive/2010/05/14/a-guide-to-vcxproj-and-props-file-structure.aspx
1031 folder = os.path.dirname(project_path)
1032 if not os.path.exists(folder):
1034 project_guid = str(uuid.uuid4()).upper()
1035 cxxflags = ' '.join(target.cxxflags)
1036 ns = 'http://schemas.microsoft.com/developer/msbuild/2003'
1037 ET.register_namespace('', ns)
1038 proj_node = ET.Element('{%s}Project' % ns, DefaultTargets='Build', ToolsVersion='4.0')
1039 proj_confs_node = ET.SubElement(proj_node, '{%s}ItemGroup' % ns, Label='ProjectConfigurations')
1041 for configuration in self.configurations:
1042 proj_conf_node = ET.SubElement(proj_confs_node,
1043 '{%s}ProjectConfiguration' % ns,
1044 Include='%s|%s' % (configuration, platform))
1045 conf_node = ET.SubElement(proj_conf_node, '{%s}Configuration' % ns)
1046 conf_node.text = configuration
1047 platform_node = ET.SubElement(proj_conf_node, '{%s}Platform' % ns)
1048 platform_node.text = platform
1050 globals_node = ET.SubElement(proj_node, '{%s}PropertyGroup' % ns, Label='Globals')
1051 proj_guid_node = ET.SubElement(globals_node, '{%s}ProjectGuid' % ns)
1052 proj_guid_node.text = '{%s}' % project_guid
1053 proj_keyword_node = ET.SubElement(globals_node, '{%s}Keyword' % ns)
1054 proj_keyword_node.text = 'MakeFileProj'
1055 proj_name_node = ET.SubElement(globals_node, '{%s}ProjectName' % ns)
1056 proj_name_node.text = target.short_name()
1058 ET.SubElement(proj_node, '{%s}Import' % ns, Project='$(VCTargetsPath)\Microsoft.Cpp.Default.props')
1059 for configuration in self.configurations:
1060 conf_node = ET.SubElement(proj_node, '{%s}PropertyGroup' % ns, Label="Configuration",
1061 Condition="'$(Configuration)|$(Platform)'=='%s|%s'" % (configuration, platform))
1062 # Type of project used by the MSBuild to determine build process, see Microsoft.Makefile.targets
1063 conf_type_node = ET.SubElement(conf_node, '{%s}ConfigurationType' % ns)
1064 conf_type_node.text = 'Makefile'
1065 # This defines the version of Visual Studio which can show next to project names in the Solution Explorer
1066 platform_toolset_node = ET.SubElement(conf_node, '{%s}PlatformToolset' % ns)
1067 platform_toolset_node.text = self.toolset
1069 ET.SubElement(proj_node, '{%s}Import' % ns, Project='$(VCTargetsPath)\Microsoft.Cpp.props')
1070 ET.SubElement(proj_node, '{%s}ImportGroup' % ns, Label='ExtensionSettings')
1071 for configuration in self.configurations:
1072 prop_sheets_node = ET.SubElement(proj_node, '{%s}ImportGroup' % ns, Label='Configuration',
1073 Condition="'$(Configuration)|$(Platform)'=='%s|%s'" % (configuration, platform))
1074 ET.SubElement(prop_sheets_node, '{%s}Import' % ns,
1075 Project='$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props',
1076 Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')",
1077 Label='LocalAppDataPlatform')
1079 ET.SubElement(proj_node, '{%s}PropertyGroup' % ns, Label='UserMacros')
1080 # VS IDE (at least "Peek definition") is allergic to paths like "C:/PROGRA~2/WI3CF2~1/10/Include/10.0.14393.0/um"; see
1081 # https://developercommunity.visualstudio.com/content/problem/139659/vc-peek-definition-fails-to-navigate-to-windows-ki.html
1082 # We need to convert to long paths here. Do this once, since it's time-consuming operation.
1083 include_path_node_text = ';'.join(self.to_long_names(target.include))
1084 for cfg_name, cfg_targets in self.configurations.items():
1085 conf_node = ET.SubElement(proj_node, '{%s}PropertyGroup' % ns,
1086 Condition="'$(Configuration)|$(Platform)'=='%s|%s'" % (cfg_name, platform))
1088 'sh': os.path.join(self.gbuildparser.binpath, 'dash.exe'),
1089 'builddir': self.gbuildparser.builddir,
1090 'location': target.location,
1091 'makecmd': self.gbuildparser.makecmd,
1092 'target': target.target_name()}
1093 nmake_build_node = ET.SubElement(conf_node, '{%s}NMakeBuildCommandLine' % ns)
1094 nmake_build_node.text = cfg_targets['build'] % nmake_params
1095 nmake_clean_node = ET.SubElement(conf_node, '{%s}NMakeCleanCommandLine' % ns)
1096 nmake_clean_node.text = cfg_targets['clean'] % nmake_params
1097 nmake_rebuild_node = ET.SubElement(conf_node, '{%s}NMakeReBuildCommandLine' % ns)
1098 nmake_rebuild_node.text = cfg_targets['rebuild'] % nmake_params
1099 nmake_output_node = ET.SubElement(conf_node, '{%s}NMakeOutput' % ns)
1100 nmake_output_node.text = os.path.join(self.gbuildparser.instdir, 'program', 'soffice.bin')
1101 nmake_defs_node = ET.SubElement(conf_node, '{%s}NMakePreprocessorDefinitions' % ns)
1102 nmake_defs_node.text = ';'.join(self.defs_list(target.defs) + ['$(NMakePreprocessorDefinitions)'])
1103 include_path_node = ET.SubElement(conf_node, '{%s}IncludePath' % ns)
1104 include_path_node.text = include_path_node_text
1105 additional_options_node = ET.SubElement(conf_node, '{%s}AdditionalOptions' % ns)
1106 additional_options_node.text = cxxflags
1108 ET.SubElement(proj_node, '{%s}ItemDefinitionGroup' % ns)
1110 cxxobjects_node = ET.SubElement(proj_node, '{%s}ItemGroup' % ns)
1111 for cxxobject in target.cxxobjects:
1112 cxxabspath = os.path.join(self.gbuildparser.srcdir, cxxobject)
1113 cxxfile = cxxabspath + '.cxx'
1114 if os.path.isfile(cxxfile):
1115 ET.SubElement(cxxobjects_node, '{%s}ClCompile' % ns, Include=cxxfile)
1117 print('Source %s in project %s does not exist' % (cxxfile, target.target_name()))
1119 includes_node = ET.SubElement(proj_node, '{%s}ItemGroup' % ns)
1120 for cxxobject in target.cxxobjects:
1121 include_abs_path = os.path.join(self.gbuildparser.srcdir, cxxobject)
1122 hxxfile = include_abs_path + '.hxx'
1123 if os.path.isfile(hxxfile):
1124 ET.SubElement(includes_node, '{%s}ClInclude' % ns, Include=hxxfile)
1125 # Few files have corresponding .h files
1126 hfile = include_abs_path + '.h'
1127 if os.path.isfile(hfile):
1128 ET.SubElement(includes_node, '{%s}ClInclude' % ns, Include=hfile)
1129 ET.SubElement(proj_node, '{%s}Import' % ns, Project='$(VCTargetsPath)\Microsoft.Cpp.targets')
1130 ET.SubElement(proj_node, '{%s}ImportGroup' % ns, Label='ExtensionTargets')
1131 self.write_pretty_xml(proj_node, project_path)
1132 self.write_filters(project_path + '.filters',
1133 os.path.join(self.gbuildparser.srcdir, os.path.basename(target.location)),
1134 [cxx_node.get('Include') for cxx_node in cxxobjects_node.findall('{%s}ClCompile' % ns)],
1135 [include_node.get('Include') for include_node in includes_node.findall('{%s}ClInclude' % ns)])
1138 def get_filter(self, module_dir, proj_file):
1139 return '\\'.join(os.path.relpath(proj_file, module_dir).split('/')[:-1])
1141 def get_subfilters(self, proj_filter):
1142 parts = proj_filter.split('\\')
1143 subfilters = set([proj_filter]) if proj_filter else set()
1144 for i in range(1, len(parts)):
1145 subfilters.add('\\'.join(parts[:i]))
1148 def write_pretty_xml(self, node, file_path):
1149 xml_str = ET.tostring(node, encoding='unicode')
1150 pretty_str = minidom.parseString(xml_str).toprettyxml(encoding='utf-8')
1151 with open(file_path, 'w') as f:
1152 f.write(pretty_str.decode())
1154 def add_nodes(self, files_node, module_dir, tag, project_files):
1155 ns = 'http://schemas.microsoft.com/developer/msbuild/2003'
1157 for project_file in project_files:
1158 file_node = ET.SubElement(files_node, tag, Include=project_file)
1159 if os.path.commonprefix([module_dir, project_file]) == module_dir:
1160 project_filter = self.get_filter(module_dir, project_file)
1161 filter_node = ET.SubElement(file_node, '{%s}Filter' % ns)
1162 filter_node.text = project_filter
1163 filters |= self.get_subfilters(project_filter)
1166 def write_filters(self, filters_path, module_dir, compile_files, include_files):
1167 ns = 'http://schemas.microsoft.com/developer/msbuild/2003'
1168 ET.register_namespace('', ns)
1169 proj_node = ET.Element('{%s}Project' % ns, ToolsVersion='4.0')
1171 compiles_node = ET.SubElement(proj_node, '{%s}ItemGroup' % ns)
1172 filters |= self.add_nodes(compiles_node, module_dir, '{%s}ClCompile' % ns, compile_files)
1173 include_node = ET.SubElement(proj_node, '{%s}ItemGroup' % ns)
1174 filters |= self.add_nodes(include_node, module_dir, '{%s}ClInclude' % ns, include_files)
1176 filters_node = ET.SubElement(proj_node, '{%s}ItemGroup' % ns)
1177 for proj_filter in filters:
1178 filter_node = ET.SubElement(filters_node, '{%s}Filter' % ns, Include=proj_filter)
1179 filter_id_node = ET.SubElement(filter_node, '{%s}UniqueIdentifier' % ns)
1180 filter_id_node.text = '{%s}' % str(uuid.uuid4())
1181 self.write_pretty_xml(proj_node, filters_path)
1184 class QtCreatorIntegrationGenerator(IdeIntegrationGenerator):
1186 def __init__(self, gbuildparser, ide):
1187 IdeIntegrationGenerator.__init__(self, gbuildparser, ide)
1188 self.target_by_location = {}
1189 for target in set(self.gbuildparser.libs) | set(self.gbuildparser.exes) | set(self.gbuildparser.tests):
1190 if target.location not in self.target_by_location:
1191 self.target_by_location[target.location] = set()
1192 self.target_by_location[target.location] |= set([target])
1194 self._do_log = False # set to 'True' to activate log of QtCreatorIntegrationGenerator
1196 qtlog_path = os.path.abspath('../qtlog_.txt')
1197 self.qtlog = open(qtlog_path, 'w')
1199 def _log(self, message):
1201 self.qtlog.write(message)
1203 def log_close(self):
1207 def generate_build_configs(self, lib_folder):
1208 module_folder = os.path.join(self.base_folder, lib_folder)
1210 # In QtCreator UI, build configs are listed alphabetically,
1211 # so it can be different from the creation order.
1212 # So we prefix the names with the index.
1213 xml += QtCreatorIntegrationGenerator.build_configs_template % {
1215 'base_folder': module_folder,
1217 'name': "1-Build %s" % lib_folder,
1219 xml += QtCreatorIntegrationGenerator.build_configs_template % {
1221 'base_folder': module_folder,
1223 'name': "2-Local tests -- quick tests (unitcheck)",
1225 xml += QtCreatorIntegrationGenerator.build_configs_template % {
1227 'base_folder': module_folder,
1228 'arg': "unitcheck slowcheck screenshot",
1229 'name': "3-Local tests -- slow tests (unitcheck, slowcheck, screenshot)",
1231 xml += QtCreatorIntegrationGenerator.build_configs_template % {
1233 'base_folder': module_folder,
1234 'arg': "unitcheck slowcheck screenshot subsequentcheck",
1235 'name': "4-Local tests -- integration tests (unitcheck, slowcheck, screenshot, subsequentcheck)",
1237 xml += QtCreatorIntegrationGenerator.build_configs_template % {
1239 'base_folder': self.base_folder,
1241 'name': "5-Global tests -- quick tests (unitcheck)",
1243 xml += QtCreatorIntegrationGenerator.build_configs_template % {
1245 'base_folder': self.base_folder,
1246 'arg': "unitcheck slowcheck screenshot",
1247 'name': "6-Global tests -- slow tests (unitcheck, slowcheck, screenshot)",
1249 xml += QtCreatorIntegrationGenerator.build_configs_template % {
1251 'base_folder': self.base_folder,
1252 'arg': "unitcheck slowcheck screenshot subsequentcheck",
1253 'name': "7-Global tests -- integration tests (unitcheck, slowcheck, screenshot, subsequentcheck)",
1255 xml += QtCreatorIntegrationGenerator.build_configs_template % {
1257 'base_folder': self.base_folder,
1258 'arg': "build-nocheck",
1259 'name': "8-Global build -- nocheck",
1261 xml += QtCreatorIntegrationGenerator.build_configs_template % {
1263 'base_folder': self.base_folder,
1265 'name': "9-Global build",
1268 xml += QtCreatorIntegrationGenerator.build_configs_count_template % {
1273 def generate_meta_build_configs(self):
1275 # In QtCreator UI, build configs are listed alphabetically,
1276 # so it can be different from the creation order.
1277 # So we prefix the names with the index.
1278 xml += QtCreatorIntegrationGenerator.build_configs_template % {
1280 'base_folder': self.base_folder,
1282 'name': "01-Global Build",
1284 xml += QtCreatorIntegrationGenerator.build_configs_template % {
1286 'base_folder': self.base_folder,
1288 'name': "02-Global tests -- quick tests (unitcheck)",
1290 xml += QtCreatorIntegrationGenerator.build_configs_template % {
1292 'base_folder': self.base_folder,
1293 'arg': "unitcheck slowcheck screenshot",
1294 'name': "03-Global tests -- slow tests (unitcheck, slowcheck, screenshot)",
1296 xml += QtCreatorIntegrationGenerator.build_configs_template % {
1298 'base_folder': self.base_folder,
1299 'arg': "unitcheck slowcheck screenshot subsequentcheck",
1300 'name': "04-Global tests -- integration tests (unitcheck, slowcheck, screenshot, subsequentcheck)",
1302 xml += QtCreatorIntegrationGenerator.build_configs_template % {
1304 'base_folder': self.base_folder,
1306 'name': "05-Global tests -- performance tests (perfcheck)",
1308 xml += QtCreatorIntegrationGenerator.build_configs_template % {
1310 'base_folder': self.base_folder,
1312 'name': "06-Global tests -- tests (check)",
1314 xml += QtCreatorIntegrationGenerator.build_configs_template % {
1316 'base_folder': self.base_folder,
1317 'arg': "build-nocheck",
1318 'name': "07-Global build -- nocheck",
1320 xml += QtCreatorIntegrationGenerator.build_configs_template % {
1322 'base_folder': self.base_folder,
1323 'arg': "build-l10n-only",
1324 'name': "08-Global build -- build-l10n-only",
1326 xml += QtCreatorIntegrationGenerator.build_configs_template % {
1328 'base_folder': self.base_folder,
1329 'arg': "build-non-l10n-only",
1330 'name': "09-Global build -- build-non-l10n-only",
1332 xml += QtCreatorIntegrationGenerator.build_configs_template % {
1334 'base_folder': self.base_folder,
1336 'name': "10-Global build -- clean",
1338 xml += QtCreatorIntegrationGenerator.build_configs_template % {
1340 'base_folder': self.base_folder,
1341 'arg': "clean-build",
1342 'name': "11-Global build -- clean-build",
1344 xml += QtCreatorIntegrationGenerator.build_configs_template % {
1346 'base_folder': self.base_folder,
1347 'arg': "clean-host",
1348 'name': "12-Global build -- clean-host",
1350 xml += QtCreatorIntegrationGenerator.build_configs_count_template % {
1355 # By default, QtCreator creates 2 BuildStepList : "Build" et "Clean"
1356 # but the "clean" can be empty.
1357 build_configs_template = """
1358 <valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.%(index)s">
1359 <value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">%(base_folder)s</value>
1361 <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
1363 <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
1364 <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
1365 <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
1366 <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
1367 <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
1368 <valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments">
1369 <value type="QString">-w</value>
1370 <value type="QString">-r</value>
1372 <value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value>
1373 <value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">%(arg)s</value>
1374 <value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
1377 <value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
1378 <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
1379 <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
1380 <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
1383 <value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
1384 <value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
1385 <valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
1386 <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">%(name)s</value>
1387 <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
1388 <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
1389 <value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">%(index)s</value>
1390 <value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">true</value>
1394 build_configs_count_template = """
1395 <!-- nb build configurations -->
1396 <value type="int" key="ProjectExplorer.Target.BuildConfigurationCount">%(nb)s</value>
1399 def generate_deploy_configs(self, lib_folder):
1400 xml = QtCreatorIntegrationGenerator.deploy_configs_template % {}
1403 deploy_configs_template = """
1404 <valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
1405 <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
1406 <value type="int" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
1407 <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy</value>
1408 <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
1409 <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
1411 <value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
1412 <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy locally</value>
1413 <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
1414 <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
1416 <value type="int" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
1419 def generate_run_configs(self, lib_folder):
1421 # If we use 'soffice', it's ok only for "Run", not for "Debug".
1422 # So we put "soffice.bin" that is ok for both.
1423 loexec = "%s/instdir/program/soffice.bin" % self.base_folder
1424 xml = QtCreatorIntegrationGenerator.run_configs_template % {
1426 'workdir': self.base_folder
1430 run_configs_template = """
1431 <valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
1432 <valuelist type="QVariantList" key="Analyzer.Valgrind.AddedSuppressionFiles"/>
1433 <value type="bool" key="Analyzer.Valgrind.Callgrind.CollectBusEvents">false</value>
1434 <value type="bool" key="Analyzer.Valgrind.Callgrind.CollectSystime">false</value>
1435 <value type="bool" key="Analyzer.Valgrind.Callgrind.EnableBranchSim">false</value>
1436 <value type="bool" key="Analyzer.Valgrind.Callgrind.EnableCacheSim">false</value>
1437 <value type="bool" key="Analyzer.Valgrind.Callgrind.EnableEventToolTips">true</value>
1438 <value type="double" key="Analyzer.Valgrind.Callgrind.MinimumCostRatio">0.01</value>
1439 <value type="double" key="Analyzer.Valgrind.Callgrind.VisualisationMinimumCostRatio">10</value>
1440 <value type="bool" key="Analyzer.Valgrind.FilterExternalIssues">true</value>
1441 <value type="int" key="Analyzer.Valgrind.LeakCheckOnFinish">1</value>
1442 <value type="int" key="Analyzer.Valgrind.NumCallers">25</value>
1443 <valuelist type="QVariantList" key="Analyzer.Valgrind.RemovedSuppressionFiles"/>
1444 <value type="int" key="Analyzer.Valgrind.SelfModifyingCodeDetection">1</value>
1445 <value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
1446 <value type="bool" key="Analyzer.Valgrind.ShowReachable">false</value>
1447 <value type="bool" key="Analyzer.Valgrind.TrackOrigins">true</value>
1448 <value type="QString" key="Analyzer.Valgrind.ValgrindExecutable">valgrind</value>
1449 <valuelist type="QVariantList" key="Analyzer.Valgrind.VisibleErrorKinds">
1450 <value type="int">0</value>
1451 <value type="int">1</value>
1452 <value type="int">2</value>
1453 <value type="int">3</value>
1454 <value type="int">4</value>
1455 <value type="int">5</value>
1456 <value type="int">6</value>
1457 <value type="int">7</value>
1458 <value type="int">8</value>
1459 <value type="int">9</value>
1460 <value type="int">10</value>
1461 <value type="int">11</value>
1462 <value type="int">12</value>
1463 <value type="int">13</value>
1464 <value type="int">14</value>
1466 <value type="int" key="PE.EnvironmentAspect.Base">2</value>
1467 <valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
1469 <value type="QString" key="ProjectExplorer.CustomExecutableRunConfiguration.Arguments"></value>
1470 <value type="QString" key="ProjectExplorer.CustomExecutableRunConfiguration.Executable">%(loexec)s</value>
1471 <value type="bool" key="ProjectExplorer.CustomExecutableRunConfiguration.UseTerminal">false</value>
1472 <value type="QString" key="ProjectExplorer.CustomExecutableRunConfiguration.WorkingDirectory">%(workdir)s</value>
1473 <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Run libreoffice/instdir/program/soffice</value>
1474 <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
1475 <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.CustomExecutableRunConfiguration</value>
1476 <value type="uint" key="RunConfiguration.QmlDebugServerPort">3768</value>
1477 <value type="bool" key="RunConfiguration.UseCppDebugger">false</value>
1478 <value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
1479 <value type="bool" key="RunConfiguration.UseMultiProcess">false</value>
1480 <value type="bool" key="RunConfiguration.UseQmlDebugger">false</value>
1481 <value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
1484 <value type="int" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
1487 def generate_pro_user_content(self, lib_folder):
1489 build_configs = self.generate_build_configs(lib_folder)
1490 deploy_configs = self.generate_deploy_configs(lib_folder)
1491 run_configs = self.generate_run_configs(lib_folder)
1493 xml = QtCreatorIntegrationGenerator.pro_user_template % {
1494 'build_configs': build_configs,
1495 'deploy_configs': deploy_configs,
1496 'run_configs': run_configs,
1500 def generate_meta_pro_user_content(self):
1502 build_configs = self.generate_meta_build_configs()
1503 deploy_configs = self.generate_deploy_configs("")
1504 run_configs = self.generate_run_configs("")
1506 xml = QtCreatorIntegrationGenerator.pro_user_template % {
1507 'build_configs': build_configs,
1508 'deploy_configs': deploy_configs,
1509 'run_configs': run_configs,
1513 pro_user_template = """<?xml version="1.0" encoding="UTF-8"?>
1514 <!DOCTYPE QtCreatorProject>
1515 <!-- Written by QtCreator 3.1.1, 2015-05-14T15:54:34. -->
1518 <variable>ProjectExplorer.Project.ActiveTarget</variable>
1519 <value type="int">0</value>
1522 <!-- editor settings -->
1524 <variable>ProjectExplorer.Project.EditorSettings</variable>
1525 <valuemap type="QVariantMap">
1526 <value type="bool" key="EditorConfiguration.AutoIndent">true</value>
1527 <value type="bool" key="EditorConfiguration.AutoSpacesForTabs">false</value>
1528 <value type="bool" key="EditorConfiguration.CamelCaseNavigation">true</value>
1529 <valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.0">
1530 <value type="QString" key="language">Cpp</value>
1531 <valuemap type="QVariantMap" key="value">
1532 <value type="QByteArray" key="CurrentPreferences">CppGlobal</value>
1535 <valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.1">
1536 <value type="QString" key="language">QmlJS</value>
1537 <valuemap type="QVariantMap" key="value">
1538 <value type="QByteArray" key="CurrentPreferences">QmlJSGlobal</value>
1541 <value type="int" key="EditorConfiguration.CodeStyle.Count">2</value>
1542 <value type="QByteArray" key="EditorConfiguration.Codec">UTF-8</value>
1543 <value type="bool" key="EditorConfiguration.ConstrainTooltips">false</value>
1544 <value type="int" key="EditorConfiguration.IndentSize">4</value>
1545 <value type="bool" key="EditorConfiguration.KeyboardTooltips">false</value>
1546 <value type="int" key="EditorConfiguration.MarginColumn">80</value>
1547 <value type="bool" key="EditorConfiguration.MouseHiding">true</value>
1548 <value type="bool" key="EditorConfiguration.MouseNavigation">true</value>
1549 <value type="int" key="EditorConfiguration.PaddingMode">1</value>
1550 <value type="bool" key="EditorConfiguration.ScrollWheelZooming">true</value>
1551 <value type="bool" key="EditorConfiguration.ShowMargin">false</value>
1552 <value type="int" key="EditorConfiguration.SmartBackspaceBehavior">1</value>
1553 <value type="bool" key="EditorConfiguration.SpacesForTabs">true</value>
1554 <value type="int" key="EditorConfiguration.TabKeyBehavior">0</value>
1555 <value type="int" key="EditorConfiguration.TabSize">8</value>
1556 <value type="bool" key="EditorConfiguration.UseGlobal">true</value>
1557 <value type="int" key="EditorConfiguration.Utf8BomBehavior">1</value>
1558 <value type="bool" key="EditorConfiguration.addFinalNewLine">true</value>
1559 <value type="bool" key="EditorConfiguration.cleanIndentation">true</value>
1560 <value type="bool" key="EditorConfiguration.cleanWhitespace">true</value>
1561 <value type="bool" key="EditorConfiguration.inEntireDocument">false</value>
1566 <variable>ProjectExplorer.Project.PluginSettings</variable>
1567 <valuemap type="QVariantMap"/>
1572 <variable>ProjectExplorer.Project.Target.0</variable>
1573 <valuemap type="QVariantMap">
1574 <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Desktop</value>
1575 <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Desktop</value>
1576 <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">{0701de51-c96e-4e4f-85c3-e70b223c5076}</value>
1577 <value type="int" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
1578 <value type="int" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
1579 <value type="int" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
1581 <!-- build configurations -->
1584 <!-- deploy configurations -->
1587 <!-- plugin settings -->
1588 <valuemap type="QVariantMap" key="ProjectExplorer.Target.PluginSettings"/>
1590 <!-- run configurations -->
1595 <!-- nb targets : 1 -->
1597 <variable>ProjectExplorer.Project.TargetCount</variable>
1598 <value type="int">1</value>
1601 <variable>ProjectExplorer.Project.Updater.EnvironmentId</variable>
1602 <value type="QByteArray">{5abcafed-86f6-49f6-b1cb-380fadd21211}</value>
1605 <variable>ProjectExplorer.Project.Updater.FileVersion</variable>
1606 <value type="int">15</value>
1611 def remove_qt_files(self):
1613 def do_remove_file(loc, afile):
1615 os.remove(os.path.join(loc, afile))
1616 self._log("removed %s\n" % afile)
1618 self._log("unable to remove %s\n" % afile)
1620 do_remove_file(self.base_folder, "lo.pro")
1621 do_remove_file(self.base_folder, "lo.pro.user")
1622 for location in self.target_by_location:
1623 for f in os.listdir(location):
1624 if f.endswith('.pro') or f.endswith('.pro.user'):
1625 do_remove_file(location, f)
1627 def get_source_extension(self, src_file):
1628 path = os.path.join(self.base_folder, src_file)
1629 for ext in (".cxx", ".cpp", ".c", ".mm"):
1630 if os.path.isfile(path + ext):
1634 def get_header_extension(self, src_file):
1635 path = os.path.join(self.base_folder, src_file)
1636 for ext in (".hxx", ".hpp", ".h"):
1637 if os.path.isfile(path + ext):
1641 def build_data_libs(self):
1645 all_libs = set(self.gbuildparser.libs) | set(self.gbuildparser.exes) | set(self.gbuildparser.tests)
1646 for lib in all_libs:
1647 self._log("\nlibrary : %s, loc=%s" % (lib.short_name(), lib.location))
1648 lib_name = os.path.basename(lib.location)
1649 lib_folder = os.path.relpath(lib.location, self.base_folder)
1652 if platform =="cygwin":
1653 # absolute paths from GbuildToJson are Windows paths,
1654 # so convert everything to such ones
1656 if not ntpath.isabs(abs_path):
1657 abs_path = ntpath.join(self.gbuildparser.srcdir, path)
1658 return ntpath.relpath(abs_path, lib.location).replace('\\', '/')
1660 return os.path.relpath(path, lib.location)
1664 includepath_list = []
1665 # The explicit headers list is not mandatory :
1666 # QtCreator just needs 'include_path_list' to find all headers files.
1667 # But files listed in 'header_list' will be shown
1668 # in a specific "Headers" folder in QtCreator's Project panel.
1669 # We will list here only headers files of current lib.
1671 for file_ in lib.cxxobjects:
1672 # the file has no extension : search it
1673 # self._log("\n file : %s" % file_)
1674 ext = self.get_source_extension(file_)
1676 sources_list.append(lopath(file_ + ext))
1678 # few cxxobject files have a header beside
1679 ext = self.get_header_extension(file_)
1681 headers_list.append(lopath(file_ + ext))
1684 for cxxflag in lib.cxxflags:
1685 # extract flag for C++ standard version
1686 if cxxflag.startswith('-std'):
1687 cxxflags_list.append(cxxflag)
1689 # List all include paths
1690 for hdir in (lib.include + lib.include_sys):
1691 hf_lopath = lopath(hdir)
1692 includepath_list.append(hf_lopath)
1694 # List headers files from current lib
1695 for hdir in lib.include:
1696 if hdir.startswith(lib.location):
1697 for dirpath, _, files in os.walk(hdir):
1699 if hf.endswith(('.h', '.hxx', '.hpp', '.hrc')):
1700 hf_lopath = lopath(os.path.join(dirpath, hf))
1701 headers_list.append(hf_lopath)
1704 for key, value in lib.defs.items():
1706 if value is not None:
1707 define += '=' + value
1708 defines_list.append(define)
1710 # All data are prepared, store them for the lib.
1711 if lib_folder in self.data_libs:
1712 self.data_libs[lib_folder]['sources'] |= set(sources_list)
1713 self.data_libs[lib_folder]['headers'] |= set(headers_list)
1714 self.data_libs[lib_folder]['cxxflags'] |= set(cxxflags_list)
1715 self.data_libs[lib_folder]['includepath'] |= set(includepath_list)
1716 self.data_libs[lib_folder]['defines'] |= set(defines_list)
1718 self.data_libs[lib_folder] = {
1719 'sources': set(sources_list),
1720 'headers': set(headers_list),
1721 'cxxflags': set(cxxflags_list),
1722 'includepath': set(includepath_list),
1723 'defines': set(defines_list),
1724 'loc': lib.location,
1730 self.base_folder = self.gbuildparser.builddir
1732 # we remove existing '.pro' and '.pro.user' files
1733 self.remove_qt_files()
1735 # for .pro files, we must explicitly list all files (.c, .h)
1736 # so we can't reuse directly the same method than for kde integration.
1737 self.build_data_libs()
1739 subdirs_list = self.data_libs.keys()
1740 # Now we can create Qt files
1741 for lib_folder in subdirs_list:
1742 sources_list = sorted(self.data_libs[lib_folder]['sources'])
1743 headers_list = sorted(self.data_libs[lib_folder]['headers'])
1744 cxxflags_list = sorted(self.data_libs[lib_folder]['cxxflags'])
1745 includepath_list = sorted(self.data_libs[lib_folder]['includepath'])
1746 defines_list = sorted(self.data_libs[lib_folder]['defines'])
1747 lib_loc = self.data_libs[lib_folder]['loc']
1748 lib_name = self.data_libs[lib_folder]['name']
1750 sources = " \\\n".join(sources_list)
1751 headers = " \\\n".join(headers_list)
1752 cxxflags = " \\\n".join(cxxflags_list)
1753 includepath = " \\\n".join(includepath_list)
1754 defines = " \\\n".join(defines_list)
1757 qt_pro_file = '%s/%s.pro' % (lib_loc, lib_name)
1759 content = QtCreatorIntegrationGenerator.pro_template % {'sources': sources, 'headers': headers,
1760 'cxxflags': cxxflags, 'includepath': includepath, 'defines': defines}
1762 with open(qt_pro_file, mode) as fpro:
1764 self._log("created %s\n" % qt_pro_file)
1766 except Exception as e:
1767 print("ERROR : creating pro file=" + qt_pro_file, file=sys.stderr)
1768 print(e, file=sys.stderr)
1769 temp = traceback.format_exc() # .decode('utf8')
1770 print(temp, file=sys.stderr)
1771 print("\n\n", file=sys.stderr)
1773 # create .pro.user file
1774 qt_pro_user_file = '%s/%s.pro.user' % (lib_loc, lib_name)
1776 with open(qt_pro_user_file, mode) as fprouser:
1777 fprouser.write(self.generate_pro_user_content(lib_folder))
1778 self._log("created %s\n" % qt_pro_user_file)
1780 except Exception as e:
1781 print("ERROR : creating pro.user file=" + qt_pro_user_file, file=sys.stderr)
1782 print(e, file=sys.stderr)
1783 temp = traceback.format_exc()
1784 print(temp, file=sys.stderr)
1785 print("\n\n", file=sys.stderr)
1787 # create meta .pro file (lists all sub projects)
1788 qt_meta_pro_file = 'lo.pro'
1790 subdirs = " \\\n".join(sorted(subdirs_list))
1791 content = QtCreatorIntegrationGenerator.pro_meta_template % {'subdirs': subdirs}
1792 with open(qt_meta_pro_file, 'w+') as fmpro:
1793 fmpro.write(content)
1795 except Exception as e:
1796 print("ERROR : creating lo.pro file=" + qt_meta_pro_file, file=sys.stderr)
1797 print(e, file=sys.stderr)
1798 temp = traceback.format_exc()
1799 print(temp, file=sys.stderr)
1800 print("\n\n", file=sys.stderr)
1802 # create meta .pro.user file
1803 qt_meta_pro_user_file = 'lo.pro.user'
1805 with open(qt_meta_pro_user_file, mode) as fmprouser:
1806 fmprouser.write(self.generate_meta_pro_user_content())
1807 self._log("created %s\n" % qt_meta_pro_user_file)
1809 except Exception as e:
1810 print("ERROR : creating lo.pro.user file=" + qt_meta_pro_user_file, file=sys.stderr)
1811 print(e, file=sys.stderr)
1812 temp = traceback.format_exc()
1813 print(temp, file=sys.stderr)
1814 print("\n\n", file=sys.stderr)
1818 pro_template = """TEMPLATE = app
1820 CONFIG -= app_bundle
1823 QMAKE_CXXFLAGS += %(cxxflags)s
1825 INCLUDEPATH += %(includepath)s
1827 SOURCES += %(sources)s
1829 HEADERS += %(headers)s
1831 DEFINES += %(defines)s
1834 pro_meta_template = """TEMPLATE = subdirs
1836 SUBDIRS = %(subdirs)s
1841 parser = argparse.ArgumentParser(
1842 description='LibreOffice gbuild IDE project generator')
1843 parser.add_argument('--ide', dest='ide', required=True,
1844 help='the IDE to generate project files for')
1845 parser.add_argument('--make', dest='makecmd', required=True,
1846 help='the command to execute make')
1847 return parser.parse_args()
1850 if __name__ == '__main__':
1851 args = get_options()
1853 if args.makecmd == 'make':
1854 args.makecmd = '/usr/bin/make'
1858 'codelite': CodeliteIntegrationGenerator,
1859 'eclipsecdt': EclipseCDTIntegrationGenerator,
1860 'kdevelop': KdevelopIntegrationGenerator,
1861 'xcode': XcodeIntegrationGenerator,
1862 'vs2017': VisualStudioIntegrationGenerator,
1863 'vs2019': VisualStudioIntegrationGenerator,
1864 'vim': VimIntegrationGenerator,
1865 'debug': DebugIntegrationGenerator,
1866 'qtcreator': QtCreatorIntegrationGenerator,
1869 if args.ide not in generators.keys():
1870 print("Invalid ide. valid values are %s" % ','.join(generators.keys()))
1873 gbuildparser = GbuildParser(args.makecmd).parse()
1875 generators[args.ide](gbuildparser, args.ide).emit()
1876 print("Successfully created the project files.")
1879 # indent-tabs-mode: nil
1882 # vim: set et sw=4 ts=4: