[Libreoffice-commits] core.git: bin/gbuild-to-ideNS Makefile.in

jan Iversen jani at documentfoundation.org
Tue Jan 31 08:59:01 UTC 2017


 Makefile.in         |   19 
 bin/gbuild-to-ideNS | 1660 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 1675 insertions(+), 4 deletions(-)

New commits:
commit 8736391f4ddda5bc73221e0762653a721819bcd9
Author: jan Iversen <jani at documentfoundation.org>
Date:   Mon Jan 30 17:29:08 2017 +0100

    Gbuild-to-ide, Froze non-active supported generators.
    
    Copied gbuild-to-ide.py from d575e3a14beef8bdd3517c024b9aab8a17b3ef7b
    to gbuild-to-ideNS.py
    
    Changed Makefile.in to use gbuild-to-ideNS.py for non-actively
    supported platforms.
    
    That way these platform are stable, and not affected of new features.
    
    For now all platforms are still present in gbuild-to-ide and will
    have a "does not break" test for all new features.
    
    Change-Id: I8bb069d93c954a80de540a32b8a01889035c840d
    Reviewed-on: https://gerrit.libreoffice.org/33710
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: jan iversen <jani at documentfoundation.org>

diff --git a/Makefile.in b/Makefile.in
index 5f7b215..63f731c 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -414,17 +414,28 @@ $(1)-ide-integration: gbuildtojson $(if $(filter MACOSX,$(OS_FOR_BUILD)),python3
 
 endef
 
+define gb_Top_GbuildToIdeIntegrationNS
+$(1)-ide-integration: gbuildtojson $(if $(filter MACOSX,$(OS_FOR_BUILD)),python3.all)
+	cd $(SRCDIR) && \
+		$(if $(filter MACOSX,$(OS_FOR_BUILD)),PATH="$(INSTROOT_FOR_BUILD)/Frameworks/LibreOfficePython.framework/Versions/Current/bin:$(PATH)") \
+		$(SRCDIR)/bin/gbuild-to-ideNS --ide $(1) --make $(MAKE)
+
+endef
+
 $(foreach ide,\
-	codelite \
 	debug \
-	kdevelop \
 	vs2013 \
 	vs2015 \
+	xcode, \
+$(eval $(call gb_Top_GbuildToIdeIntegration,$(ide))))
+
+$(foreach ide,\
+	codelite \
+	kdevelop \
 	vim \
-	xcode \
 	qtcreator \
     eclipsecdt,\
-$(eval $(call gb_Top_GbuildToIdeIntegration,$(ide))))
+$(eval $(call gb_Top_GbuildToIdeIntegrationNS,$(ide))))
 
 fuzzers: Library_sal Library_salhelper Library_reg Library_store Library_unoidl codemaker Library_cppu Library_i18nlangtag Library_cppuhelper Library_comphelper StaticLibrary_ulingu StaticLibrary_jpeg StaticLibrary_findsofficepath Library_tl Rdb_services udkapi offapi Library_clew Library_gie Library_reflection Library_invocadapt Library_bootstrap Library_introspection Library_stocservices Library_xmlreader Library_gcc3_uno instsetoo_native more_fonts StaticLibrary_fuzzer Executable_wmffuzzer Executable_jpgfuzzer Executable_giffuzzer Executable_xbmfuzzer Executable_xpmfuzzer Executable_pngfuzzer Executable_bmpfuzzer Executable_svmfuzzer Executable_pcdfuzzer Executable_dxffuzzer Executable_metfuzzer Executable_ppmfuzzer Executable_psdfuzzer Executable_epsfuzzer
 
