libsbmljs_stable v5.17.0-beta1
libsbmljs
This repository hosts the build scripts for libsbmljs, a WebAssembly / JavaScript wrapper for the libSBML C++ library. This repository does not contain libsbmljs itself, but rather the interface wrapper and build scripts used to generate it. It is possible to build a custom libsbmljs against any libsbml release or checkout (but note that the wrapper is designed for libSBML 5.17.x and may not be valid for older/newer versions).
Project Structure
- The
interface/idldirectory contains all IDL wrapper code.- The
cppandjssubdirectories in theinterfacedirectory contain additional C++ and JavaScript helper methods.
- The
- The
karma/testsdirectory contains scripts for testing libsbmljs in your browser via Karma. - The
emtoolsdirectory contains a patched version of the Emscripten WebIDL binder which enables wrapping the C++std::stringtype (the original WebIDL binder could only wrap rawchar*pointers).
Building libsbmljs
It is possible to build a copy of libsbmljs based on a libSBML source tree of your choosing (stable or experimental).
What you will need before starting:
- Git (2.4.11 or later)
- SVN (1.8.15 or later, only if you want to build libSBML from svn)
- CMake (3.12.1 or later)
- Gradle (5.1.1 or later)
- Node.js (10.15.0 or later)
- Emscripten SDK (1.38.21 or later)
- Activate the Emscripten SDK using the command
source /path/to/emsdk_env.sh- Obtain the Expat XML parser source code and store it in a directory named
expatinside this directory.
- You can obtain the source code via git or download a release and unpack into the
expatdirectory. Example:
wget https://github.com/libexpat/libexpat/releases/download/R_2_2_6/expat-2.2.6.tar.bz2
mkdir expat
tar -xf expat-2.2.6.tar.bz2 -C expat --strip-components=1- Obtain the libSBML source code and store it in a directory named
libsbmlinside this repository.
- Checkout libSBML via svn or download one of the releases (stable or experimental) and unpack into the
libsbmldirectory. If you choose to download a release, we suggest downloading the archivelibSBML-x.y.z-core-plus-packages-src.tar.gz. You will have to rename the extracted directory tolibsbml. If you choose to checkout the svn code, ensure that it is checked out into thelibsbmldirectory. For example, to check out the experimental branch:
svn checkout svn://svn.code.sf.net/p/sbml/code/branches/libsbml-experimental libsbml- Build libsbmljs:
gradle -PversionTag=-alpha1 --rerun-tasks emccCompileLibSBML copyNpmMetadataOptionally, you can specify which packages should be enabled/disabled on the command line (this should never be necessary since this script will detect whether you are using a stable vs experimental build):
gradle -PversionTag=-alpha1 --rerun-tasks -PenableLayout=true -PenableRender=true -PenableFBC=true -PenableMulti=true -PenableQual=true -PenableComp=true -PenableDistrib=true -PenableDyn=true -PenableGroups=true -PenableArrays=true -PenableSpatial=true emccCompileLibSBML copyNpmMetadataTesting with Karma
The libsbmljs wrapper can be tested in the browser using Karma. You must first build libsbmljs from source as described above.
How to run testing with Karma:
- Ensure the npm dependencies are installed:
npm install- Preprocess the test files
gradle -PversionTag=-alpha1 --rerun-tasks combineTests copyKarmaConfig- You should be able to run the tests using
./node_modules/karma/bin/karma start ./build/karma.conf.js --single-runThe wrapper will be tested using Firefox. To test with other browsers, edit karma.conf.js and add the desired browsers.
Building the API Documentation
What you will need before starting:
- Node (10.15.0 or later)
- Ensure the npm dependencies are installed:
npm install- Use the following command to build the documentation using documentationjs.
gradle generateDocumentation- The HTML documentation will be written to the
build/libsbml_apidocdirectory.
How to Wrap an SBML Extension Package
We provide wrappers for accepted "core" libSBML packages like "fbc" and "comp". The procedure for adding wrappers for experimental packages is as follows:
- Ensure your
libsbmldirectory contains or points to the source tree of the "experimental" branch:
svn checkout svn://svn.code.sf.net/p/sbml/code/branches/libsbml-experimental libsbmlThe
interface/idldirectory contains wrappers for the respective SBML packages. Create a new subdirectory containing your package name.Write the IDL interface code for all the classes you would like to wrap. Each class is wrapped with a IDL
interfaceblock. Try to have one class per .idl file. Our documentation engine is documentation.js.
/**
* Document the class using documentation.js syntax.
* The documentation can usually be copied from libSBML,
* Replace or remove Doxygen-specific tags like @c, @p, @note.
*/
[Prefix="libsbml::"]
interface MyClassName {
/**
* Methods should also be documented using documentation.js syntax.
*
* @param {number} n a parameter - IDL uses long to represent the C++ int type
*
* @return {string} the return value - DOMStrings are wrap the C++ std::string type
* (this is different from vanilla Emscripten which can only wrap char*)
*/
DOMString getSomeStringAttr(unsigned long n);
};- Enumerations should be in the libsbml namespace and should have the
libsbml__idl__prefix and each enum value should be prefixed withlibsbml::
enum libsbml__idl__MyEnum_t {
"libsbml::ENUM_VALUE1",
"libsbml::ENUM_VALUE2"
};/**
* Document the class using documentation.js syntax.
* The documentation can usually be copied from libSBML,
* Replace or remove Doxygen-specific tags like @c, @p, @note.
*/
[Prefix="libsbml::"]
interface MyClassName {
/**
* Methods should also be documented using documentation.js syntax.
*
* @param {number} n a parameter - IDL uses long to represent the C++ int type
*
* @return {string} the return value - DOMStrings are wrap the C++ std::string type
* (this is different from vanilla Emscripten which can only wrap char*)
*/
DOMString getSomeStringAttr(unsigned long n);
};- Add your IDL files to the Gradle
combineIDLtask inbuild.gradle.
task combineIDL(type: ConcatFiles) {
...
if (enableMyPkg) {
include Paths.get(idl_dir, "mypkg", "file1.idl")
include Paths.get(idl_dir, "mypkg", "file2.idl")
...
}
...
}Create a C++ wrapper source file
interface/cpp/mypkg_interface_wrapper.cpp. At a minimum, this file must include the required headers for your package (usually named MyPkgExtensionTypes.h). You can also include additional C++ helper code in here if needed.Add your C++ source file to the
combineCPPtask inbuild.gradle:
task combineCPP(type: ConcatFiles) {
...
if (enableMyPkg) {
include Paths.get(cpp_dir, "mypkg_interface_wrapper.cpp")
}
...
}- Make sure the variable
ext.enableMyPkgis set to true somewhere in thebuild.gradlefile. We suggest setting it as follows:
ext.enableMyPkg = findProperty('enableMyPkg') || isExperimentalBranch- Run
gradle --rerun-tasks combineIDLand build libsbmljs as above. Also consider adding tests for your package to the karma/tests directory (and add those files to thecombineTeststask).
Contribution Guidelines
We welcome useful contributions, especially wrappers for libSBML experimental packages. In order to ensure your contribution satisfies the goals of the project, please adhere to the following:
*
FAQ
Are all classes and methods from the libSBML C++ library available in this wrapper.
- No. We have not included methods involving tasks which we believe to be irrelevant for most JavaScript applications such as: low-level XML node access, unnecessary back-pointers (e.g. getModel on every object), and methods that are deprecated or deal only with older SBML standards (e.g. SBase.isSetId). We also have not wrapped ListOfX classes because each container class in libSBML provides getNumX() and getX(index) methods to facilitate element access.
Is compression support for SBML models built-in?
- No. We have tried to minimize the size of the generated WASM binary by excluding non-essential components. You can easily compress your hosted SBML models using (HTTP compression)https://developer.mozilla.org/en-US/docs/Web/HTTP/Compression without all of the downsides mentioned above.