Generate Accessible SWF does not generate a SWF
April 25th, 2007
I am trying for hours to tell Flex, that I need an accessible SWF of my Flex-Library(There is a checkbox in the Actionscript Compiler options panel). But I only get a SWC file. So what is the deal ? Is there no solution to load a Flex Library at runtime without creating a new Project, where I merge the library into code ? The background is, that I want to exclude various classes with dependencies from my current project and export them into one SWF (without dependent classes) and load them in runtime. I want a simple solution without having XML exclude files or similar attacks on the compiler.
Joa pointed out, that the SWC is actually just a ZIP-file, where the SWF and a XML is included. So I tried to load the unpacked SWF and it seems to be possible, but no Event.COMPLETE or Event.INIT is fired. Now the magic: If I try to get my class after a setTimeout (to be sure the SWF is loaded), I effectively get the class. Furthermore both Events are fired after using getDefinition. How weird is that?
Any suggestions are welcome.
Here were my lovely code (as an Application class) to create a SWF with just one class (unfortunately not possible).
package { import flash.display.Sprite; [Compiler(include com.domain.package.ClassName)] public class LoaderSatisfier extends Sprite { public function LoaderSatisfier() { } } }
The goal were to have an Application class with some Meta-Tags to keep all classes except the certain classes from export into the SWF. What a timesaver!
Filed under: +
22 Responses to “Generate Accessible SWF does not generate a SWF”
-
Matt Chotin Says:
April 25th, 2007 at 4:50 pmHave you tried extract the SWF from the SWC and then loading it as an RSL through the -rsl compiler option?
-
André Michelle Says:
April 25th, 2007 at 4:55 pmMatt:
I am not sure, what you mean. If I declare it as a compiler option (-rsl), doesn’t that mean I merge the library into the application SWF? I want to load several classes dynamically in runtime. So I wouldn’t make sense, if I have to put them all into the compiler arguments. Some of the classes will be loaded, some not… -
Matt Chotin Says:
April 25th, 2007 at 4:57 pmNo, it loads it separately (though it does require the file at startup). If you really want it loaded later this is the kind of thing that Modules has helped with, though it isn’t perfect.
-
David C Says:
April 25th, 2007 at 5:03 pmHi !
Maybe you should use a Module instead. Modules have been created to be loaded a runtime. I haven’t used it yet, but I think that might be the solution.
Here’s a link to a presentation I read this morning about modules and rsl, I think it might help you to choose between modules and rsl.http://blogs.adobe.com/aharui/2007/03/modules.html
Good luck :)
-
André Michelle Says:
April 25th, 2007 at 5:03 pmThat wouldn’t help unfortunately. That means, I need to compile my project everytime I add a new compiled class. The classes are actually plugins extending the application in runtime.
What do you mean with ‘Modules’ ?
-
André Michelle Says:
April 25th, 2007 at 5:05 pmDavid:
Ah, modules. Well, is there any AS3 implementation out there ? I still cannot read mxml and I even don’t think about learning it ;) There are really only a few hits even on google.Update: Found these excellent articles (unfortunately mxml code)
Modular Applications (part 1)
Modular Applications (part 2) -
iiley Says:
April 26th, 2007 at 3:23 amHi Michelle,
There’s a way:
First, the reason why it will not fire Complete/Init event when you load the unpacked swf is that there’s no entry class in it. (You know the application entry of AS3 is a class that must inherited Sprite, when swf is loaded a instance of that class will be created to be the root)
So, for the case, we should create a swf that include all your classes and has a entry class(it can be a empty Class inherited Sprite), with “include-libraries library [...]” or “include class [...]” param of the compiler, you can easily compile all classes into your swf.
So, then you have a library swf that can be loaded into your application at runtime and will fire Event.COMPLETE and Event.INIT events.
-
zuric Says:
April 26th, 2007 at 4:34 amyou should try “-link-report” in mxmlc options
then you can exclude any classes you needed
“Module Chapter in Flex 2.01 doc” maybe helpThe module implementation in flex based on ApplicationDomain and Loader
the as3 implementation is more easy to write,
you just need a Loader and load other swf class with
applicationdomain when flex module also should supprot rsl and other Global Managers.flex compiler is not well in supporting module app’s build when you have many modules in different Projects. I
don’t like Ant, so I wrote a simple .bat file to compile my multi projects, and using “-link-report” to have
many opertions in including and excluding classes in different swfs.
I also wrote the module implementation in as3 project,
is very simple to write, but i get some applicationdomain bug when build
with flash 9 alpha or flash cs3
it’s said to be a bug in flash player 9.0.28this is the sample bat file for flex compiler to build:
MagicLinker: the flex framework i needed
MagicPlatform: is the Module Loader ,the shell
Modules: other sub module loaded by shell, only have the module logic class, no flex class, no duplicate classwith the shell
@ECHO OFF
REM Definition Path & Name for building
set LINK_PATH=E:\Projects\Magician\MagicLinker\bin\
set LINK_SRC=E:\Projects\Magician\MagicLinker\
set RSL_NAME=MagicLinker
set RSL_PATH=http://localhost/flex/
set DEPLOY_PATH=E:\Projects\Magician\Deploy\set Build_PATH=E:\Projects\Magician\Build\
set FLEX_CONFIG=%Build_PATH%flex-config.xmlset SRC_PATH=E:\Projects\Magician\MagicPlatform\
set APP_NAME=MagicPlatform
set REPORT_NAME=report.xmlREM Step 1 : Build the Linker
REM generate rsl swc to linker bin folder
REM compc -debug=false -source-path=%LINK_SRC% -o=%LINK_PATH%%RSL_NAME%.swc %RSL_NAME%
REM generate rsl swf to delopy folder
REM mxmlc -o=%DEPLOY_PATH%%RSL_NAME%.swf -file-specs=%LINK_SRC%%RSL_NAME%.asREM Step 2 : Build Main Application
REM Export the report of Main Application
mxmlc -link-report=%DEPLOY_PATH%%REPORT_NAME% -load-config=%FLEX_CONFIG% -external-library-path=%LINK_PATH%%RSL_NAME%.swc -runtime-shared-libraries=%RSL_PATH%%RSL_NAME%.swf -file-specs=%SRC_PATH%%
APP_NAME%.mxml -source-path+=%SRC_PATH% -defaults-css-url=%Build_PATH%defaults.css -o=%DEPLOY_PATH%%
APP_NAME%.swf
REM Step 3: Build Modules
REM Define Login Module
set MODULE_NAME=LoginModule
set MODULE_PATH=%SRC_PATH%Modules\
set MODULE_SRC=%SRC_PATH%
REM Export reports
mxmlc -load-externs=%DEPLOY_PATH%%REPORT_NAME% -external-library-path=%LINK_PATH%%RSL_NAME%.swc -runtime-shared-libraries=%RSL_PATH%%RSL_NAME%.swf -load-config=%FLEX_CONFIG% -link-report=%DEPLOY_PATH%%MODULE_NAME%
_report.xml -file-specs=%MODULE_PATH%%MODULE_NAME%.mxml -source-path+=%MODULE_SRC% -strict=false -o=%
DEPLOY_PATH%%MODULE_NAME%.swf -defaults-css-url=%Build_PATH%defaults.css
REM Define Lobby Module
set MODULE_NAME=LobbyModule
set MODULE_PATH=%SRC_PATH%Modules\
set MODULE_SRC=%SRC_PATH%
REM Export reports
mxmlc -load-externs=%DEPLOY_PATH%%REPORT_NAME% -external-library-path=%LINK_PATH%%RSL_NAME%.swc -runtime-shared-libraries=%RSL_PATH%%RSL_NAME%.swf -load-config=%FLEX_CONFIG% -link-report=%DEPLOY_PATH%%MODULE_NAME%
_report.xml -file-specs=%MODULE_PATH%%MODULE_NAME%.mxml -source-path+=%MODULE_SRC% -strict=false -o=%
DEPLOY_PATH%%MODULE_NAME%.swf -defaults-css-url=%Build_PATH%defaults.css
-
André Michelle Says:
April 26th, 2007 at 6:15 amiiley:
I already had an empty class extending Sprite, but in a FlexLibrary enviroment, there is no way to declare the class as an application class. However it is included already, but no Event is fired on load/init.If you are talking about a FlexProject:
“include-libraries library […]” or “include class […]” does compile all dependent classes into the resulting SWF, which was not the goal.Did I get you wrong ?
zuric:
You script scares me. Is it really possible, that we need that kind of overhead for this simple task?… include a class in a SWF…?
-
iiley Says:
April 26th, 2007 at 6:57 amHi Michelle,
I’v not explained clearly. :)
Well, it should be:
One library have two projects In FlexBuilder2.0.1:
1. The regular Flex Library Project, with all your classes defined that need to load at runtime.
2. The ActionScript Project(Note, not FlexProject, so you do not need to do the MXML), with only one empty entry class, but the project included the first library project and use include-libraries library […]” or “include class […]” addition compiler param to force the library classes will be compiled to the output SWF.
The 2nd project is just additional project to help you to generate the right SWF with a entry class. You also can write a ant or bat script to do that job. (note that there are two compiler, compc is used to compile library project to a SWC, and mxmlc is used to compile the SWF with a entry class)
And, when you’v generated the SWF with all library classes and a entry point. You can load it at runtime and got events fired when loaded.
BTW you can use “LinkType -> external”(by default it is “Merged into code”) to make the library classes exclude when compile your main application.
-
André Michelle Says:
April 26th, 2007 at 7:11 amiiley:
I think I understand. Expect that I have 20-30 Plugins. So for every Plugin I need a library to sort out my classes without dependencies AND a project to create an accessible SWF. So this is real overhead.I am trying to understand ANT, since I can imagine that this is the key to solve it as elegant as possible. Unfortunately I even didn’t get Flex_Ant_Tasks installed. I would love to see, that I still have only one project and different ANTs to compile the Plugin and Main-Application.
-
iiley Says:
April 26th, 2007 at 7:22 amAh, yes, It’s a mess for a the project structure if you have many plugins.
Ant will help you to simple the projects structure. I’m not familiar with Ant script too, but i know it really can make your just have one project and different ANTs(or even one ANT script) to compile the Plugin and Main-Application. :)
-
André Michelle Says:
April 26th, 2007 at 9:21 amI finally could create a working build.xml.
But still, any include class syntax like “[include -class dir="src/" includes="com.domain.plugins.Gain"/]” is failing with an error. ‘The type doesn’t support the “include-class” nested element.’ I am an absolute beginner…
compc does not support the file attribute (for having an entry)
mxmlc does not support includesHELP! ;)
-
iiley Says:
May 4th, 2007 at 6:03 pmHi Andre, have you fixed it out?
I’m not familiar with ANT script too, i just got success with the way of additional ActionScript Project.Well, i’ll try your build.xml later…
-
iiley Says:
May 6th, 2007 at 6:54 amHi Michelle,
I tried the mxmlc params again, here’s the working example(not include the brackets):
1. Include all classes in AsWing A3 swc
[-include-libraries E:\workspace\AsWingA3\bin\AsWingA3.swc]2. Include org.aswing.Component and it used classes(the classes should be in classpath of course)
[-includes org.aswing.Component]I have not installed FlexAnt too, so not tried it, but i found some info here
-
Cédric Néhémie Says:
May 15th, 2007 at 3:31 pmAbout the includes in the mxmlc task, I face the same problem, and resolving that by not using the FlexAnt anymore. By doing same your task would look like that :
Assuming that you have defined properties correctly. In that task ${includes} in the space separated list of classes to compile and ${excludes} the path to the exclusions xml file (from -link-report output).
Unfortunately its really boring to correctly create a specific exclusion file for each swf witch make your plugin swf working everywhere, at end I use the report from my main application assembler to be sure that plugin will work in the most cases.
-
Cédric Néhémie Says:
May 15th, 2007 at 3:41 pmwooops, forgot that html tags are stripped tag ^^’
[exec executable="${mxmlc.exe}"]
[arg line="-load-config='${flex.config}'"/]
[arg line="-source-path+='${flex.framework.dir}'"/]
[arg line="-output='${output}'"/]
[arg line="-link-report='${report}'"/][arg line="${includes}"/]
[arg line="${excludes}"/][arg line="-- '${file}'"/]
[/exec] -
skuud Says:
June 28th, 2007 at 6:29 pmI don’t know if you resolved your prob but
I had the same problem with Event.COMPLETE or Event.INIT on my lib
i did it that way with ant
I hope it helps
makelib.xml ant file
The "compc.exe" property must be set.
the build.propreties files
# location of the Flex 2 SDK
flex2sdk.bin.dir = /Users/manu/Developpement/lib/flex_sdk/bin# General properties
asdoc.exe = ${flex2sdk.bin.dir}/asdoc
compc.exe = ${flex2sdk.bin.dir}/compc
mxmlc.exe = ${flex2sdk.bin.dir}/mxmlc# Path properties
build.dir = build/
plugin.dir= net/site/path/to/plugin/
plugin-build.dir = build/plugin/
lib.dir = build/lib/
report.dir = build/report/
plugin-source.dir = /path/to/Eclipse/workspace/Project/src/
-
skuud Says:
June 28th, 2007 at 6:37 pmthe ant file makelib.xml
The "compc.exe" property must be set in ${build.dir}/katabunga-build.properties.
-
Sander Says:
December 25th, 2007 at 6:47 amHi André,
I’ve come up with a solution to use Flex compiled classed within the Flash Authoring environment!
Read more about it here:
http://labs.qi-ideas.com/2007/12/25/using-flex-compiled-code-within-flashGood Luck!
-
Jeff B Says:
May 23rd, 2008 at 1:13 amThe secret lies in this sentence tucked way down in the page at
http://livedocs.adobe.com/flex/3/html/help.html?content=rsl_03.html.“After you create the library, you then compile your application against the SWC file and specify the library’s SWF file’s location for use at run time.”
I use two projects, one for production and one for development. The source files are all the same, meaning the same directories are referenced by both projects.
The development project has the modules linked using RSL, while the production one has them linked as External Modules. That way when I run the development project is links up all my Library modules and creates the .SWF files automatically. Only problem is that it auto-loads all the RSLs when it starts, but that’s where the production project comes in. The application uses ModuleManager to load the libraries no matter what, but when running the development project this is a no-op using
‘if (!ApplicationDomain.currentDomain.hasDefinition(className))
loadModule(path);
// e.g. var info = ModuleManager.getModule(path);
// info.addEventListeners( for READY and ERROR );
// info.load(ApplicationDomain.currentDomain).
else
dispatchEvent(ModuleEvent.READY);’I can just run the production project (even in debug mode) to rest assured that everything is truly being dynamically loaded on-demand.
Also, you have to catch the ModuleEvents to make this work right. Using timers is not a good way, and the code is much cleaner if you get the right events going. I recommend listening for ModuleEvent.READY and ModuleEvent.ERROR so you can know either way if your load worked.
-
Mark Ledford » Event.INIT and Event.COMPLETE don’t fire when loading an unpacked swc Says:
July 24th, 2008 at 8:34 pm[...] I’ve been doing some run-time class loading involving loading SWF files into the same ApplicationDomain as the container via Loader then using getDefinitionByName to access new instances of the loaded classes. I was perplexed that the INIT and COMPLETE events weren’t being dispatched and found some info here. [...]