diff --git a/bin/gbuild-to-ideNS b/bin/gbuild-to-ideNS
new file mode 100755
index 0000000..7de2fb4
--- /dev/null
+++ b/bin/gbuild-to-ideNS
@@ -0,0 +1,1660 @@
+#! /usr/bin/env python3
+# -*- Mode: python; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+import argparse
+import os
+import os.path
+import shutil
+import re
+import sys
+import uuid
+import json
+import xml.etree.ElementTree as ET
+import xml.dom.minidom as minidom
+import traceback
+
+
+class GbuildLinkTarget:
+    def __init__(self, name, location, include, include_sys, defs, cxxobjects, cxxflags, linked_libs):
+        (self.name, self.location, self.include, self.include_sys, self.defs, self.cxxobjects, self.cxxflags, self.linked_libs) = (
+            name, location, include, include_sys, defs, cxxobjects, cxxflags, linked_libs)
+
+    def short_name(self):
+        return self.name
+
+    def is_empty(self):
+        return not self.include and not self.defs and not self.cxxobjects and not self.linked_libs
+
+    def __str__(self):
+        return '%s at %s with include path: %s, isystem includes: %s, defines: %s, objects: %s, cxxflags: %s and linked libs: %s' % (
+            self.short_name(), self.location, self.include, self.include_sys, self.defs, self.cxxobjects,
+            self.cxxflags, self.linked_libs)
+
+
+class GbuildLib(GbuildLinkTarget):
+    def __init__(self, name, library, location, include, include_sys, defs, cxxobjects, cxxflags, linked_libs):
+        GbuildLinkTarget.__init__(self, name, location, include, include_sys, defs, cxxobjects, cxxflags, linked_libs)
+        self.library = library
+
+    def short_name(self):
+        """Return the short name of target based on the Library_* makefile name"""
+        return 'Library %s' % self.name
+
+    def target_name(self):
+        return 'Library_%s' % self.library
+
+    def library_name(self):
+        return self.library
+
+class GbuildTest(GbuildLinkTarget):
+    def __init__(self, name, test, location, include, include_sys, defs, cxxobjects, cxxflags, linked_libs):
+        GbuildLinkTarget.__init__(self, name, location, include, include_sys, defs, cxxobjects, cxxflags, linked_libs)
+        self.test = test
+
+    def short_name(self):
+        """Return the short name of target based n the CppunitTest_* makefile names"""
+        return 'CppunitTest %s' % self.name
+
+    def target_name(self):
+        return 'CppunitTest_%s' % self.test
+
+    def test_name(self):
+        return self.test
+
+
+class GbuildExe(GbuildLinkTarget):
+    def __init__(self, name, executable, location, include, include_sys, defs, cxxobjects, cxxflags, linked_libs):
+        GbuildLinkTarget.__init__(self, name, location, include, include_sys, defs, cxxobjects, cxxflags, linked_libs)
+        self.executable = executable
+
+    def short_name(self):
+        """Return the short name of target based on the Executable_* makefile name"""
+        return 'Executable %s' % self.name
+
+    def target_name(self):
+        return 'Executable_%s' % self.executable
+
+
+class GbuildParser:
+    def __init__(self, makecmd):
+        self.makecmd = makecmd
+        self.binpath = os.path.dirname(os.environ['GPERF']) # woha, this is quite a hack
+        (self.srcdir, self.builddir, self.instdir, self.workdir) = (os.environ['SRCDIR'], os.environ['BUILDDIR'], os.environ['INSTDIR'], os.environ['WORKDIR'])
+        (self.libs, self.exes, self.tests, self.modulenamelist) = ([], [], [], [])
+        (self.libnames, self.exenames, self.testnames, self.target_by_path, self.target_by_location) = ({}, {}, {}, {}, {})
+
+    includepattern = re.compile('-I(\S+)')
+    isystempattern = re.compile('-isystem\s*(\S+)')
+    warningpattern = re.compile('-W\S+')
+    libpattern = re.compile('Library_(.*)\.mk')
+    exepattern = re.compile('Executable_(.*)\.mk')
+    testpattern = re.compile('CppunitTest_(.*)\.mk')
+
+    @staticmethod
+    def __split_includes(includes):
+        foundisystem = GbuildParser.isystempattern.findall(includes)
+        foundincludes = [includeswitch.strip() for includeswitch in GbuildParser.includepattern.findall(includes) if
+                len(includeswitch) > 2]
+        return (foundincludes, foundisystem)
+
+    @staticmethod
+    def __split_objs(objsline):
+        return [obj for obj in objsline.strip().split(' ') if len(obj) > 0 and obj != 'CXXOBJECTS' and obj != '+=']
+
+    @staticmethod
+    def __split_defs(defsline):
+        defs = {}
+        alldefs = [defswitch.strip() for defswitch in defsline.strip().lstrip('-D').split(' -D') if len(defswitch) > 2]
+        for d in alldefs:
+            defparts = d.split('=')
+            if len(defparts) == 1:
+                defparts.append(None)
+            defs[defparts[0]] = defparts[1]
+        defs["LIBO_INTERNAL_ONLY"] = None
+        return defs
+
+    @staticmethod
+    def __split_flags(flagsline, flagslineappend):
+        return [cxxflag.strip() for cxxflag in GbuildParser.warningpattern.sub('', '%s %s' % (flagsline, flagslineappend)).split(' ') if len(cxxflag) > 1]
+
+    @staticmethod
+    def __lib_from_json(json):
+        (foundincludes, foundisystem) = GbuildParser.__split_includes(json['INCLUDE'])
+        return GbuildLib(
+            GbuildParser.libpattern.match(os.path.basename(json['MAKEFILE'])).group(1),
+            json['LINKTARGET'],
+            os.path.dirname(json['MAKEFILE']),
+            foundincludes,
+            foundisystem,
+            GbuildParser.__split_defs(json['DEFS']),
+            GbuildParser.__split_objs(json['CXXOBJECTS']),
+            GbuildParser.__split_flags(json['CXXFLAGS'], json['CXXFLAGSAPPEND']),
+            json['LINKED_LIBS'].strip().split(' '))
+
+    @staticmethod
+    def __test_from_json(json):
+        (foundincludes, foundisystem) = GbuildParser.__split_includes(json['INCLUDE'])
+        testname_match = GbuildParser.testpattern.match(os.path.basename(json['MAKEFILE']))
+
+        # Workaround strange writer test makefile setup
+        if testname_match is None:
+            testname = "StrangeWriterMakefiles"
+        else:
+            testname = testname_match.group(1)
+
+        return GbuildTest(
+            testname,
+            json['LINKTARGET'],
+            os.path.dirname(json['MAKEFILE']),
+            foundincludes,
+            foundisystem,
+            GbuildParser.__split_defs(json['DEFS']),
+            GbuildParser.__split_objs(json['CXXOBJECTS']),
+            GbuildParser.__split_flags(json['CXXFLAGS'], json['CXXFLAGSAPPEND']),
+            json['LINKED_LIBS'].strip().split(' '))
+
+    @staticmethod
+    def __exe_from_json(json):
+        (foundincludes, foundisystem) = GbuildParser.__split_includes(json['INCLUDE'])
+        return GbuildExe(
+            GbuildParser.exepattern.match(os.path.basename(json['MAKEFILE'])).group(1),
+            json['LINKTARGET'],
+            os.path.dirname(json['MAKEFILE']),
+            foundincludes,
+            foundisystem,
+            GbuildParser.__split_defs(json['DEFS']),
+            GbuildParser.__split_objs(json['CXXOBJECTS']),
+            GbuildParser.__split_flags(json['CXXFLAGS'], json['CXXFLAGSAPPEND']),
+            json['LINKED_LIBS'].strip().split(' '))
+
+    def parse(self):
+        for jsonfilename in os.listdir(os.path.join(self.workdir, 'GbuildToJson', 'Library')):
+            with open(os.path.join(self.workdir, 'GbuildToJson', 'Library', jsonfilename), 'r') as f:
+                lib = self.__lib_from_json(json.load(f))
+                self.libnames[lib.library] = lib.name
+                self.libs.append(lib)
+        for jsonfilename in os.listdir(os.path.join(self.workdir, 'GbuildToJson', 'Executable')):
+            with open(os.path.join(self.workdir, 'GbuildToJson', 'Executable', jsonfilename), 'r') as f:
+                exe = self.__exe_from_json(json.load(f))
+                self.exenames[exe.executable] = exe.name
+                self.exes.append(exe)
+        for jsonfilename in os.listdir(os.path.join(self.workdir, 'GbuildToJson', 'CppunitTest')):
+            with open(os.path.join(self.workdir, 'GbuildToJson', 'CppunitTest', jsonfilename), 'r') as f:
+                test = self.__test_from_json(json.load(f))
+                self.testnames[test.test] = test.name
+                self.tests.append(test)
+        for target in set(self.libs) | set(self.exes) | set(self.tests):
+            if target.location not in self.target_by_location:
+                self.target_by_location[target.location] = set()
+            self.target_by_location[target.location] |= set([target])
+            for cxx in target.cxxobjects:
+                path = '/'.join(cxx.split('/')[:-1])
+                if path not in self.target_by_path:
+                    self.target_by_path[path] = set()
+                self.target_by_path[path] |= set([target])
+        for path in self.target_by_path:
+            if len(set(self.target_by_path[path])) > 1:
+                print('fdo#70422: multiple target use dir %s: %s' % (
+                    path, ', '.join([target.short_name() for target in set(self.target_by_path[path])])))
+        for location in self.target_by_location:
+            self.modulenamelist.append(os.path.split(location)[1])
+        return self
+
+
+class IdeIntegrationGenerator:
+
+    def __init__(self, gbuildparser, ide):
+        self.gbuildparser = gbuildparser
+        self.ide = ide
+
+    def emit(self):
+        pass
+
+class EclipseCDTIntegrationGenerator(IdeIntegrationGenerator):
+
+    def __init__(self, gbuildparser, ide):
+        IdeIntegrationGenerator.__init__(self, gbuildparser, ide)
+
+    def create_include_paths(self):
+        for module in self.gbuildparser.modulenamelist:
+            modulepath = os.path.join(self.gbuildparser.builddir, module)
+            includedirfile = open(os.path.join(modulepath, '.eclipsesettingfile'), 'w')
+            modulelibs = []
+            for lib in self.gbuildparser.target_by_path.keys():
+                if lib.startswith(module+'/'):
+                    modulelibs.append(lib)
+            include = set()
+            for lib in modulelibs:
+                for target in self.gbuildparser.target_by_path[lib]:
+                    include |= set(target.include)
+            includedirfile.write('\n'.join(include))
+            includedirfile.close()
+
+
+    def create_macros(self):
+        for module in self.gbuildparser.modulenamelist:
+            modulepath = os.path.join(self.gbuildparser.builddir, module)
+            macrofile = open(os.path.join(modulepath, '.macros'), 'w')
+            modulelibs = []
+            for lib in self.gbuildparser.target_by_path.keys():
+                if lib.startswith(module+'/'):
+                    modulelibs.append(lib)
+            define = []
+            defineset = set()
+            for lib in modulelibs:
+                for target in self.gbuildparser.target_by_path[lib]:
+                    for i in target.defs.keys():
+                        tmp = str(i) +','+str(target.defs[i])
+                        if tmp not in defineset:
+                            defineset.add(tmp)
+            macrofile.write('\n'.join(defineset))
+            macrofile.close()
+
+
+    def create_settings_file(self):
+
+        settingsfiletemplate = """\
+<?xml version="1.0" encoding="UTF-8"?>
+<cdtprojectproperties>
+<section name="org.eclipse.cdt.internal.ui.wizards.settingswizards.IncludePaths">
+<language name="C++ Source File">
+
+
+</language>
+<language name="C Source File">
+
+</language>
+<language name="Object File">
+
+</language>
+<language name="Assembly Source File">
+
+</language>
+</section>
+<section name="org.eclipse.cdt.internal.ui.wizards.settingswizards.Macros">
+<language name="C++ Source File">
+
+</language>
+<language name="C Source File">
+
+</language>
+<language name="Object File">
+
+</language>
+<language name="Assembly Source File">
+
+</language>
+</section>
+</cdtprojectproperties>
+""" 
+
+        for module in self.gbuildparser.modulenamelist:
+            tempxml = []
+            modulepath = os.path.join(self.gbuildparser.builddir, module)
+
+            settingsfile = open(os.path.join(modulepath, 'eclipsesettingfile.xml'), 'w')
+            settingsfile.write(settingsfiletemplate)
+            settingsfile.close()
+
+            settingsfile = open(os.path.join(modulepath, 'eclipsesettingfile.xml'), 'r')
+            tempxml = settingsfile.readlines()
+            tempinclude = open(os.path.join(modulepath, '.eclipsesettingfile'), 'r')
+            tempmacro = open(os.path.join(modulepath, '.macros'), 'r')
+            for includepath in tempinclude:
+                if includepath[-1:] == "\n":
+                    includepath = includepath[:-1]
+                templine = "<includepath>%s</includepath>\n" % includepath
+                tempxml.insert(5, templine)
+
+            for line in tempmacro:
+                macroskeyvalue = line.split(',')
+                macrokey = macroskeyvalue[0]
+                macrovalue = macroskeyvalue[1]
+                if macrovalue[-1:] == "\n":
+                    macrovalue = macrovalue[:-1] 
+                templine = "<macro><name>%s</name><value>%s</value></macro>\n" %(macrokey, macrovalue)
+                tempxml.insert(-13, templine)
+            tempxml="".join(tempxml)
+            settingsfile.close
+
+            settingsfile = open(os.path.join(modulepath, 'eclipsesettingfile.xml'), 'w')
+            settingsfile.write(tempxml)
+            settingsfile.close()
+            os.remove(os.path.join(modulepath, '.eclipsesettingfile'))
+            os.remove(os.path.join(modulepath, '.macros'))
+
+    def emit(self):
+        self.create_include_paths()
+        self.create_macros()
+        self.create_settings_file() 
+
+class DebugIntegrationGenerator(IdeIntegrationGenerator):
+
+    def __init__(self, gbuildparser, ide):
+        IdeIntegrationGenerator.__init__(self, gbuildparser, ide)
+
+    def emit(self):
+        print(self.gbuildparser.srcdir)
+        print(self.gbuildparser.builddir)
+        for lib in self.gbuildparser.libs:
+            print(lib)
+        for exe in self.gbuildparser.exes:
+            print(exe)
+        for test in self.gbuildparser.tests:
+            print(test)
+
+
+class VimIntegrationGenerator(IdeIntegrationGenerator):
+
+    def __init__(self, gbuildparser, ide):
+        IdeIntegrationGenerator.__init__(self, gbuildparser, ide)
+
+    def emit(self):
+        global_list = []
+        for lib in set(self.gbuildparser.libs) | set(self.gbuildparser.tests):
+            entries = []
+            for file in lib.cxxobjects:
+                filePath = os.path.join(self.gbuildparser.srcdir, file) + ".cxx"
+                entry = {'directory': lib.location, 'file': filePath, 'command': self.generateCommand(lib, filePath)}
+                entries.append(entry)
+            global_list.extend(entries)
+        export_file = open('compile_commands.json', 'w')
+        json.dump(global_list, export_file)
+
+    def generateCommand(self, lib, file):
+        command = 'clang++ -Wall'
+        for key, value in lib.defs.items():
+            command += ' -D'
+            command += key
+            if value is not None:
+                command += '='
+                command += value
+
+        # The directory of the file is missing from lib's include list, as that
+        # one is not the same for all source files in the lib.
+        command += ' -I' + os.path.dirname(file)
+
+        for include in lib.include:
+            command += ' -I'
+            command += include
+        for isystem in lib.include_sys:
+            command += ' -isystem '
+            command += isystem
+        for cxxflag in lib.cxxflags:
+            command += ' '
+            command += cxxflag
+        command += ' -c '
+        command += file
+        # Help clang when the tree is configured for gcc.
+        for gnu in ('-std=gnu++11', '-std=gnu++1y'):
+            command = command.replace(gnu, '-std=c++11')
+        return command
+
+
+class KdevelopIntegrationGenerator(IdeIntegrationGenerator):
+
+    def encode_int(self, i):
+        temp = '%08x' % i
+        return '\\x%s\\x%s\\x%s\\x%s' % (temp[0:2], temp[2:4], temp[4:6], temp[6:8])
+
+    def encode_string(self, string):
+        result = self.encode_int(len(string) * 2)
+        for c in string.encode('utf-16-be'):
+            if c in range(32, 126):
+                result += chr(c)
+            else:
+                result += '\\x%02x' % c
+        return result
+
+    def generate_buildsystemconfigtool(self, configid, tool, args, exe, typenr):
+        return KdevelopIntegrationGenerator.buildsystemconfigtooltemplate % {'configid': configid, 'tool': tool,
+                                                                             'args': args, 'exe': exe, 'typenr': typenr}
+
+    buildsystemconfigtooltemplate = """
+[CustomBuildSystem][BuildConfig%(configid)d][Tool%(tool)s]
+Arguments=%(args)s
+Enabled=true
+Environment=
+Executable=%(exe)s
+Type=%(typenr)d
+
+"""
+
+    def generate_buildsystemconfig(self, configid, moduledir, builddir, title, buildparms=''):
+        result = KdevelopIntegrationGenerator.buildsystemconfigtemplate % {'configid': configid, 'builddir': builddir,
+                                                                           'title': title}
+        result += self.generate_buildsystemconfigtool(configid, 'Clean', 'clean %s' % buildparms,
+                                                      self.gbuildparser.makecmd, 3)
+        result += self.generate_buildsystemconfigtool(configid, 'Build', 'all %s' % buildparms,
+                                                      self.gbuildparser.makecmd, 0)
+        return result
+
+    buildsystemconfigtemplate = """
+[CustomBuildSystem][BuildConfig%(configid)d]
+BuildDir=file://%(builddir)s
+Title=%(title)s
+
+"""
+
+    def generate_buildsystem(self, moduledir):
+        result = KdevelopIntegrationGenerator.buildsystemtemplate % {'defaultconfigid': 0}
+        result += self.generate_buildsystemconfig(0, moduledir, moduledir, 'Module Build -- Release')
+        result += self.generate_buildsystemconfig(1, moduledir, self.gbuildparser.builddir, 'Full Build -- Release')
+        result += self.generate_buildsystemconfig(2, moduledir, moduledir, 'Module Build -- Debug', 'debug=T')
+        result += self.generate_buildsystemconfig(3, moduledir, self.gbuildparser.builddir, 'Full Build -- Debug',
+                                                  'debug=T')
+        return result
+
+    buildsystemtemplate = """
+[CustomBuildSystem]
+CurrentConfiguration=BuildConfig%(defaultconfigid)d
+
+"""
+
+    def generate_launch(self, launchid, launchname, executablepath, args, workdir):
+        return KdevelopIntegrationGenerator.launchtemplate % {'launchid': launchid, 'launchname': launchname,
+                                                              'executablepath': executablepath, 'args': args,
+                                                              'workdir': workdir}
+
+    launchtemplate = """
+[Launch][Launch Configuration %(launchid)d]
+Configured Launch Modes=execute
+Configured Launchers=nativeAppLauncher
+Name=%(launchname)s
+Type=Native Application
+
+[Launch][Launch Configuration %(launchid)d][Data]
+Arguments=%(args)s
+Dependencies=@Variant(\\x00\\x00\\x00\\t\\x00\\x00\\x00\\x00\\x00)
+Dependency Action=Nothing
+EnvironmentGroup=default
+Executable=file://%(executablepath)s
+External Terminal=konsole --noclose --workdir %%workdir -e %%exe
+Project Target=
+Use External Terminal=false
+Working Directory=file://%(workdir)s
+isExecutable=true
+
+"""
+
+    def generate_launches(self, moduledir):
+        launches = ','.join(['Launch Configuration %d' % i for i in range(7)])
+        result = KdevelopIntegrationGenerator.launchestemplate % {'launches': launches}
+        result += self.generate_launch(0, 'Local tests -- quick tests (unitcheck)', self.gbuildparser.makecmd,
+                                       'unitcheck', moduledir)
+        result += self.generate_launch(1, 'Local tests -- slow tests (unitcheck, slowcheck, screenshot)', self.gbuildparser.makecmd,
+                                       'unitcheck slowcheck screenshot', moduledir)
+        result += self.generate_launch(2, 'Local tests -- integration tests (unitcheck, slowcheck, screenshot, subsequentcheck)',
+                                       self.gbuildparser.makecmd, 'unitcheck slowcheck screenshot subsequentcheck', moduledir)
+        result += self.generate_launch(3, 'Global tests -- quick tests (unitcheck)', self.gbuildparser.makecmd,
+                                       'unitcheck', self.gbuildparser.builddir)
+        result += self.generate_launch(4, 'Global tests -- slow tests (unitcheck, slowcheck, screenshot)',
+                                       self.gbuildparser.makecmd, 'unitcheck slowcheck screenshot', self.gbuildparser.builddir)
+        result += self.generate_launch(5, 'Global tests -- integration tests (unitcheck, slowcheck, screenshot, subsequentcheck)',
+                                       self.gbuildparser.makecmd, 'unitcheck slowcheck screenshot subsequentcheck',
+                                       self.gbuildparser.builddir)
+        result += self.generate_launch(6, 'Run LibreOffice',
+                                       os.path.join(self.gbuildparser.instdir, 'program/soffice.bin'), '',
+                                       self.gbuildparser.instdir)
+        return result
+
+    launchestemplate = """
+[Launch]
+Launch Configurations=%(launches)s
+
+"""
+
+    def write_modulebeef(self, moduledir, modulename):
+        beefdir = os.path.join(moduledir, '.kdev4')
+        os.mkdir(beefdir)
+        beeffile = open(os.path.join(beefdir, 'Module_%s.kdev4' % modulename), 'w')
+        beeffile.write(self.generate_buildsystem(moduledir))
+        beeffile.write(self.generate_launches(moduledir))
+        beeffile.close()
+
+    def write_modulestub(self, moduledir, modulename):
+        stubfile = open(os.path.join(moduledir, 'Module_%s.kdev4' % modulename), 'w')
+        stubfile.write(KdevelopIntegrationGenerator.modulestubtemplate % {'modulename': modulename,
+                                                                          'builditem': self.encode_string(
+                                                                              'Module_%s' % modulename)})
+        stubfile.close()
+
+    modulestubtemplate = """
+[Buildset]
+BuildItems=@Variant(\\x00\\x00\\x00\\t\\x00\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x0b\\x00\\x00\\x00\\x00\\x01%(builditem)s)
+
+[Project]
+Name=Module_%(modulename)s
+Manager=KDevCustomBuildSystem
+VersionControl=kdevgit
+"""
+
+    def write_includepaths(self, path):
+        includedirfile = open(os.path.join(path, '.kdev_include_paths'), 'w')
+        include = set()
+        for target in self.gbuildparser.target_by_path[path]:
+            include |= set(target.include)
+        includedirfile.write('\n'.join(include))
+        includedirfile.close()
+
+    def __init__(self, gbuildparser, ide):
+        IdeIntegrationGenerator.__init__(self, gbuildparser, ide)
+
+    def emit(self):
+        for path in self.gbuildparser.target_by_path:
+            self.write_includepaths(path)
+        for location in self.gbuildparser.target_by_location:
+            for f in os.listdir(location):
+                if f.endswith('.kdev4'):
+                    try:
+                        os.remove(os.path.join(location, f))
+                    except OSError:
+                        shutil.rmtree(os.path.join(location, f))
+        for location in self.gbuildparser.target_by_location:
+            modulename = os.path.split(location)[1]
+            self.write_modulestub(location, modulename)
+            self.write_modulebeef(location, modulename)
+
+
+class XcodeIntegrationGenerator(IdeIntegrationGenerator):
+
+    def indent(self, file, level):
+        if level == 0:
+            return
+        for i in range(0, level):
+            file.write(' ')
+
+    def write_object(self, object, file, indent):
+        if isinstance(object, int):
+            file.write('%d' % object)
+        elif isinstance(object, str) and not re.search('[^A-Za-z0-9_]', object):
+            file.write('%s' % object)
+        elif isinstance(object, str):
+            file.write('"%s"' % object)
+        elif isinstance(object, dict):
+            self.write_dict(object, file, indent)
+
+    # Write a dictionary out as an "old-style (NeXT) ASCII plist"
+    def write_dict(self, dict, file, indent):
+        file.write('{')
+        file.write('\n')
+        for key in sorted(dict.keys()):
+            self.indent(file, indent + 1)
+            file.write('%s = ' % key)
+            self.write_object(dict[key], file, indent + 1)
+            file.write(';\n')
+        self.indent(file, indent)
+        file.write('}')
+
+    def write_dict_to_plist(self, dict, file):
+        file.write('// !$*UTF8*$!\n')
+        self.write_dict(dict, file, 0)
+
+    def get_product_type(self, modulename):
+        if modulename in self.gbuildparser.libs:
+            return 'com.apple.product-type.library.dynamic'
+        elif modulename in self.gbuildparser.exes:
+            return 'com.apple.product-type.something'
+
+    counter = 0
+
+    def generate_id(self):
+        XcodeIntegrationGenerator.counter = XcodeIntegrationGenerator.counter + 1
+        return str('X%07x' % XcodeIntegrationGenerator.counter)
+
+    def generate_build_phases(self, modulename):
+        result = [self.sourcesBuildPhaseId]
+        return result
+
+    def generate_root_object(self, modulename):
+        result = {'isa': 'PBXProject',
+                  'attributes': {'LastUpgradeCheck': '0500',
+                                 'ORGANIZATIONNAME': 'LibreOffice'},
+                  'buildConfigurationList': self.generate_id(),
+                  'compatibilityVersion': 'Xcode 3.2',
+                  'hasScannedForEncodings': 0,
+                  'knownRegions': ['en'],
+                  'mainGroup': self.mainGroupId,
+                  'productRefGroup': self.productRefGroupId,
+                  'projectDirPath': '',
+                  'projectRoot': '',
+                  'targets': self.targetId}
+        return result
+
+    def generate_target(self, modulename):
+        result = {'isa': 'PBXNativeTarget',
+                  'buildConfigurationList': self.generate_id(),
+                  'buildPhases': self.generate_build_phases(modulename),
+                  'buildRules': [],
+                  'dependencies': [],
+                  'name': modulename,
+                  'productName': modulename,
+                  'productReference': self.productReferenceId,
+                  'productType': self.get_product_type(modulename)}
+        return result
+
+    def generate_main_group(self, modulename):
+        result = {'isa': 'PBXGroup',
+                  'children': [self.subMainGroupId, self.productGroupId],
+                  'sourceTree': '<group>'}
+        return result
+
+    def generate_sub_main_children(self, modulename):
+        return {}
+
+    def generate_sub_main_group(self, modulename):
+        result = {'isa': 'PBXGroup',
+                  'children': self.generate_sub_main_children(modulename),
+                  'path': modulename,
+                  'sourceTree': '<group>'}
+        return result
+
+    def generate_product_group(self, modulename):
+        result = {'isa': 'PBXGroup',
+                  'children': [self.productReferenceId],
+                  'name': 'Products',
+                  'sourceTree': '<group>'}
+        return result
+
+    def build_source_list(self, module):
+        self.sourceRefList = {}
+        self.sourceList = {}
+
+        for i in module.cxxobjects:
+            ref = self.generate_id()
+            self.sourceList[self.generate_id()] = ref
+            self.sourceRefList[ref] = {'lastKnownFileType': 'sourcecode.cpp.cpp',
+                                       'path': i + '.cxx',
+                                       'sourceTree': '<group>'}
+
+    def generate_sources_build_phase(self, modulename):
+        result = {'isa': 'PBXSourcesBuildPhase',
+                  'buildActionMask': 2147483647,
+                  'files': self.sourceList.keys(),
+                  'runOnlyForDeploymentPostprocessing': 0}
+        return result
+
+    def generate_project(self, target):
+        self.rootObjectId = self.generate_id()
+        self.mainGroupId = self.generate_id()
+        self.subMainGroupId = self.generate_id()
+        self.productReferenceId = self.generate_id()
+        self.productRefGroupId = self.generate_id()
+        self.productGroupId = self.generate_id()
+        self.targetId = self.generate_id()
+        self.build_source_list(target)
+        self.sourcesBuildPhaseId = self.generate_id()
+        objects = {self.rootObjectId: self.generate_root_object(target),
+                   self.targetId: self.generate_target(target),
+                   self.mainGroupId: self.generate_main_group(target),
+                   self.subMainGroupId: self.generate_sub_main_group(target),
+                   self.productGroupId: self.generate_product_group(target),
+                   self.sourcesBuildPhaseId: self.generate_sources_build_phase(target)
+                   }
+        for i in self.sourceList.keys():
+            ref = self.sourceList[i]
+            objects[i] = {'isa': 'PBXBuildFile',
+                          'fileRef': ref}
+            objects[ref] = {'isa': 'PBXFileReference',
+                            'lastKnownFileType': self.sourceRefList[ref]['lastKnownFileType'],
+                            'path': self.sourceRefList[ref]['path']}
+        project = {'archiveVersion': 1,
+                   'classes': {},
+                   'objectVersion': 46,
+                   'objects': objects,
+                   'rootObject': self.rootObjectId}
+        return project
+
+    # For some reverse-engineered documentation on the project.pbxproj format,
+    # see http://www.monobjc.net/xcode-project-file-format.html .
+    def write_xcodeproj(self, moduledir, target):
+        xcodeprojdir = os.path.join(moduledir, '%s.xcodeproj' % target.name)
+        try:
+            os.mkdir(xcodeprojdir)
+        except:
+            pass
+        self.write_dict_to_plist(self.generate_project(target),
+                                 open(os.path.join(xcodeprojdir, 'project.pbxproj'), 'w'))
+
+    def __init__(self, gbuildparser, ide):
+        IdeIntegrationGenerator.__init__(self, gbuildparser, ide)
+
+    def emit(self):
+        self.rootlocation = './'
+        for location in self.gbuildparser.target_by_location:
+            # module = location.split('/')[-1]
+            # module_directory = os.path.join(self.rootlocation, module)
+            for target in self.gbuildparser.target_by_location[location]:
+                # project_path = os.path.join(module_directory, '%s.pbxroj' % target.name)
+                self.write_xcodeproj(location, target)
+
+
+class VisualStudioIntegrationGenerator(IdeIntegrationGenerator):
+
+    def __init__(self, gbuildparser, ide):
+        IdeIntegrationGenerator.__init__(self, gbuildparser, ide)
+        self.toolset = self.retrieve_toolset(ide)
+        self.solution_directory = './'
+        self.configurations = {
+            'Build': {
+                'build': self.module_make_command('%(target)s'),
+                'clean': self.module_make_command('%(target)s.clean'),
+                'rebuild': self.module_make_command('%(target)s.clean %(target)s')
+            },
+            'Unit Tests': {
+                'build': self.module_make_command('unitcheck'),
+                'clean': self.module_make_command('clean'),
+                'rebuild': self.module_make_command('clean unitcheck'),
+            },
+            'Integration tests': {
+                'build': self.module_make_command('unitcheck slowcheck screenshot subsequentcheck'),
+                'clean': self.module_make_command('clean'),
+                'rebuild': self.module_make_command('clean unitcheck slowcheck screenshot subsequentcheck')
+            }
+        }
+
+    def retrieve_toolset(self, ide):
+        ide_toolset_map = {'vs2013': 'v120', 'vs2015': 'v140'}
+        return ide_toolset_map[ide]
+
+    def module_make_command(self, targets):
+        return '%(sh)s -c "PATH=\\"/bin:$PATH\\";BUILDDIR=\\"%(builddir)s\\" %(makecmd)s -rsC %(location)s ' + targets + '"'
+
+    class Project:
+
+        def __init__(self, guid, target, project_path):
+            self.guid = guid
+            self.target = target
+            self.path = project_path
+
+    def emit(self):
+        all_projects = []
+        for location in self.gbuildparser.target_by_location:
+            projects = []
+            module = location.split('/')[-1]
+            module_directory = os.path.join(self.solution_directory, module)
+            for target in self.gbuildparser.target_by_location[location]:
+                project_path = os.path.join(module_directory, '%s.vcxproj' % target.name)
+                project_guid = self.write_project(project_path, target)
+                p = VisualStudioIntegrationGenerator.Project(project_guid, target, project_path)
+                projects.append(p)
+            self.write_solution(os.path.join(module_directory, '%s.sln' % module), projects)
+            all_projects += projects
+
+        self.write_solution(os.path.join(self.solution_directory, 'LibreOffice.sln'), all_projects)
+
+    nmake_project_guid = '8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942'
+
+    def get_dependency_libs(self, linked_libs, library_projects):
+        dependency_libs = {}
+        for linked_lib in linked_libs:
+            for library_project in library_projects:
+                if library_project.target.library_name() == linked_lib:
+                    dependency_libs[library_project.guid] = library_project
+        return dependency_libs
+
+    def write_solution(self, solution_path, projects):
+        print('Solution %s:' % os.path.splitext(os.path.basename(solution_path))[0], end='')
+        library_projects = [project for project in projects if project.target in self.gbuildparser.libs]
+        with open(solution_path, 'w') as f:
+            f.write('Microsoft Visual Studio Solution File, Format Version 12.00\n')
+            for project in projects:
+                target = project.target
+                print(' %s' % target.name, end='')
+                proj_path = os.path.relpath(project.path, os.path.abspath(os.path.dirname(solution_path)))
+                f.write('Project("{%s}") = "%s", "%s", "{%s}"\n' %
+                        (VisualStudioIntegrationGenerator.nmake_project_guid,
+                         target.short_name(), proj_path, project.guid))
+                libs_in_solution = self.get_dependency_libs(target.linked_libs,
+                                                            library_projects)
+                if libs_in_solution:
+                    f.write('\tProjectSection(ProjectDependencies) = postProject\n')
+                    for lib_guid in libs_in_solution.keys():
+                        f.write('\t\t{%(guid)s} = {%(guid)s}\n' % {'guid': lib_guid})
+                    f.write('\tEndProjectSection\n')
+                f.write('EndProject\n')
+            f.write('Global\n')
+            platform = 'Win32'
+            f.write('\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n')
+            for cfg in self.configurations:
+                f.write('\t\t%(cfg)s|%(platform)s = %(cfg)s|%(platform)s\n' % {'cfg': cfg, 'platform': platform})
+            f.write('\tEndGlobalSection\n')
+            f.write('\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\n')
+            # Specifies project configurations for solution configuration
+            for project in projects:
+                for cfg in self.configurations:
+                    params = {'guid': project.guid, 'sol_cfg': cfg, 'proj_cfg': cfg, 'platform': platform}
+                    f.write('\t\t{%(guid)s}.%(sol_cfg)s|%(platform)s.ActiveCfg = %(proj_cfg)s|%(platform)s\n' % params)
+                    # Build.0 is basically 'Build checkbox' in configuration manager
+                    f.write('\t\t{%(guid)s}.%(sol_cfg)s|%(platform)s.Build.0 = %(proj_cfg)s|%(platform)s\n' % params)
+            f.write('\tEndGlobalSection\n')
+            f.write('EndGlobal\n')
+        print('')
+
+    def write_project(self, project_path, target):
+        # See info at http://blogs.msdn.com/b/visualstudio/archive/2010/05/14/a-guide-to-vcxproj-and-props-file-structure.aspx
+        folder = os.path.dirname(project_path)
+        if not os.path.exists(folder):
+            os.makedirs(folder)
+        project_guid = str(uuid.uuid4()).upper()
+        ns = 'http://schemas.microsoft.com/developer/msbuild/2003'
+        ET.register_namespace('', ns)
+        proj_node = ET.Element('{%s}Project' % ns, DefaultTargets='Build', ToolsVersion='4.0')
+        proj_confs_node = ET.SubElement(proj_node, '{%s}ItemGroup' % ns, Label='ProjectConfigurations')
+        platform = 'Win32'
+        for configuration in self.configurations:
+            proj_conf_node = ET.SubElement(proj_confs_node,
+                                           '{%s}ProjectConfiguration' % ns,
+                                           Include='%s|%s' % (configuration, platform))
+            conf_node = ET.SubElement(proj_conf_node, '{%s}Configuration' % ns)
+            conf_node.text = configuration
+            platform_node = ET.SubElement(proj_conf_node, '{%s}Platform' % ns)
+            platform_node.text = platform
+
+        globals_node = ET.SubElement(proj_node, '{%s}PropertyGroup' % ns, Label='Globals')
+        proj_guid_node = ET.SubElement(globals_node, '{%s}ProjectGuid' % ns)
+        proj_guid_node.text = '{%s}' % project_guid
+        proj_keyword_node = ET.SubElement(globals_node, '{%s}Keyword' % ns)
+        proj_keyword_node.text = 'MakeFileProj'
+        proj_name_node = ET.SubElement(globals_node, '{%s}ProjectName' % ns)
+        proj_name_node.text = target.short_name()
+
+        ET.SubElement(proj_node, '{%s}Import' % ns, Project='$(VCTargetsPath)\Microsoft.Cpp.Default.props')
+        for configuration in self.configurations:
+            conf_node = ET.SubElement(proj_node, '{%s}PropertyGroup' % ns, Label="Configuration",
+                                      Condition="'$(Configuration)|$(Platform)'=='%s|%s'" % (configuration, platform))
+            # Type of project used by the MSBuild to determine build process, see Microsoft.Makefile.targets
+            conf_type_node = ET.SubElement(conf_node, '{%s}ConfigurationType' % ns)
+            conf_type_node.text = 'Makefile'
+            # VS2012: I need to have this otherwise the names of projects will contain text Visual Studio 2010 in the Solution Explorer
+            platform_toolset_node = ET.SubElement(conf_node, '{%s}PlatformToolset' % ns)
+            platform_toolset_node.text = self.toolset
+
+        ET.SubElement(proj_node, '{%s}Import' % ns, Project='$(VCTargetsPath)\Microsoft.Cpp.props')
+        ET.SubElement(proj_node, '{%s}ImportGroup' % ns, Label='ExtensionSettings')
+        for configuration in self.configurations:
+            prop_sheets_node = ET.SubElement(proj_node, '{%s}ImportGroup' % ns, Label='Configuration',
+                                             Condition="'$(Configuration)|$(Platform)'=='%s|%s'" % (configuration, platform))
+            ET.SubElement(prop_sheets_node, '{%s}Import' % ns,
+                          Project='$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props',
+                          Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')",
+                          Label='LocalAppDataPlatform')
+
+        ET.SubElement(proj_node, '{%s}PropertyGroup' % ns, Label='UserMacros')
+        for cfg_name, cfg_targets in self.configurations.items():
+            conf_node = ET.SubElement(proj_node, '{%s}PropertyGroup' % ns,
+                                      Condition="'$(Configuration)|$(Platform)'=='%s|%s'" % (cfg_name, platform))
+            nmake_params = {
+                'sh': os.path.join(self.gbuildparser.binpath, 'dash.exe'),
+                'builddir': self.gbuildparser.builddir,
+                'location': target.location,
+                'makecmd': self.gbuildparser.makecmd,
+                'target': target.target_name()}
+            nmake_build_node = ET.SubElement(conf_node, '{%s}NMakeBuildCommandLine' % ns)
+            nmake_build_node.text = cfg_targets['build'] % nmake_params
+            nmake_clean_node = ET.SubElement(conf_node, '{%s}NMakeCleanCommandLine' % ns)
+            nmake_clean_node.text = cfg_targets['clean'] % nmake_params
+            nmake_rebuild_node = ET.SubElement(conf_node, '{%s}NMakeReBuildCommandLine' % ns)
+            nmake_rebuild_node.text = cfg_targets['rebuild'] % nmake_params
+            nmake_output_node = ET.SubElement(conf_node, '{%s}NMakeOutput' % ns)
+            nmake_output_node.text = os.path.join(self.gbuildparser.instdir, 'program', 'soffice.exe')
+            nmake_defs_node = ET.SubElement(conf_node, '{%s}NMakePreprocessorDefinitions' % ns)
+            nmake_defs_node.text = ';'.join(list(target.defs) + ['$(NMakePreprocessorDefinitions)'])
+            include_path_node = ET.SubElement(conf_node, '{%s}IncludePath' % ns)
+            include_path_node.text = ';'.join(target.include + ['$(IncludePath)'])
+
+        ET.SubElement(proj_node, '{%s}ItemDefinitionGroup' % ns)
+
+        cxxobjects_node = ET.SubElement(proj_node, '{%s}ItemGroup' % ns)
+        for cxxobject in target.cxxobjects:
+            cxxabspath = os.path.join(self.gbuildparser.srcdir, cxxobject)
+            cxxfile = cxxabspath + '.cxx'
+            if os.path.isfile(cxxfile):
+                ET.SubElement(cxxobjects_node, '{%s}ClCompile' % ns, Include=cxxfile)
+            else:
+                print('Source %s in project %s does not exist' % (cxxfile, target.name))
+
+        includes_node = ET.SubElement(proj_node, '{%s}ItemGroup' % ns)
+        for cxxobject in target.cxxobjects:
+            include_abs_path = os.path.join(self.gbuildparser.srcdir, cxxobject)
+            hxxfile = include_abs_path + '.hxx'
+            if os.path.isfile(hxxfile):
+                ET.SubElement(includes_node, '{%s}ClInclude' % ns, Include=hxxfile)
+            # Few files have corresponding .h files
+            hfile = include_abs_path + '.h'
+            if os.path.isfile(hfile):
+                ET.SubElement(includes_node, '{%s}ClInclude' % ns, Include=hfile)
+        ET.SubElement(proj_node, '{%s}Import' % ns, Project='$(VCTargetsPath)\Microsoft.Cpp.targets')
+        ET.SubElement(proj_node, '{%s}ImportGroup' % ns, Label='ExtensionTargets')
+        self.write_pretty_xml(proj_node, project_path)
+        self.write_filters(project_path + '.filters',
+                           os.path.join(self.gbuildparser.srcdir, os.path.basename(target.location)),
+                           [cxx_node.get('Include') for cxx_node in cxxobjects_node.findall('{%s}ClCompile' % ns)],
+                           [include_node.get('Include') for include_node in includes_node.findall('{%s}ClInclude' % ns)])
+        return project_guid
+
+    def get_filter(self, module_dir, proj_file):
+        return '\\'.join(os.path.relpath(proj_file, module_dir).split('/')[:-1])
+
+    def get_subfilters(self, proj_filter):
+        parts = proj_filter.split('\\')
+        subfilters = set([proj_filter])
+        for i in range(1, len(parts)):
+            subfilters.add('\\'.join(parts[:i]))
+        return subfilters
+
+    def write_pretty_xml(self, node, file_path):
+        xml_str = ET.tostring(node, encoding='unicode')
+        pretty_str = minidom.parseString(xml_str).toprettyxml(encoding='utf-8')
+        with open(file_path, 'w') as f:
+            f.write(pretty_str.decode())
+
+    def add_nodes(self, files_node, module_dir, tag, project_files):
+        ns = 'http://schemas.microsoft.com/developer/msbuild/2003'
+        filters = set()
+        for project_file in project_files:
+            file_node = ET.SubElement(files_node, tag, Include=project_file)
+            if os.path.commonprefix([module_dir, project_file]) == module_dir:
+                project_filter = self.get_filter(module_dir, project_file)
+                filter_node = ET.SubElement(file_node, '{%s}Filter' % ns)
+                filter_node.text = project_filter
+                filters |= self.get_subfilters(project_filter)
+        return filters
+
+    def write_filters(self, filters_path, module_dir, compile_files, include_files):
+        ns = 'http://schemas.microsoft.com/developer/msbuild/2003'
+        ET.register_namespace('', ns)
+        proj_node = ET.Element('{%s}Project' % ns, ToolsVersion='4.0')
+        filters = set()
+        compiles_node = ET.SubElement(proj_node, '{%s}ItemGroup' % ns)
+        filters |= self.add_nodes(compiles_node, module_dir, '{%s}ClCompile' % ns, compile_files)
+        include_node = ET.SubElement(proj_node, '{%s}ItemGroup' % ns)
+        filters |= self.add_nodes(include_node, module_dir, '{%s}ClInclude' % ns, include_files)
+
+        filters_node = ET.SubElement(proj_node, '{%s}ItemGroup' % ns)
+        for proj_filter in filters:
+            filter_node = ET.SubElement(filters_node, '{%s}Filter' % ns, Include=proj_filter)
+            filter_id_node = ET.SubElement(filter_node, '{%s}UniqueIdentifier' % ns)
+            filter_id_node.text = '{%s}' % str(uuid.uuid4())
+        self.write_pretty_xml(proj_node, filters_path)
+
+
+class QtCreatorIntegrationGenerator(IdeIntegrationGenerator):
+
+    def __init__(self, gbuildparser, ide):
+        IdeIntegrationGenerator.__init__(self, gbuildparser, ide)
+        self.target_by_location = {}
+        for target in set(self.gbuildparser.libs) | set(self.gbuildparser.exes):
+            if target.location not in self.target_by_location:
+                self.target_by_location[target.location] = set()
+            self.target_by_location[target.location] |= set([target])
+
+        self._do_log = False  # set to 'True' to activate log of QtCreatorIntegrationGenerator
+        if self._do_log:
+            qtlog_path = os.path.abspath('../qtlog_.txt')
+            self.qtlog = open(qtlog_path, 'w')
+
+    def _log(self, message):
+        if self._do_log:
+            self.qtlog.write(message)
+
+    def log_close(self):
+        if self._do_log:
+            self.qtlog.close()
+
+    def generate_build_configs(self, lib_folder):
+        module_folder = os.path.join(self.base_folder, lib_folder)
+        xml = ""
+        # In QtCreator UI, build configs are listed alphabetically,
+        # so it can be different from the creation order.
+        # So we prefix the names with the index.
+        xml += QtCreatorIntegrationGenerator.build_configs_template % {
+            'index': '0',
+            'base_folder': module_folder,
+            'arg': "",
+            'name': "1-Build %s" % lib_folder,
+        }
+        xml += QtCreatorIntegrationGenerator.build_configs_template % {
+            'index': '1',
+            'base_folder': module_folder,
+            'arg': "unitcheck",
+            'name': "2-Local tests -- quick tests (unitcheck)",
+        }
+        xml += QtCreatorIntegrationGenerator.build_configs_template % {
+            'index': '2',
+            'base_folder': module_folder,
+            'arg': "unitcheck slowcheck screenshot",
+            'name': "3-Local tests -- slow tests (unitcheck, slowcheck, screenshot)",
+        }
+        xml += QtCreatorIntegrationGenerator.build_configs_template % {
+            'index': '3',
+            'base_folder': module_folder,
+            'arg': "unitcheck slowcheck screenshot subsequentcheck",
+            'name': "4-Local tests -- integration tests (unitcheck, slowcheck, screenshot, subsequentcheck)",
+        }
+        xml += QtCreatorIntegrationGenerator.build_configs_template % {
+            'index': '4',
+            'base_folder': self.base_folder,
+            'arg': "unitcheck",
+            'name': "5-Global tests -- quick tests (unitcheck)",
+        }
+        xml += QtCreatorIntegrationGenerator.build_configs_template % {
+            'index': '5',
+            'base_folder': self.base_folder,
+            'arg': "unitcheck slowcheck screenshot",
+            'name': "6-Global tests -- slow tests (unitcheck, slowcheck, screenshot)",
+        }
+        xml += QtCreatorIntegrationGenerator.build_configs_template % {
+            'index': '6',
+            'base_folder': self.base_folder,
+            'arg': "unitcheck slowcheck screenshot subsequentcheck",
+            'name': "7-Global tests -- integration tests (unitcheck, slowcheck, screenshot, subsequentcheck)",
+        }
+        xml += QtCreatorIntegrationGenerator.build_configs_template % {
+            'index': '7',
+            'base_folder': self.base_folder,
+            'arg': "build-nocheck",
+            'name': "8-Global build -- nocheck",
+        }
+        xml += QtCreatorIntegrationGenerator.build_configs_template % {
+            'index': '8',
+            'base_folder': self.base_folder,
+            'arg': "",
+            'name': "9-Global build",
+        }
+
+        xml += QtCreatorIntegrationGenerator.build_configs_count_template % {
+            'nb': '9',
+        }
+        return xml
+
+    def generate_meta_build_configs(self):
+        xml = ""
+        # In QtCreator UI, build configs are listed alphabetically,
+        # so it can be different from the creation order.
+        # So we prefix the names with the index.
+        xml += QtCreatorIntegrationGenerator.build_configs_template % {
+            'index': '0',
+            'base_folder': self.base_folder,
+            'arg': "",
+            'name': "01-Global Build",
+        }
+        xml += QtCreatorIntegrationGenerator.build_configs_template % {
+            'index': '1',
+            'base_folder': self.base_folder,
+            'arg': "unitcheck",
+            'name': "02-Global tests -- quick tests (unitcheck)",
+        }
+        xml += QtCreatorIntegrationGenerator.build_configs_template % {
+            'index': '2',
+            'base_folder': self.base_folder,
+            'arg': "unitcheck slowcheck screenshot",
+            'name': "03-Global tests -- slow tests (unitcheck, slowcheck, screenshot)",
+        }
+        xml += QtCreatorIntegrationGenerator.build_configs_template % {
+            'index': '3',
+            'base_folder': self.base_folder,
+            'arg': "unitcheck slowcheck screenshot subsequentcheck",
+            'name': "04-Global tests -- integration tests (unitcheck, slowcheck, screenshot, subsequentcheck)",
+        }
+        xml += QtCreatorIntegrationGenerator.build_configs_template % {
+            'index': '4',
+            'base_folder': self.base_folder,
+            'arg': "perfcheck",
+            'name': "05-Global tests -- performance tests (perfcheck)",
+        }
+        xml += QtCreatorIntegrationGenerator.build_configs_template % {
+            'index': '5',
+            'base_folder': self.base_folder,
+            'arg': "check",
+            'name': "06-Global tests -- tests (check)",
+        }
+        xml += QtCreatorIntegrationGenerator.build_configs_template % {
+            'index': '6',
+            'base_folder': self.base_folder,
+            'arg': "build-nocheck",
+            'name': "07-Global build -- nocheck",
+        }
+        xml += QtCreatorIntegrationGenerator.build_configs_template % {
+            'index': '7',
+            'base_folder': self.base_folder,
+            'arg': "build-l10n-only",
+            'name': "08-Global build -- build-l10n-only",
+        }
+        xml += QtCreatorIntegrationGenerator.build_configs_template % {
+            'index': '8',
+            'base_folder': self.base_folder,
+            'arg': "build-non-l10n-only",
+            'name': "09-Global build -- build-non-l10n-only",
+        }
+        xml += QtCreatorIntegrationGenerator.build_configs_template % {
+            'index': '9',
+            'base_folder': self.base_folder,
+            'arg': "clean",
+            'name': "10-Global build -- clean",
+        }
+        xml += QtCreatorIntegrationGenerator.build_configs_template % {
+            'index': '10',
+            'base_folder': self.base_folder,
+            'arg': "clean-build",
+            'name': "11-Global build -- clean-build",
+        }
+        xml += QtCreatorIntegrationGenerator.build_configs_template % {
+            'index': '11',
+            'base_folder': self.base_folder,
+            'arg': "clean-host",
+            'name': "12-Global build -- clean-host",
+        }
+        xml += QtCreatorIntegrationGenerator.build_configs_count_template % {
+            'nb': '12',
+        }
+        return xml
+
+    # By default, QtCreator creates 2 BuildStepList : "Build" et "Clean"
+    # but the "clean" can be empty.
+    build_configs_template = """
+    <valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.%(index)s">
+    <value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">%(base_folder)s</value>
+
+    <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
+
+     <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
+      <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
+      <valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments">
+       <value type="QString">-w</value>
+       <value type="QString">-r</value>
+      </valuelist>
+      <value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value>
+      <value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">%(arg)s</value>
+      <value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
+     </valuemap>
+
+     <value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
+    </valuemap>
+
+    <value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
+    <value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
+    <valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
+    <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">%(name)s</value>
+    <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+    <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
+    <value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">%(index)s</value>
+    <value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">true</value>
+   </valuemap>
+   """
+
+    build_configs_count_template = """
+   <!-- nb build configurations -->
+   <value type="int" key="ProjectExplorer.Target.BuildConfigurationCount">%(nb)s</value>
+   """
+
+    def generate_deploy_configs(self, lib_folder):
+        xml = QtCreatorIntegrationGenerator.deploy_configs_template % {}
+        return xml
+
+    deploy_configs_template = """
+   <valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
+    <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
+     <value type="int" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
+    </valuemap>
+    <value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
+    <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy locally</value>
+    <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+    <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
+   </valuemap>
+   <value type="int" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
+    """
+
+    def generate_run_configs(self, lib_folder):
+
+        # If we use 'soffice', it's ok only for "Run", not for "Debug".
+        # So we put "soffice.bin" that is ok for both.
+        loexec = "%s/instdir/program/soffice.bin" % self.base_folder
+        xml = QtCreatorIntegrationGenerator.run_configs_template % {
+            'loexec': loexec,
+            'workdir': self.base_folder
+        }
+        return xml
+
+    run_configs_template = """
+   <valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
+    <valuelist type="QVariantList" key="Analyzer.Valgrind.AddedSuppressionFiles"/>
+    <value type="bool" key="Analyzer.Valgrind.Callgrind.CollectBusEvents">false</value>
+    <value type="bool" key="Analyzer.Valgrind.Callgrind.CollectSystime">false</value>
+    <value type="bool" key="Analyzer.Valgrind.Callgrind.EnableBranchSim">false</value>
+    <value type="bool" key="Analyzer.Valgrind.Callgrind.EnableCacheSim">false</value>
+    <value type="bool" key="Analyzer.Valgrind.Callgrind.EnableEventToolTips">true</value>
+    <value type="double" key="Analyzer.Valgrind.Callgrind.MinimumCostRatio">0.01</value>
+    <value type="double" key="Analyzer.Valgrind.Callgrind.VisualisationMinimumCostRatio">10</value>
+    <value type="bool" key="Analyzer.Valgrind.FilterExternalIssues">true</value>
+    <value type="int" key="Analyzer.Valgrind.LeakCheckOnFinish">1</value>
+    <value type="int" key="Analyzer.Valgrind.NumCallers">25</value>
+    <valuelist type="QVariantList" key="Analyzer.Valgrind.RemovedSuppressionFiles"/>
+    <value type="int" key="Analyzer.Valgrind.SelfModifyingCodeDetection">1</value>
+    <value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
+    <value type="bool" key="Analyzer.Valgrind.ShowReachable">false</value>
+    <value type="bool" key="Analyzer.Valgrind.TrackOrigins">true</value>
+    <value type="QString" key="Analyzer.Valgrind.ValgrindExecutable">valgrind</value>
+    <valuelist type="QVariantList" key="Analyzer.Valgrind.VisibleErrorKinds">
+     <value type="int">0</value>
+     <value type="int">1</value>
+     <value type="int">2</value>
+     <value type="int">3</value>
+     <value type="int">4</value>
+     <value type="int">5</value>
+     <value type="int">6</value>
+     <value type="int">7</value>
+     <value type="int">8</value>
+     <value type="int">9</value>
+     <value type="int">10</value>
+     <value type="int">11</value>
+     <value type="int">12</value>
+     <value type="int">13</value>
+     <value type="int">14</value>
+    </valuelist>
+    <value type="int" key="PE.EnvironmentAspect.Base">2</value>
+    <valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
+
+    <value type="QString" key="ProjectExplorer.CustomExecutableRunConfiguration.Arguments"></value>
+    <value type="QString" key="ProjectExplorer.CustomExecutableRunConfiguration.Executable">%(loexec)s</value>
+    <value type="bool" key="ProjectExplorer.CustomExecutableRunConfiguration.UseTerminal">false</value>
+    <value type="QString" key="ProjectExplorer.CustomExecutableRunConfiguration.WorkingDirectory">%(workdir)s</value>
+    <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Run libreoffice/instdir/program/soffice</value>
+    <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+    <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.CustomExecutableRunConfiguration</value>
+    <value type="uint" key="RunConfiguration.QmlDebugServerPort">3768</value>
+    <value type="bool" key="RunConfiguration.UseCppDebugger">false</value>
+    <value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
+    <value type="bool" key="RunConfiguration.UseMultiProcess">false</value>
+    <value type="bool" key="RunConfiguration.UseQmlDebugger">false</value>
+    <value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
+
+   </valuemap>
+   <value type="int" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
+    """
+
+    def generate_pro_user_content(self, lib_folder):
+
+        build_configs = self.generate_build_configs(lib_folder)
+        deploy_configs = self.generate_deploy_configs(lib_folder)
+        run_configs = self.generate_run_configs(lib_folder)
+
+        xml = QtCreatorIntegrationGenerator.pro_user_template % {
+            'build_configs': build_configs,
+            'deploy_configs': deploy_configs,
+            'run_configs': run_configs,
+        }
+        return xml
+
+    def generate_meta_pro_user_content(self):
+
+        build_configs = self.generate_meta_build_configs()
+        deploy_configs = self.generate_deploy_configs("")
+        run_configs = self.generate_run_configs("")
+
+        xml = QtCreatorIntegrationGenerator.pro_user_template % {
+            'build_configs': build_configs,
+            'deploy_configs': deploy_configs,
+            'run_configs': run_configs,
+        }
+        return xml
+
+    pro_user_template = """<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE QtCreatorProject>
+<!-- Written by QtCreator 3.1.1, 2015-05-14T15:54:34. -->
+<qtcreator>
+ <data>
+  <variable>ProjectExplorer.Project.ActiveTarget</variable>
+  <value type="int">0</value>
+ </data>
+
+ <!-- editor settings -->
+ <data>
+  <variable>ProjectExplorer.Project.EditorSettings</variable>
+  <valuemap type="QVariantMap">
+   <value type="bool" key="EditorConfiguration.AutoIndent">true</value>
+   <value type="bool" key="EditorConfiguration.AutoSpacesForTabs">false</value>
+   <value type="bool" key="EditorConfiguration.CamelCaseNavigation">true</value>
+   <valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.0">
+    <value type="QString" key="language">Cpp</value>
+    <valuemap type="QVariantMap" key="value">
+     <value type="QByteArray" key="CurrentPreferences">CppGlobal</value>
+    </valuemap>
+   </valuemap>
+   <valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.1">
+    <value type="QString" key="language">QmlJS</value>
+    <valuemap type="QVariantMap" key="value">
+     <value type="QByteArray" key="CurrentPreferences">QmlJSGlobal</value>
+    </valuemap>
+   </valuemap>
+   <value type="int" key="EditorConfiguration.CodeStyle.Count">2</value>
+   <value type="QByteArray" key="EditorConfiguration.Codec">UTF-8</value>
+   <value type="bool" key="EditorConfiguration.ConstrainTooltips">false</value>
+   <value type="int" key="EditorConfiguration.IndentSize">4</value>
+   <value type="bool" key="EditorConfiguration.KeyboardTooltips">false</value>
+   <value type="int" key="EditorConfiguration.MarginColumn">80</value>
+   <value type="bool" key="EditorConfiguration.MouseHiding">true</value>
+   <value type="bool" key="EditorConfiguration.MouseNavigation">true</value>
+   <value type="int" key="EditorConfiguration.PaddingMode">1</value>
+   <value type="bool" key="EditorConfiguration.ScrollWheelZooming">true</value>
+   <value type="bool" key="EditorConfiguration.ShowMargin">false</value>
+   <value type="int" key="EditorConfiguration.SmartBackspaceBehavior">1</value>
+   <value type="bool" key="EditorConfiguration.SpacesForTabs">true</value>
+   <value type="int" key="EditorConfiguration.TabKeyBehavior">0</value>
+   <value type="int" key="EditorConfiguration.TabSize">8</value>
+   <value type="bool" key="EditorConfiguration.UseGlobal">true</value>
+   <value type="int" key="EditorConfiguration.Utf8BomBehavior">1</value>
+   <value type="bool" key="EditorConfiguration.addFinalNewLine">true</value>
+   <value type="bool" key="EditorConfiguration.cleanIndentation">true</value>
+   <value type="bool" key="EditorConfiguration.cleanWhitespace">true</value>
+   <value type="bool" key="EditorConfiguration.inEntireDocument">false</value>
+  </valuemap>
+ </data>
+
+ <data>
+  <variable>ProjectExplorer.Project.PluginSettings</variable>
+  <valuemap type="QVariantMap"/>
+ </data>
+
+ <!-- target -->
+ <data>
+  <variable>ProjectExplorer.Project.Target.0</variable>
+  <valuemap type="QVariantMap">
+   <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Desktop</value>
+   <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Desktop</value>
+   <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">{0701de51-c96e-4e4f-85c3-e70b223c5076}</value>
+   <value type="int" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
+   <value type="int" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
+   <value type="int" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
+
+   <!-- build configurations -->
+   %(build_configs)s
+
+   <!-- deploy configurations -->
+   %(deploy_configs)s
+
+   <!-- plugin settings -->
+   <valuemap type="QVariantMap" key="ProjectExplorer.Target.PluginSettings"/>
+
+   <!-- run configurations -->
+   %(run_configs)s
+
+  </valuemap>
+ </data>
+ <!-- nb targets : 1 -->
+ <data>
+  <variable>ProjectExplorer.Project.TargetCount</variable>
+  <value type="int">1</value>
+ </data>
+ <data>
+  <variable>ProjectExplorer.Project.Updater.EnvironmentId</variable>
+  <value type="QByteArray">{5abcafed-86f6-49f6-b1cb-380fadd21211}</value>
+ </data>
+ <data>
+  <variable>ProjectExplorer.Project.Updater.FileVersion</variable>
+  <value type="int">15</value>
+ </data>
+</qtcreator>
+"""
+
+    def remove_qt_files(self):
+
+        def do_remove_file(loc, afile):
+            try:
+                os.remove(os.path.join(loc, afile))
+                self._log("removed %s\n" % afile)
+            except OSError:
+                self._log("unable to remove %s\n" % afile)
+
+        do_remove_file(self.base_folder, "lo.pro")
+        do_remove_file(self.base_folder, "lo.pro.user")
+        for location in self.target_by_location:
+            for f in os.listdir(location):
+                if f.endswith('.pro') or f.endswith('.pro.user'):
+                    do_remove_file(location, f)
+
+    def get_source_extension(self, src_file):
+        path = os.path.join(self.base_folder, src_file)
+        for ext in (".cxx", ".cpp", ".c", ".mm"):
+            if os.path.isfile(path + ext):
+                return ext
+        return ""
+
+    def get_header_extension(self, src_file):
+        path = os.path.join(self.base_folder, src_file)
+        for ext in (".hxx", ".hpp", ".h"):
+            if os.path.isfile(path + ext):
+                return ext
+        return ""
+
+    def build_data_libs(self):
+
+        self.data_libs = {}
+
+        all_libs = set(self.gbuildparser.libs) | set(self.gbuildparser.exes)
+        for lib in all_libs:
+            self._log("\nlibrary : %s, loc=%s" % (lib.short_name(), lib.location))
+            lib_name = os.path.basename(lib.location)
+            lib_folder = os.path.relpath(lib.location, self.base_folder)
+
+            def lopath(path):
+                return os.path.relpath(path, lib.location)
+
+            defines_list = []
+            sources_list = []
+            includepath_list = []
+            # The explicit headers list is not mandatory :
+            # QtCreator just needs 'include_path_list' to find all headers files.
+            # But files listed in 'header_list' will be shown
+            # in a specific "Headers" folder in QtCreator's Project panel.
+            # We will list here only headers files of current lib.
+            headers_list = []
+            for file_ in lib.cxxobjects:
+                # the file has no extension : search it
+                # self._log("\n    file : %s" % file_)
+                ext = self.get_source_extension(file_)
+                if ext:
+                    sources_list.append(lopath(file_ + ext))
+
+                # few cxxobject files have a header beside
+                ext = self.get_header_extension(file_)
+                if ext:
+                    headers_list.append(lopath(file_ + ext))
+
+            # List all include paths
+            for hdir in lib.include:
+                hf_lopath = lopath(hdir)
+                includepath_list.append(hf_lopath)
+
+            # List headers files from current lib
+            for hdir in lib.include:
+                if hdir.startswith(lib.location):
+                    for hf in os.listdir(hdir):
+                        if hf.endswith(('.h', '.hxx', '.hpp', '.hrc')):
+                            hf_lopath = lopath(os.path.join(hdir, hf))
+                            headers_list.append(hf_lopath)
+
+            # List defines
+            for key, value in lib.defs.items():
+                define = key
+                if value is not None:
+                    define += '=' + value
+                defines_list.append(define)
+
+            # All datas are prepared, store them for the lib.
+            if lib_folder in self.data_libs:
+                self.data_libs[lib_folder]['sources'] |= set(sources_list)
+                self.data_libs[lib_folder]['headers'] |= set(headers_list)
+                self.data_libs[lib_folder]['includepath'] |= set(includepath_list)
+                self.data_libs[lib_folder]['defines'] |= set(defines_list)
+            else:
+                self.data_libs[lib_folder] = {
+                    'sources': set(sources_list),
+                    'headers': set(headers_list),
+                    'includepath': set(includepath_list),
+                    'defines': set(defines_list),
+                    'loc': lib.location,
+                    'name': lib_name
+                }
+
+    def emit(self):
+
+        self.base_folder = self.gbuildparser.builddir
+
+        # we remove existing '.pro' and '.pro.user' files
+        self.remove_qt_files()
+
+        # for .pro files, we must explicitly list all files (.c, .h)
+        # so we can't reuse directly the same method than for kde integration.
+        self.build_data_libs()
+
+        subdirs_list = self.data_libs.keys()
+        # Now we can create Qt files
+        for lib_folder in subdirs_list:
+            sources_list = sorted(self.data_libs[lib_folder]['sources'])
+            headers_list = sorted(self.data_libs[lib_folder]['headers'])
+            includepath_list = sorted(self.data_libs[lib_folder]['includepath'])
+            defines_list = sorted(self.data_libs[lib_folder]['defines'])
+            lib_loc = self.data_libs[lib_folder]['loc']
+            lib_name = self.data_libs[lib_folder]['name']
+
+            sources = " \\\n".join(sources_list)
+            headers = " \\\n".join(headers_list)
+            includepath = " \\\n".join(includepath_list)
+            defines = " \\\n".join(defines_list)
+
+            # create .pro file
+            qt_pro_file = '%s/%s.pro' % (lib_loc, lib_name)
+            try:
+                content = QtCreatorIntegrationGenerator.pro_template % {'sources': sources, 'headers': headers, 'includepath': includepath, 'defines': defines}
+                mode = 'w+'
+                with open(qt_pro_file, mode) as fpro:
+                    fpro.write(content)
+                self._log("created %s\n" % qt_pro_file)
+
+            except Exception as e:
+                print("ERROR : creating pro file=" + qt_pro_file, file=sys.stderr)
+                print(e, file=sys.stderr)
+                temp = traceback.format_exc()  # .decode('utf8')
+                print(temp, file=sys.stderr)
+                print("\n\n", file=sys.stderr)
+
+            # create .pro.user file
+            qt_pro_user_file = '%s/%s.pro.user' % (lib_loc, lib_name)
+            try:
+                with open(qt_pro_user_file, mode) as fprouser:
+                    fprouser.write(self.generate_pro_user_content(lib_folder))
+                self._log("created %s\n" % qt_pro_user_file)
+
+            except Exception as e:
+                print("ERROR : creating pro.user file=" + qt_pro_user_file, file=sys.stderr)
+                print(e, file=sys.stderr)
+                temp = traceback.format_exc()
+                print(temp, file=sys.stderr)
+                print("\n\n", file=sys.stderr)
+
+        # create meta .pro file (lists all sub projects)
+        qt_meta_pro_file = 'lo.pro'
+        try:
+            subdirs = " \\\n".join(subdirs_list)
+            content = QtCreatorIntegrationGenerator.pro_meta_template % {'subdirs': subdirs}
+            with open(qt_meta_pro_file, 'w+') as fmpro:
+                fmpro.write(content)
+
+        except Exception as e:
+            print("ERROR : creating lo.pro file=" + qt_meta_pro_file, file=sys.stderr)
+            print(e, file=sys.stderr)
+            temp = traceback.format_exc()
+            print(temp, file=sys.stderr)
+            print("\n\n", file=sys.stderr)
+
+        # create meta .pro.user file
+        qt_meta_pro_user_file = 'lo.pro.user'
+        try:
+            with open(qt_meta_pro_user_file, mode) as fmprouser:
+                fmprouser.write(self.generate_meta_pro_user_content())
+            self._log("created %s\n" % qt_meta_pro_user_file)
+
+        except Exception as e:
+            print("ERROR : creating lo.pro.user file=" + qt_meta_pro_user_file, file=sys.stderr)
+            print(e, file=sys.stderr)
+            temp = traceback.format_exc()
+            print(temp, file=sys.stderr)
+            print("\n\n", file=sys.stderr)
+
+        self.log_close()
+
+    pro_template = """TEMPLATE = app
+CONFIG += console
+CONFIG -= app_bundle
+CONFIG -= qt
+
+INCLUDEPATH += %(includepath)s
+
+SOURCES += %(sources)s
+
+HEADERS += %(headers)s
+
+DEFINES += %(defines)s
+
+"""
+    pro_meta_template = """TEMPLATE = subdirs
+
+SUBDIRS = %(subdirs)s
+"""
+
+
+if __name__ == '__main__':
+    parser = argparse.ArgumentParser(
+        description='LibreOffice gbuild IDE project generator')
+    parser.add_argument('--ide', dest='ide', required=True,
+                        help='the IDE to generate project files for')
+    parser.add_argument('--make', dest='makecmd', required=True,
+                        help='the command to execute make')
+    args = parser.parse_args()
+    # FIXME: Hack
+    if args.makecmd == 'make':
+        args.makecmd = '/usr/bin/make'
+
+    paths = {}
+    generators = {
+        'eclipsecdt': EclipseCDTIntegrationGenerator,
+        'kdevelop': KdevelopIntegrationGenerator,
+        'xcode': XcodeIntegrationGenerator,
+        'vs2013': VisualStudioIntegrationGenerator,
+        'vs2015': VisualStudioIntegrationGenerator,
+        'vim': VimIntegrationGenerator,
+        'debug': DebugIntegrationGenerator,
+        'qtcreator': QtCreatorIntegrationGenerator,
+    }
+
+    if args.ide not in generators.keys():
+        print("Invalid ide. valid values are %s" % ','.join(generators.keys()))
+        sys.exit(1)
+
+    gbuildparser = GbuildParser(args.makecmd).parse()
+
+    generators[args.ide](gbuildparser, args.ide).emit()
+    print("Successfully created the project files.")
+
+# Local Variables:
+# indent-tabs-mode: nil
+# End:
+#
+# vim: set et sw=4 ts=4:


More information about the Libreoffice-commits mailing list