Whilst the Lua Virtual Machine (LVM) can compile Lua source dynamically and this can prove
very flexible during development, you will use less RAM resources if you precompile
your sources before execution.

## Compiling Lua directly on your ESP8266

-  The standard [string.dump \(function)](https://www.lua.org/manual/5.1/manual.html#pdf-string.dump) returns a string containing the binary code for the specified function and you can write this to a SPIFFS file.

-  [`node.compile()`](modules/node/#nodecompile) wraps this 'load and dump to file' operation into a single atomic library call.

The issue with both of these approaches is that compilation is RAM-intensive and hence
you will find that you will need to break your application into a lot of small and
compilable modules in order to avoid hitting RAM constraints.  This can be mitigated
by doing all compiles immediately after a [node.restart()`](modules/node/#noderestart).

## Compiling Lua on your PC for Uploading

If you install `lua` on your development PC or Laptop then you can use the standard Lua
compiler to syntax check any Lua source before downloading it to the ESP8266 module.  However,
the NodeMCU compiler output uses different data types (e.g. it supports ROMtables) so the
compiled output from standard `luac` cannot run on the ESP8266.

Compiling source on one platform for use on another (e.g. Intel 64-bit Windows to ESP8266) is
known as _cross-compilation_ and the NodeMCU firmware build now automatically generates
a `luac.cross` image as standard in the firmware root directory; this can be used to
compile and to syntax-check Lua source on the Development machine for execution under
NodeMCU Lua on the ESP8266.

`luac.cross` will translate Lua source files into binary files that can be later loaded
and executed by the LVM.  Such binary files, which normally have the `.lc` (lua code)
extension are loaded directly by the LVM without the RAM overhead of compilation.

Each `luac.cross` execution produces a single output file containing the bytecodes
for all source files given in the output file `luac.out`, but you would normally
change this with the `-o` option. If you wish you can mix Lua source files (and
even Lua binary files) on the command line. You can use '-' to indicate the
standard input as a source file and '--' to signal the end of options (that is, all
remaining arguments will be treated as files even if they start with '-').

`luac.cross` supports the standard `luac` options `-l`, `-o`, `-p`, `-s` and `-v`,
as well as the `-h` option which produces the current help overview.

NodeMCU also implements some major extensions to support the use of the
[Lua Flash Store (LFS)](lfs.md)), in that it can produce an LFS image file which
is loaded as an overlay into the firmware in flash memory; the LVM can access and
execute this code directly from flash without needing to store code in RAM.  This
mode is enabled by specifying the `-f`option.

`luac.cross` supports two separate image formats:

-  **Compact relocatable**. This is selected by the `-f` option. Here the compiler compresses the compiled binary so that image is small for downloading over Wifi/WAN (e.g. a full 64Kb LFS image is compressed down to a 22Kb file.) The LVM processes such image in two passes with the integrity of the image validated on the first, and the LFS itself gets updated on the second.  The LVM also checks that the image will fit in the allocated LFS region before loading, but you can also use the `-m` option to throw a compile error if the image is too large, for example `-m 0x10000` will raise an error if the image will not load into a 64Kb regions.

-  **Absolute**. This is selected by the `-a <baseAddr>` option. Here the compiler fixes all addresses relative to the base address specified. This allows an LFS absolute image to be loaded directly into the ESP flash using a tool such as  `esptool.py`.  _Note that the new NodeMCU loader uses the `-f` compact relocatable form and does relocation based on the Partition Table, so this option is deprecated and will be removed in future releases.

These two modes target two separate use cases: the compact relocatable format
facilitates simple OTA updates to an LFS based Lua application; the absolute format
facilitates factory installation of LFS based applications.

Also note that the `app/lua/luac_cross` make and Makefile can be executed to build
just the `luac.cross` image.  You must first ensure that the following options in
`app/include/user_config.h` are matched to your target configuration:

```c
// When using Lua 5.1, two different builds are now supported.
// The main difference is in the // processing of numeric data types.
// If LUA_NUMBER_INTEGRAL is defined, then
// all numeric calculations are done in integer, with divide being an integer
// operation, and decimal fraction constants are illegal.
// Otherwise all floating point operations use doubles. All integer values
// can be represented exactly in floating point.

//#define LUA_NUMBER_INTEGRAL

// When using Lua 5.3, two different builds are now supported. 
// If LUA_NUMBER_64BITS is defined, then doubles are used to hold floating
// point numbers and integers are 64 bits long. Integers smaller than 2^53 can be i
// converted to doubles and back without any loss of precision.
// Otherwise all floating point operations use floats, and integers are 32-bit.
// Only integers under 2^24 can be represented exactly in floating point.
// Note that Lua 5.3 also supports Integers natively, but you have to be careful 
// not to promote an integer to a floating point variable as you can lose precision.

//#define LUA_NUMBER_64BITS
```

Note that the use of LFS and the LFS region size is now configured through the partition table.

Developers have successfully built this on Linux (including docker builds), MacOS, Win10/WSL and WinX/Cygwin.
