我见过的几乎每个Java项目都使用Maven或Ant。它们是很好的工具,我认为几乎任何项目都可以使用它们。但是,什么都发生在使?它用于各种非Java项目,并且可以轻松处理Java。当然,如果使用Windows,则必须下载make.exe,但JDK并未随附Ant和Maven。
与Java一起使用时,make是否存在一些基本缺陷?仅仅是因为Ant和Maven是用Java编写的吗?
我见过的几乎每个Java项目都使用Maven或Ant。它们是很好的工具,我认为几乎任何项目都可以使用它们。但是,什么都发生在使?它用于各种非Java项目,并且可以轻松处理Java。当然,如果使用Windows,则必须下载make.exe,但JDK并未随附Ant和Maven。
与Java一起使用时,make是否存在一些基本缺陷?仅仅是因为Ant和Maven是用Java编写的吗?
Answers:
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
和
javac Main.java This.java That.java Other.java
是白天和黑夜。
数百种课程加剧了这一点,并且变得站不住脚。
然后,您将其与以下事实结合起来:java倾向于以目录中的文件组的形式进行组织,而C和其他趋于更扁平化的文件则更是如此。Make对使用文件层次结构没有太多直接支持。
在收集级别,Make也不很擅长确定哪些文件已过期。
使用Ant,它将检查并汇总所有过时的文件,然后一次性编译它们。Make将仅在每个文件上调用Java编译器。使make不执行此操作需要足够的外部工具才能真正表明Make不能完全胜任该任务。
这就是为什么诸如Ant和Maven之类的替代产品兴起的原因。
$?
自动变量,该变量扩展为“比目标更新的所有先决条件”。模式规则还具有多个目标的功能,这些目标仅运行一次配方即可更新所有.class
文件。将其与文件,文本功能(如$(wildcard)
,)的一些巧妙用法结合使用$(shell)
,$(eval)
您可以教会makefile查找分散在目录布局中的构建目标。
这个古老的make
程序可以很好地处理C和C ++等单独编译的语言。您编译一个模块,该模块#include
用于提取其他包含文件的文本,并写入单个目标文件作为输出。编译器是一个一次性的系统,具有单独的链接步骤,用于将目标文件绑定到可执行二进制文件中。
但是,在Java中,编译器必须实际编译使用导入的其他类import
。尽管可以编写一些东西来从Java源代码生成所有必要的依赖关系,因此make
可以一次以正确的顺序构建类,但这仍然无法处理诸如循环依赖关系之类的情况。
Java编译器还可以通过缓存其他类的编译结果,同时编译依赖于已编译类结果的其他类来提高效率。make
单独使用这种自动依赖关系评估实际上是不可能的。
该问题基于错误的假设:大量开发人员确实使用make
。请参阅Java构建工具:Ant与Maven。至于为什么不使用make
开发人员:许多开发人员从未使用过make
,或者使用它并以燃烧超过一千个太阳的烈火来讨厌它。因此,他们使用替代工具。
make
具有许多“功能”,这些功能在编写时可能就很有意义了,但现在更像是错误,例如,您必须在某些位置使用TAB字符而不是空格。那种事情可能不会打扰那些真正有经验的人make
,但它会使我们其他人发疯。
make depend
有人吗?)
实际上,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+=$$<)
关于每种技术优点的所有其他答案都是正确的。Ant
并且Maven
可能比make更适合Java,或者正如Hank Gay指出的那样,它们可能不是:)
但是,您问过用Java编写Ant和Maven是否重要。尽管在StackOverflow上我们不考虑这样的想法(已关闭!与编程无关!等等),但是这当然是其中的一部分。在轨道上,我们使用Rake,C dudes使用make,在Java中,我们使用Ant和Maven。虽然Ant或Maven开发人员确实会比其他开发人员更好地照顾Java开发人员,但还有另一个问题:您在其中编写Ant任务是什么?Java。如果您是Java开发人员,那很容易。
是的,部分原因是使用以您使用的语言编写的工具。
make
来自UNIX背景,因此可以通过编写有用的紧凑型实用程序并将它们一起管道化来完成该工具。这就是为什么大多数拼接是使用Shell命令完成的原因。
make
小型Unix实用程序的所有说法都是对的。GIT也是该过程的孩子。就个人而言,我不会说这不是更好。但这对于Java程序员来说是一个巨大的范式转变。Ant与Java的思维方式更为一致。
蚂蚁和后来的Maven旨在解决某些头痛Make
(在此过程中创建新头痛),这只是进化。
不久之后,几个开源Java项目意识到Ant可以解决Makefiles所带来的问题。
来自http://ant.apache.org/faq.html#history
他们解决任何问题还是只是创建一种额外的学习格式都是一个主观的话题。事实是,这几乎是每一项新发明的历史:创造者说它解决了很多问题,而原始用户则说那是美德。
它的主要优点是可以与Java集成。
我想类似的历史也会 rake
。
我认为最可能的解释是,在关键时期(1990年代后期),有几个因素阻止了Java社区中对make的使用:
简而言之,尽管make最肯定可以用于Java项目,但仍有一点机会使其成为事实上的Java构建工具。那一刻过去了。
简短答案:因为 make
不好。即使在C前端,您也会看到许多替代选择。
长答案:make
有几个缺陷,使其几乎不适合编译C,而根本不适合编译Java。如果需要,可以强制它编译Java,但是会遇到问题,其中一些问题没有合适的解决方案或解决方法。这里有一些:
make
内在地希望文件之间具有树状的依赖关系,其中一个文件是构建多个其他文件的输出。在处理头文件时,这已经在C语言中适得其反。make
需要make
生成一个特定的包含文件来表示C文件对其头文件的依赖关系,因此对后者的更改将导致重建前文件。但是,由于C文件本身没有被重新创建(仅被重新构建),因此make经常需要将目标指定为.PHONY
。幸运的是,GCC支持自动生成这些文件。
在Java中,依赖性可以是循环的,并且没有用于自动生成make
格式的类依赖性的工具。ant
的Depend
任务可以直接读取类文件,确定要导入的类,并删除任何过期的类文件。否则,任何不重要的依赖关系都可能导致您被迫使用重复的干净构建,从而消除了使用构建工具的任何优势。
尽管Java和C都不鼓励在源代码文件名中使用空格,make
但是即使空格位于文件路径中,也会出现问题。例如,考虑您的源代码是否存在于中C:\My Documents\My Code\program\src
。这足以打破make
。这是因为make
将文件名视为字符串。ant
将路径视为特殊对象。
make
需要明确设置要为每个目标构建的文件。ant
允许指定要自动扫描源文件的文件夹。看起来似乎不太方便,但是请考虑在Java中,每个新类都需要一个新文件。将文件添加到项目中会很快变得很麻烦。
而最大的问题是make
:
Java的座右铭是“编译一次到处运行”。但是,将编译限制为基于POSIX的系统(实际上对Java的支持实际上是最差的)并不是故意的。
构建规则make
本质上是小的bash
脚本。即使有make
Windows 的端口,它也必须与端口捆绑在一起,才能使Windows正常工作,该端口bash
包括用于文件系统的POSIX仿真层。
这有两个变种:
MSYS
它试图将POSIX转换限制为文件路径,因此在运行不是专门为其设计的外部工具时可能会遇到麻烦。
cygwin
它提供了完整的POSIX仿真。但是,生成的程序仍倾向于依赖该仿真层。
因此,在Windows上,标准构建工具甚至根本不make
存在,而是MSBuild
一个基于XML的工具,原则上更接近ant
。
相比之下,它ant
是用Java构建的,可以在任何地方运行,并且包含称为“任务”的内部工具,用于以独立于平台的方式操纵文件和执行命令。它具有足够的通用性,与使用ant
相比,您实际上可以在Windows中使用C程序轻松构建C程序make
。
最后一个未成年人:
您最初可能不会注意到这一点,但是C程序通常不附带Makefile
。它们附带了CMakeLists.txt
或bash
生成实际脚本的配置脚本Makefile
。相反,使用构建的Java程序的源代码ant
附带了ant
预先构建的脚本。A Makefile
是其他工具的产物-这make
本身不适合用作构建工具。ant
是独立的,可处理Java构建过程所需的一切,而无需任何其他要求或依赖性。
ant
在任何平台上运行时,它都可以正常工作。您无法使用来实现make
。它与平台和配置的依赖程度令人难以置信。
除非我不是一个人,否则没有人会错误地使用make for java是错误的。
“使用GNU Make管理项目”(在GFDL下可用)包含一整章专门讨论make
与Java项目一起使用。
由于它包含一长串(并且希望很公平)使用make代替其他工具的利弊清单,因此您可能想看看那里。(请参阅:http : //oreilly.com/catalog/make3/book/)
从前,我从事使用gmake的Java项目。我的回忆很模糊,但是IIRC很难处理javac期望的软件包目录结构。我还记得,除非您有一些琐碎的事情,否则构建JAR文件很麻烦。
make
。对于跨平台语言来说,拥有仅在一个系统上可用的makefile并不是一件好事。