-
Notifications
You must be signed in to change notification settings - Fork 0
Exports Files
Alongside js files the src dir includes "exports files" (e.g. src/ol/map.exports
). An export file declares symbols and properties that are to be exported when creating builds of the library. For example the src/ol/map.exports
file includes this:
@exportClass ol.Map ol.MapOptions
@exportProperty ol.Map.prototype.addLayer
This declares that the ol.Map
symbol, and that the ol.Map.prototype.addLayer
property, should be exported, i.e. made available to lib users.
Exports files are processed by the bin/generate-exports
script, using its --exports
switch. This script receives a list of exports files as its input, and outputs @exportSymbol
and @exportProperty
statements. The output of generate-exports --exports
goes into build/src/external/src/exports.js
, which is then used as an input file for the ol.js
build (see build/ol.json
).
Note: the src/google.exports
file just makes the goog.require
function be exported as a null function. This is just to be able to execute the examples both with Plovr in raw mode (?mode=RAW
) – where goog.require
statements are required – and against the ol.js
build.
The src/objectliterals.exports
file is specific. This file declares the config objects and properties for the lib's single-arg constructors. These declarations are done with the @exportObjectLiteral
and @exportObjectLiteralProperty
directives. This file is also processed with the bin/generate-exports
script, but using the --externs
and --typedef
switches.
The generate-exports --externs
generates Closure externs from the @exportObjectLiteral
and @exportObjectLiteralProperty
directives. The build.py
script places these externs in the build/src/external/externs/types.js
file, which is used as a regular externs file by the Closure compiler (see build/ol.json
).
The generate-exports --typedef
command generate typedef's for the object literals declared with @exportObjectLiteral
and @exportObjectLiteralProperty
. The build.py
script places the typedef's in the build/src/external/src/types.js
, which, like exports.js
, is used as an input file for the ol.js build (see build/ol.json
).
Externs define types for config objects created by lib users, while typedef's define types created internally by the lib.
OL3 devs and contributors need to create new exports files when adding new API elements to the lib. They also need to declare single-arg constructors' config objects and properties in src/objectliterals.exports
.
build/src/internal/src/requireall.js
is used in the build.py build-all
target to ensure that all source files are passed to the compiler.
Before reading on, you should have a thorough understand of how the Closure Compiler handles exports and externs.
The exports/externs/typedefs system is required so that the same source files can be used in several modes:
- Uncompiled (i.e.
mode=RAW
) - Application and ol3 library compiled together
- ol3 library compiled, application uncompiled
Cases 1 are 2 similar: no exports are needed (except for ol.Object
property get
and set
methods whose names must be preserved), and object literals passed to single argument constructors are defined as @typedef
s so that they can be type checked and the compiler can rename their properties. Everything is "internal".
Case 3 is more complicated: we need to ensure that the appropriate library functions are exported so they can be used by application code. However, anything that is exported will be included in the built library and so increase the library size, hence the need for custom builds. Coarse-grained control over the custom build contents is achieved by deciding which .exports
files to pass to the compiler. Object literals to single argument constructors are more complicated: these are supplied by the application, so the compiled library must not rename their properties. So, in "external" mode, in addition to the @typedef
s, each object literals must be shadowed by an @extern
declaration that declares an @interface
in the olx
namespace. A separate namespace is needed to avoid conflicts with the ol
namespace used internally. Furthermore, a shadow derived class (e.g. ol.MapExport
) is defined for each exported class that transparently translates the un-renamed external object literal into a possibly renamed internal object literal. This derived class is exported as its parent class by a cunning rename when it's exported. Easy, huh?
Luckily, all this complexity is handled by the generate-exports
script. The ol3 developer need only add his declarations to the .exports
files and everything is auto-generated from this single source.
Using @export
in the source code means that all exported symbols would always be exported, this prevents custom builds.
This also prevents custom builds, as well as increasing the generated code size.