IT戦記

プログラミング、起業などについて書いているプログラマーのブログです😚

C/C++ のコードを Flash Player で動かす! Alchemy を速攻試してみる。

はじめに

Adobe から C/C++ で書いたコードを Flash や AIR で動かす Alchemy というものがリリースされましたね!
Alchemy - Adobe Labs

これはすごい!ということで、少し試してみたいと思います。
その様子をリアルタイムに書いていきます。ちゃんと出来るかな

環境

OS は Mac OS X で gcc 、 java は入っているものとします。
ホームディレクトリ(/Users/amachang)に AlchemyTest というディレクトリを作って作業します。

インストール

まずは、いろいろインストールします。

Flash Player 10 Debugger Version

Adobe Flash Player - Debug Downloads
ここからダウンロードしてきて、普通にインストールします。

Flex SDK

以下から Flex SDK をダウンロードします。
Flex SDK
現段階での最新の Stable のやつをダウンロードしました。具体的には以下のバージョンのものです。
http://opensource.adobe.com/wiki/display/flexsdk/download?build=3.2.0.3794&pkgtype=1
ダウンロードできたら、解凍します。今回は FlexSDK という名前のディレクトリを作ってそこに解凍しました。

$ unzip flex_sdk_3.2.0.3794.zip -d FlexSDK

とりあえず、 bin に PATH を通しておきましょう。

$ export PATH=/Users/amachang/AlchemyTest/FlexSDK/bin:$PATH

試しに、なんか適当な ActionScript のファイルから swf ファイルを作ってみましょう。
以下のように、適当なディレクトリを作って

$ mkdir Src
$ cd Src

そこに、以下のようなファイル Hoge.as を置きます。

package {
    import flash.display.Sprite
    public class Hoge extends Sprite {
        public function Hoge() { } 
    }   
}

で、さっき FlexSDK に解凍したツールを使ってコンパイルします。

$ mxmlc Hoge.as
設定ファイル "/Users/amachang/AlchemyTest/FlexSDK/frameworks/flex-config.xml" をロードしています
/Users/amachang/AlchemyTest/Src/Hoge.swf (555 bytes)

おおお。 swf ファイルがちゃんとできましたね。
というわけで、次は Alchemy Toolkit Package を導入します。
ここまでのディレクトリ構成は以下のような感じです。

