Chapter 49. Understanding Compilation

Table of Contents

1. Overview
2. The Command Line Compiler
2.1. Running the Command Line Compiler
2.2. Command Line Options
2.3. Compile-time constants
2.4. New DHTML Runtime and new URL parameters
2.5. Incremental Compilation
3. LZO Binary Compilation
3.1. Building with LZO Libraries
4. Compiler Errors and Warnings
5. Compiler Directives
5.1. Conditional Compilation of Runtime-Dependent code
5.2. Font and Face

1. Overview

You can compile your applications for any of several runtimes using any of several techniques. In this chapter we'll look at invoking the compiler and its various options directly from the command line.

You can also invoke compilation using the Developer Toolbar, or by using URLs to invoke the OpenLaszlo Server directly. Both these techniques are described in Section 1.4.2, “The Developer Toolbar”in Chapter 4. Overview of OpenLaszlo Application Development.

2. The Command Line Compiler

In OpenLaszlo, 'the compiler' consists (currently) of two phases:

  • the view compiler, which compiles LZX to JavaScript

  • the script compiler, which compiles JavaScript to the target runtime (SWF8, SWF1o and DHTML). lzc invokes both those phases (although you can ask for the intermediate output).

The Debugger needs an OL server to be able to evaluate forms (it calls the server to compile the form and then loads and runs the result). It will try to talk to OL server (using the url the application was loaded from), so it should 'just work', so long as you are running a server, even if you don't use the server for compiling your application.

[Note] Note

If you use the command-line compiler to compile a SOLO application, you won't be able to evaluate any expression that requires the Debugger to send code to the server for compilation.

2.1. Running the Command Line Compiler

To run lzc you must do so from a current directory that matches the value of LPS_HOME, and LPS_HOME must be set to the correct value for the build.

Say the application to be compiled is

$LPS_HOME/laszlo-explorer/basics/mediatst.lzx

To compile it correctly you would set the current directory first:

cd $LPS_HOME;

and then compile using

lzc --script --runtime=dhtml laszlo-explorer/basics/mediatst.lzx;

Let's say the file $LPS_HOME/laszlo-explorer/basics/mediatst.lzx wants to reference the file $LPS_HOME/laszlo-explorer/basics/assets/background.jpg. It might contain the following reference.

<canvas>
  <view resource="assets/background.jpg"/>
</canvas>

Running LZC from other than LPS_HOME will result in a file not found error.

2.2. Command Line Options

Here are the options available for compilation:

Options:

--help

lists all options.

-D<name>=<value>

Set the name/var property to value (See Compiler.getProperties).

-D<name>

Short for -Dname=true.

-v

Write progress information to standard output.

--mcache on|off

Turns on/off media cache. Default is off.

--onerror [throw|warn]

Action to take on compilation errors. Defaults to warn.

--script-cache-dir <directory>

Location of script cache directory (default <lps>/work/scache).

--media-cache-dir <directory>

Location of media cache directory (default <lps>/work/cache/cmcache).

--flush-script-cache

Doesn't flush script cache before compiling.

Output options:

--runtime=[swf8|swf9|dhtml]

Compile to swf8, swf9, or dhtml.

--output <file> (or -o <file>)

The name of the output file. This option is only valid when there is one input file.

--dir outputdir

Output directory.

-g | --debug

Add debugging information into the output object.

-p | --profile

Add profiling information into the output object.

Logging options:

-l<loglevel>

Logging level (See org.apache.log4j.Level)

-l<loggerName>=<loglevel>

Logging level (See org.apache.log4j.Level)

-lp file

Log4j properties files

--log logfile

Specify logfile (output still goes to console as well)

--schema

Writes the schema to standard output.

--script

Writes JavaScript to standard output.

2.3. Compile-time constants

You can define compile-time constants to `lzc` by using `-D_name_=_value_`, where _value_ should be either `true` or `false`. By convention, we use `$` as the first character of _name_, but nothing enforces that.

The compiler will compile only the chosen branch of an if statement when the condition expression is a compile-time constant (i.e., just the constant name, no other computation). For example:

  if ($slow) {
    ... slow way ...
  } else {
    ... fast way ...
  }

