javac选项以递归方式编译给定目录下的所有java文件


127

我正在使用javac编译器来编译项目中的Java文件。这些文件分布在几个包像这样:com.vistas.utilcom.vistas.convertercom.vistas.LineHelpercom.current.mdcontect

这些软件包中的每一个都有几个java文件。我正在使用像这样的javac:

javac com/vistas/util/*.java com/vistas/converter/*.java
      com.vistas.LineHelper/*.java com/current/mdcontect/*.java

(一行)

除了提供这么多路径之外,我如何要求编译器递归地编译来自父com目录的所有Java文件?


2
您应该真正了解一下Ant或Maven之类的工具。
洛朗·皮瑞恩

Answers:


220

我还建议使用某种构建工具(AntMaven,已经建议使用Ant,并且更容易上手)或处理编译的IDE(Eclipse使用具有协调策略的增量编译,您甚至不必请务必按任何“编译”按钮)。

使用Javac

如果您需要尝试更大的项目并且附近没有任何合适的构建工具,则可以随时使用一个javac提供的小技巧:可以在文件中指定要编译的类名。您只需要javac使用@前缀将文件名传递给。

如果您可以创建*.java项目中所有文件的列表,则很简单:

# Linux / MacOS
$ find -name "*.java" > sources.txt
$ javac @sources.txt

:: Windows
> dir /s /B *.java > sources.txt
> javac @sources.txt
  • 优点是,这是一种快速简便的解决方案。
  • 缺点是,sources.txt每次创建新的源文件或重命名现有的文件时,都必须重新生成文件,这很容易忘记(因此容易出错)并且很繁琐。

使用构建工具

从长远来看,最好使用专门用于构建软件的工具。

使用蚂蚁

如果您创建一个build.xml描述如何构建软件的简单文件:

<project default="compile">
    <target name="compile">
        <mkdir dir="bin"/>
        <javac srcdir="src" destdir="bin"/>
    </target>
</project>

您可以通过运行以下命令来编译整个软件:

$ ant
  • 好处是您正在使用易于扩展的标准构建工具。
  • 缺点是您必须下载,设置和学习其他工具。请注意,大多数IDE(例如NetBeans和Eclipse)都对编写构建文件提供了强大的支持,因此在这种情况下您无需下载任何内容。

使用Maven

Maven的设置和使用并不是那么简单,但是学习它很有意义。这是一个很棒的教程,可以在5分钟内启动一个项目

  • (对我而言)主要优点是它也可以处理依赖关系,因此您无需再下载任何Jar文件并手动管理它们,我发现它对于构建,打包和测试较大的项目更有用。
  • 缺点是它的学习曲线很陡峭,并且如果Maven插件喜欢抑制错误:-)另一件事是,很多工具也可以在Maven存储库中运行(例如Sbt用于Scala,Ivy用于Ant,Gradle用于Groovy) 。

使用IDE

现在,什么可以提高您的开发效率。有一些开源替代方案(例如EclipseNetBeans,我更喜欢前者),甚至还有商业化的替代方案(例如IntelliJ),它们非常受欢迎且功能强大。

他们可以在后台管理项目建设,因此您不必处理所有命令行内容。但是,如果您知道后台实际发生的情况,那么总是很方便的,这样您就可以找出诸如的偶然错误ClassNotFoundException

另一注

对于较大的项目,始终建议使用IDE 构建工具。前者可以提高您的生产率,而后者则可以在项目中使用不同的IDE(例如,Maven可以使用简单的mvn eclipse:eclipse命令生成Eclipse项目描述符)。而且,拥有一个可以通过单行命令进行测试/构建的项目很容易介绍给新同事和连续集成服务器。小菜一碟 :-)


4
使用时javac,最好指定输出目录。find -name "*.java" > sources.txt && javac -d bin @sources.txt。否则,*。class文件将保存到源文件所在的目录中。
Maksim Dmitriev 2014年

1
千真万确。虽然在我看来,如果有人刚开始玩的javac,这个概念CLASSPATH,如何在执行代码java,如何处理包,这应该是正在运行的根文件夹等,通常并不清楚。因此,我省略了输出目录。无论如何,谢谢你的建议!
rlegendi

6
对于遇到此问题的Mac用户,find命令为:(find . -name "*.java" > sources.txt请注意.
MrDuk

@MrDuk如何添加“。” 做?是否在当前目录中搜索?
布雷迪·希恩

@BradySheehan它将开始从给定的路径搜索。“。” 表示从当前字典开始。请注意,您必须指定查找路径(在OS X中)
Kris

39
find . -name "*.java" -print | xargs javac 

有点残酷,但是像地狱一样工作。(仅在小型程序上使用,这绝对没有效率)


1
如果您使用此考虑因素find ... -print0xargs -0 ...而不是不
打乱

29

如果您的外壳支持它,这样会起作用吗?

javac com/**/*.java 

如果您的外壳不支持**,那么也许

javac com/*/*/*.java

可以工作(对于具有3个组件的所有程序包-或多或少地适应)。


我试图在Windows 10的命令提示符中使用此命令。有人可以确认它是否在Windows 10上有效,或者我做错了吗
Dan

26

在通常情况下,如果要编译整个项目,则只需向javac提供主类,然后让它编译所有必需的依赖项:

javac -sourcepath . path/to/Main.java


非常简单的方法,不依赖其他文件
linquize 2015年

这是最好的,人们没有太多的时间去学习蚂蚁(像我)谁是最简单的一个
哈姆扎阿巴德

不幸的是,这很懒。如果您不触摸Main.java,那么创建第二个文件后可能就不会触摸,其他任何东西都不会得到编译器。
汤姆·哈特芬

在这里也不行。尽管已更改某些依赖项,但它们不会重新编译。@ TomHawtin-tackline我之前尝试过触摸主菜单,但没有任何操作。也许需要所有方面。虽然有点尴尬。

4

javac -cp "jar_path/*" $(find . -name '*.java')

(我不想使用xargs,因为它可以将它们拆分并多次运行javac,每个都有一个java文件的子集,其中一些文件可能会导入未在同一javac命令行上指定的其他文件)

如果您有App.java入口点,则最好使用freaker的-sourcepath方法。它根据导入依赖关系编译它需要的所有其他Java文件。例如:

javac -cp "jar_path/*" -sourcepath src/ src/com/companyname/modulename/App.java

您还可以指定一个目标类文件目录:-d target/


3

我建议您学习使用ant,它非常适合此任务,并且易于掌握和有据可查。

您只需要在build.xml文件中定义一个这样的目标:

<target name="compile">
    <javac srcdir="your/source/directory"
           destdir="your/output/directory"
           classpath="xyz.jar" />
</target>

2

我只是将make与一个简单的makefile一起使用,如下所示:

JAVAC = javac -Xlint:unchecked
sources = $(shell find . -type f -name '*.java')
classes = $(sources:.java=.class)

all : $(classes)

clean :
        rm -f $(classes)

%.class : %.java
        $(JAVAC) $<

它一次编译一个源,并且仅在必要时才重新编译。


1

javac命令不遵循递归编译过程,因此您可以在运行命令时指定每个目录,或者提供一个文本文件,其中包含要包含的目录:

javac -classpath "${CLASSPATH}" @java_sources.txt

0

我一直在Xcode JNI项目中使用它来递归地构建测试类:

find ${PROJECT_DIR} -name "*.java" -print | xargs javac -g -classpath ${BUILT_PRODUCTS_DIR} -d ${BUILT_PRODUCTS_DIR}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.