Сборка Flex-приложений с помощью Ant
В то время как Adobe выпустили бесплатный SDK для разработки Flex-приложений, просто неприлично не уметь собирать приложения с его помощью. А если вы работаете на заказ, то бессвязный набор ваших исходных кодов вряд ли вдохновит заказчика: что ему с ними делать? Как собрать из них приложение в случае необходимости? Тем более, что часто заказчик неспециалист: ему что, покупать себе Flex Builder, осваивать его? Если в разработке Flash-приложений мы отдавали fla с классами и на пальцах объясняли что куда (а заказчик вынужден был смириться с тем, что ему понадобится среда разработки Flash - отнюдь не бесплатная), то с бесплатным SDK мы просто обязаны дать заказчику код, который он в любой момент может использовать для сборки приложения.
В качестве лирического отступления замечу, что раньше для того чтобы удовлетворить потребности заказчика во внезапной кастомизации вашего детища, вы вынуждены были создавать конфигурационные xml-и, совершать действия по их загрузке и парсингу: все только для того чтобы снизить вероятность необходимости перекомпилировать приложение. Если предоставить заказчику возможность легко собирать приложения, мы можем дать ему на откуп кастомизацию средствами css, xml-файлов, включаемых в mx:Model, а также resource bundles (то есть упрощенная локализация и тексты менюшек-заголовков-кнопочек, которые могут по вашему незнанию языка содержать ошибки), которые компилируются в приложение. Представьте, как можно упростить жизнь разработчику! При этом вовсе не умаляя преимуществ заказчика, а, возможно, лишь увеличивая их!
Ну и, опять же, все преимущества, которые дает автоматическая сборка: возможность автоматических билдов, легкость в поддержке сложных проектов, возможность запускать с билдом тесты (об этом - в следующих сериях).
В общем, перейдем к демонстрации.
Повторю цель моих изысканий: дать возможность любому, у кого на компьютере распакован Flex SDK, собрать ваше приложение, указав при этом лишь путь к папке с SDK. Причем любому - это любому вне зависимости от платформы (Windows, MacOS, Unix...). При этом я, лично, не хотел бы включать в проект файлы самого sdk без необходимости: зачем? Они ведь и так есть!
Основными кирпичиками нашего эксперимента будут: платформонезависимый компилятор mxmlc, файл flex-config.xml, html-темплэйты (wrappers) и, собственно, сам Ant, о котором мы уже писали.
Пока вы изучаете ссылки, вкратце скажу, что компилятор может принимать параметры как из коммандной строки, так и из специального файла flex-config.xml (который может называться и по-другому). А может и оттуда, и оттуда. Вообще, это довольно сложный и неочевидный путь подобрать все опции чтобы ничего не конфликтовало и все компилилось. Потому я и выкладываю тут проверенный результат. Flex SDK содержит темплэйт такого файла, используемый по умолчанию (в том числе, как я понимаю, и самим Flex Builder'ом). Он находится flex_sdk_2_root\frameworks\flex-config.xml. Понятно, что менять параметры в нем некошерно: во-первых, это отразится и на остальных ваших проектах, а, во-вторых, у другого человека, компилирующего ваш проект, настройки могут оказаться другими.
А содержится там многое: пути к библиотекам, опции компилятора, информация о шрифтах, метаданные генерируемого swf-файла (для тех, кто не в танке: mxmlc занимается только генерацией swf. html и прочее он не генерирует). То есть все, что можно задать компилятору в командной строке. Но представьте себе такую командную строку и структурированный читаемый xml-файл. По-моему, с xml работать приятнее.
Для простоты манипуляции я решил задавать пути к классам из командной строки (чтобы в любой момент легко их было поменять в ant'овском скрипте используя его переменные итд. Хотя и в flex-config.xml имеются для этого токены.). Но мое решение не абсолютное - вы сами можете выработать свое. Остальные опции, не требующие путей, будут задаваться во flex-config.xml. В частности, для задания пути к стандартным библиотекам мы будем использовать токен flexlib, который сами же и зададим.
Далее приведу мой билд-файл чтобы можно было его изучить (весь тестовый проект можно будет скачать - ссылка внизу :):
<?xml version="1.0"?>
<!-- ======================================================================
Jul 15, 2006 7:02:58 PM
Test App
A simple test app
Constantiner (constantiner (at) gmail.com)
====================================================================== -->
<project
name="Test App"
default="build"
basedir=".">
<property file="local.properties"/>
<!-- dirs -->
<property name="flex.sdk.dir" location="."/>
<property name="build.dir" location="build/"/>
<property name="src.dir" location="src/"/>
<property name="lib.src" location="lib/src/"/>
<property name="lib.swc" location="lib/swc/"/>
<property name="flex.config.xml" location="flex-config.xml"/>
<!-- files -->
<property name="mxmlc.jar" location="${flex.sdk.dir}/lib/mxmlc.jar"/>
<property name="main.application" location="${src.dir}/Main.mxml"/>
<property name="output.swf.name" value="test_app"/>
<property name="main.application.out" location="${build.dir}/${output.swf.name}.swf"/>
<!-- wrapper -->
<property
name="wrapper.dir"
location="${flex.sdk.dir}/resources/html-templates/express-installation-with-history"/>
<property name="output.html.name" value="${output.swf.name}.html"/>
<property name="output.html" location="${build.dir}/${output.html.name}"/>
<property name="unnamed.output.html" location="${build.dir}/index.template.html"/>
<property name="swf.width" value="640"/>
<property name="swf.height" value="480"/>
<property name="swf.title" value="Пример очень простого приложения"/>
<property name="swf.version.major" value="9"/>
<property name="swf.version.minor" value="0"/>
<property name="swf.version.revision" value="0"/>
<property name="swf.application" value="${output.swf.name}"/>
<property name="swf.swf" value="${output.swf.name}"/>
<property name="swf.bgcolor" value="#FFFFFF"/>
<description>
A simple test app
</description>
<!-- =================================
target: build
================================= -->
<target
name="build"
depends="clear,init,compile,copy.wrapper,prepare.wrapper"
description="-->Simple test application">
</target>
<!-- - - - - - - - - - - - - - - - - -
target: copy.wrapper
- - - - - - - - - - - - - - - - - -->
<target name="copy.wrapper">
<copy todir="${build.dir}">
<fileset dir="${wrapper.dir}" />
</copy>
</target>
<!-- - - - - - - - - - - - - - - - - -
target: prepare.wrapper
- - - - - - - - - - - - - - - - - -->
<target name="prepare.wrapper">
<move
file="${unnamed.output.html}"
tofile="${output.html}" />
<replaceregexp
file="${output.html}"
flags="gs"
match="\$\{width\}"
replace="${swf.width}"/>
<replaceregexp
file="${output.html}"
flags="gs"
match="\$\{height\}"
replace="${swf.height}"/>
<replaceregexp
file="${output.html}"
flags="gs"
match="\$\{title\}"
replace="${swf.title}"
encoding="utf-8"/>
<replaceregexp
file="${output.html}"
flags="gs"
match="\$\{version_major\}"
replace="${swf.version.major}"/>
<replaceregexp
file="${output.html}"
flags="gs"
match="\$\{version_minor\}"
replace="${swf.version.minor}"/>
<replaceregexp
file="${output.html}"
flags="gs"
match="\$\{version_revision\}"
replace="${swf.version.revision}"/>
<replaceregexp
file="${output.html}"
flags="gs"
match="\$\{application\}"
replace="${swf.application}"/>
<replaceregexp
file="${output.html}"
flags="gs"
match="\$\{bgcolor\}"
replace="${swf.bgcolor}"/>
<replaceregexp
file="${output.html}"
flags="gs"
match="\$\{swf\}"
replace="${swf.swf}"/>
</target>
<!-- - - - - - - - - - - - - - - - - -
target: compile
- - - - - - - - - - - - - - - - - -->
<target name="compile">
<java
jar="${mxmlc.jar}"
fork="true"
maxmemory="512m"
failonerror="true">
<arg value="+flexlib=${flex.sdk.dir}/frameworks"/>
<arg value="-load-config=${flex.config.xml}"/>
<arg value="-output=${main.application.out}"/>
<arg value="-source-path"/>
<arg value="${src.dir}"/>
<arg value="${lib.src}"/>
<arg value="-library-path+=${lib.swc}"/>
<arg value="${main.application}" />
</java>
</target>
<!-- - - - - - - - - - - - - - - - - -
target: clear
- - - - - - - - - - - - - - - - - -->
<target name="clear">
<delete failonerror="false">
<fileset dir="${build.dir}" includes="**/*.*" />
</delete>
</target>
<!-- - - - - - - - - - - - - - - - - -
target: init
- - - - - - - - - - - - - - - - - -->
<target name="init">
<mkdir
dir="${build.dir}"/>
</target>
</project>
По традиции в файле local.properties мы указываем путь к папке, содержащей Flex SDK (той, что содержит в себе bin, framework, lib итд.). Это единственная переменная величина в проекте, задаваемая ручками при компиляции на другой машине (свойство flex.sdk.dir).
Структура проекта проста: она содержит папку src, содержащую Main.mxml (само приложение) и другие написанные нами as- и mxml-классы. То есть это те артефакты, которые созданы в рамках данного проекта. Есть также папочка lib, которая содержит внешние библиотеки (реюзабельную составляющую). Она делится на две подпапки: src и swc. В первой содержатся библиотеки, поставляемые в виде исходного кода, а во второй, соответственно, в виде swc (в данном проект е таковых нет, но я эту возможность занес).
Ну и по целям нашего билд-файла:
- clear очищает каталог с прежним билдом.
- init создает каталог с билдом.
- compile компилирует наш проект.
- copy.wrapper копирует наш html-wrapper.
- prepare.wrapper приводит его в вид, пригодный для использования.
И действительно, мы можем заметить, что в свойстве wrapper.dir ant-файла мы указываем каталог с нужным нам темплейтом (из шести имеющихся). Также в отдельном блоке свойств мы задаем все возможные параметры нашего html-фйла, в него подставляемые. Можно создать и свой вариант по образу и подобию предзаготовленных.
Вот такая вот приятная вещь. И, главное, что с этим можно баловаться: менять wrapper (очень просто!), менять тему (тоже просто: compile.theme в flex-config.xml). Куча приятных вкусностей.
Ну а теперь можно скачать мой простой тестовый проект. Кстати, специально для Роста он содержит в себе более навороченные примеры работы с Flex 2 logging API (а сам по себе тестовый проект, собственно, ничего и не делает. Так, безделица :)
Ну вот, такая сумбурная заметка, которая будет полезна профессионалам. В принципе, можно задавать вопросы :)
Комментариев 12:
>>Пока вы изучаете ссылки, вкратце скажу, что компилятор может принимать параметры как из коммандной строки, так и из специального файла flex-config.xml
Так мы же ссылки изучаем! Как мы можем при этом слушать, что ты говоришь? Издеваешься, да?
Ну это же типо лекция. Типа вы там картинки смотрите, спите, а я распинаюсь, рассказываю. Ты лучше скажи - у тебя получился билд?
Почти получился.
Cлетает на compile:
[java] Unable to access jarfile D:\Swf\Flex 2\flex_ant_test"C:\Program Files\Adobe\Flex Builder 2\Flex SDK 2\lib\mxmlc.jar +flexlib=C:\Program Files\Adobe\Flex Builder 2\Flex SDK 2/frameworks -load-config=D:\Swf\Flex
Подозреваю, это из-за того, сколь смело я использую пробелы в именах каталогов (d:\swf\flex2\): переношу все во d:\temp, получаю уже более оптимистичную структуру:
compile:
[java] Unable to access jarfile D:\tmp\flex_ant_test"C:\Program Files\Adobe
\Flex Builder 2\Flex SDK 2\lib\mxmlc.jar +flexlib=C:\Program Files\Adobe\Flex Bu
ilder 2\Flex SDK 2/frameworks -load-config=D:\tmp\flex_ant_test\flex-config.xml
-output=D:\tmp\flex_ant_test\build\test_app.swf -source-path D:\tmp\flex_ant_tes
t\src D:\tmp\flex_ant_test\lib\src -library-path+=D:\tmp\flex_ant_test\lib\swc D
:\tmp\flex_ant_test\src\Main.mxml
К сожалению, прямо сейчас зовет работа, так что я еще с этим побалуюсь немного попозже.
Чорт, имена каталогов -- d:\swf\flex 2\, и d:\tmp\, как же я так.
Так что в итоге? Получилось?
*сорри за оффтоп*
помнишь, ты на семинаре риалтайма цитировал Фаулера, прикольную фразу про то, что чем больше ИДЕ за тебя делает, тем больше времени остается на то, чтобы пить пиво. :)
можешь вспомнить точную цитату или дать ссылку, откуда это взято? :)
Фаулер. Рефакторинг. Улучшение существующего кода. СПб. Символ, 2004. Стр. 64:
Я очень ленивый программист. Моя лень проявляется в частности, в том, что я не запоминаю деталей кода, который пишу. На самом деле, опасаясь перегрузить свою голову, я умышленно стараюсь не запоминать того, что могу найти. Я стараюсь записывать все, что в противном случае пришлось бы запомнить, в код. Благодаря этому я меньше волнуюсь из-за того, что Old Peculier [Jackson] убивает клетки моего головного мозга.
И там примечание, что Old Peculier - это сорт пива.
Думаю, что речь идет об этой цитате :)
спасибо. :) хм. тоже хорошая формулировка, но тогда ты её сформулировал более лаконично :)
Думаю, что тогда это была вольная интерпретация :)
Кость, давай закончим с самзнаешь чем и попробуем сделать work environment наподобие Rails Live CD? Не обязательно для запуска чисто с диска, но в идеале разворачивания всего, что нужно для сборки/работы, 1-2 кликами.
Я долгое время изучаю и трясу знакомых сишников, как делается пакетная установка большого количества софта в их компаниях. Пока, если честно, все весьма глухо, но если речь об Eclipse/Ant, то их мы поставим. А там и Flex, и FDT, и JDT, и RadRails.
И Red5 поставится. Дело за малым... слушай, да вообще почти ни за чем :)
Но это, я думаю, уже осенью. Но обсудить можно и сейчас :)
Бизнес на ровном месте! Сетка тематических сайтов,... Кто хочет много трафика с YouTube? Новые идеи полу...
Отправить комментарий
Вернуться на главную