$ pwd
/Users/amachang/AlchemyTest
$ tree -L 2
.
|-- FlexSDK
|   |-- AIR SDK Readme.txt
|   |-- SDK license.pdf
|   |-- ant
|   |-- asdoc
|   |-- bin
|   |-- flex-sdk-description.xml
|   |-- frameworks
|   |-- lib
|   |-- license-adobesdk.htm
|   |-- license-adobesdk_ja.htm
|   |-- license-mpl.htm
|   |-- readme.htm
|   |-- readme_ja.htm
|   |-- runtimes
|   |-- samples
|   `-- templates
|-- Src
|   |-- Hoge.as
|   `-- Hoge.swf
`-- flex_sdk_3.2.0.3794.zip

10 directories, 11 files
Alchemy Toolkit Package

次は Alchemy Toolkit Package をダウンロードしてきます。
Alchemy Toolkit Package
ダウンロードしたら、作業ディレクトリに置いて AlchemyToolkit というディレクトリに解凍します。

$ unzip alchemy_sdk_darwin_p1_111708.zip -d AlchemyToolkit

少し、ディレクトリ構成を見てみましょう。

$ tree -L 2 AlchemyToolkit
AlchemyToolkit
`-- alchemy-darwin-v0.4a
    |-- CHANGES
    |-- LICENSE
    |-- README.cygwin
    |-- README.darwin
    |-- README.ubuntu
    |-- achacks
    |-- avm2-libc
    |-- bin
    |-- config
    |-- flashlibs
    `-- samples

7 directories, 5 files

AlchemyToolkit のトップはこんな感じのディレクトリ構成になっています。
まず、 avm2-libc というのがありますね。この中にが libc.so の代わりにリンクされるライブラリが入っているのでしょうか。
また、 bin にツールが入っているのでしょうか。README を読む前に bin の中身を確認してみましょう。

$ ls AlchemyToolkit/alchemy-darwin-v0.4a/bin/
ExplSWF.pl			ShrSWF.pl			llvm-as				llvm-prof
GetABC2.pl			V10SWF.pl			llvm-bcanalyzer			llvm-ranlib
ImplSWF.pl			alc-util			llvm-config			llvm-stub
LICENSE-LLVM.TXT		asc.jar				llvm-db				llvm-upgrade
LICENSE-LLVMC.TXT		gccas				llvm-dis			llvm2cpp
LICENSE-ZLIB.TXT		gccld				llvm-extract			llvmc
PutABC2.pl			gluegen				llvm-gcc4-darwin-install	opt
PutBIN.pl			llc				llvm-ld				swfbridge
README-LLVM			lli				llvm-link			zpipe
README-ZLIB			llvm-ar				llvm-nm				zpipe.pl

おおお LLVM のツールがいっぱい入っています。
というわけで avm2-libc の中をみてみます。

$ ls -la AlchemyToolkit/alchemy-darwin-v0.4a/avm2-libc/
total 0
drwxr-xr-x   5 amachang  staff   170 11 14 03:09 .
drwxr-xr-x   8 amachang  staff   442 11 14 03:09 ..
drwxr-xr-x   2 amachang  staff   102 11 14 03:09 avm2
drwxr-xr-x  10 amachang  staff  2822 11 14 03:09 include
drwxr-xr-x   2 amachang  staff   136 11 18 20:19 lib

そして、この lib の中に

$ ls -la AlchemyToolkit/alchemy-darwin-v0.4a/avm2-libc/lib/
total 7544
drwxr-xr-x  2 amachang  staff      136 11 18 20:19 .
drwxr-xr-x  5 amachang  staff      170 11 14 03:09 ..
-rw-r--r--  1 amachang  staff  1564524 11 14 03:09 avm2-libc.l.bc
-rw-r--r--  1 amachang  staff  2297544 11 14 03:09 avm2-libstdc++.l.bc

LLVM のバイトコードが入っていました。

ちょっと寄り道、します。
avm2-libc.l.bc をディスアセンブルしてみましょう!

$ cd AlchemyToolkit/alchemy-darwin-v0.4a/
$ bin/llvm-dis avm2-libc/lib/avm2-libc.l.bc 

おお。成功したみたいです。 avm2-libc.l.ll というファイルが出来ました。
LLVM というものを全然しらないのですが、そのファイルの中身を見てみると冒頭に ActionScript 3.0 のソースコードみたいなものが見えます。そして、アセンブラのようなものが見えます。
きっと LLVM のアセンブラなのでしょう。

; ModuleID = 'avm2-libc/lib/avm2-libc.l.bc'
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-s0:0:64-f80:128:128"target triple = "i686-apple-darwin8"
module asm "import flash.utils.*"
module asm "import flash.display.*"
module asm "import flash.text.*"
module asm "import flash.events.*"
module asm "import flash.net.*"
module asm "import flash.system.*"
module asm "" 
module asm "public var gdomainClass:Class;"
module asm "public var gshell:Boolean = false;"
module asm "" 
module asm "public function establishEnv():void"
module asm "{"
module asm "  try"
module asm "  {"
module asm "    var ns:Namespace = new Namespace(\22avmplus\22);"
module asm "  "
module asm "    gdomainClass = ns::[\22Domain\22];"
module asm "    gshell = true;"
module asm "  }"
:
:

初見だと、どこがエントリーポイントかもわかりませんね

寄り道が過ぎたので、インストールに取りかかりましょう。
まず、 AlchemyToolkit/alchemy-darwin-v0.4a に移動します。

$ cd AlchemyToolkit/alchemy-darwin-v0.4a

で、 ./config を実行します。

$ ./config 
Generating alchemy-setup...
Turning execution bit on for Alchemy binaries...

Add "source /Users/amachang/AlchemyTest/AlchemyToolkit/alchemy-darwin-v0.4a/alchemy-setup" to your login script.
  "alc-home" takes you to the Alchemy install folder.
  "alc-on" puts Alchemy gcc toolchain replacements at the front of your path.
  "alc-off" restores original path.
  "alc-util" shows you various Alchemy-related environment vars
You need Flash 10 or AIR 1.5 and the Flex 3.2 SDK installed for testing.

alchemy-setup というファイルが作られました。「このファイルを login スクリプトに入れろ」と言われますが、とりあえず使うだけなので手動で実行するだけにします。

$ source alchemy-setup

そうすると、 alc-on alc-off が使えるようになります。これは、実際は環境変数 PATH などを切り替えることをします。
alc-on にした状態で gcc と叩くと achacks/gcc が実行されるといった具合ですね。
というわけで、 alc-on を実行します。

$ alc-on

環境変数を見てみましょう。

$ echo $PATH
/Users/amachang/AlchemyTest/AlchemyToolkit/alchemy-darwin-v0.4a/achacks:/Users/amachang/AlchemyTest/AlchemyToolkit/alchemy-darwin-v0.4a/bin:/Users/amachang/AlchemyTest/FlexSDK/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/X11/bin:/opt/local/bin

先頭に、 achacks ディレクトリが追加されていますね。 alc-off を実行すれば環境変数は元に戻ります。
次は、 sample をコンパイルして実行してみたいですね。

サンプルをコンパイルして実行する

サンプルは、 Alchemy Toolkit の直下の samples ディレクトリにありました。

$ cd AlchemyToolkit/alchemy-darwin-v0.4a/samples/
$ ls -la
total 0
drwxr-xr-x  6 amachang  staff  204 11 14 03:09 .
drwxr-xr-x  9 amachang  staff  510 11 18 21:39 ..
drwxr-xr-x  2 amachang  staff  170 11 14 03:09 AS3API
drwxr-xr-x  2 amachang  staff  204 11 14 03:09 AS3Lib
drwxr-xr-x  2 amachang  staff  102 11 14 03:09 HelloFlash
drwxr-xr-x  3 amachang  staff  204 11 14 03:09 stringecho
HelloFlash

まずは、 HelloFlash を実行してみましょう。
HelloFlash ディレクトリの中には HelloFlash.c というファイルが入っていました。
内容はこんな感じ

#include <stdlib.h>
#include <stdio.h>

int main(int argc, char* argv[])
{
	printf("Hello Flash!\n");
}

とりあえず、なにも考えずに gcc でコンパイルしてみます

$ cd HelloFlash
$ gcc HelloFlash.c 
WARNING: While resolving call to function 'main' arguments were dropped!

45416.achacks.swf, 354510 bytes written

なんか、 WARNING が出ましたが成功したみたいです。
そして、 a.exe というファイルが出来ました。

$ ls -la
total 704
drwxr-xr-x  2 amachang  staff     136 11 18 21:51 .
drwxr-xr-x  6 amachang  staff     204 11 14 03:09 ..
-r--r--r--  1 amachang  staff     104 11 14 03:09 HelloFlash.c
-rwxr-xr-x  1 amachang  staff  354590 11 18 21:51 a.exe

何も考えずに実行してみましょう。ドキドキ

$ ./a.exe 
/Users/amachang/AlchemyTest/FlexSDK/bin/adl _sb_45518/app.xml 2> /tmp/adl.trace & echo $!
Hello Flash!

おおおお。ちゃんと Hello Flash! と表示されました!

ちょっと寄り道
この a.exe っていうのがどういうファイルなのか気になったので調べてみる

$ file a.exe 
a.exe: a /Users/amachang/AlchemyTest/AlchemyToolkit/alchemy-darwin-v0.4a/bin/swfbridge script text executable

swfbridge というコマンドで実行されるスクリプト?開いてみる。
バイナリだった。。

$ head -3 a.exe 
#!/Users/amachang/AlchemyTest/AlchemyToolkit/alchemy-darwin-v0.4a/bin/swfbridge
FWS
(バイナリ)

って感じのファイル。
FWS って swf ファイルのマジックだったっけ?
そんな感じのファイルらしい。 swfbridge ってどんなものなんだろう。 adl を呼び出してるみたいだけど。
app.xml っていうファイルを自動で作って adl を呼び出すツールかな
ちょっと strings してみた

$ strings /Users/amachang/AlchemyTest/AlchemyToolkit/alchemy-darwin-v0.4a/bin/swfbridge
PATH
Couldn't write setup
_sb_%d
Couldn't create temp dir
error: %s
pid%d
%s/app.xml
<application xmlns="http://ns.adobe.com/air/application/1.5">
<id>com.adobe.%s</id>
<version>1.0</version>
<filename>%s</filename>
<name>%s</name>
<initialWindow>
<x>0</x>
<y>0</y>
<visible>false</visible>
<content>app.swf</content>
</initialWindow>
</application>
%s/app.swf
SWF: %s
:

おおお。 XML はけーん。 a.exe から app.xml と app.swf を作って adl に渡すみたいだなー。

またもや脱線しすぎました。

stringecho

次のサンプルは stringecho です。

$ cd ../stringecho

とりあえず、ディレクトリ構成は以下のようは感じになっています。

$ tree
.
|-- as3
|   `-- EchoTest.as
|-- readme.txt
`-- stringecho.c

1 directory, 3 files

readme.txt がありますね。でも、読んじゃうともったいないので、何も考えずにコンパイルしてみます。

$ gcc stringecho.c 
WARNING: While resolving call to function 'main' arguments were dropped!

46476.achacks.swf, 355002 bytes written

なんか、成功しました。では、実行します。ドキドキ

$ ./a.exe

おおおお

AIR さんに怒られました!これはこれで嬉しいですね。
というわけで、 readme.txt を読みます。
なるほど、以下のように swc オプションを付けることで、 swf から使える *.swc ファイルになるようになるようです。

$ gcc stringecho.c -swc -o stringecho.swc
WARNING: While resolving call to function 'main' arguments were dropped!

47506.achacks.swf, 362570 bytes written
frame rate: 60
frame count: 1
69 : 4
72 : 362500
76 : 33
1 : 0
0 : 0
frame rate: 24
frame count: 1
69 : 4
77 : 506
64 : 31
63 : 16
65 : 4
9 : 3
41 : 26
82 : 471
1 : 0
0 : 0
  adding: catalog.xml (deflated 75%)
  adding: library.swf (deflated 61%)

で、 stringecho.swc ファイルが出来るので、 EchoTest.as のコンパイル時に指定してあげます。

$ mxmlc -library-path+=stringecho.swc --target-player=10.0.0 as3/EchoTest.as

そうすると、 as3/EchoTest.swf が出来ます。
ただ、一見これを実行しても何もおきません。
以下のように、 trace 関数に結果を渡しているので、結果を見るには mm.cfg とかめんどくさい設定をしなければならないからです。

package {
    import flash.display.Sprite;
    import cmodule.stringecho.CLibInit;

    public class EchoTest extends Sprite
    {   
        public function EchoTest()
        {   
            var loader:CLibInit = new CLibInit;
            var lib:Object = loader.init();
    
            trace(lib.echo("foo"));
        }   
    }   
}

てっとり早く結果を見たいので、わざと Error を発生させましょう。

package {
    import flash.display.Sprite;
    import cmodule.stringecho.CLibInit;

    public class EchoTest extends Sprite
    {   
        public function EchoTest()
        {   
            var loader:CLibInit = new CLibInit;
            var lib:Object = loader.init();
    
            // 結果をエラーに乗せる
            throw Error(lib.echo("foo"));
        }   
    }   
}

というわけで、これで出来た EchoTest.swf をブラウザで開きます。

おおおお。ちゃんとError に foo という文字列が運ばれてきましたね!
この swf は以下のように swfbridge でも実行出来るようです。

$ ../../bin/swfbridge as3/EchoTest.swf


ちなみに、 C 言語側のコードはこんな感じです。 main で初期化して C 言語の関数を Flash から扱えるようにしているみたいですね。

//Simple String Echo example
//mike chambers
//[email protected]

#include <stdlib.h>
#include <stdio.h>

//Header file for AS3 interop APIs
//this is linked in by the compiler (when using flaccon)
#include "AS3.h"

//Method exposed to ActionScript
//Takes a String and echos it
static AS3_Val echo(void* self, AS3_Val args)
{
	//initialize string to null
	char* val = NULL;
	
	//parse the arguments. Expect 1.
	//pass in val to hold the first argument, which
	//should be a string
	AS3_ArrayValue( args, "StrType", &val );
	
	//if no argument is specified
	if(val == NULL)
	{
		char* nullString = "null";
		//return the string "null"
		return AS3_String(nullString);
	}
	
	//otherwise, return the string that was passed in
	return AS3_String(val);
}

//entry point for code
int main()
{
	//define the methods exposed to ActionScript
	//typed as an ActionScript Function instance
	AS3_Val echoMethod = AS3_Function( NULL, echo );

	// construct an object that holds references to the functions
	AS3_Val result = AS3_Object( "echo: AS3ValType", echoMethod );

	// Release
	AS3_Release( echoMethod );

	// notify that we initialized -- THIS DOES NOT RETURN!
	AS3_LibInit( result );

	// should never get here!
	return 0;
}

自分でも何か作ってみる

最初に作った Src ディレクトリに移動して

$ cd /Users/amachang/AlchemyTest/Src
まずは hello

hello.c を書く

#include "AS3.h"

static AS3_Val hello(void* self, AS3_Val args)
{
    return AS3_String("Hello, world.");
}

int main()
{
    AS3_Val method = AS3_Function( NULL, hello );

    AS3_Val object = AS3_Object( "hello: AS3ValType", method );

    AS3_Release( method );

    AS3_LibInit( object );

    return 0;
}

Hello.as

package {
    import flash.display.Sprite;
    import cmodule.hello.CLibInit;

    public class Hello extends Sprite {
        public function Hello() {
            throw Error(new CLibInit().init().hello());
        }
    }
}

で、コンパイル

$ gcc hello.c -swc -o hello.swc && mxmlc -library-path+=hello.swc --target-player=10.0.0 Hello.as 
WARNING: While resolving call to function 'main' arguments were dropped!

49833.achacks.swf, 358742 bytes written
frame rate: 60
frame count: 1
69 : 4
72 : 358677
76 : 28
1 : 0
0 : 0
frame rate: 24
frame count: 1
69 : 4
77 : 506
64 : 31
63 : 16
65 : 4
9 : 3
41 : 26
82 : 471
1 : 0
0 : 0
  adding: catalog.xml (deflated 75%)
  adding: library.swf (deflated 60%)
設定ファイル "/Users/amachang/AlchemyTest/FlexSDK/frameworks/flex-config.xml" をロードしています
/Users/amachang/AlchemyTest/Src/Hello.swf (142645 bytes)

おおお。では、実行。 Hello, world! というエラーが出れば成功。ドキドキ

おおおおお。成功

クロージャを渡す

AS 側からクロージャを渡して

package {
    import flash.display.Sprite;
    import cmodule.hello.CLibInit;

    public class Hello extends Sprite {
        public function Hello() {
            var message:String = "Hello, ";
            new CLibInit().init().hello(function(message2:String):* {
                message += message2;
            }); 

            throw Error(message);
        }   
    }   
}

C 言語側で実行

#include <stdio.h>
#include <stdlib.h>
#include "AS3.h"

static AS3_Val hello(void* self, AS3_Val args)
{
    AS3_Val callback;
    AS3_ArrayValue(args, "AS3ValType", &callback);

    AS3_Call(callback, AS3_Undefined(), AS3_Array("StrType", " world."));

    return 0;
}

int main()
{
    AS3_Val method = AS3_Function( NULL, hello );

    AS3_Val object = AS3_Object( "hello: AS3ValType", method );

    AS3_Release( method );

    AS3_LibInit( object );

    return 0;
}


おおおお。成功
何かとサクサクできた。

Alchemy の gcc は何をしているか

hoge.c が hoge.swc になる過程を順に見て行きましょう。

1. C/C++ を LLVM 用のバイナリにコンパイルする
$ llvm-gcc -v -emit-llvm -nostdinc -I/Users/amachang/AlchemyTest/AlchemyToolkit/alchemy-darwin-v0.4a/avm2-libc/include -I/usr/local/include --include /Users/amachang/AlchemyTest/AlchemyToolkit/alchemy-darwin-v0.4a/avm2-libc/avm2/AVM2Env.h hoge.c -c -o hoge.o

まずは、このように hoge.c が hoge.o にコンパイルされます。
この hoge.o は LLVM のバイトコードです。

2. avm2-libc.l.bc とリンクする
$ llvm-ld -o=hoge -O5 -internalize-public-api-list=_start,malloc,free,__adddi3,__anddi3,__ashldi3,__ashrdi3,__cmpdi2,__divdi3,__fixdfdi,__fixsfdi,__fixunsdfdi,__fixunssfdi,__floatdidf,__floatdisf,__floatunsdidf,__iordi3,__lshldi3,__lshrdi3,__moddi3,__muldi3,__negdi2,__one_cmpldi2,__qdivrem,__adddi3,__anddi3,__ashldi3,__ashrdi3,__cmpdi2,__divdi3,__qdivrem,__fixdfdi,__fixsfdi,__fixunsdfdi,__fixunssfdi,__floatdidf,__floatdisf,__floatunsdidf,__iordi3,__lshldi3,__lshrdi3,__moddi3,__muldi3,__negdi2,__one_cmpldi2,__subdi3,__ucmpdi2,__udivdi3,__umoddi3,__xordi3,__subdi3,__ucmpdi2,__udivdi3,__umoddi3,__xordi3,__error /Users/amachang/AlchemyTest/AlchemyToolkit/alchemy-darwin-v0.4a/avm2-libc/lib/avm2-libc.l.bc hoge.o

次に、 llvm-ld でリンクされて hoge と hoge.bc が出来ます。( hoge はただ単に hoge.bc を実行する sh ファイル)
この avm2-libc.l.bc C 言語側に libc と同じ API を提供しているようですね。

3. llc というツールで ActionScript のコードを作る
$ llc -march=avm2 -avm2-use-memuser -o=hoge.as -avm2-package-name=cmodule.hoge hoge.bc

このツールで LLVM のコードが、なんと ActionScript のコードになります。

package cmodule.hoge {
// Start of file scope inline assembly
import flash.utils.*
import flash.display.*
import flash.text.*
import flash.events.*
import flash.net.*
import flash.system.*

public var gdomainClass:Class;
public var gshell:Boolean = false;

public function establishEnv():void
{
  try
  {
    var ns:Namespace = new Namespace("avmplus");
  
    gdomainClass = ns::["Domain"];
    gshell = true; 
  }
  catch(e:*) {}
  if(!gdomainClass)
  {
    var ns:Namespace = new Namespace("flash.system");
  
    gdomainClass = ns::["ApplicationDomain"];
  }
}

establishEnv();

public var glogLvl:int = Alchemy::LogLevel;

public function log(lvl:int, msg:String):void
{
  if(lvl < glogLvl)
:
:
(27436行)
4. asc.jar で、 as をコンパイルする
$ java -Xms16M -Xmx1024M -jar /Users/amachang/AlchemyTest/AlchemyToolkit/alchemy-darwin-v0.4a/bin/asc.jar -AS3 -strict -import /Users/amachang/AlchemyTest/AlchemyToolkit/alchemy-darwin-v0.4a/flashlibs/global.abc -import /Users/amachang/AlchemyTest/AlchemyToolkit/alchemy-darwin-v0.4a/flashlibs/playerglobal.abc -d -config Alchemy::Shell=false -config Alchemy::NoShell=true -config Alchemy::LogLevel=0 -config Alchemy::Vector=true -config Alchemy::NoVector=false -config Alchemy::SetjmpAbuse=false -swf cmodule.hoge.ConSprite,800,600,60 hoge.as 

そして、 hoge.as から hoge.swf が生成されます。

5. hoge.swf から ActionScript のバイトコードを取り出す
$ GetABC2.pl hoge hoge.swf.abc 
6. もっかい swf を作る
$ PutABC2.pl /Users/amachang/AlchemyTest/AlchemyToolkit/alchemy-darwin-v0.4a/achacks/swctmpl.swf temp.swf hoge.swf.abc cmodule/hello/CLibInit 
$ V10SWF.pl temp.swf library.swf 
7. catalog.xml を付けて zip で固めて swc にする

ちなみに、 catalog.xml はこんなの

<?xml version="1.0" encoding ="utf-8"?>
<swc xmlns="http://www.adobe.com/flash/swccatalog/9">
  <versions>
    <swc version="1.0" />
    <flex version="2.0" build="143452" />
  </versions>
  <features>
    <feature-script-deps />
    <feature-files />
  </features>
  <libraries>
    <library path="library.swf">
      <script name="cmodule/hello/CLibInit"  mod="1177909560000" >
        <def id="cmodule.hello:CLibInit" /> 
        <dep id="Date" type="e" /> 
        <dep id="Date" type="s" /> 
        <dep id="flash.utils:Dictionary" type="e" /> 
        <dep id="flash.utils:Dictionary" type="s" /> 
:
(略)
:
        <dep id="AS3" type="n" /> 
        <dep id="Object" type="i" /> 
      </script>
    </library>
  </libraries>
  <files>
  </files>
</swc>
$ zip hoge.swc catalog.xml library.swf 

おおおおおおおお。と言う訳で hoge.swc が出来ました。

まとめ

最後に

Alchemy 楽しいです!
みなさんも遊んでみてはいかがでしょうか。