使用Maven构建复杂的Flex项目

Zef*_*iro 5 apache-flex eclipse actionscript-3 sonatype maven

我目前正在考虑用Maven替换我们非常专有的构建环境.当前的解决方案是中央构建的内部开发,为了更容易的本地开发,我在Eclipse/Flex IDE中编译并有一个ANT脚本将所有内容复制到我的本地Apache目录(即我的ant文件没有完成构建并依赖所有项目在当地可用).

我们将Eclipse 3.6.1(Helios)与Flash Builder插件(即Flex4)一起使用,目标是Flex SDK 3.5(FlashPlayer 10.0),其中包括.swc库项目和.swf模块,这两个项目都在运行时加载,包括每个项目的资源.我们还使用外部链接/运行时共享库​​(一个大的sharedlibraries.swf包含所有内容,即不需要在部署中使用.swc文件).我已经使用Sonatypes flexmojos-maven-plugin 3.7.1安装了Maven 3.0.2 (因为它看起来比Servebox更活​​跃).我为每个Eclipse项目手动创建了pom文件,以确保一切正常,Eclipse-Maven集成似乎缺乏Flex支持.我已经定义了适当的编译器和依赖项参数,以便所有单个项目都能正确编译 - 即生成的.swf文件确实生成了我们应用程序的工作版本.我还阅读了Sonatype 的" Maven by Example "一书并查看了他们的" Maven:The Complete Reference ",同时进行了大量的谷歌搜索.

我正在努力的是我的项目的最终组装,以及其他工件(样式表).我并不完全理解"Maven方式",也怀疑Maven是为Java量身定制的,因此我的Flex项目让我有点疯狂.

我项目的基本结构:

  • 外部库:我已将那些带有install:install-file的文件添加到我的存储库,这里没有问题
  • 自己的库项目:他们每个都生成一个.swc工件,可以在其他项目中使用,Maven依赖处理正常工作,这里没问题
  • 我们的swf模块项目:我们的应用程序在运行时加载swf文件,这反过来又需要一些额外的资源(stylesheet.swf文件,本地化字符串作为单独的.xlf文件,配置文件等).这是我正在努力的.

我的swf项目的布局:

  • bin-debug /由IDE构建使用,未被Maven构建使用/忽略
  • src / Flex源(.as和.mxml文件)
  • target / Maven目标目录
  • WebContent /一个带有补充文件的目录,需要逐字复制到目标工件(目录或zip文件),以及.swf工件
  • styles / Flex .css文件需要编译成.swf样式表文件,那些是主项目swf和WebContent/content的附加工件(每个.css一个,不同的主题)

我正在使用平面层次结构在Eclipse中工作,即我的主pom文件放在一个文件夹中,该文件夹是所有项目文件夹的兄弟.例:

project_swf/src/...
project_swf/WebContent/assets/labels.xlf
project_swf/WebContent/config/config.xml
project_swf/pom.xml
lib_swc/src/...
lib_swc/pom.xml
master_build/pom.xml
master_build/swf-assembly.xml
Run Code Online (Sandbox Code Playgroud)

我已经设法使用这个主pom创建了一个'master build'构建我所有的swc和swf项目:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <name>Dragon Master Build</name>
    <description>This project can be used to build and package the client application</description>

    <properties>
        <!-- this needs to be the same as the groupId tag, which unfortunately cannot be accessed directly using ${} notation -->
        <group-id>de.zefiro.maven.example</group-id>

        <!-- parameter to plugin swf files, shown as plugin 'Build Number' in client -->
        <!-- TODO should be a build number on central system -->
        <zefiro.plugin.buildno>local_dev_mvn</zefiro.plugin.buildno>

        <!-- build all SWF files (except sharedlibraries.swf) with external references (Note: Flexmojo abuses the 'scope' concept here, but there is currently no better way) -->
        <zefiro.swf.scope>external</zefiro.swf.scope>
    </properties>

    <groupId>de.zefiro.maven.example</groupId>
    <artifactId>full_build</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>

    <build>
        <sourceDirectory>src/</sourceDirectory>
        <plugins>
            <plugin>
                <groupId>org.sonatype.flexmojos</groupId>
                <artifactId>flexmojos-maven-plugin</artifactId>
                <version>3.7.1</version>
                <extensions>true</extensions>
                <!-- We need to compile with Flex SDK 3.5 -->
                <dependencies><dependency>
                    <groupId>com.adobe.flex</groupId>
                    <artifactId>compiler</artifactId>
                    <version>3.5.0.12683</version>
                    <type>pom</type>
                </dependency></dependencies>
                <!-- configuration for the Flex compilation -->
                <configuration>
                    <targetPlayer>10.0.0</targetPlayer>
                    <incremental>false</incremental>
                    <debug>false</debug>
                    <runtimeLocales></runtimeLocales>
                    <locale>en_US</locale>
                    <optimize>true</optimize>
                    <showWarnings>true</showWarnings>
                    <strict>true</strict>
                    <useNetwork>true</useNetwork>
                    <allowSourcePathOverlap>true</allowSourcePathOverlap>
                    <definesDeclaration>
                        <property>
                            <name>ZEFIRO::META_INFO</name>
                            <value>"buildno=${zefiro.plugin.buildno}"</value>
                        </property>
                    </definesDeclaration>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <dependencies>
        <dependency>
            <groupId>com.adobe.flex.framework</groupId>
            <artifactId>flex-framework</artifactId>
            <version>3.5.0.12683</version>
            <type>pom</type>
            <exclusions>
                <!-- make sure to exclude the default 'playerglobal' transitive dependency (which would be version 9 for SDK 3.5, however, we want version 10) -->
                <exclusion>
                    <groupId>com.adobe.flex.framework</groupId>
                    <artifactId>playerglobal</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>com.adobe.flex.framework</groupId>
            <artifactId>playerglobal</artifactId>
            <!-- this artifact version must match the flex SDK version used in this project -->
            <version>3.5.0.12683</version>
            <!-- the classifier specifies the target flash player major version (default is 9 for SDK 3.5) -->
            <classifier>10</classifier>
            <type>swc</type>
        </dependency>

        [... some more dependencies needed by all projects ...]
    </dependencies>

    <modules>
        <module>../lib_swc</module>
        <module>../project_swf</module>
        [... calls all my projects ...]
    </modules>

</project>
Run Code Online (Sandbox Code Playgroud)

然后我可以使用这个简单的POM 编译我的swc库项目:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>de.zefiro.maven.example</groupId>
        <artifactId>full_build</artifactId>
        <version>1.0-SNAPSHOT</version>
        <relativePath>../master_build</relativePath>
    </parent>

    <name>Sample library project</name>
    <artifactId>lib_swc</artifactId>
    <packaging>swc</packaging>

    <dependencies>
        <dependency>
            <groupId>${group-id}</groupId>
            <artifactId>some_other_library</artifactId>
            <version>${project.version}</version> <!-- I should probably look into dependency/versioning as well, but for now this works -->
            <!-- Note: no 'Scope' here, swc files will be build "merged into code"-style. Needed as transitive dependencies don't work with Maven/Flex - we use 'external' scope for the final swf projects dependencies -->
            <type>swc</type>
        </dependency>
    </dependencies>

</project>
Run Code Online (Sandbox Code Playgroud)

我的swf用这个POM 项目:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>de.zefiro.maven.example</groupId>
        <artifactId>full_build</artifactId>
        <version>1.0-SNAPSHOT</version>
        <relativePath>../master_build</relativePath>
        </parent>

    <name>Sample SWF module</name>
    <artifactId>project_swf</artifactId>
    <packaging>swf</packaging>

    <build>
    <!-- This name needs to be exactly specified, as the runtime will load it as it's specified in the configuration xml -->
        <finalName>SampleProjectModule1</finalName>

        <!-- define the master source file, it's picked up for some projects automatically and must be specified for others. Inherits compiler parameters from parent. -->
        <plugin>
            <groupId>org.sonatype.flexmojos</groupId>
            <artifactId>flexmojos-maven-plugin</artifactId>
            <version>3.7.1</version>
            <configuration>
                <sourceFile>project_swf_master_file.as</sourceFile>
            </configuration>
        </plugin>

        <plugins>
            <plugin>
                <artifactId>maven-assembly-plugin</artifactId>
                <configuration>
                    <descriptors>
                        <descriptor>../master_build/swf-assembly.xml</descriptor>
                    </descriptors>
                </configuration>
                <executions>
                    <execution>
                        <id>WebContent-packaging</id>
                        <phase>package</phase>
                        <goals><goal>single</goal></goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

    <dependencies>
        <dependency>
            <groupId>${group-id}</groupId>
            <artifactId>project_swc</artifactId>
            <version>${project.version}</version>
            <scope>${zefiro.swf.scope}</scope> <!-- tell Flex Mojo that we want to compile using runtime shared libraries (rsl) -->
            <type>swc</type>
        </dependency>
        [...]
    </dependencies>

</project>
Run Code Online (Sandbox Code Playgroud)

据我所知,每个POM文件生成一个目标文件(使用包装标签指定),并且在使用Flex mojo时,这需要格式为swf或swc.我似乎无法在这里指定多个目标,并且还努力获取我的资源文件(Flex copy-resources复制我不需要的html包装器(对于每个项目),普通资源标签复制资源,但是不要打包他们).现在我现在的工作版本是指定一个自己的程序集描述符,它将我的目标.swf文件与WebContent /文件夹一起捆绑到一个zip文件中.Maven支持jar/war/bin文件,但是那些似乎期望某些条件成立,这不适用于我的Flex项目(例如我没有web.xml)

SWF-assembly.xml:

<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
    <id>WebContent</id>
    <formats>
        <format>zip</format>
    </formats>
    <includeBaseDirectory>false</includeBaseDirectory>
    <fileSets>
        <!-- Take the base swf artifact (only, not the other stuff which is generated there) -->
        <fileSet>
            <directory>${project.build.directory}</directory>
            <outputDirectory>/</outputDirectory>
            <includes>
                <include>*.swf</include>
            </includes>
        </fileSet>
        <!-- add the WebContent folder -->
        <fileSet>
            <directory>FCPContent</directory>
            <outputDirectory>/</outputDirectory>
        </fileSet>
    </fileSets>
</assembly>
Run Code Online (Sandbox Code Playgroud)

现在我有了目标目录,只包含.swf文件和包含我的.swf文件的zip文件以及我的WebContent/resources.在调用'mvn install'时它也放在Nexus存储库中,所以这看起来是一个很好的进步.虽然我很高兴做到完全不同,如果这更好,因为我的最终目标是有一个目录(或包含它的zip/war文件)中包含一些静态文件(我们的html包装器和加载器swf + configuration.xml ),对于我们的每个swf项目(我们在运行时加载的模块),包含.swf文件和WebContent/resources的目录 - 即我现在能够为每个项目创建的zip文件的内容.

index.html
loader.swf
config.xml
project_swf/SampleProjectModule1.swf
project_swf/assets/labels.xlf
project_swf/config/config.xml
project2_swf/module2.swf
project2_swf/cool_colors_stylesheet.swf
Run Code Online (Sandbox Code Playgroud)

所以我的问题是:如何定义这样一个以这种格式创建最终装配的Maven主项目?如果没有别的办法,可以接受一个正常工作的ANT文件,虽然我已经读到它Maven敦促我们远离那些黑客:)

我还需要编译样式表文件,然后是swf项目的附加工件.我会为此发布一个单独的问题.

Zef*_*iro 1

我的解决方案有点复杂,感觉“肮脏” - 我认为可能有一种更干净的方法,但至少我现在已经让它运行了。

基本上,我使用 Maven-assemble-plugin 创建中间 zip 存档(“war”同样有效),其中包含 swf 可执行文件以及我正在创建的每个插件的任何必要的静态资产(我们使用 OSGi -like动态加载器类似于Eclipse的工作方式,其中一个静态文件是plugin.xml,其他是翻译文件,它们都不能嵌入到.swf中)。Maven 将 .swf 文件以 Maven 文件名表示法存储为主要工件(我完全忽略了这一点)以及我的 zip 存档(根据 FinalName 标签使用 .swf 名称)。POM 和程序集文件的工作原理如我原来的问题所示。

我添加了一个空白的装配项目,其唯一目标是依赖并因此包括我的所有其他项目。该项目的输出是我最终的“真实”工件,然后我可以将其用于分发和部署。由于我不想将太多帮助程序项目聚集在 Eclipse 工作区中,因此我打破了 Maven 项目和 Eclipse 项目的 1:1 关系:我的 Maven 程序集插件仅位于 master_build 项目内的子目录“程序集”中。我在我的主 pom (master_build/pom.xml) 中为其添加了一个模块语句,该语句将作为最后一个项目在反应器中执行。(由于给定的依赖关系,排序是自动完成的 - 如果您将其指定为第一个模块并且它不是最后执行的,那么您正在构建不需要的项目:)

我还将我的装配项目 POM 设为我的主 POM 的子项目。这不是必需的,但通过这样做我可以继承我定义的 Maven 属性。它还继承了对 Flex 编译器的调用,不过由于这里没有任何可编译的内容,因此这并没有什么坏处。YMMV。

这是 POM:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>de.zefiro.maven.example</groupId>
        <artifactId>full_build</artifactId>
        <version>1.0-SNAPSHOT</version>
        <relativePath>../</relativePath>
    </parent>


    <groupId>${group-id}</groupId>
    <artifactId>full_assembly</artifactId>
    <name>Final Assembly</name>
    <version>${project.parent.version}</version>
    <packaging>pom</packaging> <!-- note that this is POM here, not war or zip -->

    <build>
        <plugins>
            <plugin>
                <artifactId>maven-assembly-plugin</artifactId>
                <version>2.2.1</version>
                <configuration>
                    <descriptors>
                        <descriptor>final-assembly.xml</descriptor>
                    </descriptors>
                </configuration>
                <executions>
                    <execution>
                        <id>Final-Packaging</id>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

    <dependencies>
        <dependency>
            <groupId>de.zefiro.maven.example</groupId>
            <artifactId>wrapper</artifactId>
            <version>1.0</version>
            <type>war</type>
        </dependency>
        <dependency>
            <groupId>${group-id}</groupId>
            <artifactId>project_swf</artifactId>
            <version>${project.version}</version>
            <type>zip</type>
            <classifier>WebContent</classifier> <!-- needs to be the ID of the assembler xml which packaged the zip file -->
        </dependency>
[... all other projects which should be packaged ...]
    </dependencies>
</project>
Run Code Online (Sandbox Code Playgroud)

遵循程序集描述符。有关详细信息,请参阅程序集描述符文档。

<assembly
    xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
    <id>FinalAssembly</id>
    <formats>
        <format>war</format> <!-- can be either zip or war, depending on what you wish -->
    </formats>
    <includeBaseDirectory>false</includeBaseDirectory>
    <dependencySets>
        <dependencySet>
            <includes>
                <include>de.zefiro.maven.example:wrapper:war:*</include>
            </includes>
            <unpack>true</unpack>
        </dependencySet>
        <dependencySet>
            <includes>
                <include>${group-id}:project_swf:zip:WebContent:${project.version}</include>
            </includes>
            <useProjectAttachments>true</useProjectAttachments>
            <unpack>true</unpack>
            <outputDirectory>sample_project_1</outputDirectory>
        </dependencySet>
[... list the same projects as in the POM file ...]
    </dependencySets>
</assembly>
Run Code Online (Sandbox Code Playgroud)

我有一份来自不同部门的档案,我正在使用它。它包含 HTML 包装器和运行的主 Flex 应用程序(稍后根据配置文件和各个项目的 plugin.xml 元数据从子目录加载所有插件)。这被放置在输出存档根目录中。所有其他项目都是我自己创建的,并放置在单独的子目录中,因此我在这里不使用通配符。由于我想要一个包含合并的所有文件的单个存档,因此我使用 dependencySet 的 unpack 选项。

请注意,在各个 swf 插件项目的程序集描述符中声明的 ID 现在用作 pom 文件的依赖项部分中的分类器以及程序集描述符中 Maven 位置的一部分。包装类型也是如此,我在这里选择了 zip。由于这仅用于中间存档,因此 zip 就可以了,对于最终组装,可以选择不同的格式。

从同一个父级继承,我可以重用我的 Maven 属性,这些属性也可以在程序集描述符中使用。

可以通过复制现有项目并将其添加到以下位置来添加新项目:

  • master_build/pom.xml 作为模块
  • 依赖项部分中的 master_build/assemble/pom.xml
  • master_build/ assembly/final- assembly.xml 作为 dependencySet

最终的工件是一个 war 文件,其中包含:

sample_project_1/SampleProjectModule1
sample_project_1/assets/labels.xlf
sample_project_1/config/config.xml
other_data/configuration.xml
application.swf
index.html
Run Code Online (Sandbox Code Playgroud)

即,我的所有 swf 项目在各自子目录中的内容与包含静态文件的wrapper.war 的内容合并。

可以从以下位置的存储库中检索它:

de.zefiro.maven.example:full_assembly:war:FinalAssembly:1.0-SNAPSHOT
Run Code Online (Sandbox Code Playgroud)

为了编译每个插件的样式表,我使用相同的基本思想,并将其转移到单个项目级别。我会在其他问题中描述它

未决问题:我无法生成文件的调试版本和发布版本。我可以将项目加倍并将它们打包在一起(就像我对样式表所做的那样),或者我可以使用不同的 groupId 运行整个 Maven 反应器(对于父 POM 和主程序集)两次,从而创建两个完全独立的路径所有涉及的项目。不过,我还没有对此进行进一步调查。