How do I make my Ant Generated swf as small as possible? - apache-flex

I have a flex project and if I build a release version of the application using flash builder with RSLs on my swf is 115k. If however I build the same application using ant the swf is 342k. Without RSLs the swf is 520k.
How do I get the swf to be as small as the one built by FlashBuilder?
Here is my ant file I have another task that copies the rsls.
<project name="EUI Client Application" default="compileClientApp">
<target name="compileClientApp" depends="compileClientBundles">
<mxmlc
file="${CLIENT_PROJECT.dir}/src/${CLIENT_PROJECT.app}.mxml"
output="${DEPLOY.dir}/${CLIENT_PROJECT.app}.swf"
keep-generated-actionscript="false"
actionscript-file-encoding="UTF-8"
incremental="false"
>
<runtime-shared-library-path path-element="${FLEX_HOME}/frameworks/libs/framework.swc">
<url rsl-url="flex4_4.0.0.7791.swf"/>
<url rsl-url="framework_4.0.0.7791.swf"/>
<url rsl-url="framework_textLayout_4.0.0.7791.swf"/>
<url rsl-url="rpc_4.0.0.7791.swf"/>
<url rsl-url="textLayout_451.swf"/>
</runtime-shared-library-path>
<source-path path-element="${CLIENT_PROJECT.dir}/src" />
<compiler.library-path dir="${LIBS.dir}" append="true">
<include name="*.swc" />
</compiler.library-path>
<compiler.library-path dir="${DEPLOY_BIN.dir}" append="true">
<include name="*.swc" />
</compiler.library-path>
</mxmlc>
</target>
<target name="generateWrapper">
<html-wrapper
title="${CLIENT_APP_TITLE}"
file="${CLIENT_PROJECT.app}.html"
height="100%" width="100%"
bgcolor="white" application="app"
swf="${CLIENT_PROJECT.app}"
version-major="10" version-minor="0" version-revision="0"
history="true" output="${DEPLOY.dir}" />
</target>
<target name="compileClientBundles">
<compileBundle bundleName="Modules" source="${CORE_PROJECT.dir}/locale" />
</target>

