为什么没有人使用make for Java?

Use*_*er1 154 java ant makefile maven

几乎我见过的每个Java项目都使用Maven或Ant.它们是很好的工具,我认为任何项目都可以使用它们.但是,什么都发生在使?它用于各种非Java项目,可以轻松处理Java.当然,如果你使用Windows,你必须下载make.exe,但是Ant和Maven也没有随JDK一起提供.

与Java一起使用时,make有一些基本缺陷吗?是不是因为Ant和Maven是用Java编写的?

Wil*_*ung 183

Make和Java的基本问题是,Make的前提是您已指定依赖项,然后是规则来解决该依赖项.

使用基本C,通常"将main.c文件转换为main.o文件,运行"cc main.c".

你可以在java中做到这一点,但你很快就能学到一些东西.

大多数情况下,javac编译器启动缓慢.

和...之间的不同:

javac Main.java
javac This.java
javac That.java
javac Other.java
Run Code Online (Sandbox Code Playgroud)

javac Main.java This.java That.java Other.java
Run Code Online (Sandbox Code Playgroud)

是白天和黑夜.

加剧了数百个课程,而且它变得难以为继.

然后你将它与java倾向于组织为目录中的文件组,而C和其他倾向于更平坦结构的事实相结合.Make对使用文件层次结构没有太多直接支持.

Make也不是很擅长在收集级别确定哪些文件已过期.

使用Ant,它将遍历并总结所有过时的文件,然后一次编译它们.Make将简单地在每个单独的文件上调用java编译器.如果没有这样做需要足够的外部工具来真正显示Make不能完成任务.

这就是Ant和Maven等替代品升级的原因.

  • 我喜欢这个.你必须说Ant需要解决javac太慢的事实. (30认同)
  • 不可以.如果您使用它,Javac并不慢,因为它被设计为使用.如果你一次使用它来编译一个文件,那就太慢了. (24认同)
  • @Casey javac并不太慢.JVM启动速度太慢. (7认同)
  • 因此,为了在庞大的Java项目中使用make,有必要维护所有已更改的.java文件的列表,然后在最后调用javac?这对我来说听起来不太理想.这是迄今为止我见过的最佳答案. (6认同)
  • GNU请至少有[`$?`自动变量(https://www.gnu.org/software/make/manual/make.html#Automatic-Variables),它扩展为"是较新的所有先决条件目标".还有的特征[图案与多个目标规则(https://www.gnu.org/software/make/manual/make.html#Pattern-Intro),这将运行配方一次更新所有的` .class`文件.再加上一些聪明的使用文件/文本功能,如`$(通配符)`,`$(壳)`,`$(EVAL)`,你可以教你的makefile发现建立散落在你的目录布局的目标. (6认同)
  • 这个答案是对的.请注意,如果使用nailgun来保持jvm正常运行,则可以使用make,从而降低性能. (2认同)
  • 此外,内部/匿名类会生成`SomeClass$1.class` 文件,并且它们可以快速累加。他们不可能使用 Make 进行跟踪。 (2认同)

Gre*_*ill 32

古老的make程序可以很好地处理C和C++等单独编译的语言.编译模块,它用于#include引入其他包含文件的文本,并将单个目标文件写为输出.编译器是一个一次一个系统,具有单独的链接步骤以将目标文件绑定到可执行二进制文件中.

但是,在Java中,编译器必须实际编译您导入的其他类import.尽管可以编写一些从Java源代码生成所有必需依赖项的东西,make以便一次一个地以正确的顺序构建类,但这仍然不能处理诸如循环依赖项之类的情况.

通过缓存其他类的编译结果,同时编译依赖于已编译的结果的其他类,Java编译器也可以更高效.make单独使用这种自动依赖性评估实际上是不可能的.

  • 这似乎更像是一个制作与javac的答案,而不是制作与蚂蚁/主人的答案.基于你的答案,为什么有人不能只使用make + javac(一次给javac一个完整的包或"模块",所以循环依赖从make中隐藏)?蚂蚁或专家会为这种方法提供任何好处吗? (7认同)
  • 此外,这仍然无法解释为什么我会使用Ant或Maven而不仅仅是直接的javac ...... (4认同)

Han*_*Gay 28

问题是基于一个不正确的假设:一个非常微不足道的开发人员确实使用了make.请参阅Java构建工具:Ant与Maven.至于为什么开发人员不会使用make:许多开发人员要么从未使用过make,要么使用过它并且用火烧得比一千个太阳更热.因此,他们使用替代工具.

  • 我们使用它,火比一千零一个太阳更热. (9认同)
  • @ User1`make`有许多在编写时可能有意义的"功能",但现在更像是bug,例如,你必须在某些地方使用TAB字符,而不是空格.这种事情可能并没有打扰那些真正体验过"制造"的人,但却让我们其他人疯狂. (5认同)
  • @reccles:它只是对构建工程的仇恨还是自己制造?Ant,Maven或其他什么会更好(即为它的类制作一个坏工具)? (4认同)
  • @HankGuy:让你的编辑担心这个细节.如果您的编辑器无法正确处理选项卡< - >空间设置,请获取一个新的编辑器,您会更高兴.但是你说对了许多功能已经过时,就像动态依赖关系的处理方式一样(`make depend` any?) (4认同)
  • @ User1这是我们正在建设的项目的规模.我们有一名全职员工维护make文件并构建依赖项.使用maven后我发现它更易于管理.现在说maven也不完美.没有什么比试图弄清楚需要什么XML设置来进行与规定设置略有不同的构建更令人愤怒的了. (3认同)
  • @HankGay,D.Shawleys评论仍然有效.显然,您的编辑器不知道源文件和Make文件之间的区别.其他编辑处理这个正确的,例如Vim.它默认配置如此,所以你永远不必考虑它. (2认同)

use*_*840 22

实际上,make可以在所有过时的java文件的一个命令中处理重新编译.如果您不想编译目录中的所有文件或想要特定订单,请更改第一行...

JAVA_FILES:=$(wildcard *.java)
#
# the rest is independent of the directory
#
JAVA_CLASSES:=$(patsubst %.java,%.class,$(JAVA_FILES))

.PHONY: classes
LIST:=

classes: $(JAVA_CLASSES)
        if [ ! -z "$(LIST)" ] ; then \
                javac $(LIST) ; \
        fi

$(JAVA_CLASSES) : %.class : %.java
        $(eval LIST+=$$<)
Run Code Online (Sandbox Code Playgroud)

  • 真好!我一直在寻找类似的东西。当通用经典版正常工作时,无需为每种语言使用不同的构建工具。谢谢! (2认同)

Dan*_*ark 17

关于每个技术优点的所有其他答案都是正确的.Ant并且Maven可能比Java更适合Java,或者正如Hank Gay指出的那样,他们可能不会:)

但是,你问过Ant和Maven是用Java编写的.虽然在StackOverflow上我们不考虑这样的想法(关闭!与编程无关!等等),当然是其中的一部分.在rails上我们使用Rake,C dudes使用make,在Java中我们使用Ant和Maven.虽然Ant或Maven开发人员可能会比其他开发人员更好地照顾Java开发人员,但还有另一个问题:你在什么时候编写Ant任务?Java的.如果您是Java开发人员,那很容易.

所以,是的,部分原因是使用以您正在使用的语言编写的工具.

  • Ant也出现在Java社区迷恋XML的时候.(这并不是说XML没有地位.) (7认同)
  • @Laurence Gonsalves,这是真的.但是,请不要在这里谈论fads :)我当时正在教Java dev,而且一切都是XML.现在它仍然是XML,但没有人关心. (3认同)
  • @D.Shawley,关于`make`和小型Unix utils都是如此.GIT也是这个过程的孩子.就个人而言,我不会说这不是更好.但对于Java程序员来说,这是一个巨大的范式转变.Ant更符合Java的思维方式. (2认同)

