Skip to content
This repository was archived by the owner on Aug 31, 2021. It is now read-only.

[[ emscripten ]] Add WebAssembly build target and standalone builder options #7330

Open
wants to merge 16 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 11 additions & 5 deletions Installer/package.txt
Original file line number Diff line number Diff line change
Expand Up @@ -602,11 +602,17 @@ component Runtime.MacOSX

component Runtime.Emscripten
into "[[ToolsFolder]]/Runtime/Emscripten/js" place
file emscripten:standalone[[BaseEditionTagLower]]-[[VersionTag]].html
file emscripten:standalone[[BaseEditionTagLower]]-[[VersionTag]].html.mem
file emscripten:standalone[[BaseEditionTagLower]]-[[VersionTag]].js
file emscripten:emscripten-startup-template.livecodescript
rfolder emscripten:emscripten-standalone-template
file emscripten-js:standalone[[BaseEditionTagLower]]-[[VersionTag]].html
file emscripten-js:standalone[[BaseEditionTagLower]]-[[VersionTag]].html.mem
file emscripten-js:standalone[[BaseEditionTagLower]]-[[VersionTag]].js
file emscripten-js:emscripten-startup-template.livecodescript
rfolder emscripten-js:emscripten-standalone-template
into "[[ToolsFolder]]/Runtime/Emscripten/wasm" place
file emscripten-wasm:standalone[[BaseEditionTagLower]]-[[VersionTag]].html
file emscripten-wasm:standalone[[BaseEditionTagLower]]-[[VersionTag]].js
file emscripten-wasm:standalone[[BaseEditionTagLower]]-[[VersionTag]].wasm
file emscripten-wasm:emscripten-startup-template.livecodescript
rfolder emscripten-wasm:emscripten-standalone-template

//////////

Expand Down
24 changes: 15 additions & 9 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -276,15 +276,21 @@ all-win-x86_64:
# Emscripten rules
################################################################

config-emscripten:
$(EMMAKE) ./config.sh --platform emscripten
config-emscripten-%:
$(EMMAKE) ./config.sh --platform emscripten-$*

compile-emscripten:
$(EMMAKE) $(MAKE) -C build-emscripten/livecode default
compile-emscripten-%:
$(EMMAKE) $(MAKE) -C build-emscripten-$*/livecode default

check-emscripten:
$(EMMAKE) $(MAKE) -C build-emscripten/livecode check
check-emscripten-%:
$(EMMAKE) $(MAKE) -C build-emscripten-$*/livecode check

all-emscripten:
$(MAKE) config-emscripten
$(MAKE) compile-emscripten
all-emscripten-%:
$(MAKE) config-emscripten-$*
$(MAKE) compile-emscripten-$*

#synonyms for *-emscripten-js
all-emscripten: all-emscripten-js
config-emscripten: config-emscripten-js
compile-emscripten: compile-emscripten-js
check-emscripten: check-emscripten-js
5 changes: 5 additions & 0 deletions buildbot.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,11 @@ def get_build_platform():
os.environ.get('BUILD_SUBPLATFORM'))
if platform[0] is None:
error('You must set $BUILD_PLATFORM')

# Assume js architecture for emscripten platform if not specified
if platform[0] is 'emscripten':
platform[0] = 'emscripten-js'

return platform

def get_buildtype():
Expand Down
9 changes: 7 additions & 2 deletions config.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,15 @@
'x86-win32', # TODO[2017-03-23] More specific ABI
'x86_64-win32',
'js-emscripten-sdk1.35',
'wasm-emscripten-sdk1.39',
)

KNOWN_PLATFORMS = (
'linux-x86', 'linux-x86_64', 'linux-armv6hf', 'linux-armv7',
'android-armv6', 'android-armv7', 'android-arm64', 'android-x86', 'android-x86_64',
'mac', 'ios',
'win-x86', 'win-x86_64',
'emscripten'
'emscripten', 'emscripten-js', 'emscripten-wasm',
)

def usage(exit_status):
Expand Down Expand Up @@ -288,10 +289,14 @@ def validate_target_arch(opts):
validate_platform(opts)

platform = opts['PLATFORM']
if platform == 'emscripten':
if platform in ['emscripten', 'emscripten-js']:
opts['TARGET_ARCH'] = 'js'
opts['UNIFORM_ARCH'] = opts['TARGET_ARCH']
return
if platform == 'emscripten-wasm':
opts['TARGET_ARCH'] = 'wasm'
opts['UNIFORM_ARCH'] = opts['TARGET_ARCH']
return

