2

我需要一些关于蚂蚁的帮助。我怎样才能让 ant 表现得与 ant 相似make -j <n>?请注意,我不是在构建 java,而是为专有语言调用外部编译器。

虽然有任务<parallel>(以及 的类似属性<for>),但它们似乎不支持依赖关系,或者更确切地说,我还没有找到一种方法来应用依赖关系。

但是,我在属性文件中确实有可用的依赖项,格式如下:

fileA=fileB fileC 
fileB=fileC

fileA/B/C 是我的目标文件的基本名称。

目前有大约 850 个文件要构建。使用<for>I 遍历此列表(通过消除依赖关系正确排序)来调用编译器。我已经被建议使用<sequential>,但这意味着将依赖项转换成块,<sequential>这有点糟糕。

关于如何使<for ... parallel="yes">循环尊重依赖关系的任何想法,或者关于如何解决这个问题的任何其他想法?

4

1 回答 1

0

我认为本机 Ant 中没有任何东西可以做到这一点,但这个示例是 Groovy 的GPars支持的“数据流并发”模型的绝对理想用例,因此您可以使用脚本任务执行某些操作:

<project name="gpars-test">
  <path id="groovy.path">
    <pathelement location="groovy-all-1.8.8.jar" />
    <pathelement location="gpars-0.12.jar" />
  </path>

  <!-- Target to build one file - expects a property "filetobuild"
       containing the name of the file to build -->
  <target name="buildOneFile">
    <echo>Imagine I just built ${filetobuild}...</echo>
  </target>

  <target name="main">
    <script language="groovy" classpathref="groovy.path"><![CDATA[
      import static groovyx.gpars.dataflow.Dataflow.task
      import groovyx.gpars.dataflow.Dataflows

      // load dependencies
      def deps = new Properties()
      new File(basedir, 'dependencies.properties').withInputStream {
        deps.load(it)
      }

      def df = new Dataflows()
      // spawn one "task" per file to be compiled
      deps.each { file, dependencies ->
        task {
          if(dependencies) {
            // wait for dependencies - reading df.something will suspend
            // this task until another task has written the same variable
            dependencies.split(/ /).each { dep ->
              def dummy = df."${dep}"
            }
          }

          // now we know all our dependencies are done, call out to build
          // this one.    
          def compiler = project.createTask('antcall')
          compiler.target = "buildOneFile"
          def prop = compiler.createParam()
          prop.name = "filetobuild"
          prop.value = file
          try {
              compiler.perform()
          } catch(Exception e) {
              // do something
          } finally {
              // we're done - this will release any other tasks that are blocked
              // depending on us
              df."${file}" = "done"
          }
        }
      }

      // now wait for all tasks to complete
      deps.each { file, dependencies ->
        def dummy = df."${file}"
      }
      println "finished"
    ]]></script>
  </target>
</project>

请注意,这确实假设您要构建的所有文件都列在依赖项文件中,包括那些没有依赖项的文件,即

fileA=fileB fileC 
fileB=fileC
fileC=

如果 no-deps 文件名未在属性中列出,那么您将不得不做更多的摆弄才能将它们放在那里 - 就在def df = new Dataflows()您需要添加一些内容之前

deps.values().collect().each { depString ->
  depString.split(/ /).each {
    // if we find a fileX that something depends on but which does not
    // itself appear in the deps map, assume it has no dependencies
    if(!deps.containsKey(it)) {
      deps.setProperty(it, "")
    }
  }
}
于 2012-11-29T13:47:52.617 回答