mirror of
https://gitlab.com/ita1024/waf.git
synced 2024-11-29 13:30:32 +01:00
174f66c523
The export symbol regular expression processing is updated to make several improvements: * The export expression (export_symbols_regex) now applies to both functions and global variables * A named capture group is used to match symbols. This allows the export expression to contain capture groups without disrupting the expression matching
80 lines
3.1 KiB
Python
80 lines
3.1 KiB
Python
#! /usr/bin/env python
|
|
# encoding: utf-8
|
|
|
|
"""
|
|
this tool supports the export_symbols_regex to export the symbols in a shared library.
|
|
by default, all symbols are exported by gcc, and nothing by msvc.
|
|
to use the tool, do something like:
|
|
|
|
def build(ctx):
|
|
ctx(features='c cshlib syms', source='a.c b.c', export_symbols_regex='mylib_.*', target='testlib')
|
|
|
|
only the symbols starting with 'mylib_' will be exported.
|
|
"""
|
|
|
|
import os
|
|
import re
|
|
from waflib.Context import STDOUT
|
|
from waflib.Task import Task
|
|
from waflib.Errors import WafError
|
|
from waflib.TaskGen import feature, after_method
|
|
|
|
class gen_sym(Task):
|
|
def run(self):
|
|
obj = self.inputs[0]
|
|
kw = {}
|
|
if 'msvc' in (self.env.CC_NAME, self.env.CXX_NAME):
|
|
re_nm = re.compile(r'External\s+\|\s+_(?P<symbol>' + self.generator.export_symbols_regex + r')\b')
|
|
cmd = (self.env.DUMPBIN or ['dumpbin']) + ['/symbols', obj.abspath()]
|
|
else:
|
|
if self.env.DEST_BINFMT == 'pe': #gcc uses nm, and has a preceding _ on windows
|
|
re_nm = re.compile(r'(T|D)\s+_(?P<symbol>' + self.generator.export_symbols_regex + r')\b')
|
|
elif self.env.DEST_BINFMT=='mac-o':
|
|
re_nm=re.compile(r'(T|D)\s+(?P<symbol>_?'+self.generator.export_symbols_regex+r')\b')
|
|
else:
|
|
re_nm = re.compile(r'(T|D)\s+(?P<symbol>' + self.generator.export_symbols_regex + r')\b')
|
|
cmd = (self.env.NM or ['nm']) + ['-g', obj.abspath()]
|
|
syms = [m.group('symbol') for m in re_nm.finditer(self.generator.bld.cmd_and_log(cmd, quiet=STDOUT, **kw))]
|
|
self.outputs[0].write('%r' % syms)
|
|
|
|
class compile_sym(Task):
|
|
def run(self):
|
|
syms = {}
|
|
for x in self.inputs:
|
|
slist = eval(x.read())
|
|
for s in slist:
|
|
syms[s] = 1
|
|
lsyms = list(syms.keys())
|
|
lsyms.sort()
|
|
if self.env.DEST_BINFMT == 'pe':
|
|
self.outputs[0].write('EXPORTS\n' + '\n'.join(lsyms))
|
|
elif self.env.DEST_BINFMT == 'elf':
|
|
self.outputs[0].write('{ global:\n' + ';\n'.join(lsyms) + ";\nlocal: *; };\n")
|
|
elif self.env.DEST_BINFMT=='mac-o':
|
|
self.outputs[0].write('\n'.join(lsyms) + '\n')
|
|
else:
|
|
raise WafError('NotImplemented')
|
|
|
|
@feature('syms')
|
|
@after_method('process_source', 'process_use', 'apply_link', 'propagate_uselib_vars')
|
|
def do_the_symbol_stuff(self):
|
|
ins = [x.outputs[0] for x in self.compiled_tasks]
|
|
self.gen_sym_tasks = [self.create_task('gen_sym', x, x.change_ext('.%d.sym' % self.idx)) for x in ins]
|
|
|
|
tsk = self.create_task('compile_sym',
|
|
[x.outputs[0] for x in self.gen_sym_tasks],
|
|
self.path.find_or_declare(getattr(self, 'sym_filename', self.target + '.def')))
|
|
self.link_task.set_run_after(tsk)
|
|
self.link_task.dep_nodes.append(tsk.outputs[0])
|
|
if 'msvc' in (self.env.CC_NAME, self.env.CXX_NAME):
|
|
self.link_task.env.append_value('LINKFLAGS', ['/def:' + tsk.outputs[0].bldpath()])
|
|
elif self.env.DEST_BINFMT == 'pe': #gcc on windows takes *.def as an additional input
|
|
self.link_task.inputs.append(tsk.outputs[0])
|
|
elif self.env.DEST_BINFMT == 'elf':
|
|
self.link_task.env.append_value('LINKFLAGS', ['-Wl,-version-script', '-Wl,' + tsk.outputs[0].bldpath()])
|
|
elif self.env.DEST_BINFMT=='mac-o':
|
|
self.link_task.env.append_value('LINKFLAGS',['-Wl,-exported_symbols_list,'+tsk.outputs[0].bldpath()])
|
|
else:
|
|
raise WafError('NotImplemented')
|
|
|