You can define compile-time constants to `lzc` by using `-D_name_=_value_`, where _value_ should be either `true` or `false`. By convention, we use `$` as the first character of _name_, but nothing enforces that. The compiler will compile only the chosen branch of an if statement when the condition expression is a compile-time constant (i.e., just the constant name, no other computation).

For example:

  if ($slow) {     ... slow way ...   } else {     ... fast way ...   } Can be made to run fast by `lzc -Dslow=false`

2.4.  New DHTML Runtime and new URL parameters

As part of the architectural overhaul, we have created a new version of the client runtime (LFC plus kernel). To invoke an application compiled for DHMTML, use the ?lzr=dhtml query.

The ?lzr parameter selects the runtime. Your choices are swf8, swf9, and dhtml. The default is specified in lps/config/lps.properties as compiler.runtime.default. The default runtime selector is swf8.

The ?lzt parameter is the 'request type', in general what kind of 'wrapper' page will be generated around your application. Your choices are: app_console or html. app_console is the developer console, html is your app in an html page. The latter can be used as a model for embedding your app in a custom page, or you can simply embed using an iframe:

<iframe src=".../app.lzx?lzt=html"></iframe>

The default for ?lzt is specified in lps/config/lps.properties as defaultRequestType. The default value is app_console.

Mnemonics:

  • lzr - Laszlo Runtime

  • lzt - Laszlo request Type

So, for example, to view an LZX application in DHTML within a browser, download it from a live server with an url parameter requesting the DHTML runtime lzt=html: http://myserver/mylaszloapp.lzx?lzr=dhtml. To request the SWF runtime, use http://myserver/mylaszloapp.lzx?lzr=swf.

To specify that the application run in the Developer Toolbar, use the lzt flag: lzt=app_console loads the application with the Developer Toolbar. lzr=swf8 and lzr=swf9 loads the application compiled for the SWF8 or SWF9 runtime, with the Developer Toolbar. Two lzr values have been added for future use, but are not currently supported: j2me, and svg

2.5. Incremental Compilation

When compiling an application to the swf10 runtime, there is an incremental compilation mode which may help to speed up recompiling the application.

The incremental compilation mode should be from the fcsh compiler shell utility (located in WEB-INF/bin/fcsh). This is a utility which is specific to compiling for the swf10 runtime. An application can be compiled within the fcsh shell, and the shell left running. When the source code is modified, you can recompile the application from within the shell.

This should be substantially faster than invoking the compiler via lzc, because internal state of the flash 10 backend compiler is kept in memory in the Java virtual machine, rather than having to be reloaded from disk.

2.5.1. Using Incremental Compilation

Where you would normally run lzc --runtime=swf10 yourapp.lzx, instead you use the modified fcsh shell, as follows. It supports a lzc command which has the same arguments: run fcsh shell script (lives in WEB-INF/bin)

FLEX_HOME=../../WEB-INF/bin/..
        Adobe Flex Compiler SHell (fcsh)
        Version 4.0.0 build 6898
        Copyright (c) 2004-2007 Adobe Systems, Inc. All rights reserved.