Osc*_*Ryz 12

Ant和后来的Maven旨在解决由Make(在创建过程中创建新的)引起的一些麻烦.它只是进化.

...此后不久,一些开源Java项目意识到Ant可以解决他们使用Makefiles时遇到的问题....

来自http://ant.apache.org/faq.html#history

他们是解决任何问题还是只是创建一个额外的格式来学习是一个主观的话题.事实是,这几乎是每一项新发明的历史:创造者说它解决了很多问题,原始用户说这些都是美德.

它的主要优点是可以与java集成.

我想例如类似的历史rake.

  • 那不是很具体.Maven解决了由make引起的头痛问题? (4认同)
  • [参考你的答案编辑,而不是你最近的评论]这仍然没有解释什么问题得到解决,只有创作者蚂蚁声称问题已经解决了......: - /我的印象是Ant最初创建的是Make的简单替代品.随着时间的推移,人们发现有些东西丢失了,所以他们添加了功能,直到Ant变得像make一样复杂,但内置了binutils(很大程度上依赖于外部工具,如cp,rm等),以及当然有XML语法. (2认同)
  • 是的,但是当一个新的替代方案的创造者能做的最好的时候就是说"这解决了老问题的问题"而没有真正说出那些对那些考虑使用哪个选项的人来说不那么有用的问题.Ant是否解决了问题*我在make中遇到了问题,还是解决了我在为我引入新问题时不认为是问题的问题? (2认同)

Oph*_*ian 9

Maven(和Ivy-enabled Ant设置)在make上解决的主要问题之一是自动依赖解析和下载依赖项jar.


Slu*_*ler 8

简短的回答:因为make不好。即使在 C 方面,您也会看到许多替代品出现。