Thanks for the replies guys but it wasn't either of those.
turns out all I needed to do was to remove the runtime-shared-library-path stuff as this is already in the flex-config.xml file. I also had to change the static-link-runtime-shared-libraries to false (so it's dynamic).
I've copied the flex-config.xml file into my build directory and use that so I can safely make changes.
This is with Flex 4 BTW - nto sure if I made that very clear.
my ant file now looks like this:
<project name="EUI Client Application" default="compileClientApp">
<target name="compileClientApp" depends="compileClientBundles">
<mxmlc
file="${CLIENT_PROJECT.dir}/src/${CLIENT_PROJECT.app}.mxml"
output="${DEPLOY.dir}/${CLIENT_PROJECT.app}.swf"
keep-generated-actionscript="false"
actionscript-file-encoding="UTF-8"
optimize="true" incremental="false"
link-report="${DEPLOY_BIN.dir}/app_link_report.xml"
>
<load-config filename="${basedir}/flex-config.xml" />
<define name="CONFIG::stub" value="false" />
<define name="CONFIG::release" value="true" />
<source-path path-element="${CLIENT_PROJECT.dir}/src" />
<compiler.library-path dir="${LIBS.dir}" append="true">
<include name="*.swc" />
</compiler.library-path>
<compiler.library-path dir="${DEPLOY_BIN.dir}" append="true">
<include name="*.swc" />
</compiler.library-path>
</mxmlc>
</target>
<target name="generateWrapper">
<html-wrapper
title="${CLIENT_APP_TITLE}"
file="${CLIENT_PROJECT.app}.html"
height="100%" width="100%"
bgcolor="white" application="app"
swf="${CLIENT_PROJECT.app}"
version-major="10" version-minor="0" version-revision="0"
history="true" output="${DEPLOY.dir}" />
</target>
<target name="compileClientBundles">
<compileBundle bundleName="Modules" source="${CORE_PROJECT.dir}/locale" />
</target>

You'll probably need to specify the paths to the external libs using the -external-library-path option.
See the docs for more info.
To use RSLs when compiling your application, you use the following application compiler options:
* runtime-shared-libraries Provides the run-time location of the shared library.
* external-library-path|externs|load-externs Provides the compile-time location of the libraries. The compiler requires this for dynamic linking.
Use the runtime-shared-libraries option to specify the location of the SWF file that the application loads as an RSL at run time. You specify the location of the SWF file relative to the deployment location of the application. For example, if you store the library.swf file in the web_root/libraries directory on the web server, and the application in the web root, you specify libraries/library.swf.
You can specify one or more libraries with this option. If you specify more than one library, separate each library with a comma.
Use the external-library-path option to specify the location of the library's SWC file or open directory that the application references at compile time. The compiler provides compile-time link checking by using the library specified by this option. You can also use the externs or load-externs options to specify individual classes or an XML file that defines the contents of the library.
The following command-line example compiles the MyApp application that uses two libraries:
mxmlc -runtime-shared-libraries=
../libraries/CustomCellRenderer/library.swf,
../libraries/CustomDataGrid/library.swf
-external-library-path=../libraries/CustomCellRenderer,
../libraries/CustomDataGrid MyApp.mxml
The order of the libraries is significant because the base classes must be loaded before the classes that use them.
You can also use a configuration file, as the following example shows:
../libraries/CustomCellRenderer
../libraries/CustomDataGrid
../libs/playerglobal.swc
../libraries/CustomCellRenderer/library.swf
../libraries/CustomDataGrid/library.swf
The runtime-shared-libraries option is the relative location of the library.swf files when the application has been deployed. The external-library-path option is the location of the SWC file or open directory at compile time. Because of this, you must know the deployment locations of the libraries relative to the application when you compile it. You do not have to know the deployment structure when you create the library, because you use the compc command-line compiler to create a SWC file.

Try separating your RSLs into their own arguments. Here's what how I have it on my build:
<runtime-shared-library-path path-element="${FLEX_HOME}/frameworks/libs/framework.swc">
<url rsl-url="${rsl.url}/framework_3.2.0.3958.swz" />
<url rsl-url="${rsl.url}/framework_3.2.0.3958.swf" />
</runtime-shared-library-path>
<runtime-shared-library-path path-element="${FLEX_HOME}/frameworks/libs/datavisualization.swc">
<url rsl-url="${rsl.url}/datavisualization_3.2.0.3958.swz" />
<url rsl-url="${rsl.url}/datavisualization_3.2.0.3958.swf" />
</runtime-shared-library-path>

Using RSL, remember to set use-network parameter to true, otherwise the compiled swf will complain security error (can't load RSL) when run in different location.

Related

Flex Ant: Compile multiple module

I am trying to compile my project by using Ant.
I did. But I have some problem. I don't know how to resolve.
<!-- Compile Modules (S) -->
<target name="compileModules" depends="compileBLP">
<record name="${LOG_DIR}/LOG_${CURR_TIME_SUBFIX}${LOG_FILE_TYPE}" append="false" action="start" />
<cpmdl file="com/dou/pi/views/dm/Module1" />
<cpmdl file="com/dou/pi/views/pim/Module2" />
<record name="${LOG_DIR}/LOG_${CURR_TIME_SUBFIX}${LOG_FILE_TYPE}" action="stop" />
</target>
<!-- Compile Modules (E) -->
<macrodef name="cpmdl">
<attribute name="file" />
<sequential>
<echo>#{file}</echo>
<mxmlc file="${SRC_DIR}/#{file}.mxml" output='${DEPLOY_DIR}/#{file}.swf' optimize="true" debug="false" incremental="false" fork="true">
<compiler.source-path path-element="${SRC_DIR}" />
<source-path path-element="${FLEX_HOME}/frameworks" />
<compiler.library-path dir="${FLEX_HOME}/frameworks" append="true">
<include name="libs" />
</compiler.library-path>
<compiler.library-path dir="${basedir}" append="true">
<include name="libs" />
<include name="src/assets/swc" />
</compiler.library-path>
<source-path path-element="${SRC_DIR}" />
</mxmlc>
</sequential>
</macrodef>
You can see. If I compile 2 modules, I have to load file config 2 times.
[mxmlc] Loading configuration file C:\Program Files\Adobe\Adobe Flash Builder 4 Plug-in\sdks\4.1.0\frameworks\flex-config.xml
[mxmlc] D:\Projects\BLP\BUILD\DEPLOY\com\dou\pi\views\dm\Module1.swf (1233413 bytes)
[mxmlc] Loading configuration file C:\Program Files\Adobe\Adobe Flash Builder 4 Plug-in\sdks\4.1.0\frameworks\flex-config.xml
[mxmlc] D:\Projects\BLP\BUILD\DEPLOY\com\dou\pi\views\pim\Module2.swf (963045 bytes)
Maybe, that is not good.
I though, can we load it just 1 time?
Hope you can give me any suggestion.
Thanks.
There's really nothing to be done here. The loading of the config file is done internally by mxmlc, not ant. Remember, each time you call mxmlc in your ant script, it's launching a new instance of it, so each instance has to load the configuration for itself.
It's similar to how, if you launch your web browser, close it, and reopen it, you'll end up loading your homepage twice. There's nothing in the environment that can save the page to memory to pass it in to the second invocation of the program.

‘Flex Error #1001: Digest mismatch with RSL’ when updating *just* the Flex web application

I get the following error when I update just the Flex web application’s swf file:
Flex Error #1001: Digest mismatch with RSL
I understand why this is happening (because the digest that was in catalog.xml of the RSLs don’t match what the Flex web application’s swf file is expecting) but can’t find a way to successfully update just the Flex web application. My question is how can this be done using ANT with Flex 3.6 SDK?
I have attempted to have the Flex web application ignore the digest value by setting the ‘compute-digest’ property to false on the compc tag for all RSLs:
<compc compiler.as3="true"
output="${temp-swc-dir}/#{name}.swc"
incremental="false"
fork="false"
compiler.show-deprecation-warnings="false"
compiler.verbose-stacktraces="${VERBOSE}"
compute-digest="false"
>
But when the mxmlc is executed, it fails mentioning about the digest. Is there something that needs to change in my mxmlc tag?
<mxmlc file="${target-dir}/#{build-directory}/revolution/src/${SWF_NAME}.mxml"
output="${target-dir}/#{build-directory}/${SWF_NAME}.swf"
actionscript-file-encoding="UTF-8"
keep-generated-actionscript="false"
incremental="false"
debug="#{qa-build}"
fork="false"
static-link-runtime-shared-libraries="false"
use-network="true"
>
<runtime-shared-library-path path-element="${target-dir}/#{build-directory}/swc/as3corelib.swc">
<url rsl-url="rsl/as3corelib.swf" />
</runtime-shared-library-path>
<runtime-shared-library-path path-element="${target-dir}/#{build-directory}/swc/asx.swc">
<url rsl-url="rsl/asx.swf" />
</runtime-shared-library-path>
<runtime-shared-library-path path-element="${target-dir}/#{build-directory}/swc/top-level-tools.swc">
<url rsl-url="rsl/top-level-tools.swf" />
</runtime-shared-library-path>
<source-path path-element="${target-dir}/#{build-directory}/revolution/src" />
<!-- list of path elements that form the roots of ActionScript class hierarchies. -->
<source-path path-element="${FLEX_HOME}/frameworks" />
<!-- list of SWC files or directories that contain SWC files. -->
<compiler.library-path dir="${FLEX_HOME}/frameworks/libs" append="true">
<include name="framework.swc" />
</compiler.library-path>
<compiler.library-path dir="${target-dir}/#{build-directory}/swc" append="true">
<include name="*.swc" />
</compiler.library-path>
<compiler.library-path dir="${target-dir}/#{build-directory}/revolution/libs" append="true">
<include name="*.swc" />
</compiler.library-path>
</mxmlc>
I think Flex comes with a tool to update digests. It's called "digest". I documented the steps needed to create RSLs from third party SWC libraries in my Wiki ... To me it looks as if your RSL and SWC no longer match. https://dev.c-ware.de/confluence/display/PUBLIC/Creating+RSLs+from+your+3rd+party+libs
So if you would just create the RSL from the SWC you are using you should be on the safe side.

Adobe Flex 4: Runtime Loading of Localized Framework Files

According to the Adobe asdocs, Flex framework files are supposed to be able to be loaded at runtime. These localized framework files, the ones that exist at (on windows) C:\Program Files (x86)\Adobe\Adobe Flash Builder 4.5\sdks\4.5.0\frameworks\locale, are responsible for items such as button text on Alert Dialogs, and a host of other controls. My expectation is that once these framework files are loaded I would see these resources available in my Flex app.
I've set up my project as follows:
MyProject
-src
-Flex4.5
-Referenced Libraries
-bin-debug
-bin-release
-libs
-locale (I've copied all of the directories(da_DK,en_US,es_ES,etc) of framework files for the locales I want to support inside of this dir)
Now the asdocs state that in order to do this, you have to set the compiler settings to read
-locale=en_US,da_DK,de_DE,es_ES,fi_FI,fr_FR,it_IT,ja_JP,ko_KR,nb_NO,nl_NL,pt_BR,ru_RU,sv_SE,zh_CN,zh_TW -allow-source-path-overlap=true -source-path=locale/{locale}
which I have done.
My Build Path Libraries for Flex 4.5 - C:Program Files (x86)\Adobe\Adobe Flash Builder 4.5\sdks\4.5.0 are set to be Runtime Shared library (of note, the {locale} subfolder says "Merged into code")
But when I change the language in the browser, I'm not seeing any of the framework resources.
Also, when I build my project, I don't see any indication of the locale-oriented resource files in the bin-release. Since we only deploy the contents of the bin-release folder (and not the entire project), how is this supposed to work?
I am also seeing .swz files in my bin-release (and I know these arent the localized framework resources).
Does anyone have any experience with Runtime Framework Localization?? What am I doing wrong? My expectation is that once I build my project (with the framework resources externalized) that the app would be able to load those resources, but this isn't happening and I am not interested in compiling a different version of my app for all of the locales I support.
Thanks in advance
I use the following ANT task which works for me:
<mxmlc file="${build.dir.src}/${mxml.file}" keep-generated-actionscript="false" output="${build.dir.stage}/${project.app.name}.swf"
actionscript-file-encoding="UTF-8" incremental="false" context-root="${project.app.name}" optimize="${app.optimize}"
debug="${app.debug}" configname="air" locale="en_US,ja_JP,fr_FR">
<jvmarg value="-Xmx1024m" />
<jvmarg value="-Xms512m" />
<compiler.theme append="true" file="${FLEX_HOME}/frameworks/projects/spark/MXFTEText.css" />
<source-path path-element="${FLEX_HOME}/frameworks" />
<source-path path-element="${build.dir.locale.src}/{locale}" />
<library-path dir="${FLEX_HOME}/frameworks/libs" append="true">
<include name="*.swc" />
</library-path>
<library-path dir="${FLEX_HOME}/frameworks/libs/air" append="true">
<include name="*.swc" />
</library-path>
<library-path dir="${FLEX_HOME}/frameworks/locale" append="true">
<include name="{locale}" />
</library-path>
<library-path dir="${build.dir.lib}" append="true">
<include name="*.swc" />
</library-path>
Add the following tag to the classes that use resources and read the strings in the way:
[ResourceBundle('application')]
// set up the locale chain
ResourceManager.getInstance().localeChain = [ 'en_US', 'ja_JP', 'fr_FR' ];
// load resources
ResourceManager.getInstance().getString('application', 'some.string.code');
An observation: One does not need to copy the framework files into one's project folder. They will be picked up the compiler when compiling.
Let me know if it works, else we can debug more!

Could not load definitions from resource flexTasks.tasks. It could not be found

I'm attempting to compile a Flex application from an ANT script, inside of Eclipse (CFBuilder, based on Eclipse), and I've run into this error:
Could not load definitions from resource flexTasks.tasks. It could not be found.
I haven't been able to find anything that gives directions on where this file (flexTasks.tasks) should be copied to, if it's needed at all. Some places indicate that it should be part of the flexTasks.jar file. I've tried two different things:
Copy the jar file into the ant/plugins/lib folder (and restart my CF Builder instance)
Specify the path to the jar in the classpath attribute, as suggested by the comment on this page
Neither helps me get past this error.
Here's my build script, for reference:
<project name="Tagging" default="compile-tagging" basedir=".">
<!-- setup flex compilation capability -->
<taskdef resource="flexTasks.tasks" />
<property name="flex.src" value="./src" />
<property name="flex.bin" value="./bin"/>
<target name="compile-tagging">
<mxmlc
file="${flex.src}/main.mxml"
output="${flex.bin}/main.swf"
keep-generated-actionscript="true">
<source-path path-element="${FLEX_HOME}/frameworks" />
</mxmlc>
</target>
</project>
Adam, I believe you need to tell taskdef where to look for the file. try keeping flextasks.jar in the same directory as your ant file (for now... you can move it later after you get it working).
then, you can do something like this:
<taskdef name="mxmlc" classname="WhateverTheTaskIsNamed" classpath="flexTAsks.jar" />
While not ideal, this code is working for me at the moment:
<project name="IOLTagging" default="go" basedir=".">
<!-- setup flex compilation capability -->
<property name="FLEX_HOME" value="C:/program files (x86)/Adobe/Adobe Flash Builder Beta 2/sdks/3.4.1/" />
<taskdef name="mxmlc" classname="flex.ant.MxmlcTask" classpath="${FLEX_HOME}/ant/lib/flexTasks.jar" />
<taskdef name="html-wrapper" classname="flex.ant.HtmlWrapperTask" classpath="${FLEX_HOME}/ant/lib/flexTasks.jar" />
<property name="flex.src" value="./src" />
<property name="flex.bin" value="./bin"/>
<property name="swf.name" value="main" />
<target name="go" depends="compile-flex" />
<target name="compile-flex">
<mxmlc
file="${flex.src}/main.mxml"
output="${flex.bin}/${swf.name}.swf"
debug="false"
keep-generated-actionscript="false">
<source-path path-element="${FLEX_HOME}/frameworks" />
<compiler.library-path dir="${basedir}/libs" append="true">
<include name="*.swc" />
</compiler.library-path>
</mxmlc>
</target>
</project>
I had the same problem, and the reason was in lack of permissions to acces $FLEX_HOME/ant.
You can also put the flexTasks.jar in ~/.ant/lib directory
If you run ant -diagnostics you should see the jar in USER_HOME/.ant/lib jar listing
I think you should have solved this problem. just trying flexmonkey today and also got the same problem.
"Could not load definitions from resource flexTasks.tasks. It could not be found."
solution is to make sure the flexTasks.jar is included in the dir lib of your project workplace.
when I copied flexTasks.jar from flashbuild folder \ant\lib and built it again. the problem is fixed.

Using ant, does anyone know how to build a SWF made up of SWCs (that you've built) that include resource bundles?

I'm trying to write an ant build script to build my group's flex app, and I've run into some roadblocks that I'm hoping someone on SO has seen before.
We have two projects that we build into SWCs and these components contain resource bundles. One SWC requires the other SWC. We have one project that we build into our application (the SWF) which uses both SWCs.
When I build the SWCs, I get no complaints about resource bundles not being found, and when I open the SWCs in winzip, I can see the bundles (in /locale/EN_US, for example)
When I build the SWF, however, I get complaints about not being able to find the resource bundles in the two swc's, but no complaints about not being able to find any other resource bundles (like the flex framework ones).
This is the kind of message I get from ant:
[mxmlc] Error: Unable to resolve resource bundle "whatever" for locale "en_US".
[mxmlc]
Surely, I am not the first person to hit this gotcha, so does anyone know what the problem is here?
Am I building the SWCs wrong, or the SWF?
For reference, here's one of my build tasks using compc (for some reason, I can't get the opening target tag to show up)
<path id="facet.sourcePath">
<pathelement location="${flex.facet.src}"/>
</path>
<property name="facet.sourcePath" refid="facet.sourcePath"/>
<echo message="sourcePath is ${facet.sourcePath}"/>
<fileset dir="${facet.sourcePath}" id="facet.sources">
<include name="**/*.as"/>
</fileset>
<pathconvert property="facet.classes" pathsep=" " refid="facet.sources">
<compositemapper>
<chainedmapper>
<globmapper from="*.as" to="*"/>
<globmapper from="${facet.sourcePath}\*" to="*" handledirsep="true" />
</chainedmapper>
<chainedmapper>
<globmapper from="*.mxml" to="*"/>
<globmapper from="${facet.sourcePath}\*" to="*" handledirsep="true" />
</chainedmapper>
</compositemapper>
</pathconvert>
<echo message="classes: ${facet.classes}"/>
<compc output="${flex.lib.output}/${facet.swc.name}" locale="EN_US"
include-classes="${facet.classes}" directory="false"
target-player="10.0.0"
>
<load-config filename="${FLEX_HOME}/frameworks/flex-config.xml"/>
<include-resource-bundles bundle="foo"/>
<include-resource-bundles bundle="bar"/>
<include-resource-bundles bundle="whatever"/>
<sp path-element="${flex.facet.dir}/locale/{locale}"/>
<keep-as3-metadata name="Bindable"/>
<keep-as3-metadata name="Remotable"/>
<keep-as3-metadata name="Embed"/>
<keep-as3-metadata name="Event"/>
<keep-as3-metadata name="ResourceBundle"/>
<source-path path-element="${flex.facet.src}"/>
<compiler.library-path append="true" dir="${flex.framework.lib}">
<include name="*.swc"/>
<include name="../locale/${locale}"/>
</compiler.library-path>
<compiler.library-path append="true" dir="${flex.rsm.lib}">
<include name="*.swc"/>
</compiler.library-path>
</compc>
</target>
and here's my mxmlc task:
<target name="flex.webapp.compile" description="compiles your flex app">
<mxmlc file="${flex.webapp.src}\RSM.mxml"
output="${flex.webapp.deploy}\ant_test\RSM.swf"
use-network="true"
keep-generated-actionscript="true"
debug="true"
locale="en_US"
incremental="true"
actionscript-file-encoding="utf-8"
target-player="10.0.0"
>
<load-config filename="${FLEX_HOME}/frameworks/flex-config.xml"/>
<include-resource-bundles bundle="RSM"/>
<source-path path-element="${FLEX_HOME}/frameworks"/>
<source-path path-element="${flex.webapp.src}" />
<source-path path-element="${flex.webapp.dir}/locale/en_US" />
<source-path path-element="${flex.rsm.lib}" />
<sp path-element="${flex.core.dir}/locale/{locale}"/>
<sp path-element="${flex.facet.dir}/locale/{locale}" />
<compiler.library-path append="true" dir="${flex.framework.lib}">
<include name="*.swc"/>
<!--include name="../locale/${locale}"/-->
</compiler.library-path>
<compiler.library-path append="true" dir="${flex.rsm.lib}">
<include name="*.swc"/>
<include name="../locale/${locale}" />
<!--include name="rsm_rb.swc" /-->
</compiler.library-path>
</mxmlc>
</target>
Arrgh!
After many hours of staring at this problem, I realized that the issue was looking me in the face the whole time.
The compc task is using 'locale="EN_US"' and the mxmlc task is using 'locale="en_US"'.
If anyone ever posts a "what's the stupidest work problem you've ever had?", this would be my answer.
btw it doesnt have to be that complicated (even in linux console!), all you need is to include libs...
daemonna#NES-KOS-29:~/Desktop/FlexUnit4Turnkey_4.0_sdk_4.0.fxp_FILES/src$ mxmlc -library-path=../libs -locale=en_US App.mxml
Loading configuration file /home/daemonna/Frameworks/flex_sdk_4.1.0.16076/frameworks/flex-config.xml
Error: Unable to resolve resource bundle "components" for locale "en_US".
....bla bla bla...
Error: Unable to resolve resource bundle "controls" for locale "en_US".
daemonna#NES-KOS-29:~/Desktop/FlexUnit4Turnkey_4.0_sdk_4.0.fxp_FILES/src$ mxmlc -library-path=../libs -library-**path=/home/daemonna/Frameworks/flex_sdk_4.1.0.16076/frameworks/locale/en_US/** -locale=en_US App.mxml
Loading configuration file /home/daemonna/Frameworks/flex_sdk_4.1.0.16076/frameworks/flex-config.xml
/home/daemonna/Desktop/FlexUnit4Turnkey_4.0_sdk_4.0.fxp_FILES/src/App.swf (37964 bytes)

Resources