如何在 Eclipse PDE 中表达项目间的依赖关系
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1390074/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to express inter project dependencies in Eclipse PDE
提问by Roland Tepp
I am looking for the best practice of handling inter project dependencies between mixed project types where some of the projects are eclipse plug-in/OSGI bundle projects (an RCP application) and others are just plain old java projects (web services modules). Few of the eclipse plug-ins have dependencies on Java projects.
我正在寻找处理混合项目类型之间的项目间依赖关系的最佳实践,其中一些项目是 Eclipse 插件/OSGI 捆绑项目(RCP 应用程序),而其他项目只是普通的旧 Java 项目(Web 服务模块)。很少有 Eclipse 插件依赖于 Java 项目。
My problem is that at least as far as I've looked, there is no way of cleanly expressing such a dependency in Eclipse PDE environment. I can have plug-in projects depend on other plug-in projects (via Import-Package
or Require-Bundle
manifest headers), but not of the plain java projects.
我的问题是,至少就我所见,没有办法在 Eclipse PDE 环境中清楚地表达这种依赖关系。我可以让插件项目依赖于其他插件项目(通过Import-Package
或Require-Bundle
清单头),但不依赖于普通的 java 项目。
I seem to be able to have project declare a dependency on a jar from another project in a workspace, but these jar files do not get picked up by neither export nor launch configuration (although, java code editing sees the libraries just fine).
我似乎能够让项目声明对工作区中另一个项目的 jar 的依赖,但是这些 jar 文件不会被导出和启动配置所获取(尽管 Java 代码编辑可以很好地看到这些库)。
The "Java projects" are used for building services to be deployed on an J2EE container (JBoss 4.2.2 for the moment) and produce in some cases multiple jar's - one for deploying to the JBoss ear and another for use by client code (an RCP application).
“Java 项目”用于构建要部署在 J2EE 容器(目前为 JBoss 4.2.2)上的服务,并在某些情况下生成多个 jar——一个用于部署到 JBoss 耳朵,另一个用于客户端代码(一个RCP 应用程序)。
The way we've "solved" this problem for now is that we have 2 more external tools launcher configurations - one for building all the jar's and another for copying these jar's to the plug-in projects. This works (sort of), but the "whole build" and "copy jars" targets incur quite a large build step, bypassing the whole eclipse incremental build feature and by copying the jars instead of just referencing the projects I am decoupling the dependency information and requesting quite a massive workspace refresh that eats up the development time like it was candy.
我们现在“解决”这个问题的方法是,我们还有 2 个外部工具启动器配置——一个用于构建所有 jar,另一个用于将这些 jar 复制到插件项目。这有效(有点),但是“整个构建”和“复制 jars”目标会导致相当大的构建步骤,绕过整个 eclipse 增量构建功能并通过复制 jars 而不是仅仅引用我正在解耦依赖信息的项目并要求大量的工作区更新,这会像糖果一样消耗开发时间。
What I would like to have is a much more "natural" workspace setup that would manage dependencies between projects and request incremental rebuilds only as they are needed, be able to use client code from service libraries in an RCP application plug-ins and be able to launch the RCP application with all the necessary classes where they are needed.
我想要的是一个更“自然”的工作区设置,它可以管理项目之间的依赖关系并仅在需要时请求增量重建,能够在 RCP 应用程序插件中使用来自服务库的客户端代码,并且能够在需要的地方使用所有必要的类启动 RCP 应用程序。
So can I have my cake and eat it too ;)
所以我可以吃蛋糕也吃吗;)
NOTE
笔记
To be clear, this is not so much about dependency management and module management at the moment as it is about Eclipse PDE configuration.
需要明确的是,目前这与依赖管理和模块管理无关,而与 Eclipse PDE 配置有关。
I am well aware of products like [Maven], [Ivy] and [Buckminster] and they solve a quite different problem (once I've solved the workspace configuration issue, these products can actually come in handy for materializing the workspace and building the product)
我很清楚像 [Maven]、[Ivy] 和 [Buckminster] 这样的产品,它们解决了一个完全不同的问题(一旦我解决了工作区配置问题,这些产品实际上可以派上用场来具体化工作区和构建产品)
采纳答案by Jens Schauder
I never did it so this is a theoretical approach. But I'd try a dependency management system like ivy or maven2.
我从来没有这样做过,所以这是一种理论方法。但我会尝试像ivy或maven2这样的依赖管理系统。
Since maven2 does much more, then just dependency management, I'd recommend ivy in this case.
由于 maven2 做得更多,那么只是依赖管理,在这种情况下我建议使用 ivy。
回答by AlBlue
Eclipse projects depend on each other by virtue of the checkbox in the project's properties (dependent projects?) which is how Eclipse decides which to build. You can set this yourself, but it's usually set when you change your Java build path. It stores the data in the .project file IIRC so once you've gone through the GUI and seen what changes, you can be more flexible in how you apply the others.
Eclipse 项目依赖于项目属性(依赖项目?)中的复选框,Eclipse 决定构建哪个项目。您可以自己设置,但通常在您更改 Java 构建路径时设置。它将数据存储在 .project 文件 IIRC 中,因此一旦您浏览了 GUI 并看到了哪些更改,您就可以更灵活地应用其他文件。
However, it sounds like you want to mix and match Jars and Bundles. The easy way to do that is just treat all projects as Java projects. In the PDE project, you can actually go in and tweak the Java build path; it'll complain and say that it isn't the right way to do it, but it will allow you to have a PDE project depend on a Java project without all that fluffy JARing up. Having said that, it wouldn't surprise me if there were runtime problems with this approach - the PDE runtime is likely to not see it that way.
但是,听起来您想要混合搭配 Jars 和 Bundle。最简单的方法是将所有项目视为 Java 项目。在 PDE 项目中,您实际上可以进入并调整 Java 构建路径;它会抱怨并说这不是正确的方法,但它允许您拥有一个依赖于 Java 项目的 PDE 项目,而不会出现所有蓬松的 JAR。话虽如此,如果这种方法存在运行时问题,我也不会感到惊讶 - PDE 运行时可能不会这样看。
The other approach is to make your JARs themselves PDE/OSGi bundles. After all, an OSGi bundle is nothing more than a JAR with a bit of extra cruft in the Manifest, and it will let you develop and assemble your projects trivially using automatic dependency management. That's probably the easiest one to go for, even if you don't really need the manifest to be present in your bundles. But doing this will mean your PDE app can be shipped with a more modular approach instead of embedding the libraries in each plugin as necessary.
另一种方法是使您的 JAR 本身成为 PDE/OSGi 包。毕竟,OSGi 包只不过是一个 JAR,在 Manifest 中有一些额外的杂物,它可以让您使用自动依赖管理轻松地开发和组装您的项目。这可能是最容易实现的方法,即使您并不真的需要将清单显示在您的包中。但是这样做意味着您的 PDE 应用程序可以采用更加模块化的方法,而不是根据需要将库嵌入到每个插件中。
So, PDE can generate OSGi bundles, and that's just another name for JAR + Manifest stuff. You can use a JAR in exactly the same way in other environments (e.g. for your EAR or other client uses) and you can take advantage of the OSGi layer in your app. There's really no reason not to do this given the type of hybrid bundle that you're talking about.
因此,PDE 可以生成 OSGi 包,这只是 JAR + Manifest 内容的另一个名称。您可以在其他环境中以完全相同的方式使用 JAR(例如,用于您的 EAR 或其他客户端使用),并且您可以在您的应用程序中利用 OSGi 层。考虑到您所谈论的混合捆绑包的类型,真的没有理由不这样做。
回答by Wade Walker
Our solution uses an Ant builder to copy the "classes" directories of the plain Java projects directly into the top directory of the plugin project. We skip the JAR building step to save time, and it works pretty well. If the plugin project depends on external JARs that're already built, we copy those in too.
我们的解决方案使用 Ant 构建器将普通 Java 项目的“classes”目录直接复制到插件项目的顶层目录中。我们跳过了 JAR 构建步骤以节省时间,它运行良好。如果插件项目依赖于已经构建的外部 JAR,我们也将它们复制进去。
Here's exactly how to set it up in Eclipse 3.5 (sorry for the odd formatting, but that's the only way I could find to preserve indentation):
这正是在 Eclipse 3.5 中设置它的方法(对于奇怪的格式很抱歉,但这是我能找到的保留缩进的唯一方法):
Create empty "classes" dir in plugin project Select plugin project, hit F5 to refresh resources Create new Ant build file in plugin project to copy dependencies (ours is shown below) Right-click plugin project, select Properties Select Builders Click "New..." (brings up Edit Configuration dialog) Select Ant Builder and click "OK" Name your builder (ours is called "PluginProject externals") Browse workspace for Buildfile (ours is ${workspace_loc:/PluginProject/copyDependencies.xml}) click Refresh tab check "Refresh resources upon completion", click "Specific resources" click "Specify Resources...", check box for the classes dir, click "Finish" Click "OK" (closes Edit Configuration dialog) Click "Up" to move "PluginProject externals" to top of builder list Click "OK" (closes Properties dialog) Open your plugin project's MANIFEST.MF Click "Runtime" tab Click "Add..." under "Classpath", select your the "classes" dir and JARs and click "OK"
Create empty "classes" dir in plugin project Select plugin project, hit F5 to refresh resources Create new Ant build file in plugin project to copy dependencies (ours is shown below) Right-click plugin project, select Properties Select Builders Click "New..." (brings up Edit Configuration dialog) Select Ant Builder and click "OK" Name your builder (ours is called "PluginProject externals") Browse workspace for Buildfile (ours is ${workspace_loc:/PluginProject/copyDependencies.xml}) click Refresh tab check "Refresh resources upon completion", click "Specific resources" click "Specify Resources...", check box for the classes dir, click "Finish" Click "OK" (closes Edit Configuration dialog) Click "Up" to move "PluginProject externals" to top of builder list Click "OK" (closes Properties dialog) Open your plugin project's MANIFEST.MF Click "Runtime" tab Click "Add..." under "Classpath", select your the "classes" dir and JARs and click "OK"
The manual creation of the empty "classes" directory in the plugin project is so you can tell your new builder to refresh that resource (which doesn't exist yet before the new builder is run). Here's what's in our copyDependencies.xml file:
在插件项目中手动创建空的“classes”目录,以便您可以告诉新构建器刷新该资源(在新构建器运行之前尚不存在)。这是我们的 copyDependencies.xml 文件中的内容:
<project name="Copy dependencies" default="copyDependencies" basedir=".">
<!--
This copying is needed because it appears that Eclipse plugins can't
depend directly on external Eclipse projects.
-->
<description>
Copies external dependency class andd JAR files into this plugin's directory.
</description>
<target name="copyDependencies">
<copy file="../External/JDOM/jdom-1.0/build/jdom.jar" todir="." preservelastmodified="true"/>
<copy file="../External/Xalan/xalan-j_2_6_0/bin/xalan.jar" todir="." preservelastmodified="true"/>
<copy file="../External/Xalan/xalan-j_2_6_0/bin/xercesImpl.jar" todir="." preservelastmodified="true"/>
<copy file="../External/Xalan/xalan-j_2_6_0/bin/xml-apis.jar" todir="." preservelastmodified="true"/>
<copy todir="./classes/com/arm" preservelastmodified="true">
<fileset dir="../Utilities/src/com/arm" excludes="**/*.java"/>
</copy>
</target>
<target name="clean" description="Deletes local copies of external classes and JARs.">
<delete file="jdom.jar" quiet="true"/>
<delete file="xalan.jar" quiet="true"/>
<delete file="xercesImpl.jar" quiet="true"/>
<delete file="xml-apis.jar" quiet="true"/>
<delete dir="./classes/com/arm/utilities" quiet="true"/>
</target>
</project>
The only downside to this method seems to be that Eclipse isn't 100% perfect about invoking the external builder when it needs to be invoked, so occasionally you have to do a "Project > Clean..." in Eclipse to force it along.
这种方法的唯一缺点似乎是 Eclipse 在需要调用外部构建器时并非 100% 完美,因此有时您必须在 Eclipse 中执行“项目 > 清理...”以强制执行它.
回答by Ben Hutchison
You have my sympathies. I too have battled with this issue and the Wall-of-Silence from the Eclipse devs on such a simple, obvious question: how to declare a dependency from a plugin to a normal Java project (such that it works at runtime)?
你有我的同情。我也曾与这个问题和来自 Eclipse 开发人员的无声墙在一个如此简单、明显的问题上进行过斗争:如何声明从插件到普通 Java 项目的依赖关系(使其在运行时工作)?
I dont think they support it. The only way Ive got around the problem is to create folders inside my plugin projects that are actually links to the bin/ folders of the java projects, and then include these folders into the plugin. That at least works, but its brittle due to the absolute filesystem paths required.
我不认为他们支持它。我解决这个问题的唯一方法是在我的插件项目中创建文件夹,这些文件夹实际上是指向 java 项目的 bin/ 文件夹的链接,然后将这些文件夹包含到插件中。这至少有效,但由于需要绝对文件系统路径,它很脆弱。
回答by ariesandes
maybe you can use "project properties" -> "deployment assembly" on Eclipse, and add other projects to your main project. The other projects are seeing like "jars" that automatically are added to your deployment file (war, ear or whatever). Maybe this can be works. At least it works for me. Good luck !!
也许您可以在 Eclipse 上使用“项目属性”->“部署程序集”,并将其他项目添加到您的主项目中。其他项目看起来像“jars”,它们会自动添加到您的部署文件(war、ear 或其他)中。也许这可以奏效。至少它对我有用。祝你好运 !!
Ariesandes.
阿里山德斯。
回答by ctr0
There is a "Link source" option in Build path properties that allows you to define additional source folders for a project. You can selected the "src" folder of another workspace project and rename it to "src2" or whatever you want. This way classes are compiled and deployed into the plug-in project output folder and can be loaded at runtime.
构建路径属性中有一个“链接源”选项,允许您为项目定义其他源文件夹。您可以选择另一个工作区项目的“src”文件夹并将其重命名为“src2”或您想要的任何名称。通过这种方式,类被编译并部署到插件项目输出文件夹中,并且可以在运行时加载。
回答by Bill Michell
With a complex set of build dependencies, I've found Maven2 and Hudson (for CI) to be a pretty nice combination. It took a while to set up the infrastructure and get my head around configuration, but after that, it just worked.
有了一组复杂的构建依赖项,我发现 Maven2 和 Hudson(用于 CI)是一个非常好的组合。设置基础设施并了解配置需要一段时间,但在那之后,它就可以正常工作了。
Of course, you are dependent then on Maven2 (or Hudson) support for your build mechanism. I'm not sure how well Eclipse Headless builds are supported. But if the only reason you're using Eclipse headless is to allow the dependencies to be expressed in a single place, do yourself a favour and switch.
当然,您的构建机制依赖于 Maven2(或 Hudson)支持。我不确定 Eclipse Headless 构建的支持情况如何。但是,如果您使用 Eclipse 无头的唯一原因是允许在一个地方表达依赖项,请帮自己一个忙并切换。
回答by Henno Vermeulen
I am having the exact same problems. We have a set of multiple normal java projects that can be built by Maven and should (currently) all share the same classpath to work properly. These projects can be used to start a server in a non-OSGi environment. Then we also have an eclipse RCP client which uses these projects as one bundle. I am perfectly able to build this one-big-bundle with Maven using the Apache Felix Maven Bundle Plugin and everything works fine. But whenever I change one class in the normal project I have to rebuild the entire bundle. Incremental build and resource linking does not work.
我遇到了完全相同的问题。我们有一组可以由 Maven 构建的多个普通 Java 项目,并且(当前)都应该共享相同的类路径才能正常工作。这些项目可用于在非 OSGi 环境中启动服务器。然后我们还有一个 eclipse RCP 客户端,它将这些项目作为一个包使用。我完全能够使用 Apache Felix Maven Bundle Plugin 用 Maven 构建这个大包,并且一切正常。但是每当我在普通项目中更改一个类时,我都必须重建整个包。增量构建和资源链接不起作用。
I tried the "solution" with linking binaries/source directories from these projects into the Manifest classpath of the one-big-bundle and it seems to work but it would be a real maintenance nightmare because I even have to link some individual files.
我尝试了“解决方案”,将这些项目中的二进制文件/源目录链接到一个大包的清单类路径中,它似乎有效,但这将是一个真正的维护噩梦,因为我什至必须链接一些单独的文件。
So ironically BECAUSE of the use of OSGi in the client I am actually thinking of collapsing our nice and modular structure with Maven modules into subpackages of only one plugin project. This is a better alternative than having extremely slow development.
因此具有讽刺意味的是,由于在客户端中使用了 OSGi,我实际上正在考虑将我们带有 Maven 模块的漂亮的模块化结构折叠成只有一个插件项目的子包。这是比极慢的开发更好的选择。
The other and better alternative (according to the OSGi guys) which I will investigate first is to make all my Maven modules into OSGi bundles. But this may be a real PITA because I depend on classpath scanning and combining multiple configuration files from several bundles (with sometimes the same name) to form one configuration.
我将首先研究的另一个更好的选择(根据 OSGi 人员的说法)是将我所有的 Maven 模块制作成 OSGi 包。但这可能是一个真正的 PITA,因为我依赖于类路径扫描并组合来自多个包(有时具有相同名称)的多个配置文件以形成一个配置。
(Specifically we use the Spring framework and we merge multiple persistence.xml files into one persistence context. We also merge several spring XML context files from different modules (all providing a different ASPECT) that should together form one Spring context to be used by Spring-DM.)
(具体来说,我们使用 Spring 框架,我们将多个 persistence.xml 文件合并到一个持久化上下文中。我们还合并了来自不同模块(都提供不同的 ASPECT)的几个 Spring XML 上下文文件,这些文件应该一起形成一个 Spring 上下文以供 Spring 使用-DM。)