我有以下项目结构:
root/
comp/
env/
version/
build.xml
build.xml
build.xml
凡根/ comp / env的/版本/ build.xml文件是:
<project name="comp-env-version" basedir=".">
<import file="../build.xml" optional="true" />
<echo>Comp Env Version tasks</echo>
<target name="run">
<echo>Comp Env Version run task</echo>
</target>
</project>
根/ comp / env的/ Build.xml是:
<project name="comp-env" basedir=".">
<import file="../build.xml" optional="true" />
<echo>Comp Env tasks</echo>
<target name="run">
<echo>Comp Env run task</echo>
</target>
</project>
根/ COMP / Build.xml是:
<project name="comp" basedir=".">
<echo>Comp tasks</echo>
</project>
每个构建文件导入父生成文件,每个孩子继承并重写父任务/属性。
我需要的是让不运行任何生成的构建XML。
例如,如果我对根/ comp / env的/版/运行“蚁族”(或类似的东西),我想获得以下的输出:
<project name="comp-env-version" basedir=".">
<echo>Comp tasks</echo>
<echo>Comp Env tasks</echo>
<echo>Comp Env Version tasks</echo>
<target name="run">
<echo>Comp Env Version run task</echo>
</target>
</project>
是否有一个Ant插件来做到这一点? 使用Maven? 什么是我的选择,如果不是?
编辑: 我需要这样的东西“MVN帮助:有效-POM”的蚂蚁。
Based on the description of the import task, it works very much like an entity includes with two additional features:
- target overriding
- special properties
For the purposes of viewing the "effective build" I don't think the special properties processing is required (though it could be added by iterating the inserted targets). So the processing to achieve this becomes.
- Parse the build.xml to a DOM
- For each top-level include tag found (only top-level are allowed), find the referenced source file.
- Parse the referenced build.xml
- insert any content from the referenced build.xml that don't collide with those in the current file.
- Repeat step 2 for referenced build.xml file(s) until no more found
- Output the resultant DOM
You can define a custom Ant task so that this processing can be defined in a task to be run from within your build. See this tutorial for more details.
Here's a basic implementation that recurses through imports and inserts the DOM elements from the referenced files. There's almost certainly a few bugs in it as I threw it together, but it should do largely what you're after:
/**
* Reads the build.xml and outputs the resolved build to stdout
*/
public static void main(String[] args) {
try {
Element root = new EffectiveBuild().parse(new File(args[0]));
XMLOutputter outputter = new XMLOutputter(Format.getPrettyFormat());
outputter.output(root, System.out);
} catch (Exception e) {
// TODO handle errors
e.printStackTrace();
}
}
/**
* Get the DOM for the passed file and iterate all imports, replacing with
* non-duplicate referenced content
*/
private Element parse(File buildFile) throws JDOMException, IOException {
Element root = getRootElement(buildFile);
List<Element> imports = root.getChildren("import");
for (int i = 0; i < imports.size(); i++) {
Element element = imports.get(i);
List<Content> importContent = parseImport(element, root, buildFile);
int replaceIndex = root.indexOf(element);
root.addContent(replaceIndex, importContent);
root.removeContent(element);
}
root.removeChildren("import");
return root;
}
/**
* Get the imported file and merge it into the parent.
*/
private List<Content> parseImport(Element element, Element currentRoot,
File buildFile) throws JDOMException, IOException {
String importFileName = element.getAttributeValue("file");
File importFile = new File(buildFile.getParentFile(), importFileName)
.getAbsoluteFile();
if (importFileName != null) {
Element importRoot = getRootElement(importFile);
return getImportContent(element, currentRoot, importRoot,
importFile);
}
return Collections.emptyList();
}
/**
* Replace the passed element with the content of the importRoot
* (not the project tag)
*/
private List<Content> getImportContent(Element element,
Element currentRoot, Element importRoot, File buildFile)
throws JDOMException, IOException {
if (currentRoot != null) {
// copy all the reference import elements to the parent if needed
List<Content> childNodes = importRoot.cloneContent();
List<Content> importContent = new ArrayList<Content>();
for (Content content : childNodes) {
if (content instanceof Element
&& ((Element) content).getName().equals("import")) {
importContent.addAll(parseImport((Element) content,
currentRoot, buildFile));
}
if (!existsInParent(currentRoot, content)) {
importContent.add(content);
} else {
// TODO note the element was skipped
}
}
return importContent;
}
return Collections.emptyList();
}
/**
* Return true if the content already defined in the parent
*/
private boolean existsInParent(Element parent, Content content) {
if (content instanceof Text) {
if (((Text) content).getText().trim().length() == 0) {
// let the pretty printer deal with the whitespace
return false;
}
return true;
}
if (content instanceof Element) {
String id = ((Element) content).getAttributeValue("name");
String name = ((Element) content).getName();
List<Content> parentContent = parent.getChildren();
if (id != null) {
for (Content content2 : parentContent) {
if (content2 instanceof Element
&& ((Element) content2).getName().equals(name)) {
String parentId = ((Element) content2)
.getAttributeValue("name");
if (parentId != null && parentId.equals(id)) {
return true;
}
}
}
}
}
return false;
}
/**
* Parse the passed file.
*/
private Element getRootElement(File buildFile) throws JDOMException,
IOException {
SAXBuilder builder = new SAXBuilder();
builder.setValidation(false);
builder.setIgnoringElementContentWhitespace(true);
Document doc = builder.build(buildFile);
Element root = doc.getRootElement();
return root;
}
Eclipse的理解蚂蚁的文件。 你可以看到什么样的任务是在你的内心的build.xml可见。 它不会是相当您所要求的格式,但它可能满足您的需求。
我一直在写现在Ant构建脚本7-8年,但我真的不明白你正试图在这里实现什么。 也许是我,但我担心,即使你得到你的编译工作(我敢肯定,你也可以),几乎没有任何人会明白/维护它。
为什么不能让事情很简单,有兄弟项目?
root
build.xml
comp
build.xml
env
build.xml
version
build.xml
个人build.xml
文件可以导入任务定义别的地方(使用Macrodef本)和您的顶层build.xml
将依次调用个别?
一旦你的基本建成运行,可以玩的常春藤或Maven更有趣的东西。
但是,如果你真的想生成构建文件,你可以给Groovy和它的模板引擎一试。
我建议,让他们使用的依赖关系树是什么蚂蚁是真的好构建您的构建文件。 如果你关注@弗拉基米尔的意见,并组织你的构建文件一样,那么你可以在“根”一个构建文件,并让它递归执行你的构建。 例如:
<!-- iterate finds all build files, excluding this one
and invokes the named target
-->
<macrodef name="iterate">
<attribute name="target"/>
<sequential>
<subant target="@{target}">
<fileset dir="."
includes="**/build.xml"
excludes="build.xml"/>
</subant>
</sequential>
</macrodef>
<target name="build" description="Build all sub projects">
<iterate target="build"/>
</target>
<target name="clean" description="Clean all sub projects">
<iterate target="clean"/>
</target>
听起来gradle这个可以帮助你。 摇篮能够导入您的Ant build.xml文件 。 然后,你就可以开始试运行 ,以获得将要执行的目标清单。
你可以在Java中,Groovy中,红宝石写一个脚本/应用程序或任何你知道最好的...脚本将解析构建文件的XML和更换由真正换出适当的DOM节点“过度缠身”的目标与他们的覆盖。 你将最终获得您的复合build.xml文件作为然后可以连载了DOM。
你可以保持手头的剧本在你的源代码控制,使您可以根据需要重新生成。
这听起来可能有点极端,但它听起来像大多数其他解决方案都出来了,你在找什么范围。
注意:您可以在Ant中运行一些脚本LANGS,所以你仍然可以使用,并为您的引发剂。
祝好运。