Ant: Using a fileset with the javac task

I want to use a FileSet to indicate exactly which files I want compiled with the Javac task. I don't want any implicit behavior. My attempts at this have failed however. Here's what I've got so far:

A FileSet that contains all my source files.

<fileset id="srcfiles" dir="${srcdir}">
    <include name="**/*.java"/>
</fileset>

And a target that tries to pass it to javac.

<target name="build">
    <javac srcdir=".">
        <fileset refid="srcfiles"/>
    </javac>
</target>

This gives me this error: javac doesn't support the nested "fileset" element.

After reading the Ant docs, I tried changing the inner most tag from fileset to sourcepath . This worked in the sense that the files were compiled, but it still errored out: srcfiles doesn't denote a path . I think the source was only compiled due to implicit rules.

How can I tell javac explicitly which individual files I want compiled? Or is this simply not how Ant is supposed to work? I come from a C++ background where identifying source files is a significant part of the build process. However, given Java's file naming and directory structure requirements, perhaps the implicit **/*.java pattern rule covers all use cases.


The ant manual for javac says :

If you wish to compile only files explicitly specified and disable javac's default searching mechanism then you can unset the sourcepath attribute:

<javac sourcepath="" srcdir="${src}"
       destdir="${build}" >
    <include name="**/*.java"/>
    <exclude name="**/Example.java"/>
</javac>

I don't think it's a good idea, though. In a well-designed project, all the files in a given directory (or in a set of directories) should be compiled. The files which shouldn't be compiled shouldn't be there at all, or should be in a separate directory.


What do you want ? Compile all *.java code from single directory ? Or just compile one file ?

If you want to compile your all java source code ? Then you must define where your source code file located, and then you must define where your build directory located. This build directory is for *.class file after you compile your java code.

The easy way is, first you must create one file which is build.properties At this file, you can define where your source code directory, where your build dir, etc. This is simple example of build.properties file

# Source Code Properties ---------------------------
project.dir=.
src.dir=${folder.project}/src
dist.dir=${folder.project}/dist
build.dir=${folder.project}/build
test.dir=${folder.project}/testing

And then, in your build.xml file you can compile your java code like this :

<!-- define build.properties file -->
<property file="build.properties" />

<target name="compile" description="Compile all java code from src dir">
    <javac  srcdir="${src.dir}" 
            destdir="${build.dir}" 
     />
</target>

With this ant task, you can compile all your java code in src directory to build directory.


Thinking in C/C++ terms is futile in that case. In C/C++ you have usually a Makefile where you list all your files to compile and each *.c or *.cc file is -from the viewpoint of the compiler - independent of each other.

Quite the opposite is true for Java: If would give only one file to the Java compiler and this class references something else, then the compiler wants to see that 'else' in binary form. The compiler will try three things:

  • Is that 'else' in some library in the classpath - if so that thing is used because it has been compiled already
  • Is that 'else' in the destination path of the compiler - it might have been compiled already from source so simply take it
  • Is that 'else' something where a source file can be found in the compiler's sourcepath - if so, then compile that first and then go back to the real task.
  • This is a little bit simplified but shows already most of the points where C/C++ is just to different:

  • Sourcefiles are not independent of each other.
  • The compiler might want compile more things than you can guess as a novice.
  • Much of that automagic stuff works only because/if the compiler can guess a mapping between .class files and .java files.
  • In Java there are not many arguments for the compiler. And all these settings apply to each source file. In C/C++ on the other hand you can have several kilobytes of define arguments, optimization settings and so on - perhaps different for each source file.
  • A Java developer doesn't want to micromanage a Java compiler - he wants to compile all files in a source directory.
  • A Java developer doesn't want to work out the exact and formal dependencies between source files - a machine is better at a task like that.
  • This all boils down to the way Ant and Maven and any decent build system in Java works: Compile complete source directories. So yes, that's the way Ant want to work.

    链接地址: http://www.djcxy.com/p/60374.html

    上一篇: macrodef'd <jar>任务的行为不像隐式文件集?

    下一篇: Ant:通过javac任务使用文件集