diff --git a/AUTHORS b/AUTHORS index 137efb000e3cc..dc848d343384c 100644 --- a/AUTHORS +++ b/AUTHORS @@ -139,3 +139,6 @@ a license to everyone to use it as detailed in LICENSE.) * Usagi Ito * Camilo Polymeris * Markus Henschel +* Ophir Lojkine +* Ryan Sturgell (copyright owned by Google, Inc.) + diff --git a/emcc b/emcc index 2dc525af461e6..1a645965741dc 100755 --- a/emcc +++ b/emcc @@ -1098,12 +1098,24 @@ try: # Find input files + # These three arrays are used to store arguments of different types for + # type-specific processing. In order to shuffle the arguments back together + # after processing, all of these arrays hold tuples (original_index, value). + # Note that the index part of the tuple can have a fractional part for input + # arguments that expand into multiple processed arguments, as in -Wl,-f1,-f2. input_files = [] + libs = [] + link_flags = [] + + # All of the above arg lists entries contain indexes into the full argument + # list. In order to add extra implicit args (embind.cc, etc) below, we keep a + # counter for the next index that should be used. + next_arg_index = len(newargs) + has_source_inputs = False has_header_inputs = False lib_dirs = [shared.path_from_root('system', 'local', 'lib'), shared.path_from_root('system', 'lib')] - libs = [] for i in range(len(newargs)): # find input files XXX this a simple heuristic. we should really analyze based on a full understanding of gcc params, # right now we just assume that what is left contains no more |-x OPT| things arg = newargs[i] @@ -1124,13 +1136,13 @@ try: if arg_ending.endswith(SOURCE_ENDINGS + BITCODE_ENDINGS + DYNAMICLIB_ENDINGS + ASSEMBLY_ENDINGS + HEADER_ENDINGS) or shared.Building.is_ar(arg): # we already removed -o , so all these should be inputs newargs[i] = '' if arg_ending.endswith(SOURCE_ENDINGS): - input_files.append(arg) + input_files.append((i, arg)) has_source_inputs = True elif arg_ending.endswith(HEADER_ENDINGS): - input_files.append(arg) + input_files.append((i, arg)) has_header_inputs = True elif arg_ending.endswith(ASSEMBLY_ENDINGS) or shared.Building.is_bitcode(arg): # this should be bitcode, make sure it is valid - input_files.append(arg) + input_files.append((i, arg)) elif arg_ending.endswith(STATICLIB_ENDINGS + DYNAMICLIB_ENDINGS): # if it's not, and it's a library, just add it to libs to find later l = unsuffixed_basename(arg) @@ -1139,7 +1151,7 @@ try: if l.startswith(prefix): l = l[len(prefix):] break - libs.append(l) + libs.append((i, l)) newargs[i] = '' else: logging.warning(arg + ' is not valid LLVM bitcode') @@ -1157,7 +1169,15 @@ try: lib_dirs.append(arg[2:]) newargs[i] = '' elif arg.startswith('-l'): - libs.append(arg[2:]) + libs.append((i, arg[2:])) + newargs[i] = '' + elif arg.startswith('-Wl,'): + # Multiple comma separated link flags can be specified. Create fake + # fractional indices for these: -Wl,a,b,c,d at index 4 becomes: + # (4, a), (4.25, b), (4.5, c), (4.75, d) + link_flags_to_add = arg.split(',')[1:] + for flag_index, flag in enumerate(link_flags_to_add): + link_flags.append((i + float(flag_index) / len(link_flags_to_add), flag)) newargs[i] = '' original_input_files = input_files[:] @@ -1173,7 +1193,7 @@ try: final_ending = ('.' + final_suffix) if len(final_suffix) > 0 else '' # Find library files - for lib in libs: + for i, lib in libs: logging.debug('looking for library "%s"', lib) found = False for prefix in LIB_PREFIXES: @@ -1183,7 +1203,7 @@ try: path = os.path.join(lib_dir, name) if os.path.exists(path): logging.debug('found library "%s" at %s', lib, path) - input_files.append(path) + input_files.append((i, path)) found = True break if found: break @@ -1199,7 +1219,7 @@ try: return False else: return True - input_files = [input_file for input_file in input_files if check(input_file)] + input_files = [(i, input_file) for (i, input_file) in input_files if check(input_file)] if len(input_files) == 0: logging.error('no input files\nnote that input files without a known suffix are ignored, make sure your input files end with one of: ' + str(SOURCE_ENDINGS + BITCODE_ENDINGS + DYNAMICLIB_ENDINGS + STATICLIB_ENDINGS + ASSEMBLY_ENDINGS + HEADER_ENDINGS)) @@ -1211,7 +1231,8 @@ try: # If we are using embind and generating JS, now is the time to link in bind.cpp if bind and final_suffix in JS_CONTAINING_SUFFIXES: - input_files.append(shared.path_from_root('system', 'lib', 'embind', 'bind.cpp')) + input_files.append((next_arg_index, shared.path_from_root('system', 'lib', 'embind', 'bind.cpp'))) + next_arg_index += 1 # Apply optimization level settings shared.Settings.apply_opt_level(opt_level, noisy=True) @@ -1331,7 +1352,8 @@ try: logging.warning('ALIASING_FUNCTION_POINTERS is on, function pointer comparisons may be invalid across types') if shared.Settings.STB_IMAGE and final_suffix in JS_CONTAINING_SUFFIXES: - input_files.append(shared.path_from_root('third_party', 'stb_image.c')) + input_files.append((next_arg_index, shared.path_from_root('third_party', 'stb_image.c'))) + next_arg_index += 1 shared.Settings.EXPORTED_FUNCTIONS += ['_stbi_load', '_stbi_load_from_memory', '_stbi_image_free'] if type(shared.Settings.EXPORTED_FUNCTIONS) in (list, tuple): @@ -1365,9 +1387,10 @@ try: # Precompiled headers support if has_header_inputs: - for header in input_files: - assert header.endswith(HEADER_ENDINGS), 'if you have one header input, we assume you want to precompile headers, and cannot have source files or other inputs as well: ' + str(input_files) + ' : ' + header - args = newargs + shared.EMSDK_CXX_OPTS + input_files + headers = [header for _, header in input_files] + for header in headers: + assert header.endswith(HEADER_ENDINGS), 'if you have one header input, we assume you want to precompile headers, and cannot have source files or other inputs as well: ' + str(headers) + ' : ' + header + args = newargs + shared.EMSDK_CXX_OPTS + headers if specified_target: args += ['-o', specified_target] logging.debug("running (for precompiled headers): " + call + ' ' + ' '.join(args)) @@ -1388,12 +1411,12 @@ try: return in_temp(unsuffixed(uniquename(input_file)) + default_object_extension) # First, generate LLVM bitcode. For each input file, we get base.o with bitcode - for input_file in input_files: + for i, input_file in input_files: file_ending = filename_type_ending(input_file) if file_ending.endswith(SOURCE_ENDINGS): logging.debug('compiling source file: ' + input_file) output_file = get_bitcode_file(input_file) - temp_files.append(output_file) + temp_files.append((i, output_file)) args = newargs + ['-emit-llvm', '-c', input_file, '-o', output_file] if file_ending.endswith(CXX_ENDINGS): args += shared.EMSDK_CXX_OPTS @@ -1407,18 +1430,18 @@ try: logging.debug('copying bitcode file: ' + input_file) temp_file = in_temp(unsuffixed(uniquename(input_file)) + '.o') shutil.copyfile(input_file, temp_file) - temp_files.append(temp_file) + temp_files.append((i, temp_file)) elif file_ending.endswith(DYNAMICLIB_ENDINGS) or shared.Building.is_ar(input_file): logging.debug('copying library file: ' + input_file) temp_file = in_temp(uniquename(input_file)) shutil.copyfile(input_file, temp_file) - temp_files.append(temp_file) + temp_files.append((i, temp_file)) elif file_ending.endswith(ASSEMBLY_ENDINGS): if not LEAVE_INPUTS_RAW: logging.debug('assembling assembly file: ' + input_file) temp_file = in_temp(unsuffixed(uniquename(input_file)) + '.o') shared.Building.llvm_as(input_file, temp_file) - temp_files.append(temp_file) + temp_files.append((i, temp_file)) else: logging.error(input_file + ': Unknown file suffix when compiling to LLVM bitcode!') sys.exit(1) @@ -1430,10 +1453,10 @@ try: # Optimize source files if llvm_opts > 0: - for i, input_file in enumerate(input_files): + for pos, (_, input_file) in enumerate(input_files): file_ending = filename_type_ending(input_file) if file_ending.endswith(SOURCE_ENDINGS): - temp_file = temp_files[i] + (_, temp_file) = temp_files[pos] logging.debug('optimizing %s', input_file) #if DEBUG: shutil.copyfile(temp_file, os.path.join(TEMP_DIR, 'to_opt.bc') # useful when LLVM opt aborts shared.Building.llvm_opt(temp_file, llvm_opts) @@ -1441,26 +1464,30 @@ try: # If we were just asked to generate bitcode, stop there if final_suffix not in JS_CONTAINING_SUFFIXES: if not specified_target: - for input_file in input_files: + for _, input_file in input_files: safe_move(get_bitcode_file(input_file), unsuffixed_basename(input_file) + final_ending) else: if len(input_files) == 1: - safe_move(temp_files[0], specified_target if specified_target else unsuffixed_basename(input_file) + final_ending) - temp_output_base = unsuffixed(temp_files[0]) + _, input_file = input_files[0] + _, temp_file = temp_files[0] + safe_move(temp_file, specified_target if specified_target else unsuffixed_basename(input_file) + final_ending) + temp_output_base = unsuffixed(temp_file) if os.path.exists(temp_output_base + '.d'): # There was a .d file generated, from -MD or -MMD and friends, save a copy of it to where the output resides, # adjusting the target name away from the temporary file name to the specified target. # It will be deleted with the rest of the temporary directory. deps = open(temp_output_base + '.d').read() deps = deps.replace(temp_output_base + default_object_extension, specified_target) - with open(os.path.join(os.path.dirname(specified_target), os.path.basename(unsuffixed(input_files[0]) + '.d')), "w") as out_dep: + with open(os.path.join(os.path.dirname(specified_target), os.path.basename(unsuffixed(input_file) + '.d')), "w") as out_dep: out_dep.write(deps) else: assert len(original_input_files) == 1 or not has_dash_c, 'fatal error: cannot specify -o with -c with multiple files' + str(sys.argv) + ':' + str(original_input_files) # We have a specified target (-o ), which is not JavaScript or HTML, and # we have multiple files: Link them logging.debug('link: ' + str(temp_files) + specified_target) - shared.Building.link(temp_files, specified_target) + # Sort arg tuples and pass the extracted values to link. + link_args = [f for (i, f) in sorted(temp_files)] + shared.Building.link(link_args, specified_target) logging.debug('stopping at bitcode') exit(0) @@ -1473,7 +1500,7 @@ try: 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 - extra_files_to_link = system_libs.calculate(temp_files, in_temp, stdout, stderr) + extra_files_to_link = system_libs.calculate([f for _, f in sorted(temp_files)], in_temp, stdout, stderr) else: extra_files_to_link = [] @@ -1481,18 +1508,20 @@ try: # First, combine the bitcode files if there are several. We must also link if we have a singleton .a if len(input_files) + len(extra_files_to_link) > 1 or \ - (not LEAVE_INPUTS_RAW and not (suffix(temp_files[0]) in BITCODE_ENDINGS or suffix(temp_files[0]) in DYNAMICLIB_ENDINGS) and shared.Building.is_ar(temp_files[0])): - linker_inputs = temp_files + extra_files_to_link + (not LEAVE_INPUTS_RAW and not (suffix(temp_files[0][1]) in BITCODE_ENDINGS or suffix(temp_files[0][1]) in DYNAMICLIB_ENDINGS) and shared.Building.is_ar(temp_files[0][1])): + linker_inputs = [val for _, val in sorted(temp_files + link_flags)] + extra_files_to_link logging.debug('linking: ' + str(linker_inputs)) - shared.Building.link(linker_inputs, in_temp(target_basename + '.bc'), force_archive_contents=len([temp for temp in temp_files if not temp.endswith(STATICLIB_ENDINGS)]) == 0) + shared.Building.link(linker_inputs, in_temp(target_basename + '.bc'), force_archive_contents=len([temp for i, temp in temp_files if not temp.endswith(STATICLIB_ENDINGS)]) == 0) final = in_temp(target_basename + '.bc') else: if not LEAVE_INPUTS_RAW: - shutil.move(temp_files[0], in_temp(target_basename + '.bc')) + _, temp_file = temp_files[0] + shutil.move(temp_file, in_temp(target_basename + '.bc')) final = in_temp(target_basename + '.bc') else: - final = in_temp(input_files[0]) - shutil.copyfile(input_files[0], final) + _, input_file = input_files[0] + final = in_temp(input_file) + shutil.copyfile(input_file, final) log_time('link') diff --git a/emscripten-version.txt b/emscripten-version.txt index 1992f2ad5b1af..18abf253a38f3 100644 --- a/emscripten-version.txt +++ b/emscripten-version.txt @@ -1,2 +1,2 @@ -1.18.2 +1.18.3 diff --git a/src/library.js b/src/library.js index 0d649258a3e5d..9dd2aedc8149b 100644 --- a/src/library.js +++ b/src/library.js @@ -3222,39 +3222,6 @@ LibraryManager.library = { {{{ makeStructuralReturn([makeGetTempDouble(0, 'i32'), makeGetTempDouble(1, 'i32')]) }}}; }, #endif - strtoll__deps: ['_parseInt64'], - strtoll: function(str, endptr, base) { - return __parseInt64(str, endptr, base, '-9223372036854775808', '9223372036854775807'); // LLONG_MIN, LLONG_MAX. - }, - strtoll_l__deps: ['strtoll'], - strtoll_l: function(str, endptr, base) { - return _strtoll(str, endptr, base); // no locale support yet - }, - strtol__deps: ['_parseInt'], - strtol: function(str, endptr, base) { - return __parseInt(str, endptr, base, -2147483648, 2147483647, 32); // LONG_MIN, LONG_MAX. - }, - strtol_l__deps: ['strtol'], - strtol_l: function(str, endptr, base) { - return _strtol(str, endptr, base); // no locale support yet - }, - strtoul__deps: ['_parseInt'], - strtoul: function(str, endptr, base) { - return __parseInt(str, endptr, base, 0, 4294967295, 32, true); // ULONG_MAX. - }, - strtoul_l__deps: ['strtoul'], - strtoul_l: function(str, endptr, base) { - return _strtoul(str, endptr, base); // no locale support yet - }, - strtoull__deps: ['_parseInt64'], - strtoull: function(str, endptr, base) { - return __parseInt64(str, endptr, base, 0, '18446744073709551615', true); // ULONG_MAX. - }, - strtoull_l__deps: ['strtoull'], - strtoull_l: function(str, endptr, base) { - return _strtoull(str, endptr, base); // no locale support yet - }, - environ: 'allocate(1, "i32*", ALLOC_STATIC)', __environ__deps: ['environ'], __environ: '_environ', @@ -3619,28 +3586,6 @@ LibraryManager.library = { return pdest|0; }, - strlwr__deps:['tolower'], - strlwr: function(pstr){ - var i = 0; - while(1) { - var x = {{{ makeGetValue('pstr', 'i', 'i8') }}}; - if (x == 0) break; - {{{ makeSetValue('pstr', 'i', '_tolower(x)', 'i8') }}}; - i++; - } - }, - - strupr__deps:['toupper'], - strupr: function(pstr){ - var i = 0; - while(1) { - var x = {{{ makeGetValue('pstr', 'i', 'i8') }}}; - if (x == 0) break; - {{{ makeSetValue('pstr', 'i', '_toupper(x)', 'i8') }}}; - i++; - } - }, - strcat__asm: true, strcat__sig: 'iii', strcat__deps: ['strlen'], @@ -3681,132 +3626,6 @@ LibraryManager.library = { // ctype.h // ========================================================================== - isascii: function(chr) { - return chr >= 0 && (chr & 0x80) == 0; - }, - toascii: function(chr) { - return chr & 0x7F; - }, - toupper: function(chr) { - if (chr >= {{{ charCode('a') }}} && chr <= {{{ charCode('z') }}}) { - return chr - {{{ charCode('a') }}} + {{{ charCode('A') }}}; - } else { - return chr; - } - }, - _toupper: 'toupper', - toupper_l__deps: ['toupper'], - toupper_l: function(str, endptr, base) { - return _toupper(str, endptr, base); // no locale support yet - }, - - tolower__asm: true, - tolower__sig: 'ii', - tolower: function(chr) { - chr = chr|0; - if ((chr|0) < {{{ charCode('A') }}}) return chr|0; - if ((chr|0) > {{{ charCode('Z') }}}) return chr|0; - return (chr - {{{ charCode('A') }}} + {{{ charCode('a') }}})|0; - }, - _tolower: 'tolower', - tolower_l__deps: ['tolower'], - tolower_l: function(chr) { - return _tolower(chr); // no locale support yet - }, - - // The following functions are defined as macros in glibc. - islower: function(chr) { - return chr >= {{{ charCode('a') }}} && chr <= {{{ charCode('z') }}}; - }, - islower_l__deps: ['islower'], - islower_l: function(chr) { - return _islower(chr); // no locale support yet - }, - isupper: function(chr) { - return chr >= {{{ charCode('A') }}} && chr <= {{{ charCode('Z') }}}; - }, - isupper_l__deps: ['isupper'], - isupper_l: function(chr) { - return _isupper(chr); // no locale support yet - }, - isalpha: function(chr) { - return (chr >= {{{ charCode('a') }}} && chr <= {{{ charCode('z') }}}) || - (chr >= {{{ charCode('A') }}} && chr <= {{{ charCode('Z') }}}); - }, - isalpha_l__deps: ['isalpha'], - isalpha_l: function(chr) { - return _isalpha(chr); // no locale support yet - }, - isdigit: function(chr) { - return chr >= {{{ charCode('0') }}} && chr <= {{{ charCode('9') }}}; - }, - isdigit_l__deps: ['isdigit'], - isdigit_l: function(chr) { - return _isdigit(chr); // no locale support yet - }, - isxdigit: function(chr) { - return (chr >= {{{ charCode('0') }}} && chr <= {{{ charCode('9') }}}) || - (chr >= {{{ charCode('a') }}} && chr <= {{{ charCode('f') }}}) || - (chr >= {{{ charCode('A') }}} && chr <= {{{ charCode('F') }}}); - }, - isxdigit_l__deps: ['isxdigit'], - isxdigit_l: function(chr) { - return _isxdigit(chr); // no locale support yet - }, - isalnum: function(chr) { - return (chr >= {{{ charCode('0') }}} && chr <= {{{ charCode('9') }}}) || - (chr >= {{{ charCode('a') }}} && chr <= {{{ charCode('z') }}}) || - (chr >= {{{ charCode('A') }}} && chr <= {{{ charCode('Z') }}}); - }, - isalnum_l__deps: ['isalnum'], - isalnum_l: function(chr) { - return _isalnum(chr); // no locale support yet - }, - ispunct: function(chr) { - return (chr >= {{{ charCode('!') }}} && chr <= {{{ charCode('/') }}}) || - (chr >= {{{ charCode(':') }}} && chr <= {{{ charCode('@') }}}) || - (chr >= {{{ charCode('[') }}} && chr <= {{{ charCode('`') }}}) || - (chr >= {{{ charCode('{') }}} && chr <= {{{ charCode('~') }}}); - }, - ispunct_l__deps: ['ispunct'], - ispunct_l: function(chr) { - return _ispunct(chr); // no locale support yet - }, - isspace: function(chr) { - return (chr == 32) || (chr >= 9 && chr <= 13); - }, - isspace_l__deps: ['isspace'], - isspace_l: function(chr) { - return _isspace(chr); // no locale support yet - }, - isblank: function(chr) { - return chr == {{{ charCode(' ') }}} || chr == {{{ charCode('\t') }}}; - }, - isblank_l__deps: ['isblank'], - isblank_l: function(chr) { - return _isblank(chr); // no locale support yet - }, - iscntrl: function(chr) { - return (0 <= chr && chr <= 0x1F) || chr === 0x7F; - }, - iscntrl_l__deps: ['iscntrl'], - iscntrl_l: function(chr) { - return _iscntrl(chr); // no locale support yet - }, - isprint: function(chr) { - return 0x1F < chr && chr < 0x7F; - }, - isprint_l__deps: ['isprint'], - isprint_l: function(chr) { - return _isprint(chr); // no locale support yet - }, - isgraph: function(chr) { - return 0x20 < chr && chr < 0x7F; - }, - isgraph_l__deps: ['isgraph'], - isgraph_l: function(chr) { - return _isgraph(chr); // no locale support yet - }, // Lookup tables for glibc ctype implementation. __ctype_b_loc__deps: ['malloc'], __ctype_b_loc: function() { diff --git a/src/library_sdl.js b/src/library_sdl.js index eabfe3e5eb817..d9639907b852e 100644 --- a/src/library_sdl.js +++ b/src/library_sdl.js @@ -943,11 +943,67 @@ var LibrarySDL = { var ret = info.volume * 128; // MIX_MAX_VOLUME if (volume != -1) { info.volume = volume / 128; - if (info.audio) info.audio.volume = info.volume; + if (info.audio) { + info.audio.volume = info.volume; // For