■
Gradle refresh时产生的classpath错误
现象
选中项目⇒Gradle⇒refresh之后, ディフォルト出力フォルダ从“APIBot/bin/main”变成了“APIBot/bin/default”
Git上有一些内容可以参考
1. #3825(Closed)
Gradle从4.4版本开始,为每一个源文件目录使用一个单独的出力目录,
缺省情况下,这些出力目录都在bin目录下。
例子:
eclipse {
classpath.defaultOutputDir = file('build-eclipse')
}
虽然通过上述命令指定了缺省目录,但生成的classpath如下,编译的目标目录还是在bin下面
<classpathentry path="build-eclipse" kind="output"/> <classpathentry output="bin/main" kind="src" path="src/main/java"> <attributes> <attribute name="gradle_scope" value="main"/> <attribute name="gradle_used_by_scope" value="main,test,integrationTest"/> </attributes> </classpathentry> <classpathentry output="bin/main" kind="src" path="src/main/resources"> <attributes> <attribute name="gradle_scope" value="main"/> <attribute name="gradle_used_by_scope" value="main,test,integrationTest"/> </attributes> </classpathentry> <classpathentry output="bin/test" kind="src" path="src/test/java"> <attributes> <attribute name="gradle_scope" value="test"/> <attribute name="gradle_used_by_scope" value="test"/> </attributes> </classpathentry> <classpathentry output="bin/test" kind="src" path="src/test/resources"> <attributes> <attribute name="gradle_scope" value="test"/> <attribute name="gradle_used_by_scope" value="test"/> </attributes> </classpathentry>
defaultOutputDir正如其字面意思一样,是为那些没有指定目标目录的源文件准备的。
Gradle目前给每个目标目录指定了目标目录,因此defaultOutputDir应该没有什么机会被用到
解决方案
classpath { defaultOutputDir = file('build/classes/java/main') file.whenMerged { entries.each { source -> // This seems kludgy. If the second test is omitted, it fails processing a 'Project Dependency' entry if (source.kind == 'src' && source.toString().contains('output')) { source.output = 'build/classes/java/main' } } } }
其实想给所有源文件指定目标目录,更像是应该用outputBaseDir
outputBaseDir这个功能在Gradle的#3829票里面准备提供。
2. #4563(Closed)
内容和3825一样。因此被关闭
3. #3839(Open)
oehme提供了一个临时解决方案
classpath { file.whenMerged { entries.each { entry -> if (entry instanceof org.gradle.plugins.ide.eclipse.model.Output) { entry.path = entry.path.replace('bin', 'build/eclipse') } } } }
今后可能会提供一个永久解决方案
classpath {
outputBaseDir = 'build/eclipse'
}
apply plugin: 'java' apply plugin: 'eclipse' eclipse { classpath { file { //if you want to mess with the resulting XML in whatever way you fancy withXml { def node = it.asNode() node.appendNode('xml', 'is what I love') } //closure executed after .classpath content is loaded from existing file //从既存文件中载入.classpath的内容之后,这个闭包内容会被执行 //but before gradle build information is merged //但是gradle build information被merge之前。 // beforeMerged { classpath -> //you can tinker with the Classpath here } //closure executed after .classpath content is loaded from existing file //从既存文件中载入.classpath的内容之后,这个闭包内容会被执行(跟beforeMerged相同) //and after gradle build information is merged //但是gradle build information被merge之后。 whenMerged { classpath -> //you can tinker with the Classpath here } } } }
关键还是gradle build information的merge时间点,以及什么information。
从跑出来的一些例子看,这个information应该是指所有依赖关系
Gradle官方文档中关于defaultOutputDir的描述
缺省就是bin/default
所以一定要指定。