我有以下项目结构:

root/
    comp/
        env/
           version/
                  build.xml
           build.xml
        build.xml

root / comp / env / version / 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>

root / 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>

root / comp / build.xml是:

<project name="comp" basedir=".">
    <echo>Comp tasks</echo>
</project>

每个构建文件都会导入父构建文件,每个子项都会继承覆盖父任务/属性。

我需要的是获得生成的构建XML而不运行任何东西

例如,如果我在root / comp / env / version /上运行“ant”(或类似的东西),我想得到以下输出:

<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? 如果没有,我有什么选择?

编辑: 我需要像Ant的“mvn help:effective-pom”之类的东西。

#1楼 票数:5

根据导入任务的描述,它非常像实体包含两个附加功能:

  • 目标覆盖
  • 特殊属性

为了查看“有效构建”,我不认为需要特殊属性处理(尽管可以通过迭代插入的目标来添加它)。 所以实现这一目标的过程就变成了。

  1. 将build.xml解析为DOM
    • 对于找到的每个顶级包含标记(仅允许顶级),找到引用的源文件。
    • 解析引用的build.xml
    • 插入引用的build.xml中不会与当前文件中的内容冲突的任何内容。
    • 对引用的build.xml文件重复步骤2,直到找不到为止
    • 输出结果DOM

您可以定义自定义Ant任务,以便可以在要在构建中运行的任务中定义此处理。 有关详细信息,请参阅本教程

这是一个基本实现,它通过导入进行递归并从引用的文件中插入DOM元素。 当我把它扔在一起时,几乎肯定会有一些错误,但它应该在很大程度上完成你所追求的:

/**
 * 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;
}

#2楼 票数:0

Eclipse了解Ant文件。 您可以看到内部build.xml中可见的任务。 它不是您要求的格式,但它可能满足您的需求。

#3楼 票数:0

我已经编写了7到8年的Ant构建脚本,但我真的不明白你想要在这里实现什么。 也许是我,但我担心,即使你让你的构建工作(我相信你可以),几乎没有其他人会理解/维护它。

为什么不保持简单和兄弟项目?

root
    build.xml
    comp
        build.xml
    env
        build.xml
    version
        build.xml

单个build.xml文件可以在其他地方导入任务定义(使用Macrodef),你的顶级build.xml会按顺序调用各个?

一旦你的基本版本运行,你可以玩Ivy或Maven来获得更多有趣的东西。

但是如果你真的想生成构建文件,你可以尝试使用Groovy及其模板引擎。

#4楼 票数:0

我建议构建你的构建文件,以便它们使用依赖树,这是蚂蚁真正擅长的。 如果您遵循@ Vladimir的建议并构建类似的构建文件,那么您可以在“root”中拥有一个构建文件,并以递归方式执行构建。 例如:

<!-- 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>

#5楼 票数:0

听起来像gradle可以帮助你。 Gradle能够导入您的ant build.xml文件 然后你可以开始一个干运行来获得要执行的目标列表。

#6楼 票数:0

您可以用Java,Groovy,Ruby或者您最熟悉的任何内容编写脚本/应用程序...脚本将解析构建文件的xml,并通过实际交换相应的DOM节点来替换“over-ridden”目标及其覆盖。 你最终得到的是你的复合build.xml作为一个DOM,然后可以序列化。

您可以在源代码管理中保留脚本,以便您可以根据需要进行重新生成。

这可能听起来有点极端,但听起来大多数其他解决方案都超出了您的需求范围。

注意:您可以从Ant运行一些脚本lang,因此您仍然可以使用And作为启动器。

祝好运。

  ask by inakiabt translate from so

未解决问题?本站智能推荐:

2回复

如何用ant构建jar文件?

根据培训任务,我需要使用ant创建.jar文件。 src的普通类的程序集没有问题。 但是我在项目中存在logger ,他的libraries和.properties文件。 因此,错误飞出: 和 我有build.xml 和这个结构 如何以及在何处将 Java 文件中的库和属性收集
2回复

简单的Java Ant构建问题

对Ant来说是全新的,我只有一个简单的问题。 我运行蚂蚁与一个输入文件: ant -Dargs="input.txt" run ,但它说,它无法找到input.txt (没有这样的文件或目录)。 我在src和bin上方的同一目录中有build.xml文件和input.txt 。 这是我的b
2回复

Ant /构建JAR:构建失败,找不到参考task.path

我正在使用build.xml生成JAR文件的项目。 当我尝试构建它时,出现以下错误: 生成文件:D:\\ xxxxx \\ trunk \\ project-java \\ build.xml 建立失败D:\\ xxxxxtrunk \\ project-java \\ bu
1回复

需要向我的ant版本build.xml添加参数

当前,我正在使用jenkins运行build.xml和ant版本以生成.apk 我需要将参数传递给ant版本(ant release -Dcustompackagename='com.google.android.projection.kitchensink' )并生成第二个apk。
3回复

ant build Oxygen Dita-Ot中的Java类路径错误

嗨,即使包含jdk路径位置,我也收到此错误。 其显示 cmd代码生成了这个 类路径或集成器xml文件有问题吗? 我遵循了氧气分析网站和书中给出的步骤。 我认为问题在于本节 我的集成商的行号(44,66)对此说,我无法理解。
1回复

在使用ant build.xml进行编译时,如何在没有JDK库的情况下使用外部库

我的程序以前使用过JDK 1.4。 现在我想用1.6来编译它。 它已经成功地针对1.4进行了编译,但是当我将JDK更改为1.6时,出现了以下编译错误。 但是我的类路径中有jaxb-libs-jwsdp-1.6 jar,其中包含带有上述构造函数的StartTagInfo类。 如果有人
1回复

我如何使用从 xml 文件中获取匹配的字符串使用ant标记并替换其他xml文件中匹配的字符串

我的要求是匹配 data.xml 文件中的以下标签并使用 in ant 替换 display.xml 文件中的内容 我需要匹配 data.xml 文件中的内容并替换 display.xml 文件中的内容。 我的最终输出应该是这样的: 我该如何解决这个问题? 提前致谢
2回复

Apache Ant安装Windows 7

当我在命令行上执行ant -version时,它说未识别。 有关如何解决的任何想法? 我正在尝试为Java项目制作build.xml。