diff options
-rw-r--r-- | Makefile.in | 19 | ||||
-rwxr-xr-x | bin/gbuild-to-ide | 1873 | ||||
-rwxr-xr-x | bin/gbuild-to-ideNS | 1667 |
3 files changed, 654 insertions, 2905 deletions
diff --git a/Makefile.in b/Makefile.in index 2866783d7fe0..29521cecc26e 100644 --- a/Makefile.in +++ b/Makefile.in @@ -460,28 +460,15 @@ $(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,\ - debug \ - testIde \ - xcode, \ -$(eval $(call gb_Top_GbuildToIdeIntegration,$(ide)))) - $(foreach ide,\ codelite \ vs2015 \ kdevelop \ vim \ qtcreator \ - eclipsecdt,\ -$(eval $(call gb_Top_GbuildToIdeIntegrationNS,$(ide)))) + eclipsecdt,\ + xcode, \ +$(eval $(call gb_Top_GbuildToIdeIntegration,$(ide)))) fuzzers: Library_sal Library_salhelper Library_reg Library_store Library_unoidl codemaker Library_cppu Library_i18nlangtag Library_cppuhelper Library_comphelper StaticLibrary_ulingu StaticLibrary_findsofficepath Library_tl Library_basegfx Library_canvastools Library_cppcanvas Library_dbtools Library_deploymentmisc Library_deploymentmisc Library_editeng Library_fwe Library_fwi Library_i18nutil Library_localebe1 Library_sax Library_sofficeapp Library_ucbhelper Library_opencl Rdb_services udkapi offapi Library_clew Library_gie Library_icg Library_reflection Library_invocadapt Library_bootstrap Library_introspection Library_stocservices Library_xmlreader Library_gcc3_uno instsetoo_native more_fonts StaticLibrary_boost_locale StaticLibrary_fuzzerstubs StaticLibrary_fuzzer_core StaticLibrary_fuzzer_calc StaticLibrary_fuzzer_draw StaticLibrary_fuzzer_writer Library_forui Library_binaryurp Library_io Library_invocation Library_namingservice Library_proxyfac Library_uuresolver Module_ure 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 Executable_pctfuzzer Executable_pcxfuzzer Executable_rasfuzzer Executable_tgafuzzer Executable_tiffuzzer Executable_hwpfuzzer Executable_602fuzzer Executable_lwpfuzzer Executable_olefuzzer Executable_pptfuzzer Executable_rtffuzzer Executable_cgmfuzzer Executable_ww2fuzzer Executable_ww6fuzzer Executable_ww8fuzzer Executable_qpwfuzzer Executable_slkfuzzer Executable_fodtfuzzer Executable_fodsfuzzer Executable_fodpfuzzer Executable_xlsfuzzer Executable_scrtffuzzer Executable_wksfuzzer Executable_diffuzzer diff --git a/bin/gbuild-to-ide b/bin/gbuild-to-ide index 4f6a94058fab..abf7c7c572bb 100755 --- a/bin/gbuild-to-ide +++ b/bin/gbuild-to-ide @@ -19,50 +19,89 @@ import json import xml.etree.ElementTree as ET import xml.dom.minidom as minidom import traceback -import collections -import subprocess +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, location, include, include_sys, defs, cxxobjects, cxxflags, linked_libs): + GbuildLinkTarget.__init__(self, name, location, include, include_sys, defs, cxxobjects, cxxflags, linked_libs) + + 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.name + + def library_name(self): + return self.name + +class GbuildTest(GbuildLinkTarget): + def __init__(self, name, location, include, include_sys, defs, cxxobjects, cxxflags, linked_libs): + GbuildLinkTarget.__init__(self, name, location, include, include_sys, defs, cxxobjects, cxxflags, linked_libs) + + 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.name + +class GbuildExe(GbuildLinkTarget): + def __init__(self, name, location, include, include_sys, defs, cxxobjects, cxxflags, linked_libs): + GbuildLinkTarget.__init__(self, name, location, include, include_sys, defs, cxxobjects, cxxflags, linked_libs) + + 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.name + 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.modules = collections.OrderedDict() - - - _includepattern = re.compile('-I(\S+)') - _isystempattern = re.compile('-isystem\s*(\S+)') - _warningpattern = re.compile('-W\S+') - _buildpattern = {'Library': re.compile('Library_(.*)\.mk'), - 'Executable': re.compile('Executable_(.*)\.mk'), - 'CppunitTest': re.compile('CppunitTest_(.*)\.mk')} - _allheaders=[] - _jsonsrcdir='' - def get_json_srcdir(self): - return self._jsonsrcdir - def __split_includes(json_srcdir,includes): - foundisystem = GbuildParser._isystempattern.findall(includes) - foundincludes=[] - for includeswitch in GbuildParser._includepattern.findall(includes): - if len(includeswitch) > 2: - if includeswitch.strip()[:len(json_srcdir)] == json_srcdir: - foundincludes.append(includeswitch.strip()[len(json_srcdir)+1:]) - else: - foundincludes.append(includeswitch.strip()) + (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.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) - def __split_objs(module,objsline, ext): - retObj = [] - for obj in objsline.strip().split(' '): - if module in obj: - obj = obj[len(module)+1:] - if len(obj) > 0 and obj != 'CXXOBJECTS' and obj != '+=': - retObj.append(obj + ext) - return sorted(retObj) + @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] @@ -79,1082 +118,128 @@ class GbuildParser: 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] - - - def parse(self): - # current json blacklist, this is just for reference: - # bridges - # connectivity compilerplugins cli_ure cppu cppuhelper cpputools - # dictionaries - # extensions external - # helpcompiler helpcontent2 - # i18npool icon-themes - # javaunohelper jurt - # lingucomponent - # odk - # sal scaddins shell solenv stoc - # tools translations - # udkapi unoid - # Add handling of BLACKLIST - - # Relation between json object and file extension - jsonSrc = { - 'CXXOBJECTS': '.cxx', 'OBJCOBJECTS': '.m', 'OBJCXXOBJECTS': '.mm', 'COBJECTS': '.c', - 'LEXOBJECTS': '.l', 'YACCOBJECTS': '.y', - - 'GENCXXOBJECTS': '.cxx', # remark is in workdir/GenCxxObject - 'ASMOBJECTS': '.s', #not in json, due to Blacklist ? - 'GENCOBJECTS': '.c', #not in json, due to Blacklist ? - 'JAVAOBJECTS': '.java', #not in json, due to Blacklist ? - 'PYTHONOBJECTS': '.py' #not in json, due to Blacklist ? - } - - - moduleDict = {} - self.find_all_headers() - - for jsontype in ['Library', 'Executable', 'CppunitTest']: - for jsonfilename in os.listdir(os.path.join(self.workdir, 'GbuildToJson', jsontype)): - with open(os.path.join(self.workdir, 'GbuildToJson', jsontype, jsonfilename), 'r') as f: - jsondata = json.load(f) - match = GbuildParser._buildpattern[jsontype].match(os.path.basename(jsondata['MAKEFILE'])).group(1) - jsondata['location'] = os.path.dirname(jsondata['MAKEFILE']) - module = jsondata['location'].split('/')[-1] - json_srcdir=jsondata['location'][:-(len(module)+1)] - jsondata['MAKEFILE']=jsondata['MAKEFILE'][len(jsondata['location'])+1:] - jsondata['ILIBTARGET']='../' + jsondata['ILIBTARGET'][len(json_srcdir)+1:] - - (jsondata['include'], jsondata['include_sys']) = GbuildParser.__split_includes(json_srcdir, jsondata['INCLUDE']) - jsondata['name'] = match - jsondata['build_type'] = jsontype - jsondata['target_name'] = module + '_' + jsontype + '_' + match - jsondata['DEFS'] = GbuildParser.__split_defs(jsondata['DEFS']) - jsondata['LINKED_LIBS'] = jsondata['LINKED_LIBS'].strip().split(' ') - jsondata['CXXFLAGS'] += ' -DLIBO_INTERNAL_ONLY' - for i in ['CXXFLAGS', 'CFLAGS', 'OBJCFLAGS', 'OBJCXXFLAGS']: - jsondata[i] = GbuildParser.__split_flags(jsondata[i], jsondata[i+'APPEND']) - for i in jsonSrc: - if not i in jsondata: - jsondata[i] = '' - jsondata[i] = GbuildParser.__split_objs(module, jsondata[i], jsonSrc[i]) - - if not module in moduleDict: - moduleDict[module] = {'targets': [],'headers':{}} - moduleDict[module]['targets'].append(jsondata) - moduleDict[module]['headers'] =self.headers_of(module) - self._jsonsrcdir=json_srcdir - moduleDict['include']={ 'targets': [], 'headers':self.headers_of('include')} - - for i in sorted(moduleDict): - module = moduleDict[i] - src = [] - for target in module['targets']: - target['module'] = i - for ext in jsonSrc: - src.extend(target[ext]) - module['sources'] = sorted(src) - self.modules[i] = module - return self - - - - def find_all_headers(self): - - cmdResult=subprocess.check_output(['git', 'ls-files','--','*.h','*.hxx', '*.hpp'], cwd=self.srcdir, stderr=subprocess.PIPE,) - - - allfiles={} - for file in cmdResult.splitlines(): - strfile=file.decode() - modulename=strfile.split('/')[0] - if not modulename in allfiles: - allfiles[modulename]=[] - modulename_len=len(modulename) - allfiles[modulename].append(strfile[modulename_len + 1:]) - - self._allheaders = allfiles - - def headers_of(self,modulename): - if modulename in self._allheaders: #for the modules that not have headers - headersof = self._allheaders[modulename] - else: - headersof=[] - return headersof - - - -class IdeIntegrationGenerator: - - def __init__(self, gbuildparser, ide): - (self.gbuildparser, self.ide) = (gbuildparser, ide) - - def emit(self): - pass - - - -class testVS2013Ide(IdeIntegrationGenerator): - - def __init__(self, gbuildparser, ide): - IdeIntegrationGenerator.__init__(self, gbuildparser, ide) - self.toolset = self.retrieve_toolset() - self.solution_directory = './windows' - self.configurations = { - 'Release': { - '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') - }, - 'Debug': { - 'build': self.module_make_command('unitcheck'), - 'clean': self.module_make_command('clean'), - 'rebuild': self.module_make_command('clean unitcheck'), - } - } - srcdir=self.gbuildparser.get_json_srcdir() - self.env_variables={ - 'SRCDIR': srcdir,'BUILDDIR':os.path.dirname(srcdir),'INSTDIR':os.path.join(srcdir,'instdir'),'WORKDIR':os.path.join(srcdir,'workdir') - } - def tmp_json_env_var(self): - pass - - def retrieve_toolset(self): - return {'vs2015': 'v140', 'testIde':'v120'}.get(self.ide, None) - - 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 = [] - props_path=os.path.join(self.solution_directory,'PropertySheet.props') - self.write_props(props_path) - for module in self.gbuildparser.modules: - projects = [] - module_directory = os.path.join(self.solution_directory, module) - if module != 'include': # FIXME - project_path = os.path.join(module_directory, '%s.vcxproj' % module) - project_guid = self.twrite_project(project_path, module) - self.write_filters(project_path + '.filters', module, self.gbuildparser.modules[module]['headers']) - for target in self.gbuildparser.modules[module]['targets']: - p = self.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['name'] == linked_lib: - dependency_libs[library_project.guid] = library_project - return dependency_libs - def write_props(self,props_path): - ns = 'http://schemas.microsoft.com/developer/msbuild/2003' - ET.register_namespace('', ns) - proj_node = ET.Element('{%s}Project' % ns, DefaultTargets='Build', ToolsVersion='4.0') - imp_grp_node=ET.SubElement(proj_node,'{%s}ImportGroup' % ns, Label='PropertySheets') - prop_grp_node = ET.SubElement(proj_node, '{%s}PropertyGroup' % ns, Label='UserMacros') - for key,value in self.env_variables.items(): - vsrcdir=ET.SubElement(prop_grp_node,key) - vsrcdir.text=value - prop_grp_node2 = ET.SubElement(proj_node, '{%s}PropertyGroup' % ns) - itm_def_node = ET.SubElement(proj_node, '{%s}ItemDefinitionGroup' % ns) - itm_grp = ET.SubElement(proj_node, '{%s}ItemGroup' % ns) - for key, value in self.env_variables.items(): - build_macro_node = ET.SubElement(itm_grp, '{%s}BuildMacro' % ns, Include=key) - value_node = ET.SubElement(build_macro_node, '{%s}Value' % ns) - value_node.text='$(%s)' % key - self.write_pretty_xml(proj_node,props_path) - - def write_solution(self, solution_path, projects): - library_projects = [project for project in projects if project.target['build_type'] == 'Library'] - 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 - 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['target_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('Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{B9292527-A979-4D13-A598-C75A33222174}"\n') - f.write('\tProjectSection(SolutionItems) = preProject\n') - f.write('\t\tsolenv/vs/LibreOffice.natvis = solenv/vs/LibreOffice.natvis\n') - 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') - - 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['target_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('../..', '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) - includes=[os.path.join('../..',elem) if elem[1] != ':' else elem for elem in target['include'] ] - include_path_node.text = ';'.join(includes + ['$(IncludePath)']) - - ET.SubElement(proj_node, '{%s}ItemDefinitionGroup' % ns) - - cxxobjects_node = ET.SubElement(proj_node, '{%s}ItemGroup' % ns) - for cxxobject in target['CXXOBJECTS']: - cxxrelpath= os.path.join('../..',target['location'].split('/')[-1], cxxobject) - cxxabspath = os.path.join(self.gbuildparser.srcdir,target['location'].split('/')[-1], cxxobject) - cxxfile = cxxabspath - if os.path.isfile(cxxfile): - ET.SubElement(cxxobjects_node, '{%s}ClCompile' % ns, Include=cxxrelpath) - else: - print('Source %s in project %s does not exist' % (cxxfile, target['target_name'])) - - includes_node = ET.SubElement(proj_node, '{%s}ItemGroup' % ns) - for cxxobject in target['CXXOBJECTS']: - include_rel_path = os.path.join('../..',target['location'].split('/')[-1], cxxobject) - include_abs_path = os.path.join(self.gbuildparser.srcdir,target['location'].split('/')[-1], cxxobject) - hxxfile = include_abs_path - if os.path.isfile(hxxfile): - ET.SubElement(includes_node, '{%s}ClInclude' % ns, Include=include_rel_path) - # Few files have corresponding .h files - hfile = include_abs_path - if os.path.isfile(hfile): - ET.SubElement(includes_node, '{%s}ClInclude' % ns, Include=include_rel_path) - 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) - - return project_guid - - - def twrite_project(self, project_path, module): - 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') + return [cxxflag.strip() for cxxflag in GbuildParser.warningpattern.sub('', '%s %s' % (flagsline, flagslineappend)).split(' ') if len(cxxflag) > 1] - 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 - 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_root_namespace=ET.SubElement(globals_node, '{%s}RootNamespace' % ns) - proj_root_namespace.text = module - - - ET.SubElement(proj_node, '{%s}Import' % ns, Project='$(VCTargetsPath)\Microsoft.Cpp.Default.props') - for configuration in self.configurations: - property_group_node=ET.SubElement(proj_node,'{%s}PropertyGroup' % ns, Label="Configuration", Condition="'$(Configuration)|$(Platform)'=='%s|%s'" % (configuration,platform)) - conf_type=ET.SubElement(property_group_node,'{%s}ConfigurationType' % ns) - conf_type.text='Application' - use_dbg_lib=ET.SubElement(property_group_node,'{%s}UseDebugLibraries' % ns) - use_dbg_lib.text='true' - platform_toolset_node = ET.SubElement(property_group_node, '{%s}PlatformToolset' % ns) - platform_toolset_node.text = self.toolset - char_set_node=ET.SubElement(property_group_node,'{%s}CharacterSet' %ns) - char_set_node.text='MultiByte' - #on debug there ist a whole programoptimization - - 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=ET.SubElement(proj_node,'{%s}ImportGroup' % ns, Label='PropertySheets',Condition="'$(Configuration)|$(Platform)'=='%s|%s'" % (configuration,platform)) - ET.SubElement(prop_sheets,'{%s}Import' % ns,Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props",Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')",Label="LocalAppDataPlatform") - ET.SubElement(prop_sheets, '{%s}Import' % ns, Project="../PropertySheet.props") - ET.SubElement(proj_node, '{%s}PropertyGroup' % ns, Label='UserMacros') - for configuration in self.configurations: - item_def_group=ET.SubElement(proj_node,'{%s}ItemDefinitionGroup' % ns,Condition="'$(Configuration)|$(Platform)'=='%s|%s'" % (configuration,platform)) - #compiler options - cl_compile=ET.SubElement(item_def_group,'{%s}ClCompile' % ns) - warn_lvl=ET.SubElement(cl_compile,'{%s}WarningLevel' % ns) - warn_lvl.text='Level4' - opt_node=ET.SubElement(cl_compile,'{%s}Optimization' % ns) - opt_node.text='Disabled' - sdl_check=ET.SubElement(cl_compile,'{%s}SDLCheck' % ns) - sdl_check.text='true' - for target in self.gbuildparser.modules[module]['targets']: - add_incl_dir=ET.SubElement(cl_compile,'{%s}AdditionalIncludeDirectories' % ns) - add_incl_dir.text=self.get_include_dirs(target) - add_incl_def_flag=ET.SubElement(cl_compile,'{%s}AdditionalOptions' % ns) - add_incl_def_flag.text=self.get_flags_defs(target) - - dgb_info_form=ET.SubElement(cl_compile,'{%s}DebugInformationFormat' % ns) - dgb_info_form.text='ProgramDatabase' - warn_as_error=ET.SubElement(cl_compile,'{%s}TreatWarningAsError' % ns) - warn_as_error.text='true' - run_libs=ET.SubElement(cl_compile,'{%s}RuntimeLibrary' % ns) - run_libs.text='MultiThreadedDLL' - - #linker options - #linker_node=ET.SubElement(item_def_group,'{%s}Link' % ns) - - #gen_dbg_info=ET.SubElement(linker_node,'{%s}GenerateDebugInformation}' % ns) - #gen_dbg_info.text='true' - #add_lib_dirs=ET.SubElement(linker_node,'{%s}AdditionalLibraryDirectories}' % ns) - #libname=target['ILIBTARGET'].split('/')[-1] - #libpath='../' + target['ILIBTARGET'][:-(len(libname)+1)] - #add_lib_dirs.text= libpath - #add_dep=ET.SubElement(linker_node,'{%s}AdditionalDependencies}' % ns) - #add_dep.text= libname +';kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)' - - #proj_ref_node=ET.SubElement(item_def_group,'{%s}ProjectReference' % ns) - #use_lib_dep=ET.SubElement(proj_ref_node,'{%s}UseLibraryDependencyInputs}' % ns) - #use_lib_dep.text='true' - - #cxx files - cxx_node=ET.SubElement(proj_node,'{%s}ItemGroup' % ns) - for target in self.gbuildparser.modules[module]['targets']: - for cxx_elem in target['CXXOBJECTS']: - modulename=target['module'] - cxx_cl_node=ET.SubElement(cxx_node,'{%s}ClCompile' % ns,Include=os.path.join('../..', modulename, cxx_elem)) - #miss headers - 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) - return project_guid - - def get_flags_defs(self,target): - flags=' '.join(target['CXXFLAGS']).replace('-','/') - mdefs='' - for elem_defs,elem_value in target['DEFS'].items(): - mdefs += '/D' + elem_defs - if elem_value != None: - mdefs += '=' + elem_value - mdefs += ' ' - return flags + ' ' + mdefs + '-arch:SSE -DEXCEPTIONS_ON -EHs -Od -FS -Zi -DLIBO_INTERNAL_ONLY -WX' - - def get_include_dirs(self,target): - includes='' - for elem in target['include']: - if elem[1] == ':': - tmp_inc=elem - else: - tmp_inc ='../../' + elem - tmp_inc +=';' - includes +=tmp_inc - return includes[:-1] - - - 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 write_filters(self,filters_path,module,headers): - ns = 'http://schemas.microsoft.com/developer/msbuild/2003' - ET.register_namespace('', ns) - proj_node = ET.Element('{%s}Project' % ns, ToolsVersion='4.0') - - filters_node=ET.SubElement(proj_node,'{%s}ItemGroup' % ns) - filters={'sources' : 'c;cxx;cpp','headers':'h;hxx;hpp'} - for filter_key,filter_value in filters.items(): - filter_node = ET.SubElement(filters_node,'{%s}Filter' % ns, Include='%s' % filter_key) - filter_id_node = ET.SubElement(filter_node,'{%s}UniqueIdentifier' % ns) - filter_id_node.text='{%s}' % str(uuid.uuid4()) - filter_ext_node = ET.SubElement(filter_node,'{%s}Extensions' % ns) - filter_ext_node.text = '{%s}' % filter_value - sources_node=ET.SubElement(proj_node,'{%s}ItemGroup' % ns) - for target in self.gbuildparser.modules[module]['targets']: - for cxxfile in target['CXXOBJECTS']: - cxx_file_name = cxxfile.split('/')[-1] - clinclude_node=ET.SubElement(sources_node,'{%s}ClInclude' % ns, Include='%s' % cxx_file_name) - header_filter=ET.SubElement(clinclude_node,'{%s}Filter' % ns) - header_filter.text="sources" - - headers_node=ET.SubElement(proj_node,'{%s}ItemGroup' % ns) - for header in headers: - header_file_name=header.split('/')[-1] - - clinclude_node=ET.SubElement(headers_node,'{%s}ClInclude' % ns, Include='%s' % header_file_name) - header_filter=ET.SubElement(clinclude_node,'{%s}Filter' % ns) - header_filter.text="headers" - - self.write_pretty_xml(proj_node, filters_path) - -class XcodeIntegrationGenerator(IdeIntegrationGenerator): - def __init__(self, gbuildparser, ide): - IdeIntegrationGenerator.__init__(self, gbuildparser, ide) - - typeCounter = {'PBXProject' : 000000, - 'PBXGroup' : 100000, - 'PBXFileReference' : 200000, - 'PBXNativeTarget' : 300000, - 'XCConfigurationList' : 400000, - 'PBXSourcesBuildPhase' : 500000, - 'XCBuildConfiguration' : 600000, - 'PBXBuildFile' : 700000} - - def emit(self): - mainGroupId, mainGroup = self.generate_PBXGroup(None) - rootId = self.generate_id('PBXProject') - self.rootObj = {'attributes': {'LastUpgradeCheck': '0820', - 'ORGANIZATIONNAME': 'LibreOffice', - 'TargetAttributes': {}}, - 'compatibilityVersion': 'Xcode 3.2', - 'developmentRegion': 'English', - 'isa': 'PBXProject', - 'hasScannedForEncodings': 0, - 'knownRegions': ['en'], - 'mainGroup': mainGroupId, - 'projectDirPath': self.gbuildparser.srcdir, - 'projectRoot': '', - 'buildConfigurationList': '', - 'targets': []} - pbxproj = {'archiveVersion': 1, - 'classes': {}, - 'objectVersion': 46, - 'objects': {rootId: self.rootObj, - mainGroupId: mainGroup}, - 'rootObject': rootId} - for module in self.gbuildparser.modules: - if module == 'include': - continue - moduleId, moduleObj = self.generate_PBXGroup(module) - sourceId, sourceObj = self.generate_PBXGroup('Sources') - includeId, includeObj = self.generate_PBXGroup('Headers') - targetId, targetObj = self.generate_PBXGroup('Targets') - - moduleObj['children'] = [sourceId, includeId, targetId] - pbxproj['objects'].update({sourceId: sourceObj, - includeId: includeObj, - moduleId: moduleObj, - targetId: targetObj}) - mainGroup['children'].append(moduleId) - - for i in self.gbuildparser.modules[module]['headers']: - ref = self.generate_id('PBXFileReference') - pbxproj['objects'][ref] = self.generate_PBXFileReference(module, i) - includeObj['children'].append(ref) - for i in self.gbuildparser.modules[module]['sources']: - ref = self.generate_id('PBXFileReference') - pbxproj['objects'][ref] = self.generate_PBXFileReference(module, i) - sourceObj['children'].append(ref) - for target in self.gbuildparser.modules[module]['targets']: - pbxproj['objects'].update(self.generate_target(target, module, targetObj, sourceObj['children'])) - - xcodeprojdir = './osx/libreoffice.xcodeproj' - try: - os.mkdir(xcodeprojdir) - except: - pass - with open(os.path.join(xcodeprojdir, 'project.pbxproj'), 'w') as f: - f.write('// !$*UTF8*$!\n') - self.write_object(pbxproj, f, 0) - - def indent(self, file, level): - if level != 0: - for i in range(0, level): - file.write('\t') + @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), + 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 write_object(self, object, file, indent): - if isinstance(object, int): - file.write('%d' % object) - elif isinstance(object, str): - if object == '': - file.write('""') - elif not re.search('[^A-Za-z0-9_]', object): - file.write('%s' % object) - else: - file.write('"%s"' % object) - elif isinstance(object, dict): - file.write('{') - file.write('\n') - for key in sorted(object.keys()): - self.indent(file, indent + 1) - file.write('%s = ' % key) - self.write_object(object[key], file, indent + 1) - file.write(';\n') - self.indent(file, indent) - file.write('}') - elif isinstance(object, list): - file.write('(') - for key in object: - self.write_object(key, file, 1) - file.write(',') - file.write(')') - - def generate_id(self, id): - self.typeCounter[id] += 1 - return str('X%06d' % self.typeCounter[id]) - - def generate_target(self, target, module, targetObj, sourceObj): - targetId = self.generate_id('PBXNativeTarget') - configurationListId = self.generate_id('XCConfigurationList') - configurationDebugId = self.generate_id('XCBuildConfiguration') - fileId = self.generate_id('PBXFileReference') - objects = {configurationListId: self.generate_XCBuildConfiguration(target, configurationDebugId), -#MAKE targetId: self.generate_PBXLegacyTarget(target, configurationListId), - targetId: self.generate_PBXNativeTarget(target, configurationListId), - configurationDebugId: self.generate_XCBuildConfiguration(target, configurationDebugId, debug=True), - fileId : self.generate_PBXFileReference(module, target['LINKTARGET'], explicit=target['build_type']) - } - self.rootObj['attributes']['TargetAttributes'].update( - {targetId: {'CreatedOnToolsVersion': '8.2', 'ProvisioningStyle': 'Automatic'}}) - self.rootObj['buildConfigurationList'] = configurationListId - self.rootObj['targets'].append(targetId) - targetObj['children'].append(fileId) - return objects - - def generate_PBXGroup(self, name): - obj = {'isa': 'PBXGroup', 'children': [], 'sourceTree': '<group>'} - if not name is None: - obj['name'] = name - return self.generate_id('PBXGroup'), obj - - def generate_PBXLegacyTarget(self, modulename, configurationListId): - if modulename['build_type'] == 'Library': - product = 'com.apple.product-type.library.dynamic' - elif modulename['build_type'] == 'Executable': - product = 'com.apple.product-type.executable' - elif modulename['build_type'] == 'CppunitTest': - product = 'com.apple.product-type.cppunit' - else: - product = 'com.apple.product-type.something' - - return {'isa': 'PBXLegacyTarget', - 'buildConfigurationList': configurationListId, - 'buildArgumentsString': modulename['target_name'], - 'buildPhases': [], - 'dependencies': [], - 'buildToolPath': 'make', - 'buildWorkingDirectory': self.gbuildparser.builddir, - 'name': modulename['target_name'], - 'productName': modulename['name'], - 'passBuildSettingsEnvironment': 1} - - def generate_PBXNativeTarget(self, modulename, configurationListId): - if modulename['build_type'] == 'Library': - product = 'com.apple.product-type.library.dynamic' - elif modulename['build_type'] == 'Executable': - product = 'com.apple.product-type.tool' - elif modulename['build_type'] == 'CppunitTest': - product = 'com.apple.product-type.cppunit' - else: - product = 'com.apple.product-type.something' - - return {'isa': 'PBXNativeTarget', - 'buildRules': [], - 'dependencies': [], - 'name': modulename['target_name'], - 'productName': modulename['name'], - 'productType': product, - 'buildConfigurationList': configurationListId, - 'buildPhases': [], - 'productReference': ''} - - def generate_XCBuildConfiguration(self, modulename, configurationDebugId, debug=False): - if debug: - result = {'isa': 'XCBuildConfiguration', - 'buildSettings': { - 'ALWAYS_SEARCH_USER_PATHS': 'NO', - 'CLANG_ANALYZER_NONNULL': 'YES', - 'CLANG_CXX_LANGUAGE_STANDARD': 'gnu++0x', - 'CLANG_CXX_LIBRARY': 'libc++', - 'CLANG_ENABLE_MODULES': 'YES', - 'CLANG_ENABLE_OBJC_ARC': 'YES', - 'CLANG_WARN_BOOL_CONVERSION': 'YES', - 'CLANG_WARN_CONSTANT_CONVERSION': 'YES', - 'CLANG_WARN_DIRECT_OBJC_ISA_USAGE': 'YES_ERROR', - 'CLANG_WARN_DOCUMENTATION_COMMENTS': 'YES', - 'CLANG_WARN_EMPTY_BODY': 'YES', - 'CLANG_WARN_ENUM_CONVERSION': 'YES', - 'CLANG_WARN_INFINITE_RECURSION': 'YES', - 'CLANG_WARN_INT_CONVERSION': 'YES', - 'CLANG_WARN_OBJC_ROOT_CLASS': 'YES_ERROR', - 'CLANG_WARN_SUSPICIOUS_MOVE': 'YES', - 'CLANG_WARN_UNREACHABLE_CODE': 'YES', - 'CLANG_WARN__DUPLICATE_METHOD_MATCH': 'YES', - 'CODE_SIGN_IDENTITY': '-', - 'COPY_PHASE_STRIP': 'NO', - 'DEBUG_INFORMATION_FORMAT': 'dwarf', - 'ENABLE_STRICT_OBJC_MSGSEND': 'YES', - 'ENABLE_TESTABILITY': 'YES', - 'GCC_C_LANGUAGE_STANDARD': 'gnu99', - 'GCC_DYNAMIC_NO_PIC': 'NO', - 'GCC_NO_COMMON_BLOCKS': 'YES', - 'GCC_OPTIMIZATION_LEVEL': 0, - 'GCC_PREPROCESSOR_DEFINITIONS': ['DEBUG=1', '$(inherited)'], - 'GCC_WARN_64_TO_32_BIT_CONVERSION': 'YES', - 'GCC_WARN_ABOUT_RETURN_TYPE': 'YES_ERROR', - 'GCC_WARN_UNDECLARED_SELECTOR': 'YES', - 'GCC_WARN_UNINITIALIZED_AUTOS': 'YES_AGGRESSIVE', - 'GCC_WARN_UNUSED_FUNCTION': 'YES', - 'GCC_WARN_UNUSED_VARIABLE': 'YES', - 'MACOSX_DEPLOYMENT_TARGET': '10.12', - 'MTL_ENABLE_DEBUG_INFO': 'YES', - 'ONLY_ACTIVE_ARCH': 'YES', - 'PRODUCT_NAME': '$(TARGET_NAME)', - 'SDKROOT': 'macosx', - 'HEADER_SEARCH_PATHS': modulename['include']}, - 'name': 'Debug'} - else: - result = {'isa': 'XCConfigurationList', - 'buildConfigurations': [configurationDebugId], - 'defaultConfigurationIsVisible': 0, - 'defaultConfigurationName': 'Debug'} - return result + @staticmethod + def __test_from_json(json): + (foundincludes, foundisystem) = GbuildParser.__split_includes(json['INCLUDE']) + testname_match = GbuildParser.testpattern.match(os.path.basename(json['MAKEFILE'])) - def generate_PBXFileReference(self, module, filepath, explicit=None): - obj = {'isa': 'PBXFileReference', - 'path': module + '/' + filepath, - 'name': filepath, - 'sourceTree': '<group>'} - if not explicit is None: - if explicit == 'Library': - obj['explicitFileType'] = 'compiled.mach-o.dylib' - else: - obj['explicitFileType'] = 'compiled.executable' - obj['includeInIndex'] = 0 - obj['path'] = filepath + # Workaround strange writer test makefile setup + if testname_match is None: + testname = "StrangeWriterMakefiles" else: - obj['path'] = module + '/' + filepath - return obj - - - -class VisualStudioIntegrationGenerator(IdeIntegrationGenerator): - - def __init__(self, gbuildparser, ide): - IdeIntegrationGenerator.__init__(self, gbuildparser, ide) - self.toolset = self.retrieve_toolset() - self.solution_directory = './windows' - 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): - return {'vs2015': 'v140'}.get(self.ide, None) - - 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 module in self.gbuildparser.modules: - projects = [] - module_directory = os.path.join(self.solution_directory, module) - if module != 'include': #FIXME - for target in self.gbuildparser.modules[module]['targets']: - project_path = os.path.join(module_directory, '%s.vcxproj' % target['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['name'] == linked_lib: - dependency_libs[library_project.guid] = library_project - return dependency_libs - - def write_solution(self, solution_path, projects): - library_projects = [project for project in projects if project.target['build_type'] == 'Library'] - 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 - 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['target_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('Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{B9292527-A979-4D13-A598-C75A33222174}"\n') - f.write('\tProjectSection(SolutionItems) = preProject\n') - f.write('\t\tsolenv/vs/LibreOffice.natvis = solenv/vs/LibreOffice.natvis\n') - 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') + testname = testname_match.group(1) + + return GbuildTest( + testname, + 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 defs_list(defs): - defines_list = [] - # List defines - for key, value in defs.items(): - define = key - if value is not None: - define += '=' + value - defines_list.append(define) - return defines_list - - 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['target_name'] + def __exe_from_json(json): + (foundincludes, foundisystem) = GbuildParser.__split_includes(json['INCLUDE']) + return GbuildExe( + GbuildParser.exepattern.match(os.path.basename(json['MAKEFILE'])).group(1), + 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(' ')) - 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('../..', 'program', 'soffice.exe') - nmake_defs_node = ET.SubElement(conf_node, '{%s}NMakePreprocessorDefinitions' % ns) - nmake_defs_node.text = ';'.join(self.defs_list(target['DEFS']) + ['$(NMakePreprocessorDefinitions)']) - include_path_node = ET.SubElement(conf_node, '{%s}IncludePath' % ns) - includes = [os.path.join('../..', elem) if elem[1] != ':' else elem for elem in target['include']] - include_path_node.text = ';'.join(includes + ['$(IncludePath)']) - - ET.SubElement(proj_node, '{%s}ItemDefinitionGroup' % ns) - - cxxobjects_node = ET.SubElement(proj_node, '{%s}ItemGroup' % ns) - for cxxobject in target['CXXOBJECTS']: - cxxrelpath = os.path.join('../..', target['location'].split('/')[-1], cxxobject) - cxxabspath = os.path.join(self.gbuildparser.srcdir, target['location'].split('/')[-1], cxxobject) - cxxfile = cxxabspath - if os.path.isfile(cxxfile): - ET.SubElement(cxxobjects_node, '{%s}ClCompile' % ns, Include=cxxrelpath) - else: - print('Source %s in project %s does not exist' % (cxxfile, target['target_name'])) - - includes_node = ET.SubElement(proj_node, '{%s}ItemGroup' % ns) - for cxxobject in target['CXXOBJECTS']: - include_rel_path = os.path.join('../..',target['location'].split('/')[-1], cxxobject) - include_abs_path = os.path.join(self.gbuildparser.srcdir,target['location'].split('/')[-1], cxxobject) - hxxfile = include_abs_path - if os.path.isfile(hxxfile): - ET.SubElement(includes_node, '{%s}ClInclude' % ns, Include=include_rel_path) - # Few files have corresponding .h files - hfile = include_abs_path - if os.path.isfile(hfile): - ET.SubElement(includes_node, '{%s}ClInclude' % ns, Include=include_rel_path) - 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) + 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.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.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.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 location in self.target_by_location: + self.modulenamelist.append(os.path.split(location)[1]) + return self -class DebugIntegrationGenerator(IdeIntegrationGenerator): +class IdeIntegrationGenerator: def __init__(self, gbuildparser, ide): - IdeIntegrationGenerator.__init__(self, gbuildparser, ide) + self.gbuildparser = gbuildparser + self.ide = ide def emit(self): - print(self.gbuildparser.srcdir) - print(self.gbuildparser.builddir) - print("testWinIde test:") - testWinIde(self.gbuildparser, self.ide).emit() - print("VisualStudioIntegrationGenerator test:") - VisualStudioIntegrationGenerator(self.gbuildparser, self.ide).emit() - print("XcodeIntegrationGenerator test:") - XcodeIntegrationGenerator(self.gbuildparser, self.ide).emit() - print("EclipseCDTIntegrationGenerator test:") - EclipseCDTIntegrationGenerator(self.gbuildparser, self.ide).emit() - print("KdevelopIntegrationGenerator test:") - KdevelopIntegrationGenerator(self.gbuildparser, self.ide).emit() - print("VimIntegrationGenerator test:") - VimIntegrationGenerator(self.gbuildparser, self.ide).emit() - print("QtCreatorIntegrationGenerator test:") - QtCreatorIntegrationGenerator(self.gbuildparser, self.ide).emit() - - - -# ---- Classes below this point are not actively maintained ------- - - + pass class EclipseCDTIntegrationGenerator(IdeIntegrationGenerator): def __init__(self, gbuildparser, ide): IdeIntegrationGenerator.__init__(self, gbuildparser, ide) - def create_include_path(self): - for module in self.gbuildparser.modules: - if module == 'include': - continue + 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.target_path.keys(): + for lib in self.gbuildparser.target_by_path.keys(): if lib.startswith(module+'/'): modulelibs.append(lib) - include = [] + include = set() for lib in modulelibs: - for target in self.target_path[lib]: - include.extend(target[0]['include']) + 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.modules: - if module == 'include': - continue + 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.target_path.keys(): + 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.target_path[lib]: - for i in target[0]['DEFS'].keys(): - tmp = str(i) +','+str(target[0]['DEFS'][i]) + 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)) @@ -1196,11 +281,9 @@ class EclipseCDTIntegrationGenerator(IdeIntegrationGenerator): </language> </section> </cdtprojectproperties> -""" +""" - for module in self.gbuildparser.modules: - if module == 'include': - continue + for module in self.gbuildparser.modulenamelist: tempxml = [] modulepath = os.path.join(self.gbuildparser.builddir, module) @@ -1223,7 +306,7 @@ class EclipseCDTIntegrationGenerator(IdeIntegrationGenerator): macrokey = macroskeyvalue[0] macrovalue = macroskeyvalue[1] if macrovalue[-1:] == "\n": - macrovalue = macrovalue[:-1] + macrovalue = macrovalue[:-1] templine = "<macro><name>%s</name><value>%s</value></macro>\n" %(macrokey, macrovalue) tempxml.insert(-13, templine) tempxml="".join(tempxml) @@ -1236,20 +319,24 @@ class EclipseCDTIntegrationGenerator(IdeIntegrationGenerator): os.remove(os.path.join(modulepath, '.macros')) def emit(self): - self.target_path = {} - for m in self.gbuildparser.modules: - if m == 'include': - continue - for target in self.gbuildparser.modules[m]['targets']: - for cxx in target['CXXOBJECTS']: - path = '/'.join(cxx.split('/')[:-1]) - if path not in self.target_path: - self.target_path[path] = [] - self.target_path[path].append([target]) - self.create_include_path() + self.create_include_paths() self.create_macros() - self.create_settings_file() + 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): @@ -1259,21 +346,19 @@ class VimIntegrationGenerator(IdeIntegrationGenerator): def emit(self): global_list = [] - for m in self.gbuildparser.modules: - for lib in self.gbuildparser.modules[m]['targets']: - entries = [] - for file in lib['CXXOBJECTS']: - xFile = lib['module'] + '/' + file - filePath = os.path.join(self.gbuildparser.srcdir, xFile) - entry = {'directory': lib['location'], 'file': filePath, 'command': self.generateCommand(lib, filePath)} - entries.append(entry) - global_list.extend(entries) + for lib in set(self.gbuildparser.libs) | set(self.gbuildparser.tests) | set(self.gbuildparser.exes): + 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(): + for key, value in lib.defs.items(): command += ' -D' command += key if value is not None: @@ -1284,13 +369,13 @@ class VimIntegrationGenerator(IdeIntegrationGenerator): # one is not the same for all source files in the lib. command += ' -I' + os.path.dirname(file) - for include in lib['include']: + for include in lib.include: command += ' -I' - command += os.path.abspath(include) - for isystem in lib['include_sys']: + command += include + for isystem in lib.include_sys: command += ' -isystem ' command += isystem - for cxxflag in lib['CXXFLAGS']: + for cxxflag in lib.cxxflags: command += ' ' command += cxxflag command += ' -c ' @@ -1301,7 +386,6 @@ class VimIntegrationGenerator(IdeIntegrationGenerator): return command - class KdevelopIntegrationGenerator(IdeIntegrationGenerator): def encode_int(self, i): @@ -1443,8 +527,8 @@ VersionControl=kdevgit def write_includepaths(self, path): includedirfile = open(os.path.join(path, '.kdev_include_paths'), 'w') include = set() - for target in self.target_path[path]: - include |= set(target['include']) + for target in self.gbuildparser.target_by_path[path]: + include |= set(target.include) includedirfile.write('\n'.join(include)) includedirfile.close() @@ -1452,43 +536,469 @@ VersionControl=kdevgit IdeIntegrationGenerator.__init__(self, gbuildparser, ide) def emit(self): - self.target_path = {} - for m in self.gbuildparser.modules: - for target in self.gbuildparser.modules[m]['targets']: - for cxx in target['CXXOBJECTS']: - path = '/'.join(cxx.split('/')[:-1]) - path = target['module'] + '/' + path - if path not in self.target_path: - self.target_path[path] = [] - self.target_path[path].append(target) - - for path in self.target_path: + for path in self.gbuildparser.target_by_path: self.write_includepaths(path) - for modulename in self.gbuildparser.modules: - if modulename=='include': - continue - location = self.gbuildparser.srcdir + '/' + modulename - self.write_modulestub(location, modulename) - self.write_modulebeef(location, modulename) + 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.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.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 = {'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.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.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('Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{B9292527-A979-4D13-A598-C75A33222174}"\n') + f.write('\tProjectSection(SolutionItems) = preProject\n') + f.write('\t\tsolenv/vs/LibreOffice.natvis = solenv/vs/LibreOffice.natvis\n') + 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('') + + @staticmethod + def defs_list(defs): + defines_list = [] + # List defines + for key, value in defs.items(): + define = key + if value is not None: + define += '=' + value + defines_list.append(define) + return defines_list + + 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(self.defs_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.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 m in self.gbuildparser.modules: - for target in self.gbuildparser.modules[m]['targets']: - if target['location'] not in self.target_by_location: - self.target_by_location[target['location']] = [] - self.target_by_location[target['location']].append(target) + 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: @@ -1926,7 +1436,7 @@ class QtCreatorIntegrationGenerator(IdeIntegrationGenerator): 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): + if os.path.isfile(path + ext): return ext return "" @@ -1941,17 +1451,14 @@ class QtCreatorIntegrationGenerator(IdeIntegrationGenerator): self.data_libs = {} - all_libs = [] - for m in self.gbuildparser.modules: - for f in self.gbuildparser.modules[m]['targets']: - all_libs.append(f) + all_libs = set(self.gbuildparser.libs) | set(self.gbuildparser.exes) for lib in all_libs: - self._log("\nlibrary : %s, loc=%s" % (lib['target_name'], lib['location'])) - lib_name = os.path.basename(lib['location']) - lib_folder = os.path.relpath(lib['location'], self.base_folder) + 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']) + return os.path.relpath(path, lib.location) defines_list = [] sources_list = [] @@ -1962,7 +1469,7 @@ class QtCreatorIntegrationGenerator(IdeIntegrationGenerator): # 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']: + for file_ in lib.cxxobjects: # the file has no extension : search it # self._log("\n file : %s" % file_) ext = self.get_source_extension(file_) @@ -1975,20 +1482,20 @@ class QtCreatorIntegrationGenerator(IdeIntegrationGenerator): headers_list.append(lopath(file_ + ext)) # List all include paths - for hdir in lib['include']: + 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 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(): + for key, value in lib.defs.items(): define = key if value is not None: define += '=' + value @@ -2006,7 +1513,7 @@ class QtCreatorIntegrationGenerator(IdeIntegrationGenerator): 'headers': set(headers_list), 'includepath': set(includepath_list), 'defines': set(defines_list), - 'loc': lib['location'], + 'loc': lib.location, 'name': lib_name } @@ -2117,73 +1624,6 @@ SUBDIRS = %(subdirs)s """ - -class CodeliteIntegrationGenerator(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]) - - - def emit(self): - # create main workspace file - codelite_workspace_file = 'lo.workspace1' - with open(codelite_workspace_file, 'w+') as f: - f.write(self.generate_workspace_content()) - - def generate_workspace_content(self): - projects1 = '' - projects2 = '' - projects3 = '' - for module in self.gbuildparser.modulenamelist: - projects1 += CodeliteIntegrationGenerator.codelite_projects1_template.format( - name = module - ) - projects2 += CodeliteIntegrationGenerator.codelite_projects2_template.format( - name = module, - config = 'Debug' - ) - projects3 += CodeliteIntegrationGenerator.codelite_projects2_template.format( - name = module, - config = 'Release' - ) - xml = CodeliteIntegrationGenerator.codelite_workspace_template.format( - projects1, - projects2, - projects3 - ) - return xml - - - codelite_workspace_template = """<?xml version="1.0" encoding="UTF-8"?> -<CodeLite_Workspace Name="lo" Database="" SWTLW="Yes"> - <WorkspaceParserMacros/> - <WorkspaceParserPaths> - <Include Path="${{WorkspacePath}}/include"/> - </WorkspaceParserPaths> - {0} - <BuildMatrix> - <WorkspaceConfiguration Name="Debug" Selected="yes"> - <Environment/> - {1} - </WorkspaceConfiguration> - <WorkspaceConfiguration Name="Release" Selected="yes"> - <Environment/> - {2} - </WorkspaceConfiguration> - </BuildMatrix> -</CodeLite_Workspace> -""" - codelite_projects1_template = """<Project Name="{name}" Path="{name}/{name}.project" Active="No"/> -""" - - codelite_projects2_template = """<Project Name="{name}" ConfigName="{config}"/> -""" - def get_options(): parser = argparse.ArgumentParser( description='LibreOffice gbuild IDE project generator') @@ -2191,35 +1631,24 @@ def get_options(): help='the IDE to generate project files for') parser.add_argument('--make', dest='makecmd', required=True, help='the command to execute make') - #add to debug a new functions in the project keeping contributors - parser.add_argument('--debug',dest='debug',required=False, - help='debug the new functions') return parser.parse_args() - if __name__ == '__main__': args = get_options() # FIXME: Hack if args.makecmd == 'make': args.makecmd = '/usr/bin/make' - if args.debug=='test': - pass paths = {} generators = { - # Supported platforms - 'xcode': XcodeIntegrationGenerator, - 'debug': DebugIntegrationGenerator, - 'testIde': testVS2013Ide, - - # Old platforms 'eclipsecdt': EclipseCDTIntegrationGenerator, 'kdevelop': KdevelopIntegrationGenerator, + 'xcode': XcodeIntegrationGenerator, 'vs2015': VisualStudioIntegrationGenerator, 'vim': VimIntegrationGenerator, + 'debug': DebugIntegrationGenerator, 'qtcreator': QtCreatorIntegrationGenerator, - 'codelite' : CodeliteIntegrationGenerator, } if args.ide not in generators.keys(): diff --git a/bin/gbuild-to-ideNS b/bin/gbuild-to-ideNS deleted file mode 100755 index abf7c7c572bb..000000000000 --- a/bin/gbuild-to-ideNS +++ /dev/null @@ -1,1667 +0,0 @@ -#! /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, location, include, include_sys, defs, cxxobjects, cxxflags, linked_libs): - GbuildLinkTarget.__init__(self, name, location, include, include_sys, defs, cxxobjects, cxxflags, linked_libs) - - 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.name - - def library_name(self): - return self.name - -class GbuildTest(GbuildLinkTarget): - def __init__(self, name, location, include, include_sys, defs, cxxobjects, cxxflags, linked_libs): - GbuildLinkTarget.__init__(self, name, location, include, include_sys, defs, cxxobjects, cxxflags, linked_libs) - - 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.name - -class GbuildExe(GbuildLinkTarget): - def __init__(self, name, location, include, include_sys, defs, cxxobjects, cxxflags, linked_libs): - GbuildLinkTarget.__init__(self, name, location, include, include_sys, defs, cxxobjects, cxxflags, linked_libs) - - 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.name - - -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.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: - dparts = d.split(' -U') - """after dparts.pop(0), dparts will contain only undefs""" - defparts = dparts.pop(0).strip().split('=') - if len(defparts) == 1: - defparts.append(None) - defs[defparts[0]] = defparts[1] - """Drop undefed items (if any) from previous defs""" - for u in dparts: - defs.pop(u.strip(), '') - 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), - 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, - 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), - 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.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.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.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 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) | set(self.gbuildparser.exes): - 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.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.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 = {'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.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.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('Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{B9292527-A979-4D13-A598-C75A33222174}"\n') - f.write('\tProjectSection(SolutionItems) = preProject\n') - f.write('\t\tsolenv/vs/LibreOffice.natvis = solenv/vs/LibreOffice.natvis\n') - 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('') - - @staticmethod - def defs_list(defs): - defines_list = [] - # List defines - for key, value in defs.items(): - define = key - if value is not None: - define += '=' + value - defines_list.append(define) - return defines_list - - 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(self.defs_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.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 -""" - - -def get_options(): - 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') - return parser.parse_args() - - -if __name__ == '__main__': - args = get_options() - # FIXME: Hack - if args.makecmd == 'make': - args.makecmd = '/usr/bin/make' - - paths = {} - generators = { - 'eclipsecdt': EclipseCDTIntegrationGenerator, - 'kdevelop': KdevelopIntegrationGenerator, - 'xcode': XcodeIntegrationGenerator, - '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: |