move system libs calculation to its own file
This commit is contained in:
Родитель
7ec33d39d7
Коммит
157f3151a4
385
emcc
385
emcc
|
@ -49,7 +49,7 @@ emcc can be influenced by a few environment variables:
|
|||
|
||||
import os, sys, shutil, tempfile, subprocess, shlex, time, re, logging, json
|
||||
from subprocess import PIPE, STDOUT
|
||||
from tools import shared, jsrun
|
||||
from tools import shared, jsrun, system_libs
|
||||
from tools.shared import Compression, execute, suffix, unsuffixed, unsuffixed_basename, WINDOWS
|
||||
from tools.response_file import read_response_file
|
||||
|
||||
|
@ -1408,389 +1408,12 @@ try:
|
|||
|
||||
logging.debug('will generate JavaScript')
|
||||
|
||||
extra_files_to_link = []
|
||||
|
||||
if not LEAVE_INPUTS_RAW and \
|
||||
not shared.Settings.BUILD_AS_SHARED_LIB and \
|
||||
not shared.Settings.SIDE_MODULE: # shared libraries/side modules link no C libraries, need them in parent
|
||||
|
||||
# Check if we need to include some libraries that we compile. (We implement libc ourselves in js, but
|
||||
# compile a malloc implementation and stdlibc++.)
|
||||
|
||||
def read_symbols(path, exclude=None):
|
||||
symbols = map(lambda line: line.strip().split(' ')[1], open(path).readlines())
|
||||
if exclude:
|
||||
symbols = filter(lambda symbol: symbol not in exclude, symbols)
|
||||
return set(symbols)
|
||||
|
||||
lib_opts = ['-O2']
|
||||
|
||||
# XXX We also need to add libc symbols that use malloc, for example strdup. It's very rare to use just them and not
|
||||
# a normal malloc symbol (like free, after calling strdup), so we haven't hit this yet, but it is possible.
|
||||
libc_symbols = read_symbols(shared.path_from_root('system', 'lib', 'libc.symbols'))
|
||||
libcextra_symbols = read_symbols(shared.path_from_root('system', 'lib', 'libcextra.symbols'))
|
||||
libcxx_symbols = read_symbols(shared.path_from_root('system', 'lib', 'libcxx', 'symbols'), exclude=libc_symbols)
|
||||
libcxxabi_symbols = read_symbols(shared.path_from_root('system', 'lib', 'libcxxabi', 'symbols'), exclude=libc_symbols)
|
||||
|
||||
# XXX we should disable EMCC_DEBUG when building libs, just like in the relooper
|
||||
|
||||
def build_libc(lib_filename, files):
|
||||
o_s = []
|
||||
prev_cxx = os.environ.get('EMMAKEN_CXX')
|
||||
if prev_cxx: os.environ['EMMAKEN_CXX'] = ''
|
||||
musl_internal_includes = shared.path_from_root('system', 'lib', 'libc', 'musl', 'src', 'internal')
|
||||
for src in files:
|
||||
o = in_temp(os.path.basename(src) + '.o')
|
||||
execute([shared.PYTHON, shared.EMCC, shared.path_from_root('system', 'lib', src), '-o', o, '-I', musl_internal_includes] + lib_opts, stdout=stdout, stderr=stderr)
|
||||
o_s.append(o)
|
||||
if prev_cxx: os.environ['EMMAKEN_CXX'] = prev_cxx
|
||||
shared.Building.link(o_s, in_temp(lib_filename))
|
||||
return in_temp(lib_filename)
|
||||
|
||||
def build_libcxx(src_dirname, lib_filename, files):
|
||||
o_s = []
|
||||
for src in files:
|
||||
o = in_temp(src + '.o')
|
||||
srcfile = shared.path_from_root(src_dirname, src)
|
||||
execute([shared.PYTHON, shared.EMXX, srcfile, '-o', o, '-std=c++11'] + lib_opts, stdout=stdout, stderr=stderr)
|
||||
o_s.append(o)
|
||||
shared.Building.link(o_s, in_temp(lib_filename))
|
||||
return in_temp(lib_filename)
|
||||
|
||||
# libc
|
||||
def create_libc():
|
||||
logging.debug(' building libc for cache')
|
||||
libc_files = [
|
||||
'dlmalloc.c',
|
||||
os.path.join('libcxx', 'new.cpp'),
|
||||
]
|
||||
musl_files = [
|
||||
['internal', [
|
||||
'floatscan.c',
|
||||
'shgetc.c',
|
||||
]],
|
||||
['math', [
|
||||
'scalbn.c',
|
||||
'scalbnl.c',
|
||||
]],
|
||||
['stdio', [
|
||||
'__overflow.c',
|
||||
'__toread.c',
|
||||
'__towrite.c',
|
||||
'__uflow.c',
|
||||
]],
|
||||
['stdlib', [
|
||||
'atof.c',
|
||||
'strtod.c',
|
||||
]],
|
||||
['string', [
|
||||
'memcmp.c',
|
||||
'strcasecmp.c',
|
||||
'strcmp.c',
|
||||
'strncasecmp.c',
|
||||
'strncmp.c',
|
||||
]]
|
||||
]
|
||||
for directory, sources in musl_files:
|
||||
libc_files += [os.path.join('libc', 'musl', 'src', directory, source) for source in sources]
|
||||
return build_libc('libc.bc', libc_files)
|
||||
|
||||
def apply_libc(need):
|
||||
# libc needs some sign correction. # If we are in mode 0, switch to 2. We will add our lines
|
||||
try:
|
||||
if shared.Settings.CORRECT_SIGNS == 0: raise Exception('we need to change to 2')
|
||||
except: # we fail if equal to 0 - so we need to switch to 2 - or if CORRECT_SIGNS is not even in Settings
|
||||
shared.Settings.CORRECT_SIGNS = 2
|
||||
if shared.Settings.CORRECT_SIGNS == 2:
|
||||
shared.Settings.CORRECT_SIGNS_LINES = [shared.path_from_root('src', 'dlmalloc.c') + ':' + str(i+4) for i in [4816, 4191, 4246, 4199, 4205, 4235, 4227]]
|
||||
# If we are in mode 1, we are correcting everything anyhow. If we are in mode 3, we will be corrected
|
||||
# so all is well anyhow too.
|
||||
return True
|
||||
|
||||
# libcextra
|
||||
def create_libcextra():
|
||||
logging.debug('building libcextra for cache')
|
||||
musl_files = [
|
||||
['ctype', [
|
||||
'iswalnum.c',
|
||||
'iswalpha.c',
|
||||
'iswblank.c',
|
||||
'iswcntrl.c',
|
||||
'iswctype.c',
|
||||
'iswdigit.c',
|
||||
'iswgraph.c',
|
||||
'iswlower.c',
|
||||
'iswprint.c',
|
||||
'iswpunct.c',
|
||||
'iswspace.c',
|
||||
'iswupper.c',
|
||||
'iswxdigit.c',
|
||||
'towctrans.c',
|
||||
'wcswidth.c',
|
||||
'wctrans.c',
|
||||
'wcwidth.c',
|
||||
]],
|
||||
['internal', [
|
||||
'intscan.c',
|
||||
]],
|
||||
['legacy', [
|
||||
'err.c',
|
||||
]],
|
||||
['locale', [
|
||||
'iconv.c',
|
||||
'iswalnum_l.c',
|
||||
'iswalpha_l.c',
|
||||
'iswblank_l.c',
|
||||
'iswcntrl_l.c',
|
||||
'iswctype_l.c',
|
||||
'iswdigit_l.c',
|
||||
'iswgraph_l.c',
|
||||
'iswlower_l.c',
|
||||
'iswprint_l.c',
|
||||
'iswpunct_l.c',
|
||||
'iswspace_l.c',
|
||||
'iswupper_l.c',
|
||||
'iswxdigit_l.c',
|
||||
'strcoll.c',
|
||||
'strcasecmp_l.c',
|
||||
'strfmon.c',
|
||||
'strncasecmp_l.c',
|
||||
'strxfrm.c',
|
||||
'towctrans_l.c',
|
||||
'towlower_l.c',
|
||||
'towupper_l.c',
|
||||
'wcscoll.c',
|
||||
'wcscoll_l.c',
|
||||
'wcsxfrm.c',
|
||||
'wcsxfrm_l.c',
|
||||
'wctrans_l.c',
|
||||
'wctype_l.c',
|
||||
]],
|
||||
['math', [
|
||||
'__cos.c',
|
||||
'__cosdf.c',
|
||||
'__sin.c',
|
||||
'__sindf.c',
|
||||
'ilogb.c',
|
||||
'ilogbf.c',
|
||||
'ilogbl.c',
|
||||
'ldexp.c',
|
||||
'ldexpf.c',
|
||||
'ldexpl.c',
|
||||
'logb.c',
|
||||
'logbf.c',
|
||||
'logbl.c',
|
||||
'lgamma.c',
|
||||
'lgamma_r.c',
|
||||
'lgammaf.c',
|
||||
'lgammaf_r.c',
|
||||
'lgammal.c',
|
||||
'scalbnf.c',
|
||||
'signgam.c',
|
||||
'tgamma.c',
|
||||
'tgammaf.c',
|
||||
'tgammal.c'
|
||||
]],
|
||||
['misc', [
|
||||
'getopt.c',
|
||||
'getopt_long.c',
|
||||
]],
|
||||
['multibyte', [
|
||||
'btowc.c',
|
||||
'mblen.c',
|
||||
'mbrlen.c',
|
||||
'mbrtowc.c',
|
||||
'mbsinit.c',
|
||||
'mbsnrtowcs.c',
|
||||
'mbsrtowcs.c',
|
||||
'mbstowcs.c',
|
||||
'mbtowc.c',
|
||||
'wcrtomb.c',
|
||||
'wcsnrtombs.c',
|
||||
'wcsrtombs.c',
|
||||
'wcstombs.c',
|
||||
'wctob.c',
|
||||
'wctomb.c',
|
||||
]],
|
||||
['regex', [
|
||||
'fnmatch.c',
|
||||
'regcomp.c',
|
||||
'regerror.c',
|
||||
'regexec.c',
|
||||
'tre-mem.c',
|
||||
]],
|
||||
['stdio', [
|
||||
'fwprintf.c',
|
||||
'swprintf.c',
|
||||
'vfwprintf.c',
|
||||
'vswprintf.c',
|
||||
'vwprintf.c',
|
||||
'wprintf.c',
|
||||
'fputwc.c',
|
||||
'fputws.c',
|
||||
]],
|
||||
['stdlib', [
|
||||
'ecvt.c',
|
||||
'fcvt.c',
|
||||
'gcvt.c',
|
||||
'wcstod.c',
|
||||
'wcstol.c',
|
||||
]],
|
||||
['string', [
|
||||
'memccpy.c',
|
||||
'memmem.c',
|
||||
'mempcpy.c',
|
||||
'memrchr.c',
|
||||
'strcasestr.c',
|
||||
'strchrnul.c',
|
||||
'strlcat.c',
|
||||
'strlcpy.c',
|
||||
'strsep.c',
|
||||
'strverscmp.c',
|
||||
'wcpcpy.c',
|
||||
'wcpncpy.c',
|
||||
'wcscasecmp.c',
|
||||
'wcscasecmp_l.c',
|
||||
'wcscat.c',
|
||||
'wcschr.c',
|
||||
'wcscmp.c',
|
||||
'wcscpy.c',
|
||||
'wcscspn.c',
|
||||
'wcsdup.c',
|
||||
'wcslen.c',
|
||||
'wcsncasecmp.c',
|
||||
'wcsncasecmp_l.c',
|
||||
'wcsncat.c',
|
||||
'wcsncmp.c',
|
||||
'wcsncpy.c',
|
||||
'wcsnlen.c',
|
||||
'wcspbrk.c',
|
||||
'wcsrchr.c',
|
||||
'wcsspn.c',
|
||||
'wcsstr.c',
|
||||
'wcstok.c',
|
||||
'wcswcs.c',
|
||||
'wmemchr.c',
|
||||
'wmemcmp.c',
|
||||
'wmemcpy.c',
|
||||
'wmemmove.c',
|
||||
'wmemset.c',
|
||||
]]
|
||||
]
|
||||
libcextra_files = []
|
||||
for directory, sources in musl_files:
|
||||
libcextra_files += [os.path.join('libc', 'musl', 'src', directory, source) for source in sources]
|
||||
return build_libc('libcextra.bc', libcextra_files)
|
||||
|
||||
# libcxx
|
||||
def create_libcxx():
|
||||
logging.debug('building libcxx for cache')
|
||||
libcxx_files = [
|
||||
'algorithm.cpp',
|
||||
'condition_variable.cpp',
|
||||
'future.cpp',
|
||||
'iostream.cpp',
|
||||
'memory.cpp',
|
||||
'random.cpp',
|
||||
'stdexcept.cpp',
|
||||
'system_error.cpp',
|
||||
'utility.cpp',
|
||||
'bind.cpp',
|
||||
'debug.cpp',
|
||||
'hash.cpp',
|
||||
'mutex.cpp',
|
||||
'string.cpp',
|
||||
'thread.cpp',
|
||||
'valarray.cpp',
|
||||
'chrono.cpp',
|
||||
'exception.cpp',
|
||||
'ios.cpp',
|
||||
'locale.cpp',
|
||||
'regex.cpp',
|
||||
'strstream.cpp'
|
||||
]
|
||||
return build_libcxx(os.path.join('system', 'lib', 'libcxx'), 'libcxx.bc', libcxx_files)
|
||||
|
||||
def apply_libcxx(need):
|
||||
assert shared.Settings.QUANTUM_SIZE == 4, 'We do not support libc++ with QUANTUM_SIZE == 1'
|
||||
# libcxx might need corrections, so turn them all on. TODO: check which are actually needed
|
||||
shared.Settings.CORRECT_SIGNS = shared.Settings.CORRECT_OVERFLOWS = shared.Settings.CORRECT_ROUNDINGS = 1
|
||||
#logging.info('using libcxx turns on CORRECT_* options')
|
||||
return True
|
||||
|
||||
# libcxxabi - just for dynamic_cast for now
|
||||
def create_libcxxabi():
|
||||
logging.debug('building libcxxabi for cache')
|
||||
libcxxabi_files = [
|
||||
'typeinfo.cpp',
|
||||
'private_typeinfo.cpp'
|
||||
]
|
||||
return build_libcxx(os.path.join('system', 'lib', 'libcxxabi', 'src'), 'libcxxabi.bc', libcxxabi_files)
|
||||
|
||||
def apply_libcxxabi(need):
|
||||
assert shared.Settings.QUANTUM_SIZE == 4, 'We do not support libc++abi with QUANTUM_SIZE == 1'
|
||||
#logging.info('using libcxxabi, this may need CORRECT_* options')
|
||||
#shared.Settings.CORRECT_SIGNS = shared.Settings.CORRECT_OVERFLOWS = shared.Settings.CORRECT_ROUNDINGS = 1
|
||||
return True
|
||||
|
||||
# Settings this in the environment will avoid checking dependencies and make building big projects a little faster
|
||||
# 1 means include everything; otherwise it can be the name of a lib (libcxx, etc.)
|
||||
force = os.environ.get('EMCC_FORCE_STDLIBS')
|
||||
force_all = force == '1'
|
||||
|
||||
# Scan symbols
|
||||
symbolses = map(lambda temp_file: shared.Building.llvm_nm(temp_file), temp_files)
|
||||
|
||||
# Add in some hacks for js libraries. If a js lib depends on a symbol provided by a C library, it must be
|
||||
# added to here, because our deps go only one way (each library here is checked, then we check the next
|
||||
# in order - libcxx, libcxextra, etc. - and then we run the JS compiler and provide extra symbols from
|
||||
# library*.js files. But we cannot then go back to the C libraries if a new dep was added!
|
||||
# TODO: Move all __deps from src/library*.js to deps_info.json, and use that single source of info
|
||||
# both here and in the JS compiler.
|
||||
deps_info = json.loads(open(shared.path_from_root('src', 'deps_info.json')).read())
|
||||
def add_back_deps(need):
|
||||
for ident, deps in deps_info.iteritems():
|
||||
if ident in need.undefs:
|
||||
for dep in deps:
|
||||
need.undefs.add(dep)
|
||||
shared.Settings.EXPORTED_FUNCTIONS.append('_' + dep)
|
||||
for symbols in symbolses:
|
||||
add_back_deps(symbols)
|
||||
|
||||
all_needed = set()
|
||||
for symbols in symbolses:
|
||||
all_needed.update(symbols.undefs)
|
||||
for symbols in symbolses:
|
||||
all_needed.difference_update(symbols.defs)
|
||||
|
||||
# Go over libraries to figure out which we must include
|
||||
# If we have libcxx, we must force inclusion of libc, since libcxx uses new internally. Note: this is kind of hacky.
|
||||
has = need = None
|
||||
for name, create, apply_, library_symbols in [('libcxx', create_libcxx, apply_libcxx, libcxx_symbols),
|
||||
('libcextra', create_libcextra, lambda x: True, libcextra_symbols),
|
||||
('libcxxabi', create_libcxxabi, apply_libcxxabi, libcxxabi_symbols),
|
||||
('libc', create_libc, apply_libc, libc_symbols)]:
|
||||
force_this = force_all or force == name
|
||||
if not force_this:
|
||||
need = set()
|
||||
has = set()
|
||||
for symbols in symbolses:
|
||||
for library_symbol in library_symbols:
|
||||
if library_symbol in symbols.undefs:
|
||||
need.add(library_symbol)
|
||||
if library_symbol in symbols.defs:
|
||||
has.add(library_symbol)
|
||||
for haz in has: # remove symbols that are supplied by another of the inputs
|
||||
if haz in need:
|
||||
need.remove(haz)
|
||||
if shared.Settings.VERBOSE: logging.debug('considering %s: we need %s and have %s' % (name, str(need), str(has)))
|
||||
if force_this or len(need) > 0:
|
||||
force_all = True
|
||||
if apply_(need):
|
||||
# We need to build and link the library in
|
||||
logging.debug('including %s' % name)
|
||||
libfile = shared.Cache.get(name, create)
|
||||
extra_files_to_link.append(libfile)
|
||||
extra_files_to_link = system_libs.calculate(temp_files)
|
||||
else:
|
||||
extra_files_to_link = []
|
||||
|
||||
log_time('calculate system libraries')
|
||||
|
||||
|
|
|
@ -0,0 +1,384 @@
|
|||
import os, json, logging
|
||||
import shared
|
||||
|
||||
def calculate(temp_files):
|
||||
# Check if we need to include some libraries that we compile. (We implement libc ourselves in js, but
|
||||
# compile a malloc implementation and stdlibc++.)
|
||||
|
||||
def read_symbols(path, exclude=None):
|
||||
symbols = map(lambda line: line.strip().split(' ')[1], open(path).readlines())
|
||||
if exclude:
|
||||
symbols = filter(lambda symbol: symbol not in exclude, symbols)
|
||||
return set(symbols)
|
||||
|
||||
lib_opts = ['-O2']
|
||||
|
||||
# XXX We also need to add libc symbols that use malloc, for example strdup. It's very rare to use just them and not
|
||||
# a normal malloc symbol (like free, after calling strdup), so we haven't hit this yet, but it is possible.
|
||||
libc_symbols = read_symbols(shared.path_from_root('system', 'lib', 'libc.symbols'))
|
||||
libcextra_symbols = read_symbols(shared.path_from_root('system', 'lib', 'libcextra.symbols'))
|
||||
libcxx_symbols = read_symbols(shared.path_from_root('system', 'lib', 'libcxx', 'symbols'), exclude=libc_symbols)
|
||||
libcxxabi_symbols = read_symbols(shared.path_from_root('system', 'lib', 'libcxxabi', 'symbols'), exclude=libc_symbols)
|
||||
|
||||
# XXX we should disable EMCC_DEBUG when building libs, just like in the relooper
|
||||
|
||||
def build_libc(lib_filename, files):
|
||||
o_s = []
|
||||
prev_cxx = os.environ.get('EMMAKEN_CXX')
|
||||
if prev_cxx: os.environ['EMMAKEN_CXX'] = ''
|
||||
musl_internal_includes = shared.path_from_root('system', 'lib', 'libc', 'musl', 'src', 'internal')
|
||||
for src in files:
|
||||
o = in_temp(os.path.basename(src) + '.o')
|
||||
execute([shared.PYTHON, shared.EMCC, shared.path_from_root('system', 'lib', src), '-o', o, '-I', musl_internal_includes] + lib_opts, stdout=stdout, stderr=stderr)
|
||||
o_s.append(o)
|
||||
if prev_cxx: os.environ['EMMAKEN_CXX'] = prev_cxx
|
||||
shared.Building.link(o_s, in_temp(lib_filename))
|
||||
return in_temp(lib_filename)
|
||||
|
||||
def build_libcxx(src_dirname, lib_filename, files):
|
||||
o_s = []
|
||||
for src in files:
|
||||
o = in_temp(src + '.o')
|
||||
srcfile = shared.path_from_root(src_dirname, src)
|
||||
execute([shared.PYTHON, shared.EMXX, srcfile, '-o', o, '-std=c++11'] + lib_opts, stdout=stdout, stderr=stderr)
|
||||
o_s.append(o)
|
||||
shared.Building.link(o_s, in_temp(lib_filename))
|
||||
return in_temp(lib_filename)
|
||||
|
||||
# libc
|
||||
def create_libc():
|
||||
logging.debug(' building libc for cache')
|
||||
libc_files = [
|
||||
'dlmalloc.c',
|
||||
os.path.join('libcxx', 'new.cpp'),
|
||||
]
|
||||
musl_files = [
|
||||
['internal', [
|
||||
'floatscan.c',
|
||||
'shgetc.c',
|
||||
]],
|
||||
['math', [
|
||||
'scalbn.c',
|
||||
'scalbnl.c',
|
||||
]],
|
||||
['stdio', [
|
||||
'__overflow.c',
|
||||
'__toread.c',
|
||||
'__towrite.c',
|
||||
'__uflow.c',
|
||||
]],
|
||||
['stdlib', [
|
||||
'atof.c',
|
||||
'strtod.c',
|
||||
]],
|
||||
['string', [
|
||||
'memcmp.c',
|
||||
'strcasecmp.c',
|
||||
'strcmp.c',
|
||||
'strncasecmp.c',
|
||||
'strncmp.c',
|
||||
]]
|
||||
]
|
||||
for directory, sources in musl_files:
|
||||
libc_files += [os.path.join('libc', 'musl', 'src', directory, source) for source in sources]
|
||||
return build_libc('libc.bc', libc_files)
|
||||
|
||||
def apply_libc(need):
|
||||
# libc needs some sign correction. # If we are in mode 0, switch to 2. We will add our lines
|
||||
try:
|
||||
if shared.Settings.CORRECT_SIGNS == 0: raise Exception('we need to change to 2')
|
||||
except: # we fail if equal to 0 - so we need to switch to 2 - or if CORRECT_SIGNS is not even in Settings
|
||||
shared.Settings.CORRECT_SIGNS = 2
|
||||
if shared.Settings.CORRECT_SIGNS == 2:
|
||||
shared.Settings.CORRECT_SIGNS_LINES = [shared.path_from_root('src', 'dlmalloc.c') + ':' + str(i+4) for i in [4816, 4191, 4246, 4199, 4205, 4235, 4227]]
|
||||
# If we are in mode 1, we are correcting everything anyhow. If we are in mode 3, we will be corrected
|
||||
# so all is well anyhow too.
|
||||
return True
|
||||
|
||||
# libcextra
|
||||
def create_libcextra():
|
||||
logging.debug('building libcextra for cache')
|
||||
musl_files = [
|
||||
['ctype', [
|
||||
'iswalnum.c',
|
||||
'iswalpha.c',
|
||||
'iswblank.c',
|
||||
'iswcntrl.c',
|
||||
'iswctype.c',
|
||||
'iswdigit.c',
|
||||
'iswgraph.c',
|
||||
'iswlower.c',
|
||||
'iswprint.c',
|
||||
'iswpunct.c',
|
||||
'iswspace.c',
|
||||
'iswupper.c',
|
||||
'iswxdigit.c',
|
||||
'towctrans.c',
|
||||
'wcswidth.c',
|
||||
'wctrans.c',
|
||||
'wcwidth.c',
|
||||
]],
|
||||
['internal', [
|
||||
'intscan.c',
|
||||
]],
|
||||
['legacy', [
|
||||
'err.c',
|
||||
]],
|
||||
['locale', [
|
||||
'iconv.c',
|
||||
'iswalnum_l.c',
|
||||
'iswalpha_l.c',
|
||||
'iswblank_l.c',
|
||||
'iswcntrl_l.c',
|
||||
'iswctype_l.c',
|
||||
'iswdigit_l.c',
|
||||
'iswgraph_l.c',
|
||||
'iswlower_l.c',
|
||||
'iswprint_l.c',
|
||||
'iswpunct_l.c',
|
||||
'iswspace_l.c',
|
||||
'iswupper_l.c',
|
||||
'iswxdigit_l.c',
|
||||
'strcoll.c',
|
||||
'strcasecmp_l.c',
|
||||
'strfmon.c',
|
||||
'strncasecmp_l.c',
|
||||
'strxfrm.c',
|
||||
'towctrans_l.c',
|
||||
'towlower_l.c',
|
||||
'towupper_l.c',
|
||||
'wcscoll.c',
|
||||
'wcscoll_l.c',
|
||||
'wcsxfrm.c',
|
||||
'wcsxfrm_l.c',
|
||||
'wctrans_l.c',
|
||||
'wctype_l.c',
|
||||
]],
|
||||
['math', [
|
||||
'__cos.c',
|
||||
'__cosdf.c',
|
||||
'__sin.c',
|
||||
'__sindf.c',
|
||||
'ilogb.c',
|
||||
'ilogbf.c',
|
||||
'ilogbl.c',
|
||||
'ldexp.c',
|
||||
'ldexpf.c',
|
||||
'ldexpl.c',
|
||||
'logb.c',
|
||||
'logbf.c',
|
||||
'logbl.c',
|
||||
'lgamma.c',
|
||||
'lgamma_r.c',
|
||||
'lgammaf.c',
|
||||
'lgammaf_r.c',
|
||||
'lgammal.c',
|
||||
'scalbnf.c',
|
||||
'signgam.c',
|
||||
'tgamma.c',
|
||||
'tgammaf.c',
|
||||
'tgammal.c'
|
||||
]],
|
||||
['misc', [
|
||||
'getopt.c',
|
||||
'getopt_long.c',
|
||||
]],
|
||||
['multibyte', [
|
||||
'btowc.c',
|
||||
'mblen.c',
|
||||
'mbrlen.c',
|
||||
'mbrtowc.c',
|
||||
'mbsinit.c',
|
||||
'mbsnrtowcs.c',
|
||||
'mbsrtowcs.c',
|
||||
'mbstowcs.c',
|
||||
'mbtowc.c',
|
||||
'wcrtomb.c',
|
||||
'wcsnrtombs.c',
|
||||
'wcsrtombs.c',
|
||||
'wcstombs.c',
|
||||
'wctob.c',
|
||||
'wctomb.c',
|
||||
]],
|
||||
['regex', [
|
||||
'fnmatch.c',
|
||||
'regcomp.c',
|
||||
'regerror.c',
|
||||
'regexec.c',
|
||||
'tre-mem.c',
|
||||
]],
|
||||
['stdio', [
|
||||
'fwprintf.c',
|
||||
'swprintf.c',
|
||||
'vfwprintf.c',
|
||||
'vswprintf.c',
|
||||
'vwprintf.c',
|
||||
'wprintf.c',
|
||||
'fputwc.c',
|
||||
'fputws.c',
|
||||
]],
|
||||
['stdlib', [
|
||||
'ecvt.c',
|
||||
'fcvt.c',
|
||||
'gcvt.c',
|
||||
'wcstod.c',
|
||||
'wcstol.c',
|
||||
]],
|
||||
['string', [
|
||||
'memccpy.c',
|
||||
'memmem.c',
|
||||
'mempcpy.c',
|
||||
'memrchr.c',
|
||||
'strcasestr.c',
|
||||
'strchrnul.c',
|
||||
'strlcat.c',
|
||||
'strlcpy.c',
|
||||
'strsep.c',
|
||||
'strverscmp.c',
|
||||
'wcpcpy.c',
|
||||
'wcpncpy.c',
|
||||
'wcscasecmp.c',
|
||||
'wcscasecmp_l.c',
|
||||
'wcscat.c',
|
||||
'wcschr.c',
|
||||
'wcscmp.c',
|
||||
'wcscpy.c',
|
||||
'wcscspn.c',
|
||||
'wcsdup.c',
|
||||
'wcslen.c',
|
||||
'wcsncasecmp.c',
|
||||
'wcsncasecmp_l.c',
|
||||
'wcsncat.c',
|
||||
'wcsncmp.c',
|
||||
'wcsncpy.c',
|
||||
'wcsnlen.c',
|
||||
'wcspbrk.c',
|
||||
'wcsrchr.c',
|
||||
'wcsspn.c',
|
||||
'wcsstr.c',
|
||||
'wcstok.c',
|
||||
'wcswcs.c',
|
||||
'wmemchr.c',
|
||||
'wmemcmp.c',
|
||||
'wmemcpy.c',
|
||||
'wmemmove.c',
|
||||
'wmemset.c',
|
||||
]]
|
||||
]
|
||||
libcextra_files = []
|
||||
for directory, sources in musl_files:
|
||||
libcextra_files += [os.path.join('libc', 'musl', 'src', directory, source) for source in sources]
|
||||
return build_libc('libcextra.bc', libcextra_files)
|
||||
|
||||
# libcxx
|
||||
def create_libcxx():
|
||||
logging.debug('building libcxx for cache')
|
||||
libcxx_files = [
|
||||
'algorithm.cpp',
|
||||
'condition_variable.cpp',
|
||||
'future.cpp',
|
||||
'iostream.cpp',
|
||||
'memory.cpp',
|
||||
'random.cpp',
|
||||
'stdexcept.cpp',
|
||||
'system_error.cpp',
|
||||
'utility.cpp',
|
||||
'bind.cpp',
|
||||
'debug.cpp',
|
||||
'hash.cpp',
|
||||
'mutex.cpp',
|
||||
'string.cpp',
|
||||
'thread.cpp',
|
||||
'valarray.cpp',
|
||||
'chrono.cpp',
|
||||
'exception.cpp',
|
||||
'ios.cpp',
|
||||
'locale.cpp',
|
||||
'regex.cpp',
|
||||
'strstream.cpp'
|
||||
]
|
||||
return build_libcxx(os.path.join('system', 'lib', 'libcxx'), 'libcxx.bc', libcxx_files)
|
||||
|
||||
def apply_libcxx(need):
|
||||
assert shared.Settings.QUANTUM_SIZE == 4, 'We do not support libc++ with QUANTUM_SIZE == 1'
|
||||
# libcxx might need corrections, so turn them all on. TODO: check which are actually needed
|
||||
shared.Settings.CORRECT_SIGNS = shared.Settings.CORRECT_OVERFLOWS = shared.Settings.CORRECT_ROUNDINGS = 1
|
||||
#logging.info('using libcxx turns on CORRECT_* options')
|
||||
return True
|
||||
|
||||
# libcxxabi - just for dynamic_cast for now
|
||||
def create_libcxxabi():
|
||||
logging.debug('building libcxxabi for cache')
|
||||
libcxxabi_files = [
|
||||
'typeinfo.cpp',
|
||||
'private_typeinfo.cpp'
|
||||
]
|
||||
return build_libcxx(os.path.join('system', 'lib', 'libcxxabi', 'src'), 'libcxxabi.bc', libcxxabi_files)
|
||||
|
||||
def apply_libcxxabi(need):
|
||||
assert shared.Settings.QUANTUM_SIZE == 4, 'We do not support libc++abi with QUANTUM_SIZE == 1'
|
||||
#logging.info('using libcxxabi, this may need CORRECT_* options')
|
||||
#shared.Settings.CORRECT_SIGNS = shared.Settings.CORRECT_OVERFLOWS = shared.Settings.CORRECT_ROUNDINGS = 1
|
||||
return True
|
||||
|
||||
# Settings this in the environment will avoid checking dependencies and make building big projects a little faster
|
||||
# 1 means include everything; otherwise it can be the name of a lib (libcxx, etc.)
|
||||
force = os.environ.get('EMCC_FORCE_STDLIBS')
|
||||
force_all = force == '1'
|
||||
|
||||
# Scan symbols
|
||||
symbolses = map(lambda temp_file: shared.Building.llvm_nm(temp_file), temp_files)
|
||||
|
||||
# Add in some hacks for js libraries. If a js lib depends on a symbol provided by a C library, it must be
|
||||
# added to here, because our deps go only one way (each library here is checked, then we check the next
|
||||
# in order - libcxx, libcxextra, etc. - and then we run the JS compiler and provide extra symbols from
|
||||
# library*.js files. But we cannot then go back to the C libraries if a new dep was added!
|
||||
# TODO: Move all __deps from src/library*.js to deps_info.json, and use that single source of info
|
||||
# both here and in the JS compiler.
|
||||
deps_info = json.loads(open(shared.path_from_root('src', 'deps_info.json')).read())
|
||||
def add_back_deps(need):
|
||||
for ident, deps in deps_info.iteritems():
|
||||
if ident in need.undefs:
|
||||
for dep in deps:
|
||||
need.undefs.add(dep)
|
||||
shared.Settings.EXPORTED_FUNCTIONS.append('_' + dep)
|
||||
for symbols in symbolses:
|
||||
add_back_deps(symbols)
|
||||
|
||||
all_needed = set()
|
||||
for symbols in symbolses:
|
||||
all_needed.update(symbols.undefs)
|
||||
for symbols in symbolses:
|
||||
all_needed.difference_update(symbols.defs)
|
||||
|
||||
# Go over libraries to figure out which we must include
|
||||
# If we have libcxx, we must force inclusion of libc, since libcxx uses new internally. Note: this is kind of hacky.
|
||||
ret = []
|
||||
has = need = None
|
||||
for name, create, apply_, library_symbols in [('libcxx', create_libcxx, apply_libcxx, libcxx_symbols),
|
||||
('libcextra', create_libcextra, lambda x: True, libcextra_symbols),
|
||||
('libcxxabi', create_libcxxabi, apply_libcxxabi, libcxxabi_symbols),
|
||||
('libc', create_libc, apply_libc, libc_symbols)]:
|
||||
force_this = force_all or force == name
|
||||
if not force_this:
|
||||
need = set()
|
||||
has = set()
|
||||
for symbols in symbolses:
|
||||
for library_symbol in library_symbols:
|
||||
if library_symbol in symbols.undefs:
|
||||
need.add(library_symbol)
|
||||
if library_symbol in symbols.defs:
|
||||
has.add(library_symbol)
|
||||
for haz in has: # remove symbols that are supplied by another of the inputs
|
||||
if haz in need:
|
||||
need.remove(haz)
|
||||
if shared.Settings.VERBOSE: logging.debug('considering %s: we need %s and have %s' % (name, str(need), str(has)))
|
||||
if force_this or len(need) > 0:
|
||||
force_all = True
|
||||
if apply_(need):
|
||||
# We need to build and link the library in
|
||||
logging.debug('including %s' % name)
|
||||
libfile = shared.Cache.get(name, create)
|
||||
ret.append(libfile)
|
||||
return ret
|
||||
|
Загрузка…
Ссылка в новой задаче