坑
某 HIT 软构实验的目录结构如下:
其原本是一个 eclipse 项目,但我使用的是 idea + gradle,然后就遇到了下面的问题:
一个正经的项目的目录结构应该是这样:
graph TB
project-->module1
project-->module2
subgraph
module2-->src2[src]
src2-->main2[main]
src2-->test2[test]
end
subgraph
module1-->src1[src]
src1-->main1[main]
src1-->test1[test]
end
但这个 lab 显然不对劲,它把源文件和测试塞一起了,而直接 implementation("junit:junit:4.13.2")
idea 是不认的,因为它觉得 P2
不是一个测试。
然后,P3
也很诡异,它的结构是这样:
它不是把 P3
作为模块根,而是在 src
和 test
各建了一个 P3
,因此构建脚本得写得很别扭。
解决方案
一种想法是把 P2
变成一个测试,然而由于我破烂的 gradle 水平,我找不到在一个配置文件里设置多个不同名称的测试的办法。不过后来发现了一种新办法:给 P2
加上 test 的 classpath:
sourceSets {
...
create("P2") {
java.srcDir("src/P2")
compileClasspath += configurations.testCompileClasspath
runtimeClasspath += configurations.testRuntimeClasspath
}
}
爆红消失了,完美。
至于 P3
,累了,直接把整个 test
给它罢:
sourceSets {
...
val p3 = create("P3") {
java.srcDir("src/P3")
}
test {
java.srcDir("test/P3")
compileClasspath += p3.output
runtimeClasspath += p3.output
}
}
完整配置文件参考
build.gradle.kts
plugins {
id("java")
}
group = "icu.nullptr.lab1"
version = "1.0"
sourceSets {
create("P1") {
java.srcDir("src/P1")
task<Jar>("jarP1") {
archiveBaseName.set("P1")
manifest.attributes("Main-Class" to "MagicSquare")
dependsOn(runtimeClasspath)
from(runtimeClasspath)
}
}
create("P2") {
java.srcDir("src/P2")
compileClasspath += configurations.testCompileClasspath
runtimeClasspath += configurations.testRuntimeClasspath
task<Jar>("jarP2") {
archiveBaseName.set("P2")
manifest.attributes("Main-Class" to "turtle.TurtleSoup")
dependsOn(runtimeClasspath)
from(runtimeClasspath)
}
}
val p3 = create("P3") {
java.srcDir("src/P3")
task<Jar>("jarP3") {
archiveBaseName.set("P3")
manifest.attributes("Main-Class" to "FriendshipGraph")
dependsOn(runtimeClasspath)
from(runtimeClasspath)
}
}
test {
java.srcDir("test/P3")
compileClasspath += p3.output
runtimeClasspath += p3.output
}
}
tasks["build"].dependsOn("jarP1", "jarP2", "jarP3")
java {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
repositories {
mavenCentral()
}
dependencies {
// Put all external libraries into lib directory including JUnit,
// instead of using online dependencies
implementation(fileTree("lib") { include("*.jar") })
}