1

I have a project that I have been working on for a few days and I finally got it to compile cleanly. However, a git clone of the same remote branch (on the same machine, compiled in the same terminal instance) caused a compilation error. A fresh clone on a different machine had the same error. I figured it was an issue with my working directory having some additional untracked files, but I deleted all untracked files to the point where diff says the directories are identical except for things contained in the .git folder. I even checked permissions with tree and compared the resulting files with meld - they were basically identical, although a few source files had slightly different execution permissions.

The error was one that came from a file which I had excluded in the maven-compiler-plugin. This should essentially mean that the filename is never passed to javac, although I don't know exactly how it works under the hood. I realize that clearly the compiler is getting the file from somewhere if it is erroring on code inside it. In the one directory on my computer which worked, there are no errors and it compiles perfectly. On the other clones of the repo (which are, again, identical according to diff) it gives an error on this (excluded) file.

Additional experimentation showed that on a fresh git clone of the remote branch, a cp -R of the local directory, or a git clone of the local directory, compile failed. However, if I did a cp with the --archive option, the compile in the resulting directory succeeded. I narrowed it down to the --preserve=timestamps flag (which is enabled due to the fact that --archive is the same as -dR --preserve=all). If you didn't quite catch that, I'll say it again.

When I copy the directory normally, it refuses to compile properly. Only when the timestamps are preserved does it behave identically to the original directory.

I don't understand this - why does the java compiler (or maven) care about the timestamps?

matt5784
  • 3,065
  • 2
  • 24
  • 42
  • 3
    Ant/Maven (like "make" in non-Java environments) depend on the timestamps to determine whether or not a file is "out of date" and needs to be recompiled. Q: Is the only problem that "stuff is getting rebuilt"? Or is there another, more serious problem behind your question? Q: What exactly *is* the problem? – paulsm4 Jul 05 '12 at 21:09
  • I have an exclude in the configuration of the maven-compiler-plugin. In the directories which work, the exclude appears to work. In the directories which don't, the exclude also APPEARS to work (says it is compiling same number of source folders, the -sourcepath argument of javac has the same number of file arguments and does NOT include the bad file) but it gives me a compilation error on the excluded file. – matt5784 Jul 05 '12 at 21:11
  • Why do you have files which should not be compiled in your folders? Simply remove them, cause they can restored via VCS. Are you using the src/main/java defaults of Maven? – khmarbaise Jul 06 '12 at 07:42
  • BTW: Have you done a mvn clean package? Which version of the compiler plugin do you use? – khmarbaise Jul 06 '12 at 07:57
  • Yes, of course. I did about a hundred `mvn clean; mvn package` throughout the process, I think. I tested on both 2.4 and 2.5 of the plugin. The files DO need to be compiled, but due to an unrelated bug maven is incapable of doing it properly (see http://stackoverflow.com/questions/11250352/base-java-classes-still-in-the-classpath-during-maven-android-build ) so I am having to implement one of a few pretty terrible workarounds to get a correct compile. Not using src/main/java, still have `/src/com/example...` (tests are elsewhere). In the process of migrating this from ant to maven. – matt5784 Jul 06 '12 at 14:04

1 Answers1

1

The problem ended up being a Maven compiler plugin issue combined with the fact that I was trying to do something which was somewhat misguided.

Briefly, the compiler plugin passes in a list of every file you want to compile as well as a link to the source directory.

The list of files is perfectly fine, as this is how javac knows which things to compile. However, the fact that the source directory is also being passed is not ideal. When you put a file (or pattern) into the maven compiler plugin's <excludes> tag, it will no longer show up in the list of files passed to javac. However, it will most likely reside in your source directory (which maven passes to javac). This means that javac can still compile these files if it wants to, even though you excluded them. This may occur if one of the files is a dependency of another. The expected behavior here would be to throw an error - instead, it compiles the excluded file and continues on its merry way.

In my situation (as I explained in the comments) I was having issues because a file which was explicitly excluded (reason: an unrelated bug in the way maven handles classpaths means that file cannot be compiled properly by maven) was still trying to be compiled, even though I was trying to provide a pre-compiled version of the class.

In this case, if I copied the files without timestamps being preserved it thought the source files had been modified recently, and that the precompiled version of the class was out of date. Therefore javac tried to compile the excluded file. Only when I preserved the timestamps (which showed that the file had not been modified in months) did javac realize it should use the provided .class file instead.

matt5784
  • 3,065
  • 2
  • 24
  • 42
  • Alternatively, don't have files in your source path that should never be compiled. – Paŭlo Ebermann Apr 11 '13 at 20:48
  • What if I have various build targets and sometimes I want to build certain parts, but sometimes I want to build other parts? There are plenty of situations where you could easily have code in your source path that you don't want to compile, at least at times. I'm detailing a problem with a feature of a system and your solution is "Don't use that feature." That's neither constructive nor helpful. – matt5784 Apr 16 '13 at 23:08