Maven和Tycho

点进来读这篇文章的朋友,我假定你已经知道maven的基本知识,也知道Eclipse,知道Eclipse是基于OSGi,初步了解Eclipse插件开发或者说OSGi模块化开发。如果对这些知识不了解,甚至完全没有听过,那请绕开本文。

Maven简单来说是Java世界的一种新型的build工具,比ant的最大好处是依赖的管理,以及配置文件的可读性,可复用性,可扩展性。Maven的配置文件称为POM,即Project Object Model。在Maven中,每一个插件或者模块都由groupId,artifactId,version唯一标示。还有两个可选的标示元素,一个是packaging,默认支持的选项有pom,jar,maven-plugin,ejb,war,ear,rar,par等,maven会根据packaging设置的不同为模块执行不同的目标(goal);另一个是classifier,一般用不上。

最简单的pom

  1. <project> 
  2.   <modelVersion>4.0.0</modelVersion> 
  3.   <groupId>com.mycompany.app</groupId> 
  4.   <artifactId>my-app</artifactId> 
  5.   <version>1</version> 
  6. </project> 
<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.mycompany.app</groupId>
  <artifactId>my-app</artifactId>
  <version>1</version>
</project>

关于Maven的废话不多说,直接开始Tycho。如果说Maven的出现是一群Java程序员受不了繁琐的插件依赖管理,受不了冗长的ant build.xml文件而创造出来的,那Tycho则是一群Eclipse、OSGi插件开发人员受不了重复地配置类似的Maven pom.xml而创造出来的。Tycho大大简化了Eclipse、OSGi插件中的pom.xml,它实际上是一系列专用于build Eclipse插件和OSGi模块的maven插件的集合。

熟悉Eclipse插件和OSGi模块开发的程序员都知道,他们有自己的一套metadata用来描述自己的依赖,自己的各项配置。

比如MANIFEST.MF文件,就包含了模块名称,版本,依赖等丰富的信息

  1. Manifest-Version: 1.0 
  2. Bundle-ManifestVersion: 2 
  3. Bundle-Name: Dialog Editor 
  4. Bundle-SymbolicName: com.company.app; singleton:=true 
  5. Bundle-Version: 1.0.0.qualifier 
  6. Bundle-Vendor: Company 
  7. Require-Bundle: org.eclipse.ui, 
  8. org.eclipse.graphiti, 
  9. org.eclipse.graphiti.ui, 
  10. org.eclipse.core.runtime;bundle-version="3.8.0", 
  11. javax.inject;bundle-version="1.0.0", 
  12. org.eclipse.e4.core.di;bundle-version="1.1.0", 
  13. org.eclipse.e4.ui.workbench;bundle-version="0.10.2", 
  14. org.eclipse.e4.ui.di;bundle-version="0.10.1", 
  15. org.eclipse.e4.ui.services;bundle-version="0.10.1", 
  16. org.eclipse.core.resources;bundle-version="3.8.0" 
  17. Bundle-RequiredExecutionEnvironment: JavaSE-1.6 
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Dialog Editor
Bundle-SymbolicName: com.company.app; singleton:=true
Bundle-Version: 1.0.0.qualifier
Bundle-Vendor: Company
Require-Bundle: org.eclipse.ui,
 org.eclipse.graphiti,
 org.eclipse.graphiti.ui,
 org.eclipse.core.runtime;bundle-version="3.8.0",
 javax.inject;bundle-version="1.0.0",
 org.eclipse.e4.core.di;bundle-version="1.1.0",
 org.eclipse.e4.ui.workbench;bundle-version="0.10.2",
 org.eclipse.e4.ui.di;bundle-version="0.10.1",
 org.eclipse.e4.ui.services;bundle-version="0.10.1",
 org.eclipse.core.resources;bundle-version="3.8.0"
Bundle-RequiredExecutionEnvironment: JavaSE-1.6

还有build.properties,定义了所有需要在runtime用到的非代码文件(比如图片,配置文件等)

  1. source.. = src/ 
  2. output.. = bin/ 
  3. bin.includes = plugin.xml,\ 
  4.                META-INF/,\ 
  5.                .,\ 
  6.                icons/,\ 
  7.                MyModel.e4xmi 
source.. = src/
output.. = bin/
bin.includes = plugin.xml,\
               META-INF/,\
               .,\
               icons/,\
               MyModel.e4xmi


以及product文件

  1. <?xml version="1.0" encoding="UTF-8"?> 
  2. <?pde version="3.5"?> 
  3.  
  4. <product name="e4 SDK" uid="org.eclipse.e4.workbench.sdk" id="org.eclipse.e4.ui.examples.legacy.workbench.product" application="org.eclipse.ui.ide.workbench" version="0.9.0.@qualifier@" useFeatures="true" includeLaunchers="true"> 
  5.  
  6.    <aboutInfo> 
  7.       <image path="/org.eclipse.e4.ui.examples.legacy.workbench/eclipse_lg.gif"/> 
  8.    </aboutInfo> 
  9.  
  10.    <configIni use="default"> 
  11.    </configIni> 
  12.  
  13.    <launcherArgs> 
  14.       <programArgs>--launcher.XXMaxPermSize 256m</programArgs> 
  15.       <vmArgs>-Xms256m -Xmx512m</vmArgs> 
  16.       <vmArgsMac>-Xdock:icon=../Resources/Eclipse.icns -XstartOnFirstThread -Dorg.eclipse.swt.internal.carbon.smallFonts</vmArgsMac> 
  17.    </launcherArgs> 
  18.  
  19.    <windowImages i16="/org.eclipse.e4.ui.examples.legacy.workbench/eclipse.gif" i32="/org.eclipse.e4.ui.examples.legacy.workbench/eclipse32.gif" i48="/org.eclipse.e4.ui.examples.legacy.workbench/eclipse48.gif"/> 
  20.  
  21.    <splash 
  22.       location="org.eclipse.e4.ui.examples.legacy.workbench" /> 
  23.    <launcher name="eclipse"> 
  24.       <solaris/> 
  25.       <win useIco="false"> 
  26.          <bmp/> 
  27.       </win> 
  28.    </launcher> 
  29.  
  30.    <vm> 
  31.    </vm> 
  32.  
  33.    <plugins> 
  34.    </plugins> 
  35.  
  36.    <features> 
  37.       <feature id="org.eclipse.sdk"/> 
  38.       <feature id="org.eclipse.equinox.p2.user.ui"/> 
  39.       <feature id="org.eclipse.equinox.p2.user.ui.source"/> 
  40.       <feature id="org.eclipse.emf.sdk"/> 
  41.       <feature id="org.eclipse.wst.xml_ui.feature"/> 
  42.       <feature id="org.eclipse.gef"/> 
  43.       <feature id="org.eclipse.rcp.configuration"/> 
  44.       <feature id="org.eclipse.e4.sdk.runtime.feature"/> 
  45.       <feature id="org.eclipse.e4.sdk.source.feature"/> 
  46.       <feature id="org.eclipse.releng.tools"/> 
  47.    </features> 
  48.  
  49.    <configurations> 
  50.       <plugin id="org.eclipse.core.runtime" autoStart="true" startLevel="4" /> 
  51.       <plugin id="org.eclipse.equinox.common" autoStart="true" startLevel="2" /> 
  52.       <plugin id="org.eclipse.equinox.ds" autoStart="true" startLevel="2" /> 
  53.       <plugin id="org.eclipse.equinox.p2.reconciler.dropins" autoStart="true" startLevel="4" /> 
  54.       <plugin id="org.eclipse.equinox.simpleconfigurator" autoStart="true" startLevel="1" /> 
  55.       <plugin id="org.eclipse.update.configurator" autoStart="true" startLevel="3" /> 
  56.       <property name="eclipse.buildId" value="@qualifier@" /> 
  57.    </configurations> 
  58.  
  59. </product> 
<?xml version="1.0" encoding="UTF-8"?>
<?pde version="3.5"?>

<product name="e4 SDK" uid="org.eclipse.e4.workbench.sdk" id="org.eclipse.e4.ui.examples.legacy.workbench.product" application="org.eclipse.ui.ide.workbench" version="0.9.0.@qualifier@" useFeatures="true" includeLaunchers="true">

   <aboutInfo>
      <image path="/org.eclipse.e4.ui.examples.legacy.workbench/eclipse_lg.gif"/>
   </aboutInfo>

   <configIni use="default">
   </configIni>

   <launcherArgs>
      <programArgs>--launcher.XXMaxPermSize 256m</programArgs>
      <vmArgs>-Xms256m -Xmx512m</vmArgs>
      <vmArgsMac>-Xdock:icon=../Resources/Eclipse.icns -XstartOnFirstThread -Dorg.eclipse.swt.internal.carbon.smallFonts</vmArgsMac>
   </launcherArgs>

   <windowImages i16="/org.eclipse.e4.ui.examples.legacy.workbench/eclipse.gif" i32="/org.eclipse.e4.ui.examples.legacy.workbench/eclipse32.gif" i48="/org.eclipse.e4.ui.examples.legacy.workbench/eclipse48.gif"/>

   <splash
      location="org.eclipse.e4.ui.examples.legacy.workbench" />
   <launcher name="eclipse">
      <solaris/>
      <win useIco="false">
         <bmp/>
      </win>
   </launcher>

   <vm>
   </vm>

   <plugins>
   </plugins>

   <features>
      <feature id="org.eclipse.sdk"/>
      <feature id="org.eclipse.equinox.p2.user.ui"/>
      <feature id="org.eclipse.equinox.p2.user.ui.source"/>
      <feature id="org.eclipse.emf.sdk"/>
      <feature id="org.eclipse.wst.xml_ui.feature"/>
      <feature id="org.eclipse.gef"/>
      <feature id="org.eclipse.rcp.configuration"/>
      <feature id="org.eclipse.e4.sdk.runtime.feature"/>
      <feature id="org.eclipse.e4.sdk.source.feature"/>
      <feature id="org.eclipse.releng.tools"/>
   </features>

   <configurations>
      <plugin id="org.eclipse.core.runtime" autoStart="true" startLevel="4" />
      <plugin id="org.eclipse.equinox.common" autoStart="true" startLevel="2" />
      <plugin id="org.eclipse.equinox.ds" autoStart="true" startLevel="2" />
      <plugin id="org.eclipse.equinox.p2.reconciler.dropins" autoStart="true" startLevel="4" />
      <plugin id="org.eclipse.equinox.simpleconfigurator" autoStart="true" startLevel="1" />
      <plugin id="org.eclipse.update.configurator" autoStart="true" startLevel="3" />
      <property name="eclipse.buildId" value="@qualifier@" />
   </configurations>

