简体   繁体   English

使用IntelliJ IDEA构建Gradle多模块的正确结构

[英]Proper structure for Gradle multi-module builds with IntelliJ IDEA

I have a Kotlin project which is comprised of three modules: 我有一个Kotlin项目,它由三个模块组成:

Core < Service < Web

The structure is: 结构是:

build.gradle
core/
    build.gradle
service/
    build.gradle
web/
    build.gradle

The structure for the root build.gradle file is: build.gradle文件的结构是:

buildscript {
    ext.kotlin_version = '1.1.60'
    repositories {
        mavenCentral()
        jcenter()
    }
    dependencies {
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    }
}
subprojects {
    apply plugin: 'kotlin'
    apply plugin: 'jacoco'
    compileKotlin {
        kotlinOptions.jvmTarget = '1.8'
    }
    repositories {
        mavenCentral()
        jcenter()
    }
}

The individual build files look like (for core ): 各个构建文件看起来像( core ):

dependencies {
    // Kotlin
    compile "org.jetbrains.kotlin:kotlin-stdlib-jre8:$kotlin_version"
    ...
}

And for service (note the only difference is the project dependency): 对于service (注意唯一的区别是项目依赖性):

dependencies {
    compile project (':core')
    // Kotlin
    compile "org.jetbrains.kotlin:kotlin-stdlib-jre8:$kotlin_version"
    ...
}

There are a few optimizations I'd like to make, but I'm still learning Gradle, and can't find the right way to reorganize things. 我想做一些优化,但我还在学习Gradle,并且无法找到重组事物的正确方法。 The problems I have are: 我遇到的问题是:

  1. I can't build service or web individually, as they complain about not being able to find their dependent sub-projects. 我无法单独构建serviceweb ,因为他们抱怨无法找到他们的依赖子项目。 (Via a gradle build in the service/ directory, for example.) (例如,通过service/目录中的gradle build 。)

  2. How can I define the Kotlin stdlib-jre8 dependency at the root level, so it's not duplicated in my three build files? 如何在根级别定义Kotlin stdlib-jre8依赖项,所以它在我的三个构建文件中没有重复?

  3. How can my subproject/buildscript tasks of the root buildfile use the same repository definitions, so that I don't have to define mavenCentral()/jcenter() twice? root构建文件的子项目/ buildscript任务如何使用相同的存储库定义,以便我不必定义mavenCentral()/jcenter()

Basically this build structure that I have was cobbled together through some experimentation/web resources, and happens to mostly work , but I'd like some guidance on doing it the right way, such that (1) it follows good Gradle practices, and (2) still works well via auto-import into IDEA. 基本上我的构建结构通过一些实验/网络资源拼凑在一起,并且恰好在大多数情况下工作 ,但是我想要以正确的方式做一些指导,这样(1)它遵循良好的Gradle实践,并且( 2)通过自动导入到IDEA仍然可以正常工作。

  1. If you want to run a build on a module you can do by running: gradle :web:build 如果要在模块上运行构建,可以通过运行: gradle :web:build
  2. In the same way that you are adding repositories in the subprojects clause, you can add the dependencies block in there. 与在subprojects子句中添加存储库的方式相同,您可以在其中添加dependencies块。 Make sure that only the shared dependencies are in there. 确保只有共享依赖项。 For instance, compile project(':core') should only be in the relevant project. 例如, compile project(':core')应仅在相关项目中。 It's ok to have multiple dependency blocks. 可以有多个dependency块。 That said, it's usually more of a headache to use the subproject clause. 也就是说,使用subproject条款通常更令人头疼。 Because, if dependencies change for one of the modules you are forced to update that for all of them 因为,如果其中一个模块的依赖关系发生更改,则必须为所有模块更新该模块
  3. Regarding the repository definitions, they are very different. 关于repository定义,它们非常不同。 The one in the buildscript block is used by Gradle itself in order to find plugins and other 'pre-build' requirements. buildscript块中的buildscript由Gradle本身使用,以便找到插件和其他“预构建”要求。 The one on the submodules is used to find the dependencies of the source code in the given module. 子模块上的一个用于查找给定模块中源代码的依赖关系。 As mentioned on the previous point, it's easier to manage when placed on the respective module build scripts. 如前所述,当放置在相应的模块构建脚本上时,它更容易管理。

Update: 更新:

If you want to keep the same version for all modules, the variables defined on ext in the buildscript should be able to be accessed from the submodules too: ext.kotlin_version = '1.1.60' and if you have multiple ones you can add them like: 如果你想为所有模块保留相同的版本,那么也应该能够从子模块访问在builds中定义的ext上的变量: ext.kotlin_version = '1.1.60'如果你有多个,你可以添加它们喜欢:

ext {
  kotlin_version = '1.1.60'
  junit_version = '4.12'
}

Also, if you want to share code between modules, you can always extract it to gradle file and load it where needed using: apply file: "$rootDir/path/to/script.gradle" 此外,如果要在模块之间共享代码,可以始终将其提取到gradle文件并使用以下方法加载它: apply file: "$rootDir/path/to/script.gradle"

Regarding #3, I'll give you a practical example. 关于#3,我会给你一个实际的例子。

Google has its own maven repository that contains all the dependencies for an android module. Google拥有自己的maven存储库,其中包含android模块的所有依赖项。 If you have a project that contains both a server-side module and android module you may not need the server-side one to look up dependencies on the Gradle artefact repository (artefact is the name of the jar dependency). 如果你有一个包含服务器端模块和android模块的项目,你可能不需要服务器端查找Gradle artefact存储库的依赖项(artefact是jar依赖项的名称)。

As for the buildscript repositories, in your case you are only loading one classpath (pre-build) dependency which is located on mavenCentral() so you may be ok removing jcenter() here. 对于buildscript存储库,在您的情况下,您只加载一个位于mavenCentral()上的类路径(预构建)依赖项,因此您可以在这里删除jcenter()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM