switch gbuild-to-ide to use gbuildtojson
Change-Id: Ic3ac11683a44e946e844e18a7670fa7baf46110a Reviewed-on: https://gerrit.libreoffice.org/31175 Tested-by: Björn Michaelsen <bjoern.michaelsen@canonical.com> Reviewed-by: Luke Benes <lukebenes@hotmail.com> Reviewed-by: Björn Michaelsen <bjoern.michaelsen@canonical.com>
This commit is contained in:
committed by
Björn Michaelsen
parent
a62740c668
commit
78547c3374
@@ -413,8 +413,8 @@ dump-deps-sort:
|
|||||||
@$(SRCDIR)/bin/module-deps.pl -t $(MAKE) $(SRCDIR)/Makefile.gbuild
|
@$(SRCDIR)/bin/module-deps.pl -t $(MAKE) $(SRCDIR)/Makefile.gbuild
|
||||||
|
|
||||||
define gb_Top_GbuildToIdeIntegration
|
define gb_Top_GbuildToIdeIntegration
|
||||||
$(1)-ide-integration:
|
$(1)-ide-integration: gbuildtojson
|
||||||
cd $(SRCDIR) && (LC_MESSAGES=C $(MAKE) cmd="$(MAKE) -npf Makefile.gbuild all" cmd || true) | $(SRCDIR)/bin/gbuild-to-ide --ide $(1)
|
cd $(SRCDIR) && $(SRCDIR)/bin/gbuild-to-ide --ide $(1) --make $(MAKE)
|
||||||
|
|
||||||
endef
|
endef
|
||||||
|
|
||||||
|
@@ -21,21 +21,7 @@ import xml.dom.minidom as minidom
|
|||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
|
|
||||||
class GbuildParserState:
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
self.target = None
|
|
||||||
self.ilib = None
|
|
||||||
self.include = []
|
|
||||||
self.defs = {}
|
|
||||||
self.cxxobjects = []
|
|
||||||
self.cxxflags = []
|
|
||||||
self.linked_libs = []
|
|
||||||
self.include_sys = []
|
|
||||||
|
|
||||||
|
|
||||||
class GbuildLinkTarget:
|
class GbuildLinkTarget:
|
||||||
|
|
||||||
def __init__(self, name, location, include, include_sys, defs, cxxobjects, cxxflags, linked_libs):
|
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) = (
|
(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)
|
name, location, include, include_sys, defs, cxxobjects, cxxflags, linked_libs)
|
||||||
@@ -53,7 +39,6 @@ class GbuildLinkTarget:
|
|||||||
|
|
||||||
|
|
||||||
class GbuildLib(GbuildLinkTarget):
|
class GbuildLib(GbuildLinkTarget):
|
||||||
|
|
||||||
def __init__(self, name, library, location, include, include_sys, defs, cxxobjects, cxxflags, linked_libs):
|
def __init__(self, name, library, location, include, include_sys, defs, cxxobjects, cxxflags, linked_libs):
|
||||||
GbuildLinkTarget.__init__(self, name, location, include, include_sys, defs, cxxobjects, cxxflags, linked_libs)
|
GbuildLinkTarget.__init__(self, name, location, include, include_sys, defs, cxxobjects, cxxflags, linked_libs)
|
||||||
self.library = library
|
self.library = library
|
||||||
@@ -70,7 +55,6 @@ class GbuildLib(GbuildLinkTarget):
|
|||||||
|
|
||||||
|
|
||||||
class GbuildExe(GbuildLinkTarget):
|
class GbuildExe(GbuildLinkTarget):
|
||||||
|
|
||||||
def __init__(self, name, executable, location, include, include_sys, defs, cxxobjects, cxxflags, linked_libs):
|
def __init__(self, name, executable, location, include, include_sys, defs, cxxobjects, cxxflags, linked_libs):
|
||||||
GbuildLinkTarget.__init__(self, name, location, include, include_sys, defs, cxxobjects, cxxflags, linked_libs)
|
GbuildLinkTarget.__init__(self, name, location, include, include_sys, defs, cxxobjects, cxxflags, linked_libs)
|
||||||
self.executable = executable
|
self.executable = executable
|
||||||
@@ -84,186 +68,85 @@ class GbuildExe(GbuildLinkTarget):
|
|||||||
|
|
||||||
|
|
||||||
class GbuildParser:
|
class GbuildParser:
|
||||||
makecmdpattern = re.compile('^MAKE_COMMAND := (.*)')
|
def __init__(self, makecmd):
|
||||||
srcdirpattern = re.compile('^SRCDIR = (.*)')
|
self.makecmd = makecmd
|
||||||
builddirpattern = re.compile('^BUILDDIR = (.*)')
|
self.binpath = os.path.dirname(os.environ['GPERF']) # woha, this is quite a hack
|
||||||
instdirpattern = re.compile('^INSTDIR = (.*)')
|
(self.srcdir, self.builddir, self.instdir, self.workdir) = (os.environ['SRCDIR'], os.environ['BUILDDIR'], os.environ['INSTDIR'], os.environ['WORKDIR'])
|
||||||
binpathpattern = re.compile('^GPERF = (.*)gperf(.exe)?')
|
(self.libs, self.exes, self.modulenamelist) = ([], [], [])
|
||||||
libnamespattern = re.compile('^gb_Library_ILIBFILENAMES := (.*)')
|
(self.libnames, self.exenames, self.target_by_path, self.target_by_location) = ({}, {}, {}, {})
|
||||||
exenamepattern = re.compile('^gb_Executable_FILENAMES_FOR_BUILD := (.*)')
|
|
||||||
rulepattern = re.compile('^(.+?):( .*)?$')
|
|
||||||
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]*\):')
|
|
||||||
includepattern = re.compile('-I(\S+)')
|
includepattern = re.compile('-I(\S+)')
|
||||||
isystempattern = re.compile('-isystem\s*(\S+)')
|
isystempattern = re.compile('-isystem\s*(\S+)')
|
||||||
defspattern = re.compile('# DEFS := (.*)')
|
|
||||||
cxxpattern = re.compile('# CXXOBJECTS := (.*)')
|
|
||||||
linkedlibspattern = re.compile('# LINKED_LIBS := (.*)')
|
|
||||||
ilibpattern = re.compile('# ILIBTARGET := (.*)')
|
|
||||||
warningpattern = re.compile('-W\S+')
|
warningpattern = re.compile('-W\S+')
|
||||||
|
libpattern = re.compile('Library_(.*)\.mk')
|
||||||
|
exepattern = re.compile('Executable_(.*)\.mk')
|
||||||
|
|
||||||
def __init__(self):
|
@staticmethod
|
||||||
(self.makecmd, self.srcdir, self.builddir, self.instdir, self.libs, self.exes,
|
def __split_includes(includes):
|
||||||
self.libnames, self.exenames, self.target_by_path, self.target_by_location, self.modulenamelist) = ('', '', '', '', [], [], {}, {}, {}, {}, [])
|
foundisystem = GbuildParser.isystempattern.findall(includes)
|
||||||
|
foundincludes = [includeswitch.strip() for includeswitch in GbuildParser.includepattern.findall(includes) if
|
||||||
|
len(includeswitch) > 2]
|
||||||
|
return (foundincludes, foundisystem)
|
||||||
|
|
||||||
def __mapping_to_dict(self, mapping):
|
@staticmethod
|
||||||
mapping_dict = {}
|
def __split_objs(objsline):
|
||||||
for item in mapping.split(' '):
|
return [obj for obj in objsline.strip().split(' ') if len(obj) > 0 and obj != 'CXXOBJECTS' and obj != '+=']
|
||||||
library, target = item.split(':')
|
|
||||||
mapping_dict[target] = library
|
|
||||||
return mapping_dict
|
|
||||||
|
|
||||||
def _parse_hash_old(self, line, state):
|
@staticmethod
|
||||||
libmatch = GbuildParser.libpattern.match(line)
|
def __split_defs(defsline):
|
||||||
if libmatch:
|
defs = {}
|
||||||
libname = self.libnames.get(state.ilib, None)
|
alldefs = [defswitch.strip()[2:] for defswitch in defsline.strip().split(' ') if len(defswitch) > 2]
|
||||||
if state.cxxobjects:
|
for d in alldefs:
|
||||||
self.libs.append(
|
defparts = d.split('=')
|
||||||
GbuildLib(libmatch.group(2), libname, libmatch.group(1),
|
if len(defparts) == 1:
|
||||||
state.include, state.include_sys, state.defs, state.cxxobjects,
|
defparts.append(None)
|
||||||
state.cxxflags, state.linked_libs))
|
defs[defparts[0]] = defparts[1]
|
||||||
state = GbuildParserState()
|
defs["LIBO_INTERNAL_ONLY"] = None
|
||||||
return state
|
return defs
|
||||||
exematch = GbuildParser.exepattern.match(line)
|
|
||||||
if exematch:
|
|
||||||
exename = self.exenames.get(state.target, None)
|
|
||||||
if state.cxxobjects:
|
|
||||||
self.exes.append(
|
|
||||||
GbuildExe(exematch.group(2), exename, exematch.group(1),
|
|
||||||
state.include, state.include_sys, state.defs, state.cxxobjects,
|
|
||||||
state.cxxflags, state.linked_libs))
|
|
||||||
state = GbuildParserState()
|
|
||||||
return state
|
|
||||||
if line.find('# INCLUDE :=') == 0:
|
|
||||||
isystemmatch = GbuildParser.isystempattern.findall(line)
|
|
||||||
if isystemmatch:
|
|
||||||
state.include_sys = isystemmatch
|
|
||||||
state.include = [includeswitch.strip() for includeswitch in GbuildParser.includepattern.findall(line) if
|
|
||||||
len(includeswitch) > 2]
|
|
||||||
return state
|
|
||||||
defsmatch = GbuildParser.defspattern.match(line)
|
|
||||||
if defsmatch:
|
|
||||||
alldefs = [defswitch.strip()[2:] for defswitch in defsmatch.group(1).split(' ') if len(defswitch) > 2]
|
|
||||||
for d in alldefs:
|
|
||||||
defparts = d.split('=')
|
|
||||||
if len(defparts) == 1:
|
|
||||||
defparts.append(None)
|
|
||||||
state.defs[defparts[0]] = defparts[1]
|
|
||||||
state.defs["LIBO_INTERNAL_ONLY"] = None
|
|
||||||
return state
|
|
||||||
cxxmatch = GbuildParser.cxxpattern.match(line)
|
|
||||||
if cxxmatch:
|
|
||||||
state.cxxobjects = [obj for obj in cxxmatch.group(1).split(' ') if len(obj) > 0]
|
|
||||||
return state
|
|
||||||
linkedlibsmatch = GbuildParser.linkedlibspattern.match(line)
|
|
||||||
if linkedlibsmatch:
|
|
||||||
state.linked_libs = linkedlibsmatch.group(1).strip().split(' ')
|
|
||||||
return state
|
|
||||||
ilibmatch = GbuildParser.ilibpattern.match(line)
|
|
||||||
if ilibmatch:
|
|
||||||
state.ilib = os.path.basename(ilibmatch.group(1))
|
|
||||||
return state
|
|
||||||
if line.find('# T_CXXFLAGS :=') == 0:
|
|
||||||
state.cxxflags = [cxxflag.strip() for cxxflag in GbuildParser.warningpattern.sub('', line.replace('# T_CXXFLAGS :=', '')).split(' ') if len(cxxflag) > 1]
|
|
||||||
return state
|
|
||||||
# we could match a lot of other stuff here if needed for integration rpaths etc.
|
|
||||||
return state
|
|
||||||
|
|
||||||
def _parse_hash(self, line):
|
@staticmethod
|
||||||
libmatch = GbuildParser.libpattern.match(line)
|
def __split_flags(flagsline, flagslineappend):
|
||||||
if libmatch:
|
return [cxxflag.strip() for cxxflag in GbuildParser.warningpattern.sub('', '%s %s' % (flagsline, flagslineappend)).split(' ') if len(cxxflag) > 1]
|
||||||
return True
|
|
||||||
exematch = GbuildParser.exepattern.match(line)
|
|
||||||
if exematch:
|
|
||||||
return True
|
|
||||||
if line.find('# INCLUDE :=') == 0:
|
|
||||||
return True
|
|
||||||
defsmatch = GbuildParser.defspattern.match(line)
|
|
||||||
if defsmatch:
|
|
||||||
return True
|
|
||||||
cxxmatch = GbuildParser.cxxpattern.match(line)
|
|
||||||
if cxxmatch:
|
|
||||||
return True
|
|
||||||
linkedlibsmatch = GbuildParser.linkedlibspattern.match(line)
|
|
||||||
if linkedlibsmatch:
|
|
||||||
return True
|
|
||||||
ilibmatch = GbuildParser.ilibpattern.match(line)
|
|
||||||
if ilibmatch:
|
|
||||||
return True
|
|
||||||
if line.find('# T_CXXFLAGS :=') == 0:
|
|
||||||
return True
|
|
||||||
# we could match a lot of other stuff here if needed for integration rpaths etc.
|
|
||||||
return False
|
|
||||||
|
|
||||||
def _parse_without_hash(self, line):
|
@staticmethod
|
||||||
makecmdmatch = GbuildParser.makecmdpattern.match(line)
|
def __lib_from_json(json):
|
||||||
if makecmdmatch:
|
(foundincludes, foundisystem) = GbuildParser.__split_includes(json['INCLUDE'])
|
||||||
self.makecmd = makecmdmatch.group(1)
|
return GbuildLib(
|
||||||
# FIXME: Hack
|
GbuildParser.libpattern.match(os.path.basename(json['MAKEFILE'])).group(1),
|
||||||
if self.makecmd == 'make':
|
json['LINKTARGET'],
|
||||||
self.makecmd = '/usr/bin/make'
|
os.path.dirname(json['MAKEFILE']),
|
||||||
return False
|
foundincludes,
|
||||||
srcdirmatch = GbuildParser.srcdirpattern.match(line)
|
foundisystem,
|
||||||
if srcdirmatch:
|
GbuildParser.__split_defs(json['DEFS']),
|
||||||
self.srcdir = srcdirmatch.group(1)
|
GbuildParser.__split_objs(json['CXXOBJECTS']),
|
||||||
return False
|
GbuildParser.__split_flags(json['CXXFLAGS'], json['CXXFLAGSAPPEND']),
|
||||||
builddirmatch = GbuildParser.builddirpattern.match(line)
|
json['LINKED_LIBS'].strip().split(' '))
|
||||||
if builddirmatch:
|
|
||||||
self.builddir = builddirmatch.group(1)
|
|
||||||
return False
|
|
||||||
instdirmatch = GbuildParser.instdirpattern.match(line)
|
|
||||||
if instdirmatch:
|
|
||||||
self.instdir = instdirmatch.group(1)
|
|
||||||
return False
|
|
||||||
binpathmatch = GbuildParser.binpathpattern.match(line)
|
|
||||||
if binpathmatch:
|
|
||||||
self.binpath = binpathmatch.group(1)
|
|
||||||
return False
|
|
||||||
libnamesmatch = GbuildParser.libnamespattern.match(line)
|
|
||||||
if libnamesmatch:
|
|
||||||
self.libnames = self.__mapping_to_dict(libnamesmatch.group(1))
|
|
||||||
return False
|
|
||||||
exenamesmatch = GbuildParser.exenamepattern.match(line)
|
|
||||||
if exenamesmatch:
|
|
||||||
self.exenames = self.__mapping_to_dict(exenamesmatch.group(1))
|
|
||||||
return False
|
|
||||||
rulematch = self.rulepattern.match(line)
|
|
||||||
if rulematch:
|
|
||||||
return True
|
|
||||||
|
|
||||||
def parse(self, gbuildstate):
|
@staticmethod
|
||||||
workLines = []
|
def __exe_from_json(json):
|
||||||
stateActive = False
|
(foundincludes, foundisystem) = GbuildParser.__split_includes(json['INCLUDE'])
|
||||||
for line in gbuildstate:
|
return GbuildExe(
|
||||||
line = line.rstrip('\r\n')
|
GbuildParser.exepattern.match(os.path.basename(json['MAKEFILE'])).group(1),
|
||||||
if line.startswith('#'):
|
json['LINKTARGET'],
|
||||||
if self._parse_hash(line):
|
os.path.dirname(json['MAKEFILE']),
|
||||||
stateActive = True
|
foundincludes,
|
||||||
workLines.append(line)
|
foundisystem,
|
||||||
else:
|
GbuildParser.__split_defs(json['DEFS']),
|
||||||
if self._parse_without_hash(line):
|
GbuildParser.__split_objs(json['CXXOBJECTS']),
|
||||||
workLines.append(line)
|
GbuildParser.__split_flags(json['CXXFLAGS'], json['CXXFLAGSAPPEND']),
|
||||||
elif stateActive:
|
json['LINKED_LIBS'].strip().split(' '))
|
||||||
workLines.append('!END OF STATE')
|
|
||||||
|
|
||||||
state = GbuildParserState()
|
|
||||||
for line in workLines:
|
|
||||||
if line.startswith('!END OF STATE'):
|
|
||||||
state = GbuildParserState()
|
|
||||||
continue
|
|
||||||
if line.startswith('#'):
|
|
||||||
state = self._parse_hash_old(line, state)
|
|
||||||
else:
|
|
||||||
rulematch = self.rulepattern.match(line)
|
|
||||||
if rulematch:
|
|
||||||
if len(rulematch.groups()) == 2 \
|
|
||||||
and rulematch.group(2) is not None \
|
|
||||||
and ':=' in rulematch.group(2):
|
|
||||||
# Hack to make GNU make >= 4.x happy
|
|
||||||
state = self._parse_hash_old('#' + rulematch.group(2), state)
|
|
||||||
else:
|
|
||||||
state.target = os.path.basename(rulematch.group(1))
|
|
||||||
|
|
||||||
|
def parse(self):
|
||||||
|
for jsonfilename in os.listdir(os.path.join(self.workdir, 'GbuildToJson', 'Library')):
|
||||||
|
with open(os.path.join(self.workdir, 'GbuildToJson', 'Library', jsonfilename), 'r') as f:
|
||||||
|
lib = self.__lib_from_json(json.load(f))
|
||||||
|
self.libnames[lib.library] = lib.name
|
||||||
|
self.libs.append(lib)
|
||||||
|
for jsonfilename in os.listdir(os.path.join(self.workdir, 'GbuildToJson', 'Executable')):
|
||||||
|
with open(os.path.join(self.workdir, 'GbuildToJson', 'Executable', jsonfilename), 'r') as f:
|
||||||
|
exe = self.__exe_from_json(json.load(f))
|
||||||
|
self.exenames[exe.executable] = exe.name
|
||||||
|
self.exes.append(exe)
|
||||||
for target in set(self.libs) | set(self.exes):
|
for target in set(self.libs) | set(self.exes):
|
||||||
if target.location not in self.target_by_location:
|
if target.location not in self.target_by_location:
|
||||||
self.target_by_location[target.location] = set()
|
self.target_by_location[target.location] = set()
|
||||||
@@ -1697,9 +1580,13 @@ if __name__ == '__main__':
|
|||||||
description='LibreOffice gbuild IDE project generator')
|
description='LibreOffice gbuild IDE project generator')
|
||||||
parser.add_argument('--ide', dest='ide', required=True,
|
parser.add_argument('--ide', dest='ide', required=True,
|
||||||
help='the IDE to generate project files for')
|
help='the IDE to generate project files for')
|
||||||
parser.add_argument('--input', dest='input', required=False,
|
parser.add_argument('--make', dest='makecmd', required=True,
|
||||||
help='the input file, not normally used, for debugging this script')
|
help='the command to execute make')
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
# FIXME: Hack
|
||||||
|
if args.makecmd == 'make':
|
||||||
|
args.makecmd = '/usr/bin/make'
|
||||||
|
|
||||||
paths = {}
|
paths = {}
|
||||||
generators = {
|
generators = {
|
||||||
'eclipsecdt': EclipseCDTIntegrationGenerator,
|
'eclipsecdt': EclipseCDTIntegrationGenerator,
|
||||||
@@ -1716,10 +1603,7 @@ if __name__ == '__main__':
|
|||||||
print("Invalid ide. valid values are %s" % ','.join(generators.keys()))
|
print("Invalid ide. valid values are %s" % ','.join(generators.keys()))
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
if args.input:
|
gbuildparser = GbuildParser(args.makecmd).parse()
|
||||||
gbuildparser = GbuildParser().parse(open(args.input, 'r'))
|
|
||||||
else:
|
|
||||||
gbuildparser = GbuildParser().parse(sys.stdin)
|
|
||||||
|
|
||||||
generators[args.ide](gbuildparser, args.ide).emit()
|
generators[args.ide](gbuildparser, args.ide).emit()
|
||||||
print("Successfully created the project files.")
|
print("Successfully created the project files.")
|
||||||
|
Reference in New Issue
Block a user