</product>



Tycho牛逼之处就在于它可以读懂这些metadata,这样程序员就不需要在pom文件里面重新定义一遍。不止如此,为了避免程序员乌龙地在MANIFEST文件和pom文件里面定义的依赖出现冲突,Tycho甚至规定所有的依赖必须定义于MANIFEST文件中(不然没法编译),出现在pom文件中的依赖一律直接被忽略。

为了优化对Eclipse插件和OSGi模块的build,Tycho提供了专门的packaging,用来处理专门的模块生命周期,最典型的比如eclipse-repository,配合tycho-p2-director-plugin,直接就可以读懂product文件,build整个Eclipse RCP的product。


启用Tycho很简单,把下面的properties和build标签加入到parent pom文件即可,其中0.15.0是截止2012.8.26 Tycho最新的版本。

  1. <properties> 
  2.      <tycho-version>0.15.0</tycho-version> 
  3.   </properties> 
  4.  
  5.   <build> 
  6.      <plugins> 
  7.         <plugin> 
  8.            <groupId>org.eclipse.tycho</groupId> 
  9.            <artifactId>tycho-maven-plugin</artifactId> 
  10.            <version>${tycho-version}</version> 
  11.            <extensions>true</extensions> 
  12.         </plugin> 
  13.      </plugins> 
  14.   </build> 
 <properties>
      <tycho-version>0.15.0</tycho-version>
   </properties>

   <build>
      <plugins>
         <plugin>
            <groupId>org.eclipse.tycho</groupId>
            <artifactId>tycho-maven-plugin</artifactId>
            <version>${tycho-version}</version>
            <extensions>true</extensions>
         </plugin>
      </plugins>
   </build>
下面的repository标签用来设定一个Eclipse Indigo (视需要改变)的官方p2仓库,从这个仓库可以获取Tycho以及Eclipse插件或者OSGi模块化开发所需的大量编译好的模块

  1. <repository> 
  2.       <id>eclipse-indigo</id> 
  3.       <layout>p2</layout> 
  4.       <url>http://download.eclipse.org/releases/indigo</url> 
  5.    </repository> 
<repository>
      <id>eclipse-indigo</id>
      <layout>p2</layout>
      <url>http://download.eclipse.org/releases/indigo</url>
   </repository>

因为子pom可以从父pom继承到插件的配置信息,所以一般推荐在parent pom中定义插件配置,另外子pom也有重写(override)配置的权利。

比如我们来定义target-platform-configuration插件(用来build最后的product)的配置,告诉Tycho的这个maven插件我想要分别对windows,linux,macos三种操作系统build 专门的product,这样Tycho在build product的时候就会根据不同的os,选用不同的环境包并入最后的product中。

  1. <plugin> 
  2.         <groupId>org.eclipse.tycho</groupId> 
  3.         <artifactId>target-platform-configuration</artifactId> 
  4.         <version>${tycho-version}</version> 
  5.         <configuration> 
  6.           <environments> 
  7.             <environment> 
  8.               <os>win32</os> 
  9.               <ws>win32</ws> 
  10.               <arch>x86</arch> 
  11.             </environment> 
  12.             <environment> 
  13.               <os>linux</os> 
  14.               <ws>gtk</ws> 
  15.               <arch>x86_64</arch> 
  16.             </environment> 
  17.             <environment> 
  18.               <os>macosx</os> 
  19.               <ws>cocoa</ws> 
  20.               <arch>x86_64</arch> 
  21.             </environment> 
  22.           </environments> 
  23.         </configuration> 
  24.       </plugin> 