platform_arch = re.search('-(x86|x86_64|arm(64|v(6(hf)?|7)))$', platform)
if platform_arch is not None:
Expand Down
6 changes: 0 additions & 6 deletions config/arch.gypi
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,6 @@
'host_os': 'linux',
},
],
[
'OS == "emscripten"',
{
'target_arch': 'js',
},
],
],
},

Expand Down
21 changes: 18 additions & 3 deletions config/emscripten-settings.gypi
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@
'-s ALLOW_MEMORY_GROWTH=1',
'-s ASSERTIONS=1',
'-s DEMANGLE_SUPPORT=1',
'-s EMTERPRETIFY=1',
'-s EMTERPRETIFY_ASYNC=1',
'-s LINKABLE=1',
'-s RESERVED_FUNCTION_POINTERS=1024',
'-s TOTAL_MEMORY=67108864',
Expand All @@ -46,6 +44,23 @@

'target_conditions':
[
[
'toolset_arch == "wasm"',
{
'cflags':
[
'-s ASYNCIFY=1',
'-s', 'ASYNCIFY_IMPORTS=["MCEmscriptenAsyncYield"]',
],
},
{
'cflags':
[
'-s EMTERPRETIFY=1',
'-s EMTERPRETIFY_ASYNC=1',
]
},
],
[
'silence_warnings == 0',
{
Expand Down Expand Up @@ -101,7 +116,7 @@
{
'cflags':
[
'-Os',
'-O2',
'-g3',
],

Expand Down
2 changes: 1 addition & 1 deletion config/emscripten.gypi
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
'variables':
{
'mobile': 1,
'output_dir': '../emscripten-bin',
'output_dir': '../emscripten-<(target_arch)-bin',
},

'target_defaults':
Expand Down
100 changes: 82 additions & 18 deletions docs/development/build-emscripten.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

![LiveCode Community Logo](http://livecode.com/wp-content/uploads/2015/02/livecode-logo.png)

Copyright © 2015 LiveCode Ltd., Edinburgh, UK
Copyright © 2020 LiveCode Ltd., Edinburgh, UK

**Warning**: Emscripten (HTML5) platform support for LiveCode is experimental and not recommended for production use.

Expand All @@ -11,57 +11,121 @@ Copyright © 2015 LiveCode Ltd., Edinburgh, UK
You will need a 64-bit Linux machine or VM with at least 4 GB of RAM
(8 GB is recommended).

## Emscripten build architectures

There are two emscripten architectures that can be targeted for building the Emscripten engine, asm.js and WebAssembly. asm.js is based on a subset of JavaScript, whereas WebAssembly produces binary byte-code.

## Building for asm.js

The emscripten-js build target produces output in asm.js format that is converted to bytecode in order to be run through an interpreter. The emterpreted code can then be halted and resumed. This method of producing interruptable code is now deprecated but the tools are still available from the Emscripten SDK.

### Emscripten SDK

Unsurprisingly, the Emscripten SDK must be installed in order to build
an Emscripten engine.
1. Download the Emscripten SDK. The recommended method for obtaining the Emscripten SDK is to use git tools to clone the emsdk repository from github. Other methods are described in <https://emscripten.org/docs/getting_started/downloads.html>. Put it in `/opt/emsdk_js`, for example.

1. Download the portable Emscripten SDK from <https://kripken.github.io/emscripten-site>. Put it in `/opt/emsdk_portable`, for example.
`git clone https://github.com/emscripten-core/emsdk /opt/emsdk_js`

2. Check which SDKs are available by running:
2. Check that the required tools are available by running:

/opt/emsdk_portable/emsdk list
`/opt/emsdk_js/emsdk list --old`

3. Install and activate SDK 1.35.23 by running:

/opt/emsdk_portable/emsdk install sdk-1.35.23-32bit
/opt/emsdk_portable/emsdk activate sdk-1.35.23-32bit
`/opt/emsdk_js/emsdk install node-12.9.1-64bit`
`/opt/emsdk_js/emsdk activate --embedded node-12.9.1-64bit`
`/opt/emsdk_js/emsdk install emscripten-tag-1.35.23-64bit`
`/opt/emsdk_js/emsdk activate --embedded emscripten-tag-1.35.23-64bit`
`/opt/emsdk_js/emsdk install fastcomp-clang-tag-e1.35.23-64bit`
`/opt/emsdk_js/emsdk activate --embedded fastcomp-clang-tag-e1.35.23-64bit`

This will take a really long time and use an insane amount of RAM.

## Build environment
### Build environment

Before building for Emscripten, source the Emscripten SDK script that sets up the environment correctly. You need to source it with the `.` or `source` command rather than just running it.

`source /opt/emsdk_js/emsdk_env.sh`

### Configuring LiveCode

To configure LiveCode, run:

`make config-emscripten-js`

This will generate make control files in the `build-emscripten-js` directory. You can also run `config.sh` directly.

### Compiling LiveCode

To compile LiveCode, run:

`make compile-emscripten-js`

This will generate outputs in the `emscripten-bin-js` directory.

## Building for WebAssembly

The emscripten-wasm build target produces output in WebAssembly format that is then processed to allow the call stack to be saved and restored, making it possible for the engine execution to be halted and resumed. This is now the preferred method of generating interruptable code and can be built with the most recent version of the Emscripten SDK tools (version 1.39.12 as of April 2020).

### Emscripten SDK

1. Download the Emscripten SDK as described above. Put it in `/opt/emsdk_wasm`, for example.

`git clone https://github.com/emscripten-core/emsdk /opt/emsdk_wasm`

2. Check that the required tools are available by running:

`/opt/emsdk_wasm/emsdk list`

3. Install and activate SDK 1.39.12 by running:

`/opt/emsdk_wasm/emsdk install 1.39.12`
`/opt/emsdk_wasm/emsdk activate --embedded 1.39.12`

### Build environment

Before building for Emscripten, source the Emscripten SDK script that sets up the environment correctly. You need to source it with the `.` or `source` command rather than just running it.

source /opt/emsdk_portable/emsdk_env.sh
`source /opt/emsdk_wasm/emsdk_env.sh`

## Configuring LiveCode
### Configuring LiveCode

To configure LiveCode, run:

make config-emscripten
`make config-emscripten-wasm`

This will generate make control files in the `build-emscripten` directory. You can also run `config.sh` directly.
This will generate make control files in the `build-emscripten-wasm` directory. You can also run `config.sh` directly.

## Compiling LiveCode
### Compiling LiveCode

To compile LiveCode, run:

make compile-emscripten
`make compile-emscripten-wasm`

This will generate outputs in the `emscripten-bin` directory.
This will generate outputs in the `emscripten-bin-wasm` directory.

## Running LiveCode

**Note**: See also the "HTML5 Deployment" guide, available in the in-IDE dictionary.

A desktop IDE built and launched from the repository checkout folder can be used to run HTML5 standalones with the emscripten engines compiled using the steps above.

1. Enable emscripten output in the standalone settings for your stack. You can choose which architectures to include in the standalone output folder.

2. Select a browser from the "Development -> Test Target" menu

3. Click the "Test" button on the IDE toolbar.

Your stack will be compiled to a HTML5 standalone and launched in the selected browser. If "WebAssembly" output is enabled in the standalone settings of the stack then the WebAssembly engine will be used when compiling the test app, otherwise the asm.js engine will be used.

## Manual testing of HTML5 standalones.

Use the desktop build of the LiveCode IDE to run the standalone builder and create an "HTML5" standalone.

Once you've created a standalone, you can open the HTML file in a web browser to try out the engine.

Some web browsers (including Google Chrome) have JavaScript security policies that won't allow you to run the engine from a local filesystem. For these browsers, you will need to run a local web server. You can use the following steps to launch a local-only webserver listening on port 8080:

cd /path/to/my/standalone
python -m SimpleHTTPServer 8080
`cd /path/to/my/standalone`
`python -m SimpleHTTPServer 8080`

You can then load http://localhost:8080/ in a web browser to view your standalone HTML5 engine.
14 changes: 14 additions & 0 deletions docs/notes/feature-emscripten-webassembly.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# New WebAssembly option for HTML5 deployment of LiveCode apps (experimental)

The LiveCode engine can now be deployed to HTML5 as WebAssembly.
WebAssembly is supported in most major web browsers and allows HTML5
apps to run at near-native speeds.

To used WebAssembly when deploying a stack as an HTML5 application,
enable the "Build for WebAssembly" checkbox on the "HTML5" page of the
standalone settings window, and then generate the standalone in the
normal way.

For more information on HTML5 deployment, including options for
embedding LiveCode standalones in web pages, please see the "HTML5
Deployment" guide in the IDE dictionary.
Loading