Merge remote-tracking branch 'upstream/master'

This commit is contained in:
max99x 2011-07-30 04:02:27 +03:00
Родитель efacab6cd2 da3cce7259
Коммит a6e44cf635
12 изменённых файлов: 266 добавлений и 121 удалений

Двоичные данные
docs/paper.pdf

Двоичный файл не отображается.

Просмотреть файл

@ -30,7 +30,7 @@
\begin{abstract}
We present Emscripten, a compiler from LLVM (Low Level Virtual Machine) assembly to JavaScript. This
opens up two avenues for running code written
in languages other than JavaScript on the web: (1) Compile code directly into LLVM assemby, and
in languages other than JavaScript on the web: (1) Compile code directly into LLVM assembly, and
then compile that into JavaScript using Emscripten, or (2) Compile
a language's entire runtime into LLVM and then JavaScript, as in the previous
approach, and then use the compiled runtime to run code written in that language. For example, the
@ -477,7 +477,7 @@ reading from memory before a value was written (somewhat similarly to tools
like Valgrind\footnote{\url{http://valgrind.org/}}). When such problems are detected, possible solutions are to ignore the issue (if it has no actual
consqeuences), or alter the source code.
Note that it is somewhat wasteful to allocation 4 memory locations for
Note that it is somewhat wasteful to allocate 4 memory locations for
a 32-bit integer, and use only one of them. It is possible to change
that behavior with the QUANTUM\_SIZE parameter to Emscripten, however,
the difficulty is that LLVM assembly has hardcoded values that depend on

Просмотреть файл

@ -13,13 +13,11 @@ COMPILER_OPTS = ['-m32', '-g'] # Need to build as 32bit arch, for now -
# various errors on 64bit compilation
# WARNING: '-g' here will generate llvm bitcode that lli will crash on!
SPIDERMONKEY_ENGINE = [os.path.expanduser('~/Dev/tracemonkey/js/src/js'), '-m', '-j', '-p']
SPIDERMONKEY_ENGINE = [os.path.expanduser('~/Dev/mozilla-central/js/src/js'), '-m', '-j', '-p']
V8_ENGINE = [os.path.expanduser('~/Dev/v8/d8')]
# XXX Warning: Compiling the 'cubescript' test in SpiderMonkey can lead to an extreme amount of memory being
# used, see Mozilla bug 593659. Possibly also some other tests as well.
#COMPILER_ENGINE=SPIDERMONKEY_ENGINE
COMPILER_ENGINE=V8_ENGINE
COMPILER_ENGINE=SPIDERMONKEY_ENGINE
#COMPILER_ENGINE=V8_ENGINE # XXX Warning: currently appears to be broken on v8 trunk, some arguments issue
JS_ENGINE=V8_ENGINE

Просмотреть файл

@ -1783,7 +1783,7 @@ LibraryManager.library = {
return -1;
}
},
getlogin: ['getlogin_r'],
getlogin__deps: ['getlogin_r'],
getlogin: function() {
// char *getlogin(void);
// http://pubs.opengroup.org/onlinepubs/000095399/functions/getlogin.html

Просмотреть файл

@ -235,7 +235,7 @@ var LibraryManager = {
load: function() {
assert(!this.library);
for (suffix in set('', '_sdl', '_gl', '_browser')) {
for (var suffix in set('', '_sdl', '_gl', '_browser')) {
eval(processMacros(preprocess(read('library' + suffix + '.js'), CONSTANTS)));
}
},

Просмотреть файл

@ -13,7 +13,7 @@ function processMacros(text) {
// Simple #if/else/endif preprocessing for a file. Checks if the
// ident checked is true in our global. Also replaces some constants.
function preprocess(text, constants) {
for (constant in constants) {
for (var constant in constants) {
text = text.replace(eval('/' + constant + '/g'), constants[constant]);
}
var lines = text.split('\n');

Просмотреть файл

@ -301,6 +301,43 @@ function assert(condition, text) {
}
}
// Sets a value in memory in a dynamic way at run-time. Uses the
// type data. This is the same as makeSetValue, except that
// makeSetValue is done at compile-time and generates the needed
// code then, whereas this function picks the right code at
// run-time.
function setValue(ptr, value, type) {
if (type[type.length-1] === '*') type = 'i32'; // pointers are 32-bit
switch(type) {
case 'i1': {{{ makeSetValue('ptr', '0', 'value', 'i1') }}}; break;
case 'i8': {{{ makeSetValue('ptr', '0', 'value', 'i8') }}}; break;
case 'i16': {{{ makeSetValue('ptr', '0', 'value', 'i16') }}}; break;
case 'i32': {{{ makeSetValue('ptr', '0', 'value', 'i32') }}}; break;
case 'i64': {{{ makeSetValue('ptr', '0', 'value', 'i64') }}}; break;
case 'float': {{{ makeSetValue('ptr', '0', 'value', 'float') }}}; break;
case 'double': {{{ makeSetValue('ptr', '0', 'value', 'double') }}}; break;
default: abort('invalid type for setValue: ' + type);
}
}
// Parallel to setValue.
function getValue(ptr, type) {
if (type[type.length-1] === '*') type = 'i32'; // pointers are 32-bit
switch(type) {
case 'i1': return {{{ makeGetValue('ptr', '0', 'i1') }}};
case 'i8': return {{{ makeGetValue('ptr', '0', 'i8') }}};
case 'i16': return {{{ makeGetValue('ptr', '0', 'i16') }}};
case 'i32': return {{{ makeGetValue('ptr', '0', 'i32') }}};
case 'i64': return {{{ makeGetValue('ptr', '0', 'i64') }}};
case 'float': return {{{ makeGetValue('ptr', '0', 'float') }}};
case 'double': return {{{ makeGetValue('ptr', '0', 'double') }}};
default: abort('invalid type for setValue: ' + type);
}
return null;
}
// Allocates memory for some data and initializes it properly.
var ALLOC_NORMAL = 0; // Tries to use _malloc()
@ -338,30 +375,8 @@ function allocate(slab, types, allocator) {
assert(type, 'Must know what type to store in allocate!');
#endif
if (type === 'i1') {
{{{ makeSetValue(0, 'ret+i', 'curr', 'i1') }}}
i += {{{ getNativeFieldSize('i1', true) }}};
} else if (type === 'i8') {
{{{ makeSetValue(0, 'ret+i', 'curr', 'i8') }}}
i += {{{ getNativeFieldSize('i8', true) }}};
} else if (type === 'i16') {
{{{ makeSetValue(0, 'ret+i', 'curr', 'i16') }}}
i += {{{ getNativeFieldSize('i16', true) }}};
} else if (type === 'i32' || type[type.length-1] === '*') { // hardcoded pointers as 32-bit
{{{ makeSetValue(0, 'ret+i', 'curr', 'i32') }}}
i += {{{ getNativeFieldSize('i32', true) }}};
} else if (type === 'float') {
{{{ makeSetValue(0, 'ret+i', 'curr', 'float') }}}
i += {{{ getNativeFieldSize('float', true) }}};
} else if (type === 'i64') {
{{{ makeSetValue(0, 'ret+i', 'curr', 'i64') }}}
i += {{{ getNativeFieldSize('i64', true) }}};
} else if (type === 'double') {
{{{ makeSetValue(0, 'ret+i', 'curr', 'double') }}}
i += {{{ getNativeFieldSize('double', true) }}};
} else {
abort('invalid type for allocate: ' + type);
}
setValue(ret+i, curr, type);
i += Runtime.getNativeFieldSize(type, true);
}
return ret;

Просмотреть файл

@ -13,9 +13,13 @@ if (!this['Module']) {
this['Module'] = {};
}
try {
Module.arguments = arguments;
Module.arguments = scriptArgs;
} catch(e) {
Module.arguments = [];
try {
Module.arguments = arguments;
} catch(e) {
Module.arguments = [];
}
}
//*/

Просмотреть файл

@ -2895,7 +2895,7 @@ if 'benchmark' not in sys.argv:
lambda: map(ord, open(path_from_root('tests', 'poppler', 'ref.ppm'), 'r').read()).__str__().replace(' ', ''),
args='-scale-to 512 paper.pdf filename'.split(' '),
post_build=post,
js_engines=[SPIDERMONKEY_ENGINE]) # V8 bug 1257
js_engines=[V8_ENGINE]) # XXX Moz bug 675269
#, build_ll_hook=self.do_autodebug)
def test_openjpeg(self):
@ -3141,12 +3141,14 @@ if 'benchmark' not in sys.argv:
Child1(int val) : Parent(val*2) { value -= 1; printf("Child1:%d\\n", value); };
int getValSqr() { return value*value; }
int getValSqr(int more) { return value*value*more; }
int getValTimes(int times=1) { return value*times; }
};
class Child2 : Parent {
class Child2 : public Parent {
public:
Child2() : Parent(9) { printf("Child2:%d\\n", value); };
int getValCube() { return value*value*value; }
static void printStatic() { printf("*static*\\n"); }
private:
void doSomethingSecret() { printf("security breached!\\n"); }; // we should not be able to do this
};
@ -3155,6 +3157,7 @@ if 'benchmark' not in sys.argv:
basename = os.path.join(self.get_dir(), 'bindingtest')
output = Popen([BINDINGS_GENERATOR, basename, header_filename], stdout=PIPE, stderr=STDOUT).communicate()[0]
#print output
assert 'Traceback' not in output, 'Failure in binding generation: ' + output
src = '''
@ -3179,16 +3182,18 @@ if 'benchmark' not in sys.argv:
c1.mulVal(2);
print(c1.getVal());
print(c1.getValSqr());
print(c1.getValSqr_2(3));
print(c1.getValSqr(3));
print(c1.getValTimes()); // default argument should be 1
print(c1.getValTimes(2));
print('c1 v2');
c1 = new Child1_2(8);
c1 = new Child1(8); // now with a parameter, we should handle the overloading automatically and properly and use constructor #2
print(c1.getVal());
c1.mulVal(2);
print(c1.getVal());
print(c1.getValSqr());
print(c1.getValSqr_2(3));
print(c1.getValSqr(3));
print('c2')
@ -3217,6 +3222,8 @@ if 'benchmark' not in sys.argv:
} catch(e) {}
print(succeeded);
Child2.prototype.printStatic(); // static calls go through the prototype
print('*ok*');
'''
@ -3236,6 +3243,8 @@ Child1:7
14
196
588
14
28
c1 v2
Parent:16
Child1:15
@ -3252,6 +3261,7 @@ Child2:9
0
0
1
*static*
*ok*
''', post_build=post2)
@ -3668,7 +3678,8 @@ else:
USE_CLOSURE_COMPILER = 1
if USE_CLOSURE_COMPILER:
SPIDERMONKEY_ENGINE = filter(lambda x: x != '-s', SPIDERMONKEY_ENGINE) # closure generates non-strict
index = SPIDERMONKEY_ENGINE.index("options('strict')")
SPIDERMONKEY_ENGINE = SPIDERMONKEY_ENGINE[:index-1] + SPIDERMONKEY_ENGINE[index+1:] # closure generates non-strict
COMPILER = CLANG
JS_ENGINE = SPIDERMONKEY_ENGINE

Просмотреть файл

@ -47,7 +47,7 @@ import CppHeaderParser
basename = sys.argv[1]
processor = lambda line: line
processor = lambda text: text
ignored = []
if '--' in sys.argv:
@ -62,54 +62,124 @@ if '--' in sys.argv:
classes = {}
struct_parents = {}
text = ''
for header in sys.argv[2:]:
text += '//// ' + header + '\n'
text += open(header, 'r').read()
all_h_name = basename + '.all.h'
all_h = open(all_h_name, 'w')
for header in sys.argv[2:]:
all_h.write('//// ' + header + '\n')
all_h.write(processor(open(header, 'r').read()))
all_h.write(processor(text))
all_h.close()
parsed = CppHeaderParser.CppHeader(all_h_name)
for cname, clazz in parsed.classes.iteritems():
#print 'zz see', cname
if len(clazz['methods']['public']) > 0: # Do not notice stub classes
#print 'zz for real', cname, clazz, dir(clazz)
classes[cname] = clazz
for sname, struct in clazz._public_structs.iteritems():
struct_parents[sname] = cname
#print 'zz seen struct %s in %s' % (sname, cname)
for classname, clazz in parsed.classes.iteritems():
print 'zz see', classname
classes[classname] = clazz
for sname, struct in clazz._public_structs.iteritems():
struct_parents[sname] = classname
#print 'zz seen struct %s in %s' % (sname, classname)
# Various precalculations
for method in clazz['methods']['public'][:]:
constructor = method['name'] == classname
method['constructor'] = constructor # work around cppheaderparser issue
args = method['parameters']
default_param = len(args)+1
for i in range(len(args)):
if args[i].get('default'):
default_param = i+1
break
method['num_args'] = set(range(default_param-1, len(args)+1))
print 'zz ', classname, 'has num_args of', method['num_args']
if method['static']:
method['rtnType'] = method['rtnType'].replace('static', '')
# Explore all functions we need to generate, including parent classes, handling of overloading, etc.
for classname, clazz in parsed.classes.iteritems():
clazz['final_methods'] = {}
def explore(subclass):
# Do our functions first, and do not let later classes override
for method in subclass['methods']['public']:
if method['constructor']:
if clazz != subclass: continue # Subclasses cannot directly use their parent's constructors
if method['destructor']: continue # Nothing to do there
if method['name'] not in clazz['final_methods']:
clazz['final_methods'][method['name']] = {}
for key in ['name', 'constructor', 'static', 'rtnType', 'destructor', 'pure_virtual']:
clazz['final_methods'][method['name']][key] = method[key]
clazz['final_methods'][method['name']]['num_args'] = method['num_args'].copy()
clazz['final_methods'][method['name']]['parameters'] = method['parameters'][:]
clazz['final_methods'][method['name']]['origin'] = subclass
else:
# Merge the new function in the best way we can. Shared arguments must match!
curr = clazz['final_methods'][method['name']]
if curr['origin'] is not subclass: continue # child class functions mask/hide parent functions of the same name in C++
if any([curr['parameters'][i]['type'] != method['parameters'][i]['type'] for i in range(min(len(curr['parameters']), len(method['parameters'])))]):
print 'Warning: Cannot mix in overloaded functions', method['name'], 'in class', classname, ', skipping'
continue
# TODO: Other compatibility checks, if any?
if len(method['parameters']) > len(curr['parameters']):
curr['parameters'] = method['parameters']
curr['num_args'] = curr['num_args'].union(method['num_args'])
print 'zz ', classname, 'has an updated num_args of ', curr['num_args']
# Recurse
for parent in subclass['inherits']:
if parent['class'] not in classes:
print 'Warning: parent class', parent, 'not a known class. Ignoring.'
return
explore(classes[parent['class']])
explore(clazz)
for method in clazz['final_methods'].itervalues():
method['num_args'] = list(method['num_args'])
method['num_args'].sort()
# Second pass - generate bindings
# TODO: Bind virtual functions using dynamic binding in the C binding code
funcs = {} # name -> # of copies in the original, and originalname in a copy
c_funcs = []
gen_c = open(basename + '.c', 'w')
gen_js = open(basename + '.js', 'w')
gen_c.write('extern "C" {\n')
def generate_class(generating_cname, cname, clazz):
inherited = generating_cname != cname
def generate_class(generating_classname, classname, clazz): # TODO: deprecate generating?
inherited = generating_classname != classname
for method in clazz['methods']['public']:
for method in clazz['final_methods'].itervalues():
mname = method['name']
#print "zz generating: ", generating_cname, cname, mname
if cname + '::' + mname in ignored: continue
if classname + '::' + mname in ignored: continue
args = method['parameters']
constructor = mname == cname
constructor = method['constructor'] # we fixed this before
destructor = method['destructor']
static = method['static']
print "zz generating: ", generating_classname, classname, mname, constructor, method['rtnType']
if destructor: continue
if constructor and inherited: continue
if method['pure_virtual']: continue
skip = False
for i in range(len(args)):
#print 'zz arggggggg', cname, 'x', mname, 'x', args[i]['name'], 'x', args[i]['type'], 'x'
#print 'zz arggggggg', classname, 'x', mname, 'x', args[i]['name'], 'x', args[i]['type'], 'x', dir(args[i]), 'y', args[i].get('default'), 'z', args[i].get('defaltValue'), args[i].keys()
if args[i]['name'].replace(' ', '') == '':
args[i]['name'] = 'arg' + str(i+1)
elif args[i]['name'] == '&':
@ -117,7 +187,7 @@ def generate_class(generating_cname, cname, clazz):
args[i]['type'] += '&'
if '>' in args[i]['name']:
print 'WARNING: odd ">" in %s, skipping' % cname
print 'WARNING: odd ">" in %s, skipping' % classname
skip = True
break
#print 'c1', struct_parents.keys()
@ -129,14 +199,12 @@ def generate_class(generating_cname, cname, clazz):
elif sname.replace('const ', '') in struct_parents:
sname = sname.replace('const ', '')
args[i]['type'] = 'const ' + struct_parents[sname] + '::' + sname + '&'
#print 'POST arggggggg', cname, 'x', mname, 'x', args[i]['name'], 'x', args[i]['type']
#print 'POST arggggggg', classname, 'x', mname, 'x', args[i]['name'], 'x', args[i]['type']
if skip:
continue
# C
ret = ((cname + ' *') if constructor else method['rtnType']).replace('virtual ', '')
callprefix = 'new ' if constructor else 'self->'
ret = ((classname + ' *') if constructor else method['rtnType']).replace('virtual ', '')
callprefix = 'new ' if constructor else ('self->' if not static else (classname + '::'))
actualmname = ''
if mname == '__operator___assignment_':
@ -170,100 +238,145 @@ def generate_class(generating_cname, cname, clazz):
callprefix = '*self - '
continue # TODO
else:
actualmname = mname
actualmname = method.get('truename') or mname
typedargs = ', '.join( ([] if constructor else [cname + ' * self']) + map(lambda arg: arg['type'] + ' ' + arg['name'], args) )
justargs = ', '.join(map(lambda arg: arg['name'], args))
fullname = 'emscripten_bind_' + generating_cname + '__' + mname
generating_cname_suffixed = generating_cname
need_self = not constructor and not static
typedargs = ([] if not need_self else [classname + ' * self']) + map(lambda arg: arg['type'] + ' ' + arg['name'], args)
justargs = map(lambda arg: arg['name'], args)
fullname = 'emscripten_bind_' + generating_classname + '__' + mname
generating_classname_suffixed = generating_classname
mname_suffixed = mname
count = funcs.setdefault(fullname, 0)
funcs[fullname] += 1
# handle overloading
dupe = False
if count > 0:
dupe = True
suffix = '_' + str(count+1)
funcs[fullname + suffix] = fullname # this should never change
funcs[fullname + suffix] = 0
fullname += suffix
mname_suffixed += suffix
if constructor:
generating_cname_suffixed += suffix
generating_classname_suffixed += suffix
gen_c.write('''
%s %s(%s) {
argfixes = '\n'.join(map(lambda arg: ''' %s = (%s && %s.ptr) ? %s.ptr : %s;''' % (arg['name'], arg['name'], arg['name'], arg['name'], arg['name']), args))
for i in method['num_args']:
# C
gen_c.write('''
%s %s_p%d(%s) {
%s%s%s(%s);
}
''' % (ret, fullname, typedargs, 'return ' if ret.replace(' ', '') != 'void' else '', callprefix, actualmname, justargs))
''' % (ret, fullname, i, ', '.join(typedargs[:i + (0 if not need_self else 1)]), 'return ' if ret.replace(' ', '') != 'void' else '', callprefix, actualmname, ', '.join(justargs[:i])))
c_funcs.append(fullname + '_p' + str(i))
# JS
if constructor:
dupe = type(funcs[fullname]) is str
if not dupe:
gen_js.write('''
function %s(%s) {
this.ptr = _%s(%s);
}
''' % (generating_cname_suffixed, justargs, fullname, justargs))
calls = ''
print 'js loopin', method['num_args'], '|', len(args), args
for i in method['num_args']:
print ' ', i, type(i)
if i != method['num_args'][0]:
calls += ' else '
if i != method['num_args'][-1]:
calls += ' if (' + justargs[i] + ' === undefined)'
calls += '\n ' + (' ' if len(method['num_args']) > 0 else '')
if constructor:
if not dupe:
calls += '''this.ptr = _%s_p%d(%s);
''' % (fullname, i, ', '.join(justargs[:i]))
else:
calls += '''this.ptr = _%s_p%d(%s);
''' % (fullname, i, ', '.join(justargs[:i]))
else:
gen_js.write('''
calls += '''%s_%s_p%d(%s);
''' % ('return ' if ret != 'void' else '', fullname, i, ', '.join((['this.ptr'] if need_self else []) + justargs[:i]))
print 'Maekin:', classname, generating_classname, mname, mname_suffixed
if constructor:
if not dupe:
js_text = '''
function %s(%s) {
this.ptr = _%s(%s);
%s
%s
}
''' % (mname_suffixed, ', '.join(justargs), argfixes, calls)
else:
js_text = '''
function %s(%s) {
%s
%s
}
%s.prototype = %s.prototype;
''' % (generating_cname_suffixed, justargs, fullname, justargs, generating_cname_suffixed, cname))
''' % (mname_suffixed, ', '.join(justargs), argfixes, calls, mname_suffixed, classname)
else:
gen_js.write('''
js_text = '''
%s.prototype.%s = function(%s) {
%s_%s(this.ptr%s);
%s
%s
}
''' % (generating_cname, mname_suffixed, justargs, 'return ' if ret != 'void' else '', fullname, (', ' if len(justargs) > 0 else '') + justargs))
''' % (generating_classname, mname_suffixed, ', '.join(justargs), argfixes, calls)
for cname, clazz in classes.iteritems():
if cname in ignored: continue
js_text = js_text.replace('\n\n', '\n').replace('\n\n', '\n')
gen_js.write(js_text)
# Main loop
for classname, clazz in classes.iteritems():
if classname in ignored: continue
# Nothing to generate for pure virtual classes
def check_pure_virtual(clazz, progeny):
if any([check_pure_virtual(classes[parent['class']], [clazz] + progeny) for parent in clazz['inherits']]): return True
print 'Checking pure virtual for', clazz['name'], clazz['inherits']
# If we do not recognize any of the parent classes, assume this is pure virtual - ignore it
if any([((not parent['class'] in classes) or check_pure_virtual(classes[parent['class']], [clazz] + progeny)) for parent in clazz['inherits']]): return True
def dirtied(mname):
#print 'zz checking dirtiness for', mname, 'in', progeny
for progen in progeny:
for method in clazz['methods']['public']:
if method['name'] == mname and not method['pure_virtual']: return True
for method in progen['methods']['public']:
if method['name'] == mname and not method['pure_virtual']:
#print 'zz dirty'
return True
#print 'zz not dirtied'
return False
for method in clazz['methods']['public']:
if method['pure_virtual'] and not dirtied(method['name']): return True
if method['pure_virtual'] and not dirtied(method['name']):
print 'zz ignoring pure virtual class', classname, 'due to', method['name']
return True
if check_pure_virtual(clazz, []): continue
if check_pure_virtual(clazz, []):
continue
# Add a constructor if none exist
has_constructor = False
for method in clazz['methods']['public']:
mname = method['name']
has_constructor = has_constructor or (cname == mname)
has_constructor = has_constructor or (classname == mname and not method['destructor'])
print 'zz ', classname, 'has constructor?', has_constructor
if not has_constructor:
print 'zz no constructor for', classname, 'so ignoring'
continue
clazz['methods']['public'] = [{
'name': cname,
'name': classname,
'parameters': [],
'pure_virtual': False,
'destructor': False,
}] + clazz['methods']['public']
generate_class(cname, cname, clazz)
# In addition, generate all methods of parent classes. We do not inherit in JS (how would we do multiple inheritance etc.?)
for parent in clazz['inherits']:
generate_class(cname, parent['class'], classes[parent['class']])
generate_class(classname, classname, clazz)
# TODO: Add a destructor
# Finish up
funcs = funcs.keys()
gen_c.write('''
}
@ -275,9 +388,9 @@ struct EmscriptenEnsurer
// Actually use the binding functions, so DFE will not eliminate them
int sum = 0;
void *seen = (void*)%s;
''' % funcs[0])
''' % c_funcs[0])
for func in funcs[1:]:
for func in c_funcs[1:]:
gen_c.write(''' sum += (void*)%s == seen;
''' % func)

Просмотреть файл

@ -87,8 +87,8 @@ try:
CC_ARG_SKIP = ['-O1', '-O2', '-O3']
CC_ADDITIONAL_ARGS = ['-m32', '-g', '-U__i386__', '-U__x86_64__', '-U__i386', '-U__x86_64', '-U__SSE__', '-U__SSE2__', '-UX87_DOUBLE_ROUNDING', '-UHAVE_GCC_ASM_FOR_X87']
ALLOWED_LINK_ARGS = ['-f', '-help', '-o', '-print-after', '-print-after-all', '-print-before',
'-print-before-all', '-time-passes', '-v', '-verify-dom-info', '-version' ]
DISALLOWED_LINK_ARGS = []#['rc']
'-print-before-all', '-time-passes', '-v', '-verify-dom-info', '-version' ]
TWO_PART_DISALLOWED_LINK_ARGS = ['-L'] # Ignore thingsl like |-L .|
EMMAKEN_CFLAGS = os.environ.get('EMMAKEN_CFLAGS')
if EMMAKEN_CFLAGS: CC_ADDITIONAL_ARGS += EMMAKEN_CFLAGS.split(' ')
@ -125,7 +125,7 @@ try:
if '--version' in opts:
use_linker = False
if set(sys.argv[1]).issubset(set('cru')): # ar
if set(sys.argv[1]).issubset(set('cruqs')): # ar
sys.argv = sys.argv[:1] + sys.argv[3:] + ['-o='+sys.argv[2]]
assert use_linker, 'Linker should be used in this case'
@ -133,7 +133,10 @@ try:
call = LLVM_LINK
newargs = []
found_o = False
for arg in sys.argv[1:]:
i = 0
while i < len(sys.argv)-1:
i += 1
arg = sys.argv[i]
if found_o:
newargs.append('-o=%s' % arg)
found_o = False
@ -145,12 +148,13 @@ try:
prefix = arg.split('=')[0]
if prefix in ALLOWED_LINK_ARGS:
newargs.append(arg)
if arg in TWO_PART_DISALLOWED_LINK_ARGS:
i += 1
elif arg.endswith('.so'):
continue # .so's do not exist yet, in many cases
else:
# not option, so just append
if arg not in DISALLOWED_LINK_ARGS:
newargs.append(arg)
newargs.append(arg)
elif not header:
call = CXX if use_cxx else CC
newargs = [ arg for arg in sys.argv[1:] if arg not in CC_ARG_SKIP ] + CC_ADDITIONAL_ARGS
@ -170,6 +174,6 @@ try:
os.execvp(call, [call] + newargs)
except Exception, e:
print 'Error in emmaken.py. Is the config file ~/.emscripten set up properly?', e
print 'Error in emmaken.py. (Is the config file ~/.emscripten set up properly?) Error:', e
raise

Просмотреть файл

@ -25,8 +25,8 @@ BINDINGS_GENERATOR = path_from_root('tools', 'bindings_generator.py')
# Engine tweaks
if '-s' not in SPIDERMONKEY_ENGINE:
SPIDERMONKEY_ENGINE += ['-s'] # Strict mode in SpiderMonkey. With V8 we check that fallback to non-strict works too
if 'strict' not in str(SPIDERMONKEY_ENGINE):
SPIDERMONKEY_ENGINE += ['-e', "options('strict')"] # Strict mode in SpiderMonkey. With V8 we check that fallback to non-strict works too
if 'gcparam' not in str(SPIDERMONKEY_ENGINE):
SPIDERMONKEY_ENGINE += ['-e', "gcparam('maxBytes', 1024*1024*1024);"] # Our very large files need lots of gc heap