fdo#70414: Use correct target names for building Visual Studio projects.

Visual Studio projects use target Library_{library_name}/Executable_{executable_name} for building the project and Library_{library_name}.clean/Executable_{executable_name}.clean for cleaning the project. In most cases, the name of library/executable is identical to the name of Library_*/Executable_* makefile, but in ~12 cases, the names are different (e.g. makefile is Library_syssh_win, but target is Library_syssh). VS fails when it tries to build the project with incorrect target name. This patch replaces the names of targets with correct ones. Dependences also used incorrect names of libraries.

Change-Id: Ifba50465512e24e65a3c6505a5f40d477ec8cdd9
Reviewed-on: https://gerrit.libreoffice.org/8189
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
Tested-by: Caolán McNamara <caolanm@redhat.com>
This commit is contained in:
Honza Havlíček 2014-02-23 00:47:23 +01:00 committed by Caolán McNamara
parent 523cdbd2e8
commit b81ac16e65

View File

@ -20,6 +20,8 @@ import xml.etree.ElementTree as ET
class GbuildParserState: class GbuildParserState:
def __init__(self): def __init__(self):
self.target = None
self.ilib = None
self.include = [] self.include = []
self.defs = {} self.defs = {}
self.cxxobjects = [] self.cxxobjects = []
@ -43,25 +45,32 @@ class GbuildLinkTarget:
class GbuildLib(GbuildLinkTarget): class GbuildLib(GbuildLinkTarget):
def __init__(self, name, location, include, defs, cxxobjects, linked_libs): def __init__(self, name, library, location, include, defs, cxxobjects, linked_libs):
GbuildLinkTarget.__init__(self, name, location, include, defs, cxxobjects, linked_libs) GbuildLinkTarget.__init__(self, name, location, include, defs, cxxobjects, linked_libs)
self.library = library
def short_name(self): def short_name(self):
"""Return the short name of target based on the Library_* makefile name"""
return 'Library %s' % self.name return 'Library %s' % self.name
def target(self): def target_name(self):
return 'Library_%s' % self.name return 'Library_%s' % self.library
def library_name(self):
return self.library
class GbuildExe(GbuildLinkTarget): class GbuildExe(GbuildLinkTarget):
def __init__(self, name, location, include, defs, cxxobjects, linked_libs): def __init__(self, name, executable, location, include, defs, cxxobjects, linked_libs):
GbuildLinkTarget.__init__(self, name, location, include, defs, cxxobjects, linked_libs) GbuildLinkTarget.__init__(self, name, location, include, defs, cxxobjects, linked_libs)
self.executable = executable
def short_name(self): def short_name(self):
"""Return the short name of target based on the Executable_* makefile name"""
return 'Executable %s' % self.name return 'Executable %s' % self.name
def target(self): def target_name(self):
return 'Executable_%s' % self.name return 'Executable_%s' % self.executable
class GbuildParser: class GbuildParser:
@ -70,15 +79,27 @@ class GbuildParser:
builddirpattern = re.compile('^BUILDDIR = (.*)') builddirpattern = re.compile('^BUILDDIR = (.*)')
instdirpattern = re.compile('^INSTDIR = (.*)') instdirpattern = re.compile('^INSTDIR = (.*)')
binpathpattern = re.compile('^LS = (.*)ls(.exe)?') binpathpattern = re.compile('^LS = (.*)ls(.exe)?')
libnamespattern = re.compile('^gb_Library_ILIBFILENAMES := (.*)')
exenamepattern = re.compile('^gb_Executable_FILENAMES_FOR_BUILD := (.*)')
rulepattern = re.compile('^(.+?):( .*)?$')
libpattern = re.compile('# [a-z]+ to execute \(from [\'`](.*)/Library_(.*)\.mk\', line [0-9]*\):') libpattern = re.compile('# [a-z]+ to execute \(from [\'`](.*)/Library_(.*)\.mk\', line [0-9]*\):')
exepattern = re.compile('# [a-z]+ to execute \(from [\'`](.*)/Executable_(.*)\.mk\', line [0-9]*\):') exepattern = re.compile('# [a-z]+ to execute \(from [\'`](.*)/Executable_(.*)\.mk\', line [0-9]*\):')
includepattern = re.compile('# INCLUDE := (.*)') includepattern = re.compile('# INCLUDE := (.*)')
defspattern = re.compile('# DEFS := (.*)') defspattern = re.compile('# DEFS := (.*)')
cxxpattern = re.compile('# CXXOBJECTS := (.*)') cxxpattern = re.compile('# CXXOBJECTS := (.*)')
linkedlibspattern = re.compile('# LINKED_LIBS := (.*)') linkedlibspattern = re.compile('# LINKED_LIBS := (.*)')
ilibpattern = re.compile('# ILIBTARGET := (.*)')
def __init__(self): def __init__(self):
(self.makecmd, self.srcdir, self.builddir, self.instdir, self.libs, self.exes) = ('', '', '', '', [], []) (self.makecmd, self.srcdir, self.builddir, self.instdir, self.libs,
self.exes, self.libnames, self.exenames) = ('', '', '', '', [], [], {}, {})
def __mapping_to_dict(self, mapping):
mapping_dict = {}
for item in mapping.split(' '):
library,target = item.split(':')
mapping_dict[target] = library
return mapping_dict
def parse(self, gbuildstate): def parse(self, gbuildstate):
state = GbuildParserState() state = GbuildParserState()
@ -107,19 +128,35 @@ class GbuildParser:
if binpathmatch: if binpathmatch:
self.binpath = binpathmatch.group(1) self.binpath = binpathmatch.group(1)
continue continue
rulematch = self.rulepattern.match(line)
if rulematch:
state.target = os.path.basename(rulematch.group(1))
continue
libnamesmatch = GbuildParser.libnamespattern.match(line)
if libnamesmatch:
self.libnames = self.__mapping_to_dict(libnamesmatch.group(1))
continue
exenamesmatch = GbuildParser.exenamepattern.match(line)
if exenamesmatch:
self.exenames = self.__mapping_to_dict(exenamesmatch.group(1))
continue
state = GbuildParserState() state = GbuildParserState()
continue continue
libmatch = GbuildParser.libpattern.match(line) libmatch = GbuildParser.libpattern.match(line)
if libmatch: if libmatch:
libname = self.libnames.get(state.ilib, None)
self.libs.append( self.libs.append(
GbuildLib(libmatch.group(2), libmatch.group(1), state.include, state.defs, state.cxxobjects, GbuildLib(libmatch.group(2), libname, libmatch.group(1),
state.include, state.defs, state.cxxobjects,
state.linked_libs)) state.linked_libs))
state = GbuildParserState() state = GbuildParserState()
continue continue
exematch = GbuildParser.exepattern.match(line) exematch = GbuildParser.exepattern.match(line)
if exematch: if exematch:
exename = self.exenames.get(state.target, None)
self.exes.append( self.exes.append(
GbuildExe(exematch.group(2), exematch.group(1), state.include, state.defs, state.cxxobjects, GbuildExe(exematch.group(2), exename, exematch.group(1),
state.include, state.defs, state.cxxobjects,
state.linked_libs)) state.linked_libs))
state = GbuildParserState() state = GbuildParserState()
continue continue
@ -145,6 +182,9 @@ class GbuildParser:
if linkedlibsmatch: if linkedlibsmatch:
state.linked_libs = linkedlibsmatch.group(1).strip().split(' ') state.linked_libs = linkedlibsmatch.group(1).strip().split(' ')
continue continue
ilibmatch = GbuildParser.ilibpattern.match(line)
if ilibmatch:
state.ilib = os.path.basename(ilibmatch.group(1))
#we could match a lot of other stuff here if needed for integration rpaths etc. #we could match a lot of other stuff here if needed for integration rpaths etc.
return self return self
@ -583,16 +623,17 @@ class VisualStudioIntegrationGenerator(IdeIntegrationGenerator):
def get_project_directory(self, target): def get_project_directory(self, target):
return os.path.join(self.solution_directory, target.location.split('/')[-1]) return os.path.join(self.solution_directory, target.location.split('/')[-1])
def get_dependency_libs(self, linked_libs, projects): def get_dependency_libs(self, linked_libs, library_projects):
dependency_libs = {} dependency_libs = {}
for linked_lib in linked_libs: for linked_lib in linked_libs:
for project in projects: for library_project in library_projects:
if project.target.name == linked_lib: if library_project.target.library_name() == linked_lib:
dependency_libs[project.guid] = project dependency_libs[library_project.guid] = library_project
return dependency_libs return dependency_libs
def write_solution(self, solution_path, projects): def write_solution(self, solution_path, projects):
print('Solution %s:' % os.path.splitext(os.path.basename(solution_path))[0], end='') 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: with open(solution_path, 'w') as f:
f.write('Microsoft Visual Studio Solution File, Format Version 12.00\n') f.write('Microsoft Visual Studio Solution File, Format Version 12.00\n')
for project in projects: for project in projects:
@ -603,7 +644,8 @@ class VisualStudioIntegrationGenerator(IdeIntegrationGenerator):
f.write('Project("{%s}") = "%s", "%s", "{%s}"\n' % f.write('Project("{%s}") = "%s", "%s", "{%s}"\n' %
(VisualStudioIntegrationGenerator.nmake_project_guid, (VisualStudioIntegrationGenerator.nmake_project_guid,
target.short_name(), proj_path, project.guid)) target.short_name(), proj_path, project.guid))
libs_in_solution = self.get_dependency_libs(target.linked_libs, projects) libs_in_solution = self.get_dependency_libs(target.linked_libs,
library_projects)
if libs_in_solution: if libs_in_solution:
f.write('\tProjectSection(ProjectDependencies) = postProject\n') f.write('\tProjectSection(ProjectDependencies) = postProject\n')
for lib_guid in libs_in_solution.keys(): for lib_guid in libs_in_solution.keys():
@ -683,7 +725,7 @@ class VisualStudioIntegrationGenerator(IdeIntegrationGenerator):
'sh': os.path.join(self.gbuildparser.binpath, 'dash.exe'), 'sh': os.path.join(self.gbuildparser.binpath, 'dash.exe'),
'location': target.location, 'location': target.location,
'makecmd': self.gbuildparser.makecmd, 'makecmd': self.gbuildparser.makecmd,
'target': target.target()} 'target': target.target_name()}
nmake_build_node = ET.SubElement(conf_node, '{%s}NMakeBuildCommandLine' % ns) nmake_build_node = ET.SubElement(conf_node, '{%s}NMakeBuildCommandLine' % ns)
nmake_build_node.text = cfg_targets['build'] % nmake_params 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' % ns)