(fcsh) lzc --runtime=swf9 app.lzx
        calling lzc
        Compiling: app.lzx to app.swf9.swf
        swf9 compiler options changes, cleaning working dir
        Executing compiler: (cd /var/folders/xh/xhmdrA41HCKjjiditeqN1k+++TI/-Tmp-/lzswf9/./build/app; /Users/hqm/openlaszlo/trunk/WEB-INF/bin/mxmlc -load-config=/Users/hqm/openlaszlo/trunk/WEB-INF/frameworks/flex-config.xml -compiler.show-actionscript-warnings=false -compiler.source-path+=/var/folders/xh/xhmdrA41HCKjjiditeqN1k+++TI/-Tmp-/lzswf9/./build/app -compiler.headless-server=true -compiler.fonts.advanced-anti-aliasing=true -output /var/folders/xh/xhmdrA41HCKjjiditeqN1k+++TI/-Tmp-/lzswf9/./build/app/app.swf -default-size 800 600 -compiler.library-path+=/Users/hqm/openlaszlo/trunk/lps/includes/lfc/LFC9.swc -compiler.library-path+=/Users/hqm/openlaszlo/trunk/WEB-INF/flexlib -includes \$debug \$profile \$backtrace \$runtime \$swf7 \$swf8 \$as2 \$swf9 \$swf10 \$as3 \$dhtml \$j2me \$svg \$js1 -target-player=9.0.0 -compiler.incremental=true -frame two LzSpriteApplication -file-specs=/var/folders/xh/xhmdrA41HCKjjiditeqN1k+++TI/-Tmp-/lzswf9/./build/app/LzPreloader.as)
        option EMIT_AS3_ONLY set, returning without invoking flex compiler, call 'lcompile #' to compile as3
        lzc returned /Users/hqm/openlaszlo/trunk/demos/lzpix/app.swf9.swf
        fcsh: Assigned 1 as the compile target id
        Loading configuration file /Users/hqm/openlaszlo/trunk/WEB-INF/frameworks/flex-config.xml
        /var/folders/xh/xhmdrA41HCKjjiditeqN1k+++TI/-Tmp-/lzswf9/./build/app/app.swf (403317 bytes)
        (fcsh) 

then if you modify one or more .lzx files, you recompile incrementally by saying lcompile 1 (or whatever the ID number assigned by fcsh in the previous command)

touch classes/pivotlayout.lzx
(fcsh) lcompile 1
        lcompile, calling lzc with args: 
        --lzxonly
        --incremental
        --runtime=swf9
        app.lzx
        Compiling: app.lzx to app.swf9.swf
        Executing compiler: (cd /var/folders/xh/xhmdrA41HCKjjiditeqN1k+++TI/-Tmp-/lzswf9/./build/app; /Users/hqm/openlaszlo/trunk/WEB-INF/bin/mxmlc -load-config=/Users/hqm/openlaszlo/trunk/WEB-INF/frameworks/flex-config.xml -compiler.show-actionscript-warnings=false -compiler.source-path+=/var/folders/xh/xhmdrA41HCKjjiditeqN1k+++TI/-Tmp-/lzswf9/./build/app -compiler.headless-server=true -compiler.fonts.advanced-anti-aliasing=true -output /var/folders/xh/xhmdrA41HCKjjiditeqN1k+++TI/-Tmp-/lzswf9/./build/app/app.swf -default-size 800 600 -compiler.library-path+=/Users/hqm/openlaszlo/trunk/lps/includes/lfc/LFC9.swc -compiler.library-path+=/Users/hqm/openlaszlo/trunk/WEB-INF/flexlib -includes \$debug \$profile \$backtrace \$runtime \$swf7 \$swf8 \$as2 \$swf9 \$swf10 \$as3 \$dhtml \$j2me \$svg \$js1 -target-player=9.0.0 -compiler.incremental=true -frame two LzSpriteApplication -file-specs=/var/folders/xh/xhmdrA41HCKjjiditeqN1k+++TI/-Tmp-/lzswf9/./build/app/LzPreloader.as)
        option EMIT_AS3_ONLY set, returning without invoking flex compiler, call lcompile # to compile as3
        Loading configuration file /Users/hqm/openlaszlo/trunk/WEB-INF/frameworks/flex-config.xml
        Recompile: /private/var/folders/xh/xhmdrA41HCKjjiditeqN1k+++TI/-Tmp-/lzswf9/build/app/$lzc$class_pivotlayout.as
        Reason: The source file or one of the included files has been updated.
        Files changed: 1 Files affected: 0
        /var/folders/xh/xhmdrA41HCKjjiditeqN1k+++TI/-Tmp-/lzswf9/./build/app/app.swf (403318 bytes)
        renaming /var/folders/xh/xhmdrA41HCKjjiditeqN1k+++TI/-Tmp-/lzswf9/./build/app/app.swf to /Users/hqm/openlaszlo/trunk/demos/lzpix/app.swf9.swf
        (fcsh) 

You can keep modifying files and calling lcompile 1 to recompile incrementally.

3. LZO Binary Compilation

