diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/intertyper.js | 2 | ||||
-rw-r--r-- | src/jsifier.js | 69 | ||||
-rw-r--r-- | src/library.js | 4 | ||||
-rw-r--r-- | src/library_gl.js | 112 | ||||
-rw-r--r-- | src/modules.js | 17 | ||||
-rw-r--r-- | src/parseTools.js | 25 | ||||
-rw-r--r-- | src/preamble.js | 5 | ||||
-rw-r--r-- | src/settings.js | 6 |
8 files changed, 144 insertions, 96 deletions
diff --git a/src/intertyper.js b/src/intertyper.js index 6da30ae8..94d937e1 100644 --- a/src/intertyper.js +++ b/src/intertyper.js @@ -502,7 +502,7 @@ function intertyper(data, sidePass, baseLineNums) { } else { // variable var ident = item.tokens[0].text; - var private_ = findTokenText(item, 'private') >= 0; + var private_ = findTokenText(item, 'private') >= 0 || findTokenText(item, 'internal') >= 0; cleanOutTokens(LLVM.GLOBAL_MODIFIERS, item.tokens, [2, 3]); var external = false; if (item.tokens[2].text === 'external') { diff --git a/src/jsifier.js b/src/jsifier.js index 885fbc30..3f8c184c 100644 --- a/src/jsifier.js +++ b/src/jsifier.js @@ -264,9 +264,9 @@ function JSify(data, functionsOnly, givenFunctions) { assert(!item.lines); // FIXME remove this, after we are sure it isn't needed var ret = [item]; if (item.ident == '_llvm_global_ctors') { - item.JS = '\n__ATINIT__ = __ATINIT__.concat([\n' + - item.ctors.map(function(ctor) { return ' { func: function() { ' + ctor + '() } }' }).join(',\n') + - '\n]);\n'; + item.JS = '\n/* global initializers */ __ATINIT__.push(' + + item.ctors.map(function(ctor) { return '{ func: function() { ' + ctor + '() } }' }).join(',') + + ');\n'; return ret; } @@ -286,6 +286,11 @@ function JSify(data, functionsOnly, givenFunctions) { allocator = 'ALLOC_NONE'; } + if (ASM_JS && (MAIN_MODULE || SIDE_MODULE) && !item.private_ && !NAMED_GLOBALS && isIndexableGlobal(item.ident)) { + // We need this to be named (and it normally would not be), so that it can be linked to and used from other modules + Variables.globals[item.ident].linkable = 1; + } + if (isBSS(item)) { var length = calcAllocatedSize(item.type); length = Runtime.alignMemory(length); @@ -374,22 +379,11 @@ function JSify(data, functionsOnly, givenFunctions) { // Set the actual value in a postset, since it may be a global variable. We also order by dependencies there Variables.globals[item.ident].targetIdent = item.value.ident; var value = Variables.globals[item.ident].resolvedAlias = finalizeLLVMParameter(item.value); - var fix = ''; - if (BUILD_AS_SHARED_LIB == 2 && !item.private_) { - var target = item.ident; - if (isFunctionType(item.type)) { - target = item.value.ident; // the other side does not know this is an alias/function table index. So make it the alias target. - var varData = Variables.globals[target]; - assert(!varData, 'multi-level aliasing does not work yet in shared lib 2 exports'); - } - fix = '\nif (globalScope) { assert(!globalScope["' + item.ident + '"]); globalScope["' + item.ident + '"] = ' + target + ' }' + if ((MAIN_MODULE || SIDE_MODULE) && isFunctionType(item.type)) { + var target = item.value.ident; + if (!Functions.aliases[target]) Functions.aliases[target] = []; + Functions.aliases[target].push(item.ident); } - ret.push({ - intertype: 'GlobalVariablePostSet', - ident: item.ident, - dependencies: set([value]), - JS: item.ident + ' = ' + value + ';' + fix - }); return ret; } }); @@ -847,6 +841,19 @@ function JSify(data, functionsOnly, givenFunctions) { } func.JS = func.JS.replace(/\n *;/g, '\n'); // remove unneeded lines + + if (MAIN_MODULE || SIDE_MODULE) { + // Clone the function for each of its aliases. We do not know which name it will be used by in another module, + // and we do not have a heavyweight metadata system to resolve aliases during linking + var aliases = Functions.aliases[func.ident]; + if (aliases) { + var body = func.JS.substr(func.JS.indexOf('(')); + aliases.forEach(function(alias) { + func.JS += '\n' + 'function ' + alias + body; + }); + } + } + return func; } }); @@ -1254,7 +1261,7 @@ function JSify(data, functionsOnly, givenFunctions) { case 'xchg': return '(tempValue=' + makeGetValue(param1, 0, type) + ',' + makeSetValue(param1, 0, param2, type, null, null, null, null, ',') + ',tempValue)'; case 'cmpxchg': { var param3 = finalizeLLVMParameter(item.params[2]); - return '(tempValue=' + makeGetValue(param1, 0, type) + ',(' + makeGetValue(param1, 0, type) + '==(' + param2 + '|0) ? ' + makeSetValue(param1, 0, param3, type, null, null, null, null, ',') + ' : 0),tempValue)'; + return '(tempValue=' + makeGetValue(param1, 0, type) + ',(' + makeGetValue(param1, 0, type) + '==(' + param2 + '|0) ? ' + asmCoercion(makeSetValue(param1, 0, param3, type, null, null, null, null, ','), 'i32') + ' : 0),tempValue)'; } default: throw 'unhandled atomic op: ' + item.op; } @@ -1502,7 +1509,7 @@ function JSify(data, functionsOnly, givenFunctions) { // This is a call through an invoke_*, either a forced one, or a setjmp-required one // note: no need to update argsTypes at this point if (byPointerForced) Functions.unimplementedFunctions[callIdent] = sig; - args.unshift(byPointerForced ? Functions.getIndex(callIdent) : asmCoercion(callIdent, 'i32')); + args.unshift(byPointerForced ? Functions.getIndex(callIdent, undefined, sig) : asmCoercion(callIdent, 'i32')); callIdent = 'invoke_' + sig; } } else if (SAFE_DYNCALLS) { @@ -1582,6 +1589,7 @@ function JSify(data, functionsOnly, givenFunctions) { if (phase == 'pre' && !Variables.generatedGlobalBase) { Variables.generatedGlobalBase = true; // Globals are done, here is the rest of static memory + assert((TARGET_LE32 && Runtime.GLOBAL_BASE == 8) || (TARGET_X86 && Runtime.GLOBAL_BASE == 4)); // this is assumed in e.g. relocations for linkable modules print('STATIC_BASE = ' + Runtime.GLOBAL_BASE + ';\n'); print('STATICTOP = STATIC_BASE + ' + Runtime.alignMemory(Variables.nextIndexedOffset) + ';\n'); } @@ -1615,11 +1623,11 @@ function JSify(data, functionsOnly, givenFunctions) { print('/* no memory initializer */'); // test purposes } - // Run postsets right before main, and after the memory initializer has been set up + // Define postsets. These will be run in ATINIT, right before global initializers (which might need the postsets). We cannot + // run them now because the memory initializer might not have been applied yet. print('function runPostSets() {\n'); print(itemsDict.GlobalVariablePostSet.map(function(item) { return item.JS }).join('\n')); print('}\n'); - print('if (!awaitingMemoryInitializer) runPostSets();\n'); // if we load the memory initializer, this is done later if (USE_TYPED_ARRAYS == 2) { print('var tempDoublePtr = Runtime.alignMemory(allocate(12, "i8", ALLOC_STATIC), 8);\n'); @@ -1729,8 +1737,8 @@ function JSify(data, functionsOnly, givenFunctions) { } } }); - print(read('fastLong.js')); } + print(read('fastLong.js')); print('// EMSCRIPTEN_END_FUNCS\n'); print(read('long.js')); } else { @@ -1792,6 +1800,21 @@ function JSify(data, functionsOnly, givenFunctions) { substrate.addItems(data.functionStubs, 'FunctionStub'); assert(data.functions.length == 0); } else { + if (phase == 'pre') { + // ensure there is a global ctors, for runPostSets + if ('_llvm_global_ctors' in data.globalVariables) { + data.globalVariables._llvm_global_ctors.ctors.unshift('runPostSets'); // run postsets right before global initializers + hasCtors = true; + } else { + substrate.addItems([{ + intertype: 'GlobalVariableStub', + ident: '_llvm_global_ctors', + type: '[1 x { i32, void ()* }]', + ctors: ["runPostSets"], + }], 'GlobalVariable'); + } + } + substrate.addItems(sortGlobals(data.globalVariables), 'GlobalVariable'); substrate.addItems(data.aliass, 'Alias'); substrate.addItems(data.functions, 'FunctionSplitter'); diff --git a/src/library.js b/src/library.js index 822f4319..bf969fd7 100644 --- a/src/library.js +++ b/src/library.js @@ -8271,4 +8271,8 @@ function autoAddDeps(object, name) { } } +// Add aborting stubs for various libc stuff needed by libc++ +['pthread_cond_signal', 'pthread_equal', 'wcstol', 'wcstoll', 'wcstoul', 'wcstoull', 'wcstof', 'wcstod', 'wcstold', 'swprintf', 'pthread_join', 'pthread_detach', 'strcoll_l', 'strxfrm_l', 'wcscoll_l', 'toupper_l', 'tolower_l', 'iswspace_l', 'iswprint_l', 'iswcntrl_l', 'iswupper_l', 'iswlower_l', 'iswalpha_l', 'iswdigit_l', 'iswpunct_l', 'iswxdigit_l', 'iswblank_l', 'wcsxfrm_l', 'towupper_l', 'towlower_l'].forEach(function(aborter) { + LibraryManager.library[aborter] = function() { throw 'TODO: ' + aborter }; +}); diff --git a/src/library_gl.js b/src/library_gl.js index 1fa0cc9c..e59492cf 100644 --- a/src/library_gl.js +++ b/src/library_gl.js @@ -1260,6 +1260,8 @@ var LibraryGL = { return Module.ctx.isFramebuffer(fb); }, +#if DISABLE_GL_EMULATION == 0 + // GL emulation: provides misc. functionality not present in OpenGL ES 2.0 or WebGL $GLEmulation__postset: 'GLEmulation.init();', @@ -4139,6 +4141,44 @@ var LibraryGL = { }, glRotatef: 'glRotated', + glDrawBuffer: function() { throw 'glDrawBuffer: TODO' }, + glReadBuffer: function() { throw 'glReadBuffer: TODO' }, + + glLightfv: function() { throw 'glLightfv: TODO' }, + glLightModelfv: function() { throw 'glLightModelfv: TODO' }, + glMaterialfv: function() { throw 'glMaterialfv: TODO' }, + + glTexGeni: function() { throw 'glTexGeni: TODO' }, + glTexGenfv: function() { throw 'glTexGenfv: TODO' }, + glTexEnvi: function() { Runtime.warnOnce('glTexEnvi: TODO') }, + glTexEnvf: function() { Runtime.warnOnce('glTexEnvf: TODO') }, + glTexEnvfv: function() { Runtime.warnOnce('glTexEnvfv: TODO') }, + + glTexImage1D: function() { throw 'glTexImage1D: TODO' }, + glTexCoord3f: function() { throw 'glTexCoord3f: TODO' }, + glGetTexLevelParameteriv: function() { throw 'glGetTexLevelParameteriv: TODO' }, + + glShadeModel: function() { Runtime.warnOnce('TODO: glShadeModel') }, + + // Open GLES1.1 compatibility + + glGenFramebuffersOES : 'glGenFramebuffers', + glGenRenderbuffersOES : 'glGenRenderbuffers', + glBindFramebufferOES : 'glBindFramebuffer', + glBindRenderbufferOES : 'glBindRenderbuffer', + glGetRenderbufferParameterivOES : 'glGetRenderbufferParameteriv', + glFramebufferRenderbufferOES : 'glFramebufferRenderbuffer', + glRenderbufferStorageOES : 'glRenderbufferStorage', + glCheckFramebufferStatusOES : 'glCheckFramebufferStatus', + glDeleteFramebuffersOES : 'glDeleteFramebuffers', + glDeleteRenderbuffersOES : 'glDeleteRenderbuffers', + glGenVertexArraysOES: 'glGenVertexArrays', + glDeleteVertexArraysOES: 'glDeleteVertexArrays', + glBindVertexArrayOES: 'glBindVertexArray', + glFramebufferTexture2DOES: 'glFramebufferTexture2D', + +#endif // DISABLE_GL_EMULATION == 0 + // GLU gluPerspective: function(fov, aspect, near, far) { @@ -4205,25 +4245,6 @@ var LibraryGL = { _glOrtho(left, right, bottom, top, -1, 1); }, - glDrawBuffer: function() { throw 'glDrawBuffer: TODO' }, - glReadBuffer: function() { throw 'glReadBuffer: TODO' }, - - glLightfv: function() { throw 'glLightfv: TODO' }, - glLightModelfv: function() { throw 'glLightModelfv: TODO' }, - glMaterialfv: function() { throw 'glMaterialfv: TODO' }, - - glTexGeni: function() { throw 'glTexGeni: TODO' }, - glTexGenfv: function() { throw 'glTexGenfv: TODO' }, - glTexEnvi: function() { Runtime.warnOnce('glTexEnvi: TODO') }, - glTexEnvf: function() { Runtime.warnOnce('glTexEnvf: TODO') }, - glTexEnvfv: function() { Runtime.warnOnce('glTexEnvfv: TODO') }, - - glTexImage1D: function() { throw 'glTexImage1D: TODO' }, - glTexCoord3f: function() { throw 'glTexCoord3f: TODO' }, - glGetTexLevelParameteriv: function() { throw 'glGetTexLevelParameteriv: TODO' }, - - glShadeModel: function() { Runtime.warnOnce('TODO: glShadeModel') }, - // GLES2 emulation glVertexAttribPointer__sig: 'viiiiii', @@ -4351,23 +4372,6 @@ var LibraryGL = { glGetError__sig: 'i', glFrontFace__sig: 'vi', glSampleCoverage__sig: 'vi', - - // Open GLES1.1 compatibility - - glGenFramebuffersOES : 'glGenFramebuffers', - glGenRenderbuffersOES : 'glGenRenderbuffers', - glBindFramebufferOES : 'glBindFramebuffer', - glBindRenderbufferOES : 'glBindRenderbuffer', - glGetRenderbufferParameterivOES : 'glGetRenderbufferParameteriv', - glFramebufferRenderbufferOES : 'glFramebufferRenderbuffer', - glRenderbufferStorageOES : 'glRenderbufferStorage', - glCheckFramebufferStatusOES : 'glCheckFramebufferStatus', - glDeleteFramebuffersOES : 'glDeleteFramebuffers', - glDeleteRenderbuffersOES : 'glDeleteRenderbuffers', - glGenVertexArraysOES: 'glGenVertexArrays', - glDeleteVertexArraysOES: 'glDeleteVertexArrays', - glBindVertexArrayOES: 'glBindVertexArray', - glFramebufferTexture2DOES: 'glFramebufferTexture2D', }; @@ -4409,25 +4413,27 @@ var LibraryGL = { autoAddDeps(LibraryGL, '$GL'); -// Emulation requires everything else, potentially -LibraryGL.$GLEmulation__deps = LibraryGL.$GLEmulation__deps.slice(0); // the __deps object is shared -var glFuncs = []; -for (var item in LibraryGL) { - if (item != '$GLEmulation' && item.substr(-6) != '__deps' && item.substr(-9) != '__postset' && item.substr(-5) != '__sig' && item.substr(0, 2) == 'gl') { - glFuncs.push(item); - } -} -LibraryGL.$GLEmulation__deps = LibraryGL.$GLEmulation__deps.concat(glFuncs); -LibraryGL.$GLEmulation__deps.push(function() { - for (var func in Functions.getIndex.tentative) { - Functions.getIndex(func); - Functions.unimplementedFunctions[func] = LibraryGL[func.substr(1) + '__sig']; +if (!DISABLE_GL_EMULATION) { + // Emulation requires everything else, potentially + LibraryGL.$GLEmulation__deps = LibraryGL.$GLEmulation__deps.slice(0); // the __deps object is shared + var glFuncs = []; + for (var item in LibraryGL) { + if (item != '$GLEmulation' && item.substr(-6) != '__deps' && item.substr(-9) != '__postset' && item.substr(-5) != '__sig' && item.substr(0, 2) == 'gl') { + glFuncs.push(item); + } } -}); + LibraryGL.$GLEmulation__deps = LibraryGL.$GLEmulation__deps.concat(glFuncs); + LibraryGL.$GLEmulation__deps.push(function() { + for (var func in Functions.getIndex.tentative) { + Functions.getIndex(func); + Functions.unimplementedFunctions[func] = LibraryGL[func.substr(1) + '__sig']; + } + }); -if (FORCE_GL_EMULATION) { - LibraryGL.glDrawElements__deps = LibraryGL.glDrawElements__deps.concat('$GLEmulation'); - LibraryGL.glDrawArrays__deps = LibraryGL.glDrawArrays__deps.concat('$GLEmulation'); + if (FORCE_GL_EMULATION) { + LibraryGL.glDrawElements__deps = LibraryGL.glDrawElements__deps.concat('$GLEmulation'); + LibraryGL.glDrawArrays__deps = LibraryGL.glDrawArrays__deps.concat('$GLEmulation'); + } } mergeInto(LibraryManager.library, LibraryGL); diff --git a/src/modules.js b/src/modules.js index d26acbd5..a6aa2644 100644 --- a/src/modules.js +++ b/src/modules.js @@ -245,6 +245,8 @@ var Functions = { blockAddresses: {}, // maps functions to a map of block labels to label ids + aliases: {}, // in shared modules (MAIN_MODULE or SHARED_MODULE), a list of aliases for functions that have them + getSignature: function(returnType, argTypes, hasVarArgs) { var sig = returnType == 'void' ? 'v' : (isIntImplemented(returnType) ? 'i' : 'f'); for (var i = 0; i < argTypes.length; i++) { @@ -257,25 +259,32 @@ var Functions = { }, // Mark a function as needing indexing. Python will coordinate them all - getIndex: function(ident, doNotCreate) { + getIndex: function(ident, doNotCreate, sig) { if (doNotCreate && !(ident in this.indexedFunctions)) { if (!Functions.getIndex.tentative) Functions.getIndex.tentative = {}; // only used by GL emulation; TODO: generalize when needed Functions.getIndex.tentative[ident] = 0; } + var ret; if (phase != 'post' && singlePhase) { if (!doNotCreate) this.indexedFunctions[ident] = 0; // tell python we need this indexized - return "'{{ FI_" + toNiceIdent(ident) + " }}'"; // something python will replace later + ret = "'{{ FI_" + toNiceIdent(ident) + " }}'"; // something python will replace later } else { if (!singlePhase) return 'NO_INDEX'; // Should not index functions in post - var ret = this.indexedFunctions[ident]; + ret = this.indexedFunctions[ident]; if (!ret) { if (doNotCreate) return '0'; ret = this.nextIndex; this.nextIndex += 2; // Need to have indexes be even numbers, see |polymorph| test this.indexedFunctions[ident] = ret; } - return ret.toString(); + ret = ret.toString(); + } + if (SIDE_MODULE && sig) { // sig can be undefined for the GL library functions + ret = '((F_BASE_' + sig + ' + ' + ret + ')|0)'; + } else if (BUILD_AS_SHARED_LIB) { + ret = '(FUNCTION_TABLE_OFFSET + ' + ret + ')'; } + return ret; }, getTable: function(sig) { diff --git a/src/parseTools.js b/src/parseTools.js index 6bc0b7ea..dfd4b7ed 100644 --- a/src/parseTools.js +++ b/src/parseTools.js @@ -492,7 +492,9 @@ function makeGlobalUse(ident) { UNINDEXABLE_GLOBALS[ident] = 1; return ident; } - return (Runtime.GLOBAL_BASE + index).toString(); + var ret = (Runtime.GLOBAL_BASE + index).toString(); + if (SIDE_MODULE) ret = '(H_BASE+' + ret + ')'; + return ret; } return ident; } @@ -1227,15 +1229,11 @@ function indexizeFunctions(value, type) { var out = {}; if (type && isFunctionType(type, out) && value[0] === '_') { // checking for _ differentiates from $ (local vars) // add signature to library functions that we now know need indexing - if (!(value in Functions.implementedFunctions) && !(value in Functions.unimplementedFunctions)) { - Functions.unimplementedFunctions[value] = Functions.getSignature(out.returnType, out.segments ? out.segments.map(function(segment) { return segment[0].text }) : []); - } - - if (BUILD_AS_SHARED_LIB) { - return '(FUNCTION_TABLE_OFFSET + ' + Functions.getIndex(value) + ')'; - } else { - return Functions.getIndex(value); + var sig = Functions.implementedFunctions[value] || Functions.unimplementedFunctions[value]; + if (!sig) { + sig = Functions.unimplementedFunctions[value] = Functions.getSignature(out.returnType, out.segments ? out.segments.map(function(segment) { return segment[0].text }) : []); } + return Functions.getIndex(value, undefined, sig); } return value; } @@ -1627,6 +1625,9 @@ function makePointer(slab, pos, allocator, type, ptr, finalMemoryInitialization) // writing out into memory, without a normal allocation. We put all of these into a single big chunk. assert(typeof slab == 'object'); assert(slab.length % QUANTUM_SIZE == 0, slab.length); // must be aligned already + if (SIDE_MODULE && typeof ptr == 'string') { + ptr = parseInt(ptr.substring(ptr.indexOf('+'), ptr.length-1)); // parse into (H_BASE+X) + } var offset = ptr - Runtime.GLOBAL_BASE; for (var i = 0; i < slab.length; i++) { memoryInitialization[offset + i] = slab[i]; @@ -2146,7 +2147,11 @@ function processMathop(item) { } case 'select': return idents[0] + ' ? ' + makeCopyI64(idents[1]) + ' : ' + makeCopyI64(idents[2]); case 'ptrtoint': return makeI64(idents[0], 0); - case 'inttoptr': return '(' + idents[0] + '[0])'; // just directly truncate the i64 to a 'pointer', which is an i32 + case 'inttoptr': { + var m = /\(?\[(\d+),\d+\]\)?/.exec(idents[0]); + if (m) return m[1]; // constant, can just parse it right now + return '(' + idents[0] + '[0])'; // just directly truncate the i64 to a 'pointer', which is an i32 + } // Dangerous, rounded operations. TODO: Fully emulate case 'add': { if (PRECISE_I64_MATH) { diff --git a/src/preamble.js b/src/preamble.js index 55a8a3a5..ed148d9e 100644 --- a/src/preamble.js +++ b/src/preamble.js @@ -887,8 +887,6 @@ __ATEXIT__.push({ func: function() { PGOMonitor.dump() } }); addPreRun(function() { addRunDependency('pgo') }); #endif -var awaitingMemoryInitializer = false; - function loadMemoryInitializer(filename) { function applyData(data) { #if USE_TYPED_ARRAYS == 2 @@ -896,7 +894,6 @@ function loadMemoryInitializer(filename) { #else allocate(data, 'i8', ALLOC_NONE, STATIC_BASE); #endif - runPostSets(); } // always do this asynchronously, to keep shell and web as similar as possible @@ -911,8 +908,6 @@ function loadMemoryInitializer(filename) { }); } }); - - awaitingMemoryInitializer = false; } // === Body === diff --git a/src/settings.js b/src/settings.js index dff52adf..7f9dca3b 100644 --- a/src/settings.js +++ b/src/settings.js @@ -186,6 +186,8 @@ var GL_MAX_TEMP_BUFFER_SIZE = 2097152; // How large GL emulation temp buffers ar var GL_UNSAFE_OPTS = 1; // Enables some potentially-unsafe optimizations in GL emulation code var FULL_ES2 = 0; // Forces support for all GLES2 features, not just the WebGL-friendly subset. var FORCE_GL_EMULATION = 0; // Forces inclusion of full GL emulation code. +var DISABLE_GL_EMULATION = 0; // Disable inclusion of full GL emulation code. Useful when you don't want emulation + // but do need INCLUDE_FULL_LIBRARY or MAIN_MODULE. var DISABLE_EXCEPTION_CATCHING = 0; // Disables generating code to actually catch exceptions. If the code you // are compiling does not actually rely on catching exceptions (but the @@ -296,6 +298,10 @@ var SHOW_LABELS = 0; // Show labels in the generated code var PRINT_SPLIT_FILE_MARKER = 0; // Prints markers in Javascript generation to split the file later on. See emcc --split option. +var MAIN_MODULE = 0; // A main module is a file compiled in a way that allows us to link it to + // a side module using emlink.py. +var SIDE_MODULE = 0; // Corresponds to MAIN_MODULE + var BUILD_AS_SHARED_LIB = 0; // Whether to build the code as a shared library // 0 here means this is not a shared lib: It is a main file. // All shared library options (1 and 2) are currently deprecated XXX |