<plugin>
        <groupId>org.eclipse.tycho</groupId>
        <artifactId>target-platform-configuration</artifactId>
        <version>${tycho-version}</version>
        <configuration>
          <environments>
            <environment>
              <os>win32</os>
              <ws>win32</ws>
              <arch>x86</arch>
            </environment>
            <environment>
              <os>linux</os>
              <ws>gtk</ws>
              <arch>x86_64</arch>
            </environment>
            <environment>
              <os>macosx</os>
              <ws>cocoa</ws>
              <arch>x86_64</arch>
            </environment>
          </environments>
        </configuration>
      </plugin>



接下来介绍build Eclipse插件、OSGi模块的各种专门的packaging

1、普通的Eclipse插件、OSGi模块

  1. <groupId>Some-Group-Id</groupId> 
  2.   <artifactId>Bundle-SymbolicName</artifactId> 
  3.   <version>Bundle-Version</version> 
  4.   <packaging>eclipse-plugin</packaging> 
<groupId>Some-Group-Id</groupId>
  <artifactId>Bundle-SymbolicName</artifactId>
  <version>Bundle-Version</version>
  <packaging>eclipse-plugin</packaging>

2、feature模块(定义feature,feature是插件的集合,我们在给Eclipse安装插件的时候往往安装的是feature,而不是安装一个个的plugin jar)
  1. <groupId>Some-Group-Id</groupId> 
  2. <artifactId>FeatureId</artifactId> 
  3. <version>FeatureVersion</version> 
  4. <packaging>eclipse-feature</packaging> 
 <groupId>Some-Group-Id</groupId>
  <artifactId>FeatureId</artifactId>
  <version>FeatureVersion</version>
  <packaging>eclipse-feature</packaging>

3、p2仓库(为了发布,以及未来更新的各种方便,一般建议创建专门的一个模块定义仓库)

  1. <groupId>Some-Group-Id</groupId> 
  2.   <artifactId>RepositoryName</artifactId> 
  3.   <version>Version</version> 
  4.   <packaging>eclipse-repository</packaging>  
<groupId>Some-Group-Id</groupId>
  <artifactId>RepositoryName</artifactId>
  <version>Version</version>
  <packaging>eclipse-repository</packaging> 

4、product产品

  1. <groupId>Some-Group-Id</groupId> 
  2.   <artifactId>RepositoryName</artifactId> 
  3.   <version>Version</version> 
  4.   <packaging>eclipse-repository</packaging> 
  5.   <build> 
  6.     <plugins> 
  7.       <plugin> 
  8.         <groupId>org.eclipse.tycho</groupId> 
  9.         <artifactId>tycho-p2-director-plugin</artifactId> 
  10.         <version>${tycho-version}</version> 
  11.         <executions> 
  12.           <execution> 
  13.             <id>materialize-products</id> 
  14.             <goals> 
  15.               <goal>materialize-products</goal> 
  16.             </goals> 
  17.           </execution> 
  18.           <execution> 
  19.             <id>archive-products</id> 
  20.               <goals> 
  21.                 <goal>archive-products</goal> 
  22.               </goals> 
  23.           </execution> 
  24.         </executions> 
  25.       </plugin> 
  26.     </plugins> 
  27.   </build>  
<groupId>Some-Group-Id</groupId>
  <artifactId>RepositoryName</artifactId>
  <version>Version</version>
  <packaging>eclipse-repository</packaging>
  <build>
    <plugins>
      <plugin>
        <groupId>org.eclipse.tycho</groupId>
        <artifactId>tycho-p2-director-plugin</artifactId>
        <version>${tycho-version}</version>
        <executions>
          <execution>
            <id>materialize-products</id>
            <goals>
              <goal>materialize-products</goal>
            </goals>
          </execution>
          <execution>
            <id>archive-products</id>
              <goals>
                <goal>archive-products</goal>
              </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build> 

5、测试模块

把测试模块单独build是Tycho的一个特色,也是OSGi模块化开发的特色。很多人习惯把源代码放到main/src底下,把测试代码放到同一个项目的test文件夹底下,而在OSGi中,测试代码应该写在单独的模块里。这样最大的好处是执行的时候测试模块只有在测试阶段才执行,在打包阶段不执行,就不会被打进最后的产品包里。

只要把packaging设置成下面的 eclipse-test-plugin,Tycho就知道这是一个测试模块,只有在测试阶段才build它。

  1. <groupId>Some-Group-Id</groupId> 
  2.   <artifactId>Bundle-SymbolicName</artifactId> 
  3.   <version>Bundle-Version</version> 
  4.   <packaging>eclipse-test-plugin</packaging>  


 

最后放几个官方的链接:

http://maven.apache.org/guides/introduction/introduction-to-the-pom.html

http://www.eclipse.org/tycho/

http://wiki.eclipse.org/Tycho/Reference_Card

 

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值