1

我有一个项目,我已经工作了几天,我终于把它编译干净了。但是,同一远程分支的 git clone(在同一台机器上,在同一终端实例中编译)导致编译错误。另一台机器上的新克隆有同样的错误。我认为这是我的工作目录有一些额外的未跟踪文件的问题,但我删除了所有未跟踪的文件,以至于diff除了 .git 文件夹中包含的内容之外,这些目录是相同的。我什至检查了权限tree并将生成的文件与它们进行了比较meld——它们基本上是相同的,尽管一些源文件的执行权限略有不同。

该错误来自我在 maven-compiler-plugin 中排除的文件。这本质上应该意味着文件名永远不会传递给 javac,尽管我不知道它到底是如何工作的。我意识到如果编译器内部的代码出错,编译器显然会从某个地方获取文件。在我的计算机上可以运行的一个目录中,没有错误并且可以完美编译。在 repo 的其他克隆上(根据 ,它们再次相同diff),它在这个(排除的)文件上给出了一个错误。

额外的实验表明,在git clone远程分支、cp -R本地目录或本地目录的新分支git clone上,编译失败。但是,如果我使用该--archive选项执行 cp,则结果目录中的编译成功。我将其缩小到--preserve=timestamps标志(由于与--archive相同而启用-dR --preserve=all)。如果你没听清楚,我会再说一遍。

当我正常复制目录时,它拒绝正确编译。只有当时间戳被保留时,它的行为才会与原始目录相同。

我不明白这一点 - 为什么 java 编译器(或 maven)关心时间戳?

4

1 回答 1

1

问题最终是一个 Maven 编译器插件问题,再加上我试图做一些有点被误导的事情。

简而言之,编译器插件会传入您要编译的每个文件的列表以及指向源目录的链接。

文件列表非常好,因为这是 javac 知道要编译哪些东西的方式。但是,源目录也被传递的事实并不理想。当您将文件(或模式)放入 maven 编译器插件的<excludes>标签时,它将不再显示在传递给 javac 的文件列表中。但是,它很可能驻留在您的源目录中(maven 传递给 javac)。这意味着如果 javac 愿意,它仍然可以编译这些文件,即使您排除了它们。如果其中一个文件是另一个文件的依赖项,则可能会发生这种情况。这里的预期行为将是抛出一个错误 - 相反,它编译排除的文件并继续其愉快的方式。

在我的情况下(正如我在评论中解释的那样)我遇到了问题,因为一个被明确排除的文件(原因:maven 处理类路径的方式中的一个不相关的错误意味着 maven 无法正确编译文件)仍在尝试编译,即使我试图提供该类的预编译版本。

在这种情况下,如果我复制了没有保留时间戳的文件,它会认为源文件最近已被修改,并且该类的预编译版本已过时。因此 javac 试图编译排除的文件。只有当我保留了时间戳(这表明文件在几个月内没有被修改)时,javac 才意识到它应该使用提供的 .class 文件。

于 2012-07-26T21:45:27.127 回答