LZO stands for "LasZlo Object" file format.

For awhile, the 'lzc' compiler has been able to compile files into .lzo binary files by using the -c flag. It stored the library code in an intermediate platform-independent format.

In the latest release the compiler can also store precompiled platform-specific object code for both the DHTML and SWF10 runtime in the library, so that linking an application with libraries should be faster than ever.

3.1. Building with LZO Libraries

To compile a library to include native object code for both runtimes, you call lzc as follows, specifying one or more runtimes to place in the library.

lzc -c --runtime=swf10,dhtml mylibrary.lzx

3.1.1. LZO libraries which reference other external LZO libraries

We have a new rule, which is that when you compile a library that makes any external references to classes or globals in another library, that library must be already compiled down to an external binary library lzo file, and one which contains the target runtime.

For example let's say you are an ice-cream manufacturer, and have some new equipment that makes ice-cream bars. Your machine came with some software from the factory which makes basic tubs of icecream, and then you extend that software with your own custom class to make ice-cream bars.

Let's say the manufacturer supplied an lzx file to be included when you compile, called extdessert.lzx that defines a base icecream class. It's source code might be:

      extdessert.lzx:
      <library>
        <class name="icecream">
        ...
        </class>
      </library>

Then your code might look like:

      libdir/mylib.lzx:
      <library>
        <include href="../extdessert.lzx"/>
        <class name="icreambar" extends="icecream">
          <attribute name="coating" type="string" value="chocolate"/>
          <attribute name="icecreamflavor" type="string" value="vanilla"/>
          ....
        </class>
      </library>
        

Now you want to go to compile your code into a library.

If we want to compile to swf10, the extdessert file MUST be first compiled to an lzo which contains a swf10 runtime target , or the flash10 compiler will not be able to link against it properly when you build your library.

So you would in that case first build the extdessert.lzx into an lzo:

lzc -c --runtime=swf10 extdessert.lzx

and then your custom class library can be linked against it

lzc -c --runtime=swf10 libdir/mylib.lzx

So basically the rule is that when building a lzo library that depends on extending or referencing classes from other files, those files MUST be compiled to swf10 lzo's first.

4. Compiler Errors and Warnings

When the compiler detects an error that makes it impossible to compile the application, the error is reported in the browser window, or, if you invoked compilation using lzc, in the terminal window.

When the compiler detects code that may be problematic but does not prevent compilation, it issues a warning. If you have debugging enabled, the warning is displayed there. See Chapter 51, Debugging for a detailed discussion of how to detect errors.

5. Compiler Directives

5.1. Conditional Compilation of Runtime-Dependent code

You can enclose blocks of code within <switch> elements that are associated with a specific runtime. The <switch> is a compiler directive that instructs the compiler to compile or omit blocks according to the target runtime to which the application is being compiled. Within a <switch> block, use <when> to specify the runtime using a compile-time constant, like this:

<when property="compile-time-constant-name">

compile-time-constant-name can be $debug, $profile, $backtrace, $runtime, $swf7, $swf8, $as2, $swf9, $swf10, $as3, $dhtml, $j2me, $svg, or $js1.

Example 49.1. <switch> using <when> for conditional compilation

<canvas height="20" width="100%">
  <switch>
    <when property="$dhtml">
       <text>This program has been compiled for DHTML</text>
    </when>
    <otherwise>
      <text>This program has been compiled for SWF</text> 
    </otherwise>
  </switch>
</canvas>

You can also use unless in a similar way.

Example 49.2. <switch> using <unless> for conditional compilation

<canvas height="20" width="100%">
  <switch>
    <unless property="$swf10">
      <text>Not SWF10</text>
    </unless>
    <otherwise>
      <text>Must be SWF10</text>
    </otherwise>
  </switch>
</canvas>

You can also use this syntax:

<when property="$runtime" value="swf9"> // checks for string equality 

And for back compatibility:

<when runtime="swf9">

5.2. Font and Face

The <font> and <face> tags are also compiler directives. Unlike most other LZX tags, they do not correspond to a class; rather, they tell the compiler which fonts and typefaces are to be bound to objects.