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.

Reply via email to