某 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 作为模块根,而是在 srctest 各建了一个 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") })
}
最后修改:2022 年 05 月 31 日
如果觉得我的文章对你有用,请随意赞赏