长答案:make有几个缺陷使它几乎不适合编译 C,而且根本不适合编译 Java。如果需要,您可以强制它编译 Java,但预计会遇到问题,其中一些没有合适的解决方案或变通方法。以下是一些:

依赖解析

make固有地期望文件彼此之间具有树状依赖关系,其中一个文件是构建其他几个文件的输出。在处理头文件时,这在 C 中已经适得其反。make需要make生成一个特定的包含文件来表示 C 文件对其头文件的依赖关系,因此对后者的更改将导致重新构建之前的文件。但是,由于 C 文件本身不会重新创建(只是重新构建),因此 make 通常需要将目标指定为.PHONY. 幸运的是,GCC 支持自动生成这些文件。

在 Java 中,依赖可以是循环的,并且没有用于自动生成make格式类依赖的工具。相反,它antDepend任务可以直接读取类文件,确定它导入哪些类,如果其中任何一个类文件已过期,则删除该类文件。没有这个,任何非平凡的依赖都可能导致您被迫使用重复的干净构建,从而消除使用构建工具的任何优势。

文件名中的空格

虽然 Java 和 C 都不鼓励在源代码文件名中使用空格,但make即使空格在文件路径中,这也可能是问题。例如,考虑一下您的源代码是否存在于C:\My Documents\My Code\program\src. 这足以打破make。这是因为make将文件名视为字符串。ant将路径视为特殊对象。

扫描文件以进行构建

make需要明确设置为每个目标构建哪些文件。ant允许指定要自动扫描源文件的文件夹。这似乎是一个次要的便利,但考虑到在 Java 中每个新类都需要一个新文件。将文件添加到项目可能会很快成为一个大麻烦。

最大的问题是make

make 依赖于 POSIX

Java 的座右铭是“一次编译,到处运行”。但是,将编译限制在基于 POSIX 的系统上,其中 Java 支持实际上是最差的,并不是我们的意图。

构建规则make本质上是小bash脚本。即使有makeWindows的端口,为了使其正常工作,它也必须与 的端口捆绑在一起bash,其中包括文件系统的 POSIX 仿真层。

这有两种:

  1. MSYS 它试图将 POSIX 转换限制为文件路径,因此在运行不是专门为它设计的外部工具时可能会遇到令人不快的问题。

  2. cygwin它提供了完整的 POSIX 仿真。然而,由此产生的程序往往仍然依赖于该仿真层。

出于这个原因,在 Windows 上,标准构建工具甚至根本不是make,而是MSBuild,它也是一个基于 XML 的工具,原则上更接近于ant.

相比之下,它ant是用 Java 构建的,可以在任何地方运行,并包含称为“任务”的内部工具,用于以独立于平台的方式操作文件和执行命令。它的用途非常广泛,实际上ant与使用make.

还有最后一个小问题:

甚至 C 程序本身也不使用 make

您最初可能没有注意到这一点,但 C 程序通常不附带Makefile. 它们附带一个CMakeLists.txt,或一个bash配置脚本,它生成实际的Makefile. 相比之下,使用构建的 Java 程序的源代码ant附带了一个ant预构建的脚本。AMakefile是其他工具的产物 - 这就是make它本身不适合作为构建工具的程度。ant是独立的,可以处理 Java 构建过程所需的一切,没有任何额外的要求或依赖项。

当您ant在任何平台上运行时,它都可以正常工作(tm)。你不能用make. 它非常依赖平台和配置。


Dav*_*lia 6

我认为最可能的解释是,在关键时期(20世纪90年代末),有几个因素阻碍了Java社区中make的使用:

  1. 由于Java包含多个平台,因此Java程序员通常不像Unix程序员那样擅长Unix程序员(例如,C和Perl程序员).请注意,这是一般情况.毫无疑问,有一些有天赋的Java程序员对Unix有着深刻的理解.
  2. 因此,他们不太擅长制作,也不知道如何有效地使用制作.
  3. 虽然可以编写一个简单而简单的Makefile来有效地编译Java,但是需要特别注意以独立于平台的方式这样做.
  4. 因此,人们对本质上独立于平台的构建工具产生了兴趣.
  5. 正是在这种环境中创建了Ant和后来的Maven.

简而言之,虽然make肯定可以用于Java项目,但是有一个机会使它成为事实上的Java构建工具.那一刻过去了.


mik*_*yra 6

除非我不是任何人,否则假设没有人(错误)使用 make for java 是错误的。

“使用 GNU Make 管理项目”(在 GFDL 下可用)包含一个完整的章节,专门用于make与 java 项目一起使用。

因为它包含了一个很长的(希望是公平的)使用 make 而不是其他工具的利弊列表,你可能想看看那里。(见:http : //oreilly.com/catalog/make3/book/


Bri*_*Fox 5

使脚本往往具有固有的平台依赖性.Java应该是独立于平台的.因此,拥有仅适用于多平台源库的一个平台的构建系统是一个问题.