编译Eclipse的教程
从www.eclipse.org上下载Eclipse源代码包,解压缩。发现Eclipse的源代码目录和和最终编译出来的目录结果基本一摸一样,在根目录下,也是一个plugins子目录和一个features子目录,唯一缺少的是那个startup.jar和eclipse.exe。
到www.eclipse.org上看了一下build instruction,发现编译非常简单,同样使用的是ant(幸好前两天搞定了ant,^_^)。有一个build.bat脚本,要求按照不同的平台传递几个参数,分别是-os 操作系统,-ws 窗口系统,-arch CPU构架,然后build脚本根据这几个参数选择不同的build.xml文件,再调用ant来做编译工作。具体的参数可以查看Eclipse的编译帮助文档,我使用的是windows xp,所以编译参数是build -os win32 -ws win32 -arch x86。
需要注意的是,开始编译前要设定好ANT_HOME路径,简单的做法是,开始菜单-->运行,敲入set ANT_PATH=d:/apache-ant-1.6.0。我建议最好把ant的bin目录设置到PATH环境变量下,因为Eclipse的每个插件自身都带有build.xml文件,其中大部分组件都是可以直接在其目录下敲入ant直接编译的,如果你修改了某个组件的部分代码,完全可以简单的敲入ant来观察结果,而不需要回到根目录做完全的编译。
应该说的是,Eclipse本身的编译过程不算太慢。我的P4 2.8/1G RAM机器上,也就15分钟。但是如果当我改变了某个插件的某些文件,然后再回到根目录做部分编译时,我发现居然跟完整编译一次花费的时间差不多,因为很多没有改变的插件也都被重新编译打包了,这让我觉得很是不爽,不知道为什么会有这种设计,看来需要分析一下Eclipse的build脚本。
完成编译后,会发现在根目录下出现一个tmp子目录,下面是3个目录,plugins,features,以及一个随平台不同而变的目录,在我的系统下叫做setup.x86。plugins下放着所有编译出来的插件,features下则存放这所有的feature。那个win32.win32.x86下,正好就是运行Eclipse所需要的eclipse.exe和startup.exe文件,我试着把这两个文件拷贝到tmp目录下,然后双击eclipse.exe,那个长得很困难的Eclipse Splash居然就出现了,然后整个程序启动,一切OK。
为了对整个编译过程有一个理性的认识,我跟踪了一下整个Eclipse的编译过程,其实就是观察多个builk.xml之间的调用关系。
1.根目录的build.xml文件有一个target叫做allElements,其脚本如下:
<target name="allElements">
<ant antfile="${buildDirectory}/features/org.eclipse.sdk/build.xml" target="${target}" dir="${buildDirectory}/features/org.eclipse.sdk" />
</target>
显然,首先被编译的是features目录下的org.eclipse.sdk下的build.xml文件,而且执行的目标target是build.jar(了解这个属性需要阅读eclipse_src/build.xml)。所有这几行脚本的意义就是:在features/org.eclipse.sdk目录下执行ant build.jar
2.然后分析org.eclipse.sdk/build.xml文件中build.jar对应的脚本,
<target name="build.jars" depends="init" description="Build all the jars for the feature: org.eclipse.sdk.">
<antcall target="all.children">
<param name="target" value="build.jars"/>
</antcall>
</target>
沿着build.jar的depend,一直跟踪到all.features这个目标,一切都明朗了
<target name="all.features" depends="init">
<ant antfile="build.xml" dir="../org.eclipse.platform/" target="${target}"/>
<ant antfile="build.xml" dir="../org.eclipse.platform.source/" target="${target}"/>
<ant antfile="build.xml" dir="../org.eclipse.jdt/" target="${target}"/>
<ant antfile="build.xml" dir="../org.eclipse.jdt.source/" target="${target}"/>
<ant antfile="build.xml" dir="../org.eclipse.pde/" target="${target}"/>
<ant antfile="build.xml" dir="../org.eclipse.pde.source/" target="${target}"/>
</target>
显然,这个target的意思就是编译features下的另外6个feature的build.xml文件。而且,这里其实可以看到Eclipse的插件的层次关系,SDK调用了Platform,JDT,PDE各自的build.xml,显然就是说这3个插件构成了SDK。
3.剩下的跟踪步骤与前面相同,Platform调用所有构成Platform的插件的build.xml,JDT调用构成JDT的插件的build.xml,看一个例子,在features/org.eclipse.platform/build.xml下的一行:
<target name="all.plugins" depends="init">
<ant antfile="build.xml" dir="../../plugins/org.eclipse.osgi" target="${target}">
<property name="arch" value="x86"/>
<property name="os" value="win32"/>
<property name="ws" value="win32"/>
</ant>
...其它插件的调用
显然,每个在plugins目录下的插件都是通过这种方式编译的。
4.看一个具体的插件的build.xml文件,org.eclipse.core.runtime/build.xml中的一段,描叙了整个编译的过程,当然,打包部分在另一个target 中:
<target name="runtime.jar" depends="init" unless="runtime.jar" description="Create jar: runtime.jar.">
<delete dir="${temp.folder}/runtime.jar.bin"/>//删除临时目录
<mkdir dir="${temp.folder}/runtime.jar.bin"/>//创建临时目录
<!-- compile the source code -->
//编译所有的.java文件,源码目录在随后的<src path=“src“/>指定。
<javac destdir="${temp.folder}/runtime.jar.bin" failonerror="${javacFailOnError}" verbose="${javacVerbose}" debug="${javacDebugInfo}" includeAntRuntime="no" bootclasspath="${bootclasspath}" source="${javacSource}" target="${javacTarget}">
<compilerarg line="${compilerArg}"/>
<classpath>
<pathelement path="${build.result.folder}/../org.eclipse.osgi/core.jar"/>
<pathelement path="${build.result.folder}/../org.eclipse.osgi/console.jar"/>
<pathelement path="${build.result.folder}/../org.eclipse.osgi/osgi.jar"/>
<pathelement path="${build.result.folder}/../org.eclipse.osgi/resolver.jar"/>
<pathelement path="${build.result.folder}/../org.eclipse.osgi/defaultAdaptor.jar"/>
<pathelement path="${build.result.folder}/../org.eclipse.osgi/eclipseAdaptor.jar"/>
</classpath>
<src path="src/"/>
</javac>
<!-- Copy necessary resources -->
//复制一些非代码的资源文件,比如图片
<copy todir="${temp.folder}/runtime.jar.bin" failonerror="true">
<fileset dir="src/" excludes="**/*.java, **/package.htm*"/>
</copy>
//打包
<mkdir dir="${build.result.folder}"/>
<jar jarfile="${build.result.folder}/runtime.jar" basedir="${temp.folder}/runtime.jar.bin"/>
//删除临时目录
<delete dir="${temp.folder}/runtime.jar.bin"/>
</target>
对Eclipse的分析终于完成了,也解除了我先前的疑惑。当在Eclipse源码根目录敲入build命令时,编译进入eclipse_src/build.xml的“compile”这个target,它老兄第一件事就是先执行“init“和“clean“这两个target,然后再调用allElements,以下这句脚本就是了:
<target name="compile" depends="init,clean">
所以,可以说,Eclipse是没有部分编译这个概念的,唯一可想的办法就是自己进入想要重新编译的plugin,执行:
ant clean
ant build.jar
game over!
本文地址:http://www.45fan.com/dnjc/68470.html