Hey all, historically, there's been some aspects of Emscripten that people have found a bit peculiar, so we are now looking at improving Emscripten compiler behavior to operate more in the same fashion as native compilers do. This involves two types of changes: - elevating fail conditions that were previously marked as just warnings, to be rigorously reported as errors by default, - revising the header and symbol namespaces to avoid risking name pollution coming from Emscripten provided system include files and libraries.
This mail is to give a heads up for developers, so that there is enough time to adapt to these planned changes. When looking at disrupting changes, we want to ensure that they are incorporated in a way that does not come as a surprise. These changes are being discussed in pull request https://github.com/kripken/emscripten/pull/4665. As a first step, we are thinking about deprecating a number of default behavior that Emscripten has. For the time being, Emscripten will continue to support these, but a future release will change the default behavior to be more strict by default. Here's a five step list of planned changes and what kind of changes may be needed for your project: 1. The system built-in preprocessor #define EMSCRIPTEN is planned to disappear. The rationale for this is that this symbol name is not in the namespace typically reserved for compiler built-ins. Instead all code should depend on the system built-in preprocessor __EMSCRIPTEN__ to detect the Emscripten environment. The preprocessor #define __EMSCRIPTEN__ has existed for a long time, since Emscripten compiler version 1.12.2 from Feb 21, 2014 ( https://github.com/kripken/emscripten/commit/264a5a91c450b510bcee1d257372ee5d9750879b), so the Emscripten compiler you are using definitely already has it. To ensure your project is forward compatible with future Emscripten compiler versions: - Search through your code and replace all instances of "#ifdef EMSCRIPTEN" with "#ifdef __EMSCRIPTEN__" - Search through your code and replace all instances of "#if EMSCRIPTEN" with "#if __EMSCRIPTEN__" - Search through your code and replace all instances of "#elif EMSCRIPTEN" with "#elif __EMSCRIPTEN__" - Search through your code and replace all instances of "defined(EMSCRIPTEN)" with "defined(__EMSCRIPTEN__)" 2. At present, when Emscripten links the final .js/.html file and if there are any missing symbols that were not satisfied, Emscripten has not considered this as an error, but has simply issued a warning, like: warning: unresolved symbol: some_function_that_does_not_exist At runtime if code happened to reach the location that depended on the missing symbol, execution would simply abort. This behavior has been considered a bit lax, and a notable difference compared to native compilers. To unify behavior with native compilers, this situation will be considered a linker error in the future, and instead, Emscripten will report error: unresolved symbol: some_function_that_does_not_exist and quit with a non-zero process exit code. This behavior has been configurable with the Emscripten linker flag -s ERROR_ON_UNDEFINED_SYMBOLS=0/1, and the change that is being adopted is that in the future, Emscripten will default to -s ERROR_ON_UNDEFINED_SYMBOLS=1 instead of -s ERROR_ON_UNDEFINED_SYMBOLS=0. To ensure your project is forward compatible with future Emscripten compiler versions: - Make sure that the project is well-formed and includes definitions for all symbols that it uses, and perhaps #ifdefs out any code paths that should not be run in Emscripten builds. Search for instances of "warning: unresolved symbol: xxx" that might get printed at the final link stage. If there are none, then this will likely not affect your project. - To test a project build system out in advance, you can already opt in to the new default behavior by explicitly passing the linker flag -s ERROR_ON_UNDEFINED_SYMBOLS=1. - To keep on relying the old behavior with future Emscripten compiler versions, when it is desirable for a project to include missing symbols (when you know those will not be an issue), you can start passing the linker flag -s ERROR_ON_UNDEFINED_SYMBOLS=0. The linker option -s ERROR_ON_UNDEFINED_SYMBOLS=0/1 has existed since Emscripten 1.4.1 from Apr 29, 2013 ( https://github.com/kripken/emscripten/commit/3a108dc9cdbe270b23f1ce5ef32ce56ae864ce45), so all existing compiler versions do have the option. 3. Similar to the above option, it has been historically convenient to have Emscripten simply ignore any -lfoo link directives that it could not find. This has made it a bit easier to port build systems of existing projects, but like the above option, Emscripten will start behaving more strictly with respect to this in the future, and treat missing linkable libraries as an error by default. This makes Emscripten behave similar to how native compilers work. To ensure your project is forward compatible with future Emscripten compiler versions: - Make sure that the build system does not pass any -lxxx directives to libraries that do not exist. Search for existing warning messages like "WARNING:root:emcc: cannot find library "some_lib_that_does_not_exist"" at the final link step, and remove those from the command line for the final Emscripten link step in the build system. If there are none, then this will not affect your project. - In the next compiler version, when PR https://github.com/kripken/emscripten/pull/4665 is merged, Emscripten will have a new linker flag -s ERROR_ON_MISSING_LIBRARIES=0/1 option. If relying on the old behavior of simply warning when a library is not found is desirable, pass the linker flag -s ERROR_ON_MISSING_LIBRARIES=0 to the build. - To verify that your project builds clean with the new behavior, try building it by passing the linker flag -s ERROR_ON_MISSING_LIBRARIES=1. 4. Emscripten comes with its own set of system include headers, which implement Emscripten core functions. These headers exist in the path https://github.com/kripken/emscripten/tree/master/system/include/emscripten, which is a system include path that is enabled in all builds. However some of the files in this path have unfortunately been so generic that they have been reported to cause undesirable include file pollution, e.g. when projects may have had their own files "vector.h" or "threading.h" they could have mistakenly included one of the Emscripten-provided files instead. To remedy that, the directory system/include/emscripten/ is planned to be dropped from the set of system include directories in the future. To ensure your project is forward compatible with this change, search through your code and search-replace all instances of: - #include "bind.h" -> #include <emscripten/bind.h> - #include <bind.h> -> #include <emscripten/bind.h> - #include "html5.h" -> #include <emscripten/html5.h> - #include <html5.h> -> #include <emscripten/html5.h> - #include "threading.h" -> #include <emscripten/threading.h> - #include <threading.h> -> #include <emscripten/threading.h> - #include "trace.h" -> #include <emscripten/trace.h> - #include <trace.h> -> #include <emscripten/trace.h> - #include "val.h" -> #include <emscripten/val.h> - #include <val.h> -> #include <emscripten/val.h> - #include "vector.h" -> #include <emscripten/vector.h> - #include <vector.h> -> #include <emscripten/vector.h> - #include "vr.h" -> #include <emscripten/vr.h> - #include <vr.h> -> #include <emscripten/vr.h> - #include "wire.h" -> #include <emscripten/wire.h> - #include <wire.h> -> #include <emscripten/wire.h> in all locations in code, where the header files intend to refer to the Emscripten system includes. The header file emscripten.h is regarded as special so that it is possible to include it either via #include <emscripten.h> or #include <emscripten/emscripten.h> but the form #include "emscripten.h" is not encougared. This change is safe to do in all compiler versions, as Emscripten system include headers have been available for inclusion via #include <emscripten/foo.h> since Emscripten 1.0.1a from Sep 25, 2011 ( https://github.com/kripken/emscripten/commit/2f10b98df9dfb8459bcf8a174c6f851522b932b4 ). This change will ensure that Emscripten will not danger polluting header file namespaces in the future when introducing new system header files. 5. Emscripten implements a number of core system functionality via code libraries that are implemented on JS side, as system-provided files src/library_xxx.js in https://github.com/kripken/emscripten/tree/master/src. This structure has worked in a manner that all of these system-provided JS libraries have automatically been linked to each compiled project. This has been convenient for adding in new functionality, but unfortunately it risks the same type of name pollution as 4), but in the form of linked code symbols. Also, linking in the system libraries slightly creeps up link times as new system libraries are added, even though they might not always be used. To improve this behavior, the intent is to drop autolinking in a future compiler version. This means that with the exception of minimum required core system libraries (C runtime and filesystem) that are needed to implement core Emscripten runtime, other types of system libraries (GL, SDL, OpenAL, etc.) will no longer be automatically linked to by Emscripten, unless explicitly specified. To make sure your project is forward compatible with future Emscripten compiler versions: - If your project uses the EGL API, pass the linker flag -lEGL when linking the final project - If your project uses OpenGL (in any of its flavors), pass the linker flag -lGL when linking the final project - If your project uses GLEW, pass the linker flag -lGLEW when linking the final project - If your project uses GLFW, pass the linker flag -lglfw when linking the final project - If your project uses GLUT, pass the linker flag -lglut when linking the final project - If your project uses the emscripten_idb_* API, pass the linker flag -lidbstore.js when linking the final project - If your project uses libuuid, pass the linker flag -luuid when linking the final project - If your project uses OpenAL, pass the linker flag -lopenal when linking the final project - If your project uses SDL 1.4 that is implemented in JS side in Emscripten (as opposed to the newer compiled SDL2 port), pass the linker flag -lSDL when linking the final project - If your project uses the IDBFS filesystem, pass the linker flag -lidbfs.js when linking the final project - If your project uses the NODEFS filesystem, pass the linker flag -lnodefs.js when linking the final project - If your project uses the WORKERFS filesystem, pass the linker flag -lworkerfs.js when linking the final project - If your project uses WebVR, pass the linker flag -lvr.js when linking the final project - If your project uses the X11 emulation library, pass the linker flag -lX11 when linking the final project This ensures that new system libraries will not risk polluting symbol namespaces of existing projects, and that link times will keep in check with this respect as new system libraries are added. The next compiler release will not yet enforce these changes, but the old behavior will still work, and is just considered to be deprecated. To verify that your codebase builds cleanly with the new default behavior, there is an opt-in feature for building code with the deprecated features dropped. These are being discussed in https://github.com/kripken/emscripten/pull/4665. Feel free to weigh in if you have any comments! Best, Jukka -- You received this message because you are subscribed to the Google Groups "emscripten-discuss" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. For more options, visit https://groups.google.com/d/optout.
