summaryrefslogtreecommitdiff
path: root/bin/gbuild-to-ide
diff options
context:
space:
mode:
Diffstat (limited to 'bin/gbuild-to-ide')
-rwxr-xr-xbin/gbuild-to-ide638
1 files changed, 318 insertions, 320 deletions
diff --git a/bin/gbuild-to-ide b/bin/gbuild-to-ide
index bba9a9896b8a..ef1e27dd6748 100755
--- a/bin/gbuild-to-ide
+++ b/bin/gbuild-to-ide
@@ -23,94 +23,23 @@ import traceback
import subprocess
from sys import platform
import collections
+import urllib.parse
class GbuildLinkTarget:
- def __init__(self, name, location, include, include_sys, defs, cxxobjects, cxxflags, cobjects, cflags, linked_libs):
- (self.name, self.location, self.include, self.include_sys, self.defs, self.cxxobjects, self.cxxflags, self.cobjects, self.cflags, self.linked_libs) = (
- name, location, include, include_sys, defs, cxxobjects, cxxflags, cobjects, cflags, 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.cobjects 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, cobjects: %s, cflags: %s and linked libs: %s' % (
- self.short_name(), self.location, self.include, self.include_sys, self.defs, self.cxxobjects,
- self.cxxflags, self.cobjects, self.cflags, self.linked_libs)
-
-
-class GbuildLib(GbuildLinkTarget):
- def __init__(self, name, location, include, include_sys, defs, cxxobjects, cxxflags, cobjects, cflags, linked_libs):
- GbuildLinkTarget.__init__(self, name, location, include, include_sys, defs, cxxobjects, cxxflags, cobjects, cflags, 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, cobjects, cflags, linked_libs):
- GbuildLinkTarget.__init__(self, name, location, include, include_sys, defs, cxxobjects, cxxflags, cobjects, cflags, 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, cobjects, cflags, linked_libs):
- GbuildLinkTarget.__init__(self, name, location, include, include_sys, defs, cxxobjects, cxxflags, cobjects, cflags, 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:
- """Main data model object.
-
- Attributes:
- target_by_path : dict[path:string, set(target)]
- where target is one of the GbuildLinkTarget subclasses
- target_by_location : dict[path:string, set(target)]
- where target is one of the GbuildLinkTarget subclasses
- """
- 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(r'-I(\S+)')
isystempattern = re.compile(r'-isystem\s*(\S+)')
warningpattern = re.compile(r'-W\S+')
- libpattern = re.compile(r'Library_(.*)\.mk')
- exepattern = re.compile(r'Executable_(.*)\.mk')
- testpattern = re.compile(r'CppunitTest_(.*)\.mk')
@staticmethod
def __split_includes(includes):
- foundisystem = GbuildParser.isystempattern.findall(includes)
- foundincludes = [includeswitch.strip() for includeswitch in GbuildParser.includepattern.findall(includes) if
+ foundisystem = GbuildLinkTarget.isystempattern.findall(includes)
+ foundincludes = [includeswitch.strip() for includeswitch in GbuildLinkTarget.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 != 'COBJECTS' and obj != '+=']
+ return [obj for obj in objsline.strip().split(' ') if obj not in { '', 'CXXOBJECTS', 'COBJECTS', 'OBJCXXOBJECTS', 'CXXCLROBJECTS', '+=' }]
@staticmethod
def __split_defs(defsline):
@@ -131,75 +60,91 @@ class GbuildParser:
@staticmethod
def __split_flags(flagsline, flagslineappend):
- return [cxxflag.strip() for cxxflag in GbuildParser.warningpattern.sub('', '%s %s' % (flagsline, flagslineappend)).split(' ') if len(cxxflag) > 1]
+ return [cxxflag.strip() for cxxflag in GbuildLinkTarget.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),
+ def __init__(self, json):
+ (foundincludes, foundisystem) = GbuildLinkTarget.__split_includes(json['INCLUDE'])
+ (self.name, self.location, self.include, self.include_sys, self.defs, self.cxxobjects, self.objcxxobjects, self.cxxflags, self.cobjects, self.cflags, self.cxxclrobjects, self.cxxclrflags, self.linked_libs, self.linked_static_libs, self.link_target) = (
+ type(self).targetpattern.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']),
- GbuildParser.__split_objs(json['COBJECTS']),
- GbuildParser.__split_flags(json['CFLAGS'], json['CFLAGSAPPEND']),
- json['LINKED_LIBS'].strip().split(' '))
+ GbuildLinkTarget.__split_defs(json['DEFS']),
+ GbuildLinkTarget.__split_objs(json['CXXOBJECTS']),
+ GbuildLinkTarget.__split_objs(json['OBJCXXOBJECTS']),
+ GbuildLinkTarget.__split_flags(json['CXXFLAGS'], json['CXXFLAGSAPPEND']),
+ GbuildLinkTarget.__split_objs(json['COBJECTS']),
+ GbuildLinkTarget.__split_flags(json['CFLAGS'], json['CFLAGSAPPEND']),
+ GbuildLinkTarget.__split_objs(json['CXXCLROBJECTS']),
+ GbuildLinkTarget.__split_flags(json['CXXCLRFLAGS'], json['CXXCLRFLAGSAPPEND']),
+ json['LINKED_LIBS'].strip().split(' '),
+ json['LINKED_STATIC_LIBS'].strip().split(' '),
+ json['LINKTARGET'].strip())
- @staticmethod
- def __test_from_json(json):
- (foundincludes, foundisystem) = GbuildParser.__split_includes(json['INCLUDE'])
- testname_match = GbuildParser.testpattern.match(os.path.basename(json['MAKEFILE']))
+ def short_name(self):
+ """Return the short name of target based on the Foo_* makefile name"""
+ return '%s %s' % (type(self).targetprefix, self.name)
- # Workaround strange writer test makefile setup
- if testname_match is None:
- testname = "StrangeWriterMakefiles"
- else:
- testname = testname_match.group(1)
+ def target_name(self):
+ return '%s_%s' % (type(self).targetprefix, self.name)
- 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']),
- GbuildParser.__split_objs(json['COBJECTS']),
- GbuildParser.__split_flags(json['CFLAGS'], json['CFLAGSAPPEND']),
- json['LINKED_LIBS'].strip().split(' '))
+ def __str__(self):
+ return '%s at %s with include path: %s, isystem includes: %s, defines: %s, objects: %s, cxxflags: %s, cobjects: %s, cflags: %s, linked libs: %s and linked static libs: %s' % (
+ self.short_name(), self.location, self.include, self.include_sys, self.defs, self.cxxobjects,
+ self.cxxflags, self.cobjects, self.cflags, self.linked_libs, self.linked_static_libs)
- @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']),
- GbuildParser.__split_objs(json['COBJECTS']),
- GbuildParser.__split_flags(json['CFLAGS'], json['CFLAGSAPPEND']),
- json['LINKED_LIBS'].strip().split(' '))
+
+class GbuildLib(GbuildLinkTarget):
+ targetpattern = re.compile(r'Library_(.*)\.mk')
+ targetprefix = "Library"
+
+class GbuildStaticLib(GbuildLinkTarget):
+ targetpattern = re.compile(r'StaticLibrary_(.*)\.mk')
+ targetprefix = "StaticLibrary"
+
+class GbuildTest(GbuildLinkTarget):
+ targetpattern = re.compile(r'CppunitTest_(.*)\.mk')
+ targetprefix = "CppunitTest"
+
+class GbuildExe(GbuildLinkTarget):
+ targetpattern = re.compile(r'Executable_(.*)\.mk')
+ targetprefix = "Executable"
+
+
+class GbuildParser:
+ """Main data model object.
+
+ Attributes:
+ target_by_path : dict[path:string, set(target)]
+ where target is one of the GbuildLinkTarget subclasses
+ target_by_location : dict[path:string, set(target)]
+ where target is one of the GbuildLinkTarget subclasses
+ """
+ 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.static_libs, self.exes, self.tests, self.modulenamelist) = (set(), set(), set(), set(), [])
+ (self.target_by_path, self.target_by_location) = ({}, {})
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)
+ lib = GbuildLib(json.load(f))
+ self.libs.add(lib)
+ for jsonfilename in os.listdir(os.path.join(self.workdir, 'GbuildToJson', 'StaticLibrary')):
+ with open(os.path.join(self.workdir, 'GbuildToJson', 'StaticLibrary', jsonfilename), 'r') as f:
+ static_lib = GbuildStaticLib(json.load(f))
+ self.static_libs.add(static_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)
+ exe = GbuildExe(json.load(f))
+ self.exes.add(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):
+ test = GbuildTest(json.load(f))
+ self.tests.add(test)
+ for target in self.libs | self.static_libs | self.exes | 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])
@@ -303,7 +248,7 @@ class EclipseCDTIntegrationGenerator(IdeIntegrationGenerator):
</language>
</section>
</cdtprojectproperties>
-"""
+"""
for module in self.gbuildparser.modulenamelist:
tempxml = []
@@ -328,7 +273,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)
@@ -343,7 +288,7 @@ class EclipseCDTIntegrationGenerator(IdeIntegrationGenerator):
def emit(self):
self.create_include_paths()
self.create_macros()
- self.create_settings_file()
+ self.create_settings_file()
class CodeliteIntegrationGenerator(IdeIntegrationGenerator):
@@ -353,22 +298,26 @@ class CodeliteIntegrationGenerator(IdeIntegrationGenerator):
def emit(self):
self.create_workspace_file()
for module in self.gbuildparser.modulenamelist:
- self.create_project_file(module)
+ if os.path.exists(module): # ignore external modules
+ self.create_project_file(module)
#self.create_project_file('vcl')
def create_workspace_file(self):
root_node = ET.Element('CodeLite_Workspace', Name='libo2', Database='./libo2.tags', Version='10.0.0')
for module in self.gbuildparser.modulenamelist:
- ET.SubElement(root_node, 'Project', Name=module, Path='%s/%s.project' % (module, module), Active='No')
+ if os.path.exists(module): # ignore external modules
+ ET.SubElement(root_node, 'Project', Name=module, Path='%s/%s.project' % (module, module), Active='No')
build_matrix_node = ET.SubElement(root_node, 'BuildMatrix')
workspace_config_node = ET.SubElement(build_matrix_node, 'WorkspaceConfiguration', Name='Debug', Selected='yes')
ET.SubElement(workspace_config_node, 'Environment')
for module in self.gbuildparser.modulenamelist:
- ET.SubElement(workspace_config_node, 'Project', Name=module, ConfigName='Debug')
+ if os.path.exists(module): # ignore external modules
+ ET.SubElement(workspace_config_node, 'Project', Name=module, ConfigName='Debug')
workspace_config_node = ET.SubElement(build_matrix_node, 'WorkspaceConfiguration', Name='Release', Selected='yes')
ET.SubElement(workspace_config_node, 'Environment')
for module in self.gbuildparser.modulenamelist:
- ET.SubElement(workspace_config_node, 'Project', Name=module, ConfigName='Release')
+ if os.path.exists(module): # ignore external modules
+ ET.SubElement(workspace_config_node, 'Project', Name=module, ConfigName='Release')
self.write_pretty_xml(root_node, os.path.join(self.gbuildparser.builddir, 'libo2.workspace'))
@@ -386,7 +335,7 @@ class CodeliteIntegrationGenerator(IdeIntegrationGenerator):
path = '/'.join(file.split('/')[1:-1])
virtual_dirs[path].add(relative_file + '.cxx')
# add HXX files
- all_libs = set(self.gbuildparser.libs) | set(self.gbuildparser.exes)
+ all_libs = self.gbuildparser.libs | self.gbuildparser.exes
for lib in all_libs:
if lib.name == module_name:
for hdir in lib.include:
@@ -541,14 +490,14 @@ class VimIntegrationGenerator(IdeIntegrationGenerator):
def emit(self):
global_list = []
- for lib in set(self.gbuildparser.libs) | set(self.gbuildparser.tests) | set(self.gbuildparser.exes):
+ for lib in self.gbuildparser.libs | self.gbuildparser.tests | 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)
- with open('compile_commands.json', 'w') as export_file:
+ with open(os.path.join(self.gbuildparser.builddir, 'compile_commands.json'), 'w') as export_file:
json.dump(global_list, export_file)
def generateCommand(self, lib, file):
@@ -916,7 +865,7 @@ class VisualStudioIntegrationGenerator(IdeIntegrationGenerator):
def __init__(self, gbuildparser, ide):
IdeIntegrationGenerator.__init__(self, gbuildparser, ide)
- self.toolset = self.retrieve_toolset(ide)
+ self.toolset = os.environ['VCTOOLSET']
self.solution_directory = self.gbuildparser.builddir
self.configurations = {
'Build': {
@@ -936,10 +885,6 @@ class VisualStudioIntegrationGenerator(IdeIntegrationGenerator):
}
}
- def retrieve_toolset(self, ide):
- ide_toolset_map = {'vs2017': 'v141', 'vs2019': 'v142'}
- 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 + '"'
@@ -950,13 +895,21 @@ class VisualStudioIntegrationGenerator(IdeIntegrationGenerator):
self.target = target
self.path = project_path
+ # Check if the target is empty (no source files would be added to project file)
+ @staticmethod
+ def should_skip(target):
+ return not target.cxxobjects and not target.cxxclrobjects and not target.cobjects
+
def emit(self):
all_projects = []
- for location in self.gbuildparser.target_by_location:
+ for location, targets in self.gbuildparser.target_by_location.items():
projects = []
module = location.split('/')[-1]
module_directory = os.path.join(self.solution_directory, module)
- for target in self.gbuildparser.target_by_location[location]:
+ for target in targets:
+ if self.should_skip(target):
+ print(' %s: no files to add, skipping' % target.target_name())
+ continue
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)
@@ -965,20 +918,34 @@ class VisualStudioIntegrationGenerator(IdeIntegrationGenerator):
all_projects += projects
self.write_solution(os.path.join(self.solution_directory, 'LibreOffice.sln'), all_projects)
+ # this enables Python GDB pretty printers when debugging a WSL Linux build from VS
+ MIEngine_options_path = os.path.join(gbuildparser.srcdir, 'solenv/vs/Microsoft.MIEngine.Options.xml')
+ shutil.copy(MIEngine_options_path, self.solution_directory)
+
+ @staticmethod
+ def gen_guid(category, name):
+ return str(uuid.uuid5(uuid.NAMESPACE_URL, 'vnd.libreoffice.vs-ide-integration:' + category + '/' + urllib.parse.quote(name))).upper()
nmake_project_guid = '8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942'
+ nmake_folder_guid = '2150E333-8FDC-42A3-9474-1A3956D46DE8'
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:
+ if library_project.target.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='')
+ if not projects:
+ print(' no projects, skipping')
+ return
library_projects = [project for project in projects if project.target in self.gbuildparser.libs]
+ static_library_projects = [project for project in projects if project.target in self.gbuildparser.static_libs]
+ test_projects = [project for project in projects if project.target in self.gbuildparser.tests]
+ executable_projects = [project for project in projects if project.target in self.gbuildparser.exes]
with open(solution_path, 'w') as f:
f.write('Microsoft Visual Studio Solution File, Format Version 12.00\n')
for project in projects:
@@ -990,25 +957,61 @@ class VisualStudioIntegrationGenerator(IdeIntegrationGenerator):
target.short_name(), proj_path, project.guid))
libs_in_solution = self.get_dependency_libs(target.linked_libs,
library_projects)
+ libs_in_solution |= self.get_dependency_libs(target.linked_static_libs,
+ static_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('Project("{%s}") = "Utility", "Utility", "{6778240E-8B6B-47A0-AC31-7E7A257B97E6}"\n' %
+ (VisualStudioIntegrationGenerator.nmake_folder_guid))
f.write('\tProjectSection(SolutionItems) = preProject\n')
# The natvis file gives pretty-printed variable values when debugging
natvis_path = os.path.join(gbuildparser.srcdir, 'solenv/vs/LibreOffice.natvis')
f.write('\t\t%(natvis)s = %(natvis)s\n' % {'natvis': natvis_path})
+ # The natstepfilter file allows to skip specific functions when stepping into in debugging
+ natstepfilter_path = os.path.join(gbuildparser.srcdir, 'solenv/vs/LibreOffice.natstepfilter')
+ f.write('\t\t%(natstepfilter)s = %(natstepfilter)s\n' % {'natstepfilter': natstepfilter_path})
f.write('\tEndProjectSection\n')
f.write('EndProject\n')
+ # Folders to group tests/libraries/executables
+ nmake_tests_guid = 'CF544F7B-9D02-4D83-8370-5887851209B7'
+ nmake_libraries_guid = 'C624F43D-616C-4627-B58F-F5C2047B7BDC'
+ nmake_static_libraries_guid = 'EB2CD1D4-7C29-4232-9B1E-9FB1FE62D61C'
+ nmake_executables_guid = '1CD80999-9FA9-4BA9-B4D9-6E33035CF648'
+ f.write('Project("{%s}") = "Tests", "Tests", "{%s}"\n' %
+ (VisualStudioIntegrationGenerator.nmake_folder_guid, nmake_tests_guid))
+ f.write('EndProject\n')
+ f.write('Project("{%s}") = "Libraries", "Libraries", "{%s}"\n' %
+ (VisualStudioIntegrationGenerator.nmake_folder_guid, nmake_libraries_guid))
+ f.write('EndProject\n')
+ f.write('Project("{%s}") = "StaticLibraries", "StaticLibraries", "{%s}"\n' %
+ (VisualStudioIntegrationGenerator.nmake_folder_guid, nmake_static_libraries_guid))
+ f.write('EndProject\n')
+ f.write('Project("{%s}") = "Executables", "Executables", "{%s}"\n' %
+ (VisualStudioIntegrationGenerator.nmake_folder_guid, nmake_executables_guid))
+ f.write('EndProject\n')
+ # end Folders to group tests/libraries/executables
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')
+ # Group projects to folders
+ f.write('\tGlobalSection(NestedProjects) = preSolution\n')
+ for project in test_projects:
+ f.write('\t\t{%s} = {%s}\n' % (project.guid, nmake_tests_guid))
+ for project in library_projects:
+ f.write('\t\t{%s} = {%s}\n' % (project.guid, nmake_libraries_guid))
+ for project in static_library_projects:
+ f.write('\t\t{%s} = {%s}\n' % (project.guid, nmake_static_libraries_guid))
+ for project in executable_projects:
+ f.write('\t\t{%s} = {%s}\n' % (project.guid, nmake_executables_guid))
+ f.write('\tEndGlobalSection\n')
+ # end Group projects to folders
f.write('\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\n')
# Specifies project configurations for solution configuration
for project in projects:
@@ -1038,67 +1041,82 @@ class VisualStudioIntegrationGenerator(IdeIntegrationGenerator):
for key, value in defs.items():
define = key
if value is not None:
- define += '=' + VisualStudioIntegrationGenerator.escapepattern.sub(r'\1', value)
+ define += '=' + VisualStudioIntegrationGenerator.escapepattern.sub(r'\1', value).replace('""', '"')
defines_list.append(define)
return defines_list
+ ns = 'http://schemas.microsoft.com/developer/msbuild/2003'
+
+ @classmethod
+ def add_objects(cls, objects, root_path, ext, target, parent_node, flags = ''):
+ for obj in objects:
+ objfile = os.path.join(root_path, obj) + ext
+ if os.path.isfile(objfile):
+ obj_node = ET.SubElement(parent_node, '{%s}ClCompile' % cls.ns, Include=objfile)
+ if flags:
+ obj_additional_options_node = ET.SubElement(obj_node, '{%s}AdditionalOptions' % cls.ns)
+ obj_additional_options_node.text = flags
+ else:
+ print('Source %s in project %s does not exist' % (objfile, target.target_name()))
+
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()
+ project_guid = self.gen_guid('project', target.short_name())
cxxflags = ' '.join(target.cxxflags)
- 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')
+ cxxclrflags = ' '.join(target.cxxclrflags)
+ cflags = ' '.join(target.cflags)
+ ET.register_namespace('', self.ns)
+ proj_node = ET.Element('{%s}Project' % self.ns, DefaultTargets='Build', ToolsVersion='4.0')
+ proj_confs_node = ET.SubElement(proj_node, '{%s}ItemGroup' % self.ns, Label='ProjectConfigurations')
platform = 'Win32'
for configuration in self.configurations:
proj_conf_node = ET.SubElement(proj_confs_node,
- '{%s}ProjectConfiguration' % ns,
+ '{%s}ProjectConfiguration' % self.ns,
Include='%s|%s' % (configuration, platform))
- conf_node = ET.SubElement(proj_conf_node, '{%s}Configuration' % ns)
+ conf_node = ET.SubElement(proj_conf_node, '{%s}Configuration' % self.ns)
conf_node.text = configuration
- platform_node = ET.SubElement(proj_conf_node, '{%s}Platform' % ns)
+ platform_node = ET.SubElement(proj_conf_node, '{%s}Platform' % self.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)
+ globals_node = ET.SubElement(proj_node, '{%s}PropertyGroup' % self.ns, Label='Globals')
+ proj_guid_node = ET.SubElement(globals_node, '{%s}ProjectGuid' % self.ns)
proj_guid_node.text = '{%s}' % project_guid
- proj_keyword_node = ET.SubElement(globals_node, '{%s}Keyword' % ns)
+ proj_keyword_node = ET.SubElement(globals_node, '{%s}Keyword' % self.ns)
proj_keyword_node.text = 'MakeFileProj'
- proj_name_node = ET.SubElement(globals_node, '{%s}ProjectName' % ns)
+ proj_name_node = ET.SubElement(globals_node, '{%s}ProjectName' % self.ns)
proj_name_node.text = target.short_name()
- ET.SubElement(proj_node, '{%s}Import' % ns, Project='$(VCTargetsPath)\\Microsoft.Cpp.Default.props')
+ ET.SubElement(proj_node, '{%s}Import' % self.ns, Project='$(VCTargetsPath)\\Microsoft.Cpp.Default.props')
for configuration in self.configurations:
- conf_node = ET.SubElement(proj_node, '{%s}PropertyGroup' % ns, Label="Configuration",
+ conf_node = ET.SubElement(proj_node, '{%s}PropertyGroup' % self.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 = ET.SubElement(conf_node, '{%s}ConfigurationType' % self.ns)
conf_type_node.text = 'Makefile'
# This defines the version of Visual Studio which can show next to project names in the Solution Explorer
- platform_toolset_node = ET.SubElement(conf_node, '{%s}PlatformToolset' % ns)
+ platform_toolset_node = ET.SubElement(conf_node, '{%s}PlatformToolset' % self.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')
+ ET.SubElement(proj_node, '{%s}Import' % self.ns, Project='$(VCTargetsPath)\\Microsoft.Cpp.props')
+ ET.SubElement(proj_node, '{%s}ImportGroup' % self.ns, Label='ExtensionSettings')
for configuration in self.configurations:
- prop_sheets_node = ET.SubElement(proj_node, '{%s}ImportGroup' % ns, Label='Configuration',
+ prop_sheets_node = ET.SubElement(proj_node, '{%s}ImportGroup' % self.ns, Label='Configuration',
Condition="'$(Configuration)|$(Platform)'=='%s|%s'" % (configuration, platform))
- ET.SubElement(prop_sheets_node, '{%s}Import' % ns,
+ ET.SubElement(prop_sheets_node, '{%s}Import' % self.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')
+ ET.SubElement(proj_node, '{%s}PropertyGroup' % self.ns, Label='UserMacros')
# VS IDE (at least "Peek definition") is allergic to paths like "C:/PROGRA~2/WI3CF2~1/10/Include/10.0.14393.0/um"; see
# https://developercommunity.visualstudio.com/content/problem/139659/vc-peek-definition-fails-to-navigate-to-windows-ki.html
# We need to convert to long paths here. Do this once, since it's time-consuming operation.
include_path_node_text = ';'.join(self.to_long_names(target.include))
for cfg_name, cfg_targets in self.configurations.items():
- conf_node = ET.SubElement(proj_node, '{%s}PropertyGroup' % ns,
+ conf_node = ET.SubElement(proj_node, '{%s}PropertyGroup' % self.ns,
Condition="'$(Configuration)|$(Platform)'=='%s|%s'" % (cfg_name, platform))
nmake_params = {
'sh': os.path.join(self.gbuildparser.binpath, 'dash.exe'),
@@ -1106,64 +1124,41 @@ class VisualStudioIntegrationGenerator(IdeIntegrationGenerator):
'location': target.location,
'makecmd': self.gbuildparser.makecmd,
'target': target.target_name()}
- nmake_build_node = ET.SubElement(conf_node, '{%s}NMakeBuildCommandLine' % ns)
+ nmake_build_node = ET.SubElement(conf_node, '{%s}NMakeBuildCommandLine' % self.ns)
nmake_build_node.text = cfg_targets['build'] % nmake_params
- nmake_clean_node = ET.SubElement(conf_node, '{%s}NMakeCleanCommandLine' % ns)
+ nmake_clean_node = ET.SubElement(conf_node, '{%s}NMakeCleanCommandLine' % self.ns)
nmake_clean_node.text = cfg_targets['clean'] % nmake_params
- nmake_rebuild_node = ET.SubElement(conf_node, '{%s}NMakeReBuildCommandLine' % ns)
+ nmake_rebuild_node = ET.SubElement(conf_node, '{%s}NMakeReBuildCommandLine' % self.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.bin')
- nmake_defs_node = ET.SubElement(conf_node, '{%s}NMakePreprocessorDefinitions' % ns)
+ nmake_output_node = ET.SubElement(conf_node, '{%s}NMakeOutput' % self.ns)
+ nmake_output_node.text = os.path.join(self.gbuildparser.workdir, 'LinkTarget', target.link_target)
+ nmake_defs_node = ET.SubElement(conf_node, '{%s}NMakePreprocessorDefinitions' % self.ns)
nmake_defs_node.text = ';'.join(self.defs_list(target.defs) + ['$(NMakePreprocessorDefinitions)'])
- include_path_node = ET.SubElement(conf_node, '{%s}IncludePath' % ns)
+ nmake_debug_command_node = ET.SubElement(conf_node, '{%s}LocalDebuggerCommand' % self.ns)
+ nmake_debug_command_node.text = os.path.join(self.gbuildparser.instdir, 'program', 'soffice.bin')
+ nmake_debug_flavor_node = ET.SubElement(conf_node, '{%s}DebuggerFlavor' % self.ns)
+ nmake_debug_flavor_node.text = 'WindowsLocalDebugger'
+ include_path_node = ET.SubElement(conf_node, '{%s}IncludePath' % self.ns)
include_path_node.text = include_path_node_text
- additional_options_node = ET.SubElement(conf_node, '{%s}AdditionalOptions' % ns)
+ additional_options_node = ET.SubElement(conf_node, '{%s}AdditionalOptions' % self.ns)
additional_options_node.text = cxxflags
- ET.SubElement(proj_node, '{%s}ItemDefinitionGroup' % ns)
+ ET.SubElement(proj_node, '{%s}ItemDefinitionGroup' % self.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()))
-
- cobjects_node = ET.SubElement(proj_node, '{%s}ItemGroup' % ns)
- for cobject in target.cobjects:
- cabspath = os.path.join(self.gbuildparser.srcdir, cobject)
- cfile = cabspath + '.c'
- if os.path.isfile(cfile):
- ET.SubElement(cobjects_node, '{%s}ClCompile' % ns, Include=cfile)
- else:
- print('Source %s in project %s does not exist' % (cfile, 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)
- for cobject in target.cobjects:
- include_abs_path = os.path.join(self.gbuildparser.srcdir, cobject)
- 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')
+ cxxobjects_node = ET.SubElement(proj_node, '{%s}ItemGroup' % self.ns)
+ self.add_objects(target.cxxobjects, self.gbuildparser.srcdir, '.cxx', target, cxxobjects_node)
+ self.add_objects(target.cxxclrobjects, self.gbuildparser.srcdir, '.cxx', target, cxxobjects_node, cxxclrflags)
+
+ cobjects_node = ET.SubElement(proj_node, '{%s}ItemGroup' % self.ns)
+ self.add_objects(target.cobjects, self.gbuildparser.srcdir, '.c', target, cobjects_node, cflags)
+
+ ET.SubElement(proj_node, '{%s}Import' % self.ns, Project='$(VCTargetsPath)\\Microsoft.Cpp.targets')
+ ET.SubElement(proj_node, '{%s}ImportGroup' % self.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)],
- [c_node.get('Include') for c_node in cobjects_node.findall('{%s}ClCompile' % ns)],
- [include_node.get('Include') for include_node in includes_node.findall('{%s}ClInclude' % ns)])
+ [cxx_node.get('Include') for cxx_node in cxxobjects_node.findall('{%s}ClCompile' % self.ns)],
+ [c_node.get('Include') for c_node in cobjects_node.findall('{%s}ClCompile' % self.ns)])
return project_guid
def get_filter(self, module_dir, proj_file):
@@ -1183,33 +1178,27 @@ class VisualStudioIntegrationGenerator(IdeIntegrationGenerator):
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 = ET.SubElement(file_node, '{%s}Filter' % self.ns)
filter_node.text = project_filter
filters |= self.get_subfilters(project_filter)
return filters
- def write_filters(self, filters_path, module_dir, cxx_files, c_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')
+ def write_filters(self, filters_path, module_dir, cxx_files, c_files):
+ ET.register_namespace('', self.ns)
+ proj_node = ET.Element('{%s}Project' % self.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, cxx_files)
- filters |= self.add_nodes(compiles_node, module_dir, '{%s}ClCompile' % ns, c_files)
- include_node = ET.SubElement(proj_node, '{%s}ItemGroup' % ns)
- filters |= self.add_nodes(include_node, module_dir, '{%s}ClInclude' % ns, include_files)
+ compiles_node = ET.SubElement(proj_node, '{%s}ItemGroup' % self.ns)
+ filters |= self.add_nodes(compiles_node, module_dir, '{%s}ClCompile' % self.ns, cxx_files)
+ filters |= self.add_nodes(compiles_node, module_dir, '{%s}ClCompile' % self.ns, c_files)
- filters_node = ET.SubElement(proj_node, '{%s}ItemGroup' % ns)
+ filters_node = ET.SubElement(proj_node, '{%s}ItemGroup' % self.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())
+ filter_node = ET.SubElement(filters_node, '{%s}Filter' % self.ns, Include=proj_filter)
self.write_pretty_xml(proj_node, filters_path)
@@ -1218,7 +1207,7 @@ 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) | set(self.gbuildparser.tests):
+ for target in self.gbuildparser.libs | self.gbuildparser.exes | self.gbuildparser.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])
@@ -1287,7 +1276,7 @@ class QtCreatorIntegrationGenerator(IdeIntegrationGenerator):
xml += QtCreatorIntegrationGenerator.build_configs_template % {
'index': '7',
'base_folder': self.base_folder,
- 'arg': "build-nocheck",
+ 'arg': "",
'name': "8-Global build -- nocheck",
}
xml += QtCreatorIntegrationGenerator.build_configs_template % {
@@ -1346,7 +1335,7 @@ class QtCreatorIntegrationGenerator(IdeIntegrationGenerator):
xml += QtCreatorIntegrationGenerator.build_configs_template % {
'index': '6',
'base_folder': self.base_folder,
- 'arg': "build-nocheck",
+ 'arg': "",
'name': "07-Global build -- nocheck",
}
xml += QtCreatorIntegrationGenerator.build_configs_template % {
@@ -1384,14 +1373,12 @@ class QtCreatorIntegrationGenerator(IdeIntegrationGenerator):
}
return xml
- # By default, QtCreator creates 2 BuildStepList : "Build" et "Clean"
+ # By default, QtCreator creates 2 BuildStepList : "Build" and "Clean"
# but the "clean" can be empty.
build_configs_template = """
- <valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.%(index)s">
+ <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>
@@ -1405,18 +1392,15 @@ class QtCreatorIntegrationGenerator(IdeIntegrationGenerator):
<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.DisplayName">%(name)s</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>
@@ -1450,9 +1434,10 @@ class QtCreatorIntegrationGenerator(IdeIntegrationGenerator):
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
+ if platform == 'darwin':
+ loexec = "%s/instdir/LibreOfficeDev.app/Contents/MacOS/soffice" % self.base_folder
+ else:
+ loexec = "%s/instdir/program/soffice.bin" % self.base_folder
xml = QtCreatorIntegrationGenerator.run_configs_template % {
'loexec': loexec,
'workdir': self.base_folder
@@ -1516,33 +1501,33 @@ class QtCreatorIntegrationGenerator(IdeIntegrationGenerator):
<value type="int" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
"""
- def generate_pro_user_content(self, lib_folder):
+ def generate_pro_shared_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 % {
+ xml = QtCreatorIntegrationGenerator.pro_shared_template % {
'build_configs': build_configs,
'deploy_configs': deploy_configs,
'run_configs': run_configs,
}
return xml
- def generate_meta_pro_user_content(self):
+ def generate_meta_pro_shared_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 % {
+ xml = QtCreatorIntegrationGenerator.pro_shared_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"?>
+ pro_shared_template = """<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QtCreatorProject>
<!-- Written by QtCreator 3.1.1, 2015-05-14T15:54:34. -->
<qtcreator>
@@ -1640,59 +1625,44 @@ class QtCreatorIntegrationGenerator(IdeIntegrationGenerator):
</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
+ def get_file_path(self, src_file, ext_choices):
+ path = os.path.join(self.gbuildparser.srcdir, src_file)
+ for ext in ext_choices:
+ full_path = path + ext
+ if os.path.isfile(full_path):
+ return full_path
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 get_source_path(self, src_file):
+ return self.get_file_path(src_file, (".cxx", ".cpp", ".c", ".mm"))
+
+ def get_header_path(self, src_file):
+ return self.get_file_path(src_file, (".hxx", ".hpp", ".h"))
def build_data_libs(self):
self.data_libs = {}
- all_libs = set(self.gbuildparser.libs) | set(self.gbuildparser.exes) | set(self.gbuildparser.tests)
+ all_libs = self.gbuildparser.libs | self.gbuildparser.exes | self.gbuildparser.tests
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):
- if platform =="cygwin":
+ if platform == "cygwin":
# absolute paths from GbuildToJson are Windows paths,
# so convert everything to such ones
abs_path = path
if not ntpath.isabs(abs_path):
abs_path = ntpath.join(self.gbuildparser.srcdir, path)
- return ntpath.relpath(abs_path, lib.location).replace('\\', '/')
+ return abs_path.replace('\\', '/')
- return os.path.relpath(path, lib.location)
+ return os.path.abspath(path)
defines_list = []
sources_list = []
+ objcxx_sources_list = []
includepath_list = []
# The explicit headers list is not mandatory :
# QtCreator just needs 'include_path_list' to find all headers files.
@@ -1700,23 +1670,35 @@ 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 = []
+ objcxx_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))
+ path = self.get_source_path(file_)
+ if path:
+ sources_list.append(lopath(path))
# few cxxobject files have a header beside
- ext = self.get_header_extension(file_)
- if ext:
- headers_list.append(lopath(file_ + ext))
-
- cxxflags_list = []
+ path = self.get_header_path(file_)
+ if path:
+ headers_list.append(lopath(path))
+
+ for file_ in lib.objcxxobjects:
+ # the file has no extension: search it
+ path = self.get_source_path(file_)
+ if path:
+ objcxx_sources_list.append(lopath(path))
+
+ # several objcxxobject files have a header beside
+ path = self.get_header_path(file_)
+ if path:
+ objcxx_headers_list.append(lopath(path))
+
+ cxxstdversionflag = ''
for cxxflag in lib.cxxflags:
# extract flag for C++ standard version
if cxxflag.startswith('-std'):
- cxxflags_list.append(cxxflag)
+ cxxstdversionflag = cxxflag
# List all include paths
for hdir in (lib.include + lib.include_sys):
@@ -1743,14 +1725,18 @@ class QtCreatorIntegrationGenerator(IdeIntegrationGenerator):
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]['cxxflags'] |= set(cxxflags_list)
+ self.data_libs[lib_folder]['objcxx_sources'] |= set(objcxx_sources_list)
+ self.data_libs[lib_folder]['objcxx_headers'] |= set(objcxx_headers_list)
+ self.data_libs[lib_folder]['cxxstdversionflag'] = cxxstdversionflag
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),
- 'cxxflags': set(cxxflags_list),
+ 'objcxx_sources': set(objcxx_sources_list),
+ 'objcxx_headers': set(objcxx_headers_list),
+ 'cxxstdversionflag': cxxstdversionflag,
'includepath': set(includepath_list),
'defines': set(defines_list),
'loc': lib.location,
@@ -1759,21 +1745,23 @@ class QtCreatorIntegrationGenerator(IdeIntegrationGenerator):
def emit(self):
+ mode = 'w+'
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 for the meta .pro file
+ subdirs_meta_pro = []
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'])
- cxxflags_list = sorted(self.data_libs[lib_folder]['cxxflags'])
+ objcxx_sources_list = sorted(self.data_libs[lib_folder]['objcxx_sources'])
+ objcxx_headers_list = sorted(self.data_libs[lib_folder]['objcxx_headers'])
+ cxxstdversionflag = self.data_libs[lib_folder]['cxxstdversionflag']
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']
@@ -1781,16 +1769,22 @@ class QtCreatorIntegrationGenerator(IdeIntegrationGenerator):
sources = " \\\n".join(sources_list)
headers = " \\\n".join(headers_list)
- cxxflags = " \\\n".join(cxxflags_list)
+ objcxx_sources = " \\\n".join(objcxx_sources_list)
+ objcxx_headers = " \\\n".join(objcxx_headers_list)
includepath = " \\\n".join(includepath_list)
defines = " \\\n".join(defines_list)
+ # strip '-std=' or '-std:' prefix
+ assert(isinstance(cxxstdversionflag, str) and cxxstdversionflag.startswith('-std'))
+ cxxstdversion = cxxstdversionflag[5:]
# create .pro file
- qt_pro_file = '%s/%s.pro' % (lib_loc, lib_name)
+ relative_subdir_path = os.path.relpath(lib_loc, self.gbuildparser.srcdir)
+ subdirs_meta_pro.append(relative_subdir_path)
+ qt_pro_file = os.path.join(self.base_folder, relative_subdir_path, lib_name + '.pro')
try:
- content = QtCreatorIntegrationGenerator.pro_template % {'sources': sources, 'headers': headers,
- 'cxxflags': cxxflags, 'includepath': includepath, 'defines': defines}
- mode = 'w+'
+ content = QtCreatorIntegrationGenerator.pro_template % {'sources': sources, 'headers': headers, 'cxxstdversionflag': cxxstdversionflag,
+ 'cxxstdversion': cxxstdversion, 'objcxx_sources': objcxx_sources,
+ 'objcxx_headers': objcxx_headers, 'includepath': includepath, 'defines': defines}
with open(qt_pro_file, mode) as fpro:
fpro.write(content)
self._log("created %s\n" % qt_pro_file)
@@ -1802,24 +1796,24 @@ class QtCreatorIntegrationGenerator(IdeIntegrationGenerator):
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)
+ # create .pro.shared file
+ qt_pro_shared_file = os.path.join(self.base_folder, relative_subdir_path, lib_name + '.pro.shared')
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)
+ with open(qt_pro_shared_file, mode) as fproshared:
+ fproshared.write(self.generate_pro_shared_content(lib_folder))
+ self._log("created %s\n" % qt_pro_shared_file)
except Exception as e:
- print("ERROR : creating pro.user file=" + qt_pro_user_file, file=sys.stderr)
+ print("ERROR : creating pro.shared file=" + qt_pro_shared_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'
+ qt_meta_pro_file = os.path.join(self.base_folder, 'lo.pro')
try:
- subdirs = " \\\n".join(sorted(subdirs_list))
+ subdirs = " \\\n".join(sorted(subdirs_meta_pro))
content = QtCreatorIntegrationGenerator.pro_meta_template % {'subdirs': subdirs}
with open(qt_meta_pro_file, 'w+') as fmpro:
fmpro.write(content)
@@ -1831,15 +1825,15 @@ class QtCreatorIntegrationGenerator(IdeIntegrationGenerator):
print(temp, file=sys.stderr)
print("\n\n", file=sys.stderr)
- # create meta .pro.user file
- qt_meta_pro_user_file = 'lo.pro.user'
+ # create meta .pro.shared file
+ qt_meta_pro_shared_file = os.path.join(self.base_folder, 'lo.pro.shared')
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)
+ with open(qt_meta_pro_shared_file, mode) as fmproshared:
+ fmproshared.write(self.generate_meta_pro_shared_content())
+ self._log("created %s\n" % qt_meta_pro_shared_file)
except Exception as e:
- print("ERROR : creating lo.pro.user file=" + qt_meta_pro_user_file, file=sys.stderr)
+ print("ERROR : creating lo.pro.shared file=" + qt_meta_pro_shared_file, file=sys.stderr)
print(e, file=sys.stderr)
temp = traceback.format_exc()
print(temp, file=sys.stderr)
@@ -1847,12 +1841,13 @@ class QtCreatorIntegrationGenerator(IdeIntegrationGenerator):
self.log_close()
- pro_template = """TEMPLATE = app
+ pro_template = """TEMPLATE = lib
CONFIG += console
CONFIG -= app_bundle
CONFIG -= qt
+CONFIG += %(cxxstdversion)s
-QMAKE_CXXFLAGS += %(cxxflags)s
+QMAKE_CXXFLAGS += %(cxxstdversionflag)s
INCLUDEPATH += %(includepath)s
@@ -1860,6 +1855,10 @@ SOURCES += %(sources)s
HEADERS += %(headers)s
+OBJECTIVE_SOURCES += %(objcxx_sources)s
+
+OBJECTIVE_HEADERS += %(objcxx_headers)s
+
DEFINES += %(defines)s
"""
@@ -1891,8 +1890,7 @@ if __name__ == '__main__':
'eclipsecdt': EclipseCDTIntegrationGenerator,
'kdevelop': KdevelopIntegrationGenerator,
'xcode': XcodeIntegrationGenerator,
- 'vs2017': VisualStudioIntegrationGenerator,
- 'vs2019': VisualStudioIntegrationGenerator,
+ 'vs': VisualStudioIntegrationGenerator,
'vim': VimIntegrationGenerator,
'debug': DebugIntegrationGenerator,
'qtcreator': QtCreatorIntegrationGenerator,