Requirements

Prerequisite knowledge

Prior experience with using compilers will help you make the most of this article.

User level

Intermediate

The Flash C++ Compiler (FlasCC) provides a complete C/C++ development environment based on GCC that you can use to compile C/C++ code to target Adobe Flash Player and Adobe AIR. Using flascc, you can port virtually any of your existing C/C++ code to the web.

This article contains tips and tricks to help you get started with flascc.

Tips for debugging with GDB

Like most GCC-based toolchains, flascc uses GDB as its debugger. It provides a customized version of GDB to debug flascc-compiled C/C++ code that is running within Flash Player.

Setting the FLASCC_GDB_RUNTIME environment variable

To execute GDB, you must define a FLASCC_GDB_RUNTIME environment variable that contains a fully qualified path to either a standalone debugger version of Flash Player or a web browser in which the debugger version of Flash Player is installed. If the path contains spaces use either double quotes (Windows) or escape spaces with a backslash (Mac).

For example:

  • On Windows:
FLASCC_GDB_RUNTIME="/cygdrive/c/Program Files (x86)/Mozilla Firefox/firefox.exe"
  • On Mac OS X:
FLASCC_GDB_RUNTIME= export FLASCC_GDB_RUNTIME=/Users/flex/runtimes/player/11.3/mac/Flash\ Player\ Debugger.app

Using GDB in Firefox

If you are using Firefox you may want to extend or disable the plugin hang detection time to avoid the browser prematurely killing the SWF while you are debugging. For more information on how to do this, see the MozillaZine article on this topic.

Connecting GDB to a SWF hosted on a remote site

If your flascc application is running on a remote site (a staging server, for example), set the FLASCC_GDB_RUNTIME environment variable to point to your browser (as described above) and then pass the URL of your remote application to GDB when you start it, for example:

gdb www.mysite.com/games/mygame.html

Debugging SWCs with GDB

When you compile a SWC, you specify a namespace. So, when you debug that SWC, you need to tell GDB which namespace you want using the set as3namespace command. You can debug only one SWC per session. For more information, see the GDB section of docs/Reference.html of your local flascc installation or online.

Using the GDB call command

While debugging with GDB, you can use the call command to invoke a function in your code. This can be an arbitrary function in which you are interested, or it can be a function that you have added strictly for debugging purposes. For example:
(gdb) call dumpValues()

Rerunning a SWF in GDB (and disregarding the associated warnings)

When you rerun a SWF in GDB, you may see a warning like the following:
warning: Temporarily disabling breakpoints for unloaded shared library "remote:0.elf"
You can safely ignore these warnings.
Here is an example of running and rerunning a SWF in GDB:

<path>/sdk/usr/bin/gdb call.swf GNU gdb (GDB) 7.3 Copyright (C) 2011 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "--host=x86_64-apple-darwin10 --target=avm2-elf". For bug reporting instructions, please see: <http://www.gnu.org/software/gdb/bugs/>... (gdb) b main No symbol table is loaded. Use the "file" command. Make breakpoint pending on future shared library load? (y or [n]) y Breakpoint 1 (main) pending. (gdb) r Starting program: call.swf 0xdddddddd in ?? () Breakpoint 1, 0xf0000247 in main (argc=0, argv=0x200ff0) at call.c:66 66 int s = 2; (gdb) r The program being debugged has been started already. Start it from the beginning? (y or n) y warning: Temporarily disabling breakpoints for unloaded shared library "remote:0.elf" Starting program: call.swf 0xdddddddd in ?? () Breakpoint 1, 0xf0000247 in main (argc=0, argv=0x200ff0) at call.c:66 66 int s = 2; (gdb)

Disregarding the "No symbol table is loaded...." message

In certain situations, when you run GDB, you will see the following message:

No symbol table is loaded.... pending on future shared library load

You can safely ignore this warning.

Use monitor eval <longLocalVariableString> to view long Strings in GDB

GDB does not display ActionScript 3 Strings in the regular list of locals if the String is longer than 80 characters. To view these Strings, use the monitor eval command.

For example, monitor eval myLongVariable displays the String value regardless of the length.

Optimization tips

When you’re done debugging and ready to optimize, consider the following tips.

Generating a fully optimized application

By default, the flascc version of GCC produces ActionScript ByteCode (ABC). This is adequate for most of the development cycle, when fast compile times are what you need. However, for full optimization, use the -emit-llvm or -O4 options when invoking GCC. These options result in LLVM bitcode, which creates a Link Time Optimized (LTO) build. Although it takes longer to compile with these switches, you get a final fully-optimized build with everything compiled as LLVM bitcode. For example, the following command lines create a fully optimized build:

gcc test.c -emit-llvm -c -o test.o gcc test.c -O4 -c -o test.o gcc test.c -emit-llvm -emit-swf -o test.swf gcc test.c -O4 -emit-swf -o test.swf

Using GCC to generate a SWC

When you use GCC to generate a SWC you must use the -emit-swc= option to specify the AS3 package name that will contain the generated code and the internal flascc boilerplate code. This lets you link multiple flascc-generated SWCs into one SWF without any function or class collisions. The following example is from /tutorials/05_SWC/makefile:

"$(FLASCC)/usr/bin/g++" -O4 MurmurHash3.cpp as3api.cpp main.cpp -emit-swc=sample.MurmurHash -o MurmurHash.swc

For more information, see Building SWCs in docs/Reference.html of your local flascc installation.

Optimizing SWC and SWF size

