aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2014-02-08 12:14:56 -0800
committerAlon Zakai <alonzakai@gmail.com>2014-02-08 12:14:56 -0800
commit157f3151a43e02b6c335c312a3f78bac0d0110eb (patch)
tree63116ffd0784a7e1e6e5bc77f9222429f1afbf9c
parent7ec33d39d7a45992688a84dd0cf38ae992c3d710 (diff)
move system libs calculation to its own file
-rwxr-xr-xemcc385
-rw-r--r--tools/system_libs.py384
2 files changed, 388 insertions, 381 deletions
diff --git a/emcc b/emcc
index 9f62d180..a77e2c4f 100755
--- a/emcc
+++ b/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')
diff --git a/tools/system_libs.py b/tools/system_libs.py
new file mode 100644
index 00000000..42c9d67c
--- /dev/null
+++ b/tools/system_libs.py
@@ -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
+