Although GCC includes many options to minimize output size, the following are the most common techniques:

  • Use the GCC -O4 option to generate LLVM bitcode and create a fully optimized build.
  • Use an exports file to customize what is included in the build. For an example, see /tutorials/12_Stage3D/exports.txt.
  • Experiment with the various optimization options that llvm provides (such as -Os)

Targeting an older SWF

The SWF version determines which version of the AIR and Flash Player APIs are available. For example, SWF 17 equates to AIR 3.4 and Flash Player 11.4; if you specify SWF 16, your application will have access to only the AIR 3.3 and Flash Player 11.3 APIs. If, for some reason, you want to target an older SWF version, use the GCC -swf-version= option (the current default is SWF version 17, so to change it to SWF version 16, you'd specify the following:
-swf-version=16

For more information on the mapping between SWF version and Flash Player version, see Creating the extension descriptor file.

Using the C++ wrappers to Flash classes

Flascc provides a set of header files that wrap the Flash top-level classes (for example, Number and Array), as well as the Flash class library (for example, flash.display.Stage and flash.display.Stage3D). These wrappers provide access to all methods, properties, and events of the corresponding ActionScript classes. For more information, see Interop Between C/C++ And ActionScript in docs/Reference.html of your flascc installation. The wrappers are also used in tutorials/12_Stage3D/stage3d.cpp.

Customizing the default preloader

Flascc applications automatically include a simple preloader that displays as the SWF loads. You can create a customized preloader to use with your flascc application. This is explained in the flascc Reference Guide, available in the /docs directory of your flascc installation.

Adjust Java memory allocation

Although it is strongly recommended that you use 64-bit Java with flascc, some developers have been able to use 32-bit Java for certain, small applications. In this case, if the machine has limited memory, you may need to reduce the Java heap specification (the default is –jvmopt="-Xmx1500m") to a smaller number, for example, –jvmopt="-Xmx256m". You can do this when invoking GCC in the makefile. For example:

gcc -jvmopt="-Xmx256M" hello.c -o hello.exe

Conversely, if you are running 64-bit Java and your machine has memory to spare, you may want to increase the Java heap size.

64-bit Java is available from the Oracle software downloads page.

More tips

Here are some additional tips for using flascc.

Using a class in a SWC file as the Console

When you link against a SWC, you must specify the object that will be the Console.
You should call CModule.vfs.setConsole(this); before the call to initLib() in the ActionScript file and also include an implementation of write() that looks something like this:

public function write(fd:int, buf:int, nbyte:int, errno_ptr:int):int { var str:String = CModule.readString(buf, nbyte); trace(str); // or display this string in a textfield somewhere? return nbyte; }

For another example, see Console.as in the 04_Animation tutorial.

Customizing SWF dimensions

To specify the SWF dimensions, pass the -swf-size=widthxheight flag to GCC; for example: -swf-size=200x200.

Defining an import so that you can use Context3d in a function call

To define an import so that you can use Context3D in a function call, use the as3import annotation. The following example snippet is from /tutorials/Example_BulletPhysicsLibrary/bullet.i:

void positionAndRotateMesh() __attribute__((used, annotate("as3sig:public function positionAndRotateMesh(mesh:*, rigidBody:*):void"), annotate("as3package:org.bulletphysics"), annotate("as3import:flash.geom.Vector3D")));

Preventing memory leaks in wrappers for functions that return structs and objects by value

When using the SWIG compiler to create SWCs from your C/C++ header files, note the following:

  • By default, the wrappers for functions that return structs and objects by value leak memory. SWIG has no way of knowing by itself when it should free such values, so it's expected that the code that calls the wrapper will free the returned value at the appropriate time.
  • Flascc has no standard typemaps for std::string, nor any of the C++ standard library classes. Because of this, many uses of std::string or similar classes in wrappers may not work as expected, and you’ll need to write application-specific typemaps to achieve the desired behavior.

Using as3wig to create a C++ interface

You can use the flascc AS3 Wrapper Interface Generator (as3wig) to create a C++ library interface for existing ActionScript 3 ActionScript ByteCode (ABC). For an example, see /tutorials/12_Stage3D/makefile in your local installation, specifically, the following line:

sdk/usr/lib/as3wig.jar -i AGAL.abc -o AGAL

Creating a custom Console implementation

When your SWF loads, the Console class is the first class to be created and executed. It is an ActionScript class that controls when and how the flascc compiled code is initialized. It is also used by the underlying flascc POSIX implementation as the object that handles read and write requests to the various standard input, output, and error terminal streams. In some cases, you will want to create a custom Console implementation. For example, although you can interact with all of the Flash APIs using the C++ wrappers included in Flash++.h, you might prefer to use pure ActionScript 3 in your Console implementation. For information on the Console class, see the ActionScript API docs in /docs/apidocs/index.html of your flascc installation. For complete information, see /docs/Reference.html of your flascc installation.

Don't use fsync()

Flascc does not support fsync(). Instead, close the file, which will commit your changes.

Using CModule.startBackground() and CModule.startAsync()

The com.adobe.flascc.CModule ActionScript class contains convenience functions for reading and writing to domainMemory. It also manages any flascc-specific global state (for example, the VFS and POSIX interface implementations). Among other methods, note the difference between the following:

  • startAsync() - Calls the libc __start1 function which, in turn, causes main() to execute.
  • startBackground() - Creates a background Worker and runs the libc function __start1 within that Worker. This method requires SWF version 18 (Flash Player 11.5) or higher.

For information on the CModule class, see the ActionScript API docs in /docs/apidocs/index.html of your flascc installation.

Where to go from here

For further reading, see the Adobe Gaming flascc page.