Gradle initでprojectを作成する

# Gradleバージョン

```shell
% gradle --version

------------------------------------------------------------
Gradle 7.5
------------------------------------------------------------

Build time:   2022-07-14 12:48:15 UTC
Revision:     c7db7b958189ad2b0c1472b6fe663e6d654a5103

Kotlin:       1.6.21
Groovy:       3.0.10
Ant:          Apache Ant(TM) version 1.10.11 compiled on July 10 2021
JVM:          11.0.16 (Homebrew 11.0.16+0)
OS:           Mac OS X 13.2.1 aarch64
```

```shell
% brew upgrade gradle
Warning: You are using macOS 13.
We do not provide support for this pre-release version.
You will encounter build failures with some formulae.
Please create pull requests instead of asking for help on Homebrew's GitHub,
Twitter or any other official channels. You are responsible for resolving
any issues you experience while you are running this
pre-release version.

==> Upgrading 1 outdated package:
gradle 7.5 -> 7.5.1
==> Downloading https://ghcr.io/v2/homebrew/core/gradle/manifests/7.5.1
######################################################################## 100.0%
==> Downloading https://ghcr.io/v2/homebrew/core/gradle/blobs/sha256:022acd562e864e9ffd39dabc3c5c45df19b7ebe9aa0dee25b895ef410a01a3b9
==> Downloading from https://pkg-containers.githubusercontent.com/ghcr1/blobs/sha256:022acd562e864e9ffd39dabc3c5c45df19b7ebe9aa0dee25b895ef410a01a3b9?se=2023-03-26T12%3A35%
######################################################################## 100.0%
==> Upgrading gradle
  7.5 -> 7.5.1 

==> Pouring gradle--7.5.1.all.bottle.tar.gz
🍺  /opt/homebrew/Cellar/gradle/7.5.1: 11,340 files, 276.1MB
==> Running `brew cleanup gradle`...
Disable this behaviour by setting HOMEBREW_NO_INSTALL_CLEANUP.
Hide these hints with HOMEBREW_NO_ENV_HINTS (see `man brew`).
Removing: /opt/homebrew/Cellar/gradle/7.5... (11,340 files, 276.1MB)
==> `brew cleanup` has not been run in the last 30 days, running now...
Disable this behaviour by setting HOMEBREW_NO_INSTALL_CLEANUP.
Hide these hints with HOMEBREW_NO_ENV_HINTS (see `man brew`).
Removing: /Users/yuzuru/Library/Logs/Homebrew/pyenv... (64B)
Removing: /Users/yuzuru/Library/Logs/Homebrew/go... (64B)
```

バージョン確認

```shell
% gradle --version

------------------------------------------------------------
Gradle 7.5.1
------------------------------------------------------------

Build time:   2022-08-05 21:17:56 UTC
Revision:     d1daa0cbf1a0103000b71484e1dbfe096e095918

Kotlin:       1.6.21
Groovy:       3.0.10
Ant:          Apache Ant(TM) version 1.10.11 compiled on July 10 2021
JVM:          11.0.16 (Homebrew 11.0.16+0)
OS:           Mac OS X 13.2.1 aarch64
```

# basic プロジェクトを作成する

```shell
% mkdir basic-project
% cd basic-project/
```

basicを選択して作成する。

```shell
% gradle init
Starting a Gradle Daemon (subsequent builds will be faster)

Select type of project to generate:
  1: basic
  2: application
  3: library
  4: Gradle plugin
Enter selection (default: basic) [1..4] 1

Select build script DSL:
  1: Groovy
  2: Kotlin
Enter selection (default: Groovy) [1..2] 1

Generate build using new APIs and behavior (some features may change in the next minor release)? (default: no) [yes, no] 
Project name (default: basic-project): 

> Task :init
Get more help with your project: Learn more about Gradle by exploring our samples at https://docs.gradle.org/7.5.1/samples

BUILD SUCCESSFUL in 12s
2 actionable tasks: 2 executed
```

作成されるのは以下のファイルのみ。

```shell
% tree
.
├── build.gradle
├── gradle
│   └── wrapper
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── settings.gradle

2 directories, 6 files
```

# applicationプロジェクトを作成する

```shell
% gradle init

Select type of project to generate:
  1: basic
  2: application
  3: library
  4: Gradle plugin
Enter selection (default: basic) [1..4] 2

Select implementation language:
  1: C++
  2: Groovy
  3: Java
  4: Kotlin
  5: Scala
  6: Swift
Enter selection (default: Java) [1..6] 3

Split functionality across multiple subprojects?:
  1: no - only one application project
  2: yes - application and library projects
Enter selection (default: no - only one application project) [1..2] 1

Select build script DSL:
  1: Groovy
  2: Kotlin
Enter selection (default: Groovy) [1..2] 1

Generate build using new APIs and behavior (some features may change in the next minor release)? (default: no) [yes, no] 
Select test framework:
  1: JUnit 4
  2: TestNG
  3: Spock
  4: JUnit Jupiter
Enter selection (default: JUnit Jupiter) [1..4] 4

Project name (default: app-project): 
Source package (default: app.project): 

> Task :init
Get more help with your project: https://docs.gradle.org/7.5.1/samples/sample_building_java_applications.html

BUILD SUCCESSFUL in 58s
2 actionable tasks: 2 executed
```

作成されるファイルは以下の通り。

```shell
% tree
.
├── app
│   ├── build.gradle
│   └── src
│       ├── main
│       │   ├── java
│       │   │   └── app
│       │   │       └── project
│       │   │           └── App.java
│       │   └── resources
│       └── test
│           ├── java
│           │   └── app
│           │       └── project
│           │           └── AppTest.java
│           └── resources
├── gradle
│   └── wrapper
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── settings.gradle

14 directories, 8 files
```

```gradle:settings.gradle
/*
 * This file was generated by the Gradle 'init' task.
 *
 * The settings file is used to specify which projects to include in your build.
 *
 * Detailed information about configuring a multi-project build in Gradle can be found
 * in the user manual at https://docs.gradle.org/7.5.1/userguide/multi_project_builds.html
 */

rootProject.name = 'app-project'
include('app')
```

```gradle:app/build.gradle
/*
 * This file was generated by the Gradle 'init' task.
 *
 * This generated file contains a sample Java application project to get you started.
 * For more details take a look at the 'Building Java & JVM projects' chapter in the Gradle
 * User Manual available at https://docs.gradle.org/7.5.1/userguide/building_java_projects.html
 */

plugins {
    // Apply the application plugin to add support for building a CLI application in Java.
    id 'application'
}

repositories {
    // Use Maven Central for resolving dependencies.
    mavenCentral()
}

dependencies {
    // Use JUnit Jupiter for testing.
    testImplementation 'org.junit.jupiter:junit-jupiter:5.8.2'

    // This dependency is used by the application.
    implementation 'com.google.guava:guava:31.0.1-jre'
}

application {
    // Define the main class for the application.
    mainClass = 'app.project.App'
}

tasks.named('test') {
    // Use JUnit Platform for unit tests.
    useJUnitPlatform()
}
```

アプリケーションはmain関数がある。

```java:app/src/main/java/app/project/App.java
/*
 * This Java source file was generated by the Gradle 'init' task.
 */
package app.project;

public class App {
    public String getGreeting() {
        return "Hello World!";
    }

    public static void main(String[] args) {
        System.out.println(new App().getGreeting());
    }
}
```

```shell
% ./gradlew assemble

BUILD SUCCESSFUL in 608ms
5 actionable tasks: 5 executed
```

```shell
% find . -name *.jar
./app/build/libs/app.jar
./gradle/wrapper/gradle-wrapper.jar
```

# Multi applicationプロジェクトを作成する

```shell
% mkdir multi-project
% cd multi-project/
```

Gradle init


```shell
% gradle init

Select type of project to generate:
  1: basic
  2: application
  3: library
  4: Gradle plugin
Enter selection (default: basic) [1..4] 2

Select implementation language:
  1: C++
  2: Groovy
  3: Java
  4: Kotlin
  5: Scala
  6: Swift
Enter selection (default: Java) [1..6] 3

Split functionality across multiple subprojects?:
  1: no - only one application project
  2: yes - application and library projects
Enter selection (default: no - only one application project) [1..2] 2

Select build script DSL:
  1: Groovy
  2: Kotlin
Enter selection (default: Groovy) [1..2] 1

Generate build using new APIs and behavior (some features may change in the next minor release)? (default: no) [yes, no] 
Project name (default: multi-project): 
Source package (default: multi.project): 

> Task :init
Get more help with your project: https://docs.gradle.org/7.5.1/samples/sample_building_java_applications_multi_project.html

BUILD SUCCESSFUL in 18s
2 actionable tasks: 2 executed
```

作成されるファイルは以下のとおり。

```shell
% tree
.
├── app
│   ├── build.gradle
│   └── src
│       ├── main
│       │   ├── java
│       │   │   └── multi
│       │   │       └── project
│       │   │           └── app
│       │   │               ├── App.java
│       │   │               └── MessageUtils.java
│       │   └── resources
│       └── test
│           ├── java
│           │   └── multi
│           │       └── project
│           │           └── app
│           │               └── MessageUtilsTest.java
│           └── resources
├── buildSrc
│   ├── build.gradle
│   └── src
│       └── main
│           └── groovy
│               ├── multi.project.java-application-conventions.gradle
│               ├── multi.project.java-common-conventions.gradle
│               └── multi.project.java-library-conventions.gradle
├── gradle
│   └── wrapper
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── list
│   ├── build.gradle
│   └── src
│       ├── main
│       │   ├── java
│       │   │   └── multi
│       │   │       └── project
│       │   │           └── list
│       │   │               └── LinkedList.java
│       │   └── resources
│       └── test
│           ├── java
│           │   └── multi
│           │       └── project
│           │           └── list
│           │               └── LinkedListTest.java
│           └── resources
├── settings.gradle
└── utilities
    ├── build.gradle
    └── src
        ├── main
        │   ├── java
        │   │   └── multi
        │   │       └── project
        │   │           └── utilities
        │   │               ├── JoinUtils.java
        │   │               ├── SplitUtils.java
        │   │               └── StringUtils.java
        │   └── resources
        └── test
            └── resources

44 directories, 20 files
```

```gradle:settings.gradle
/*
 * This file was generated by the Gradle 'init' task.
 *
 * The settings file is used to specify which projects to include in your build.
 *
 * Detailed information about configuring a multi-project build in Gradle can be found
 * in the user manual at https://docs.gradle.org/7.5.1/userguide/multi_project_builds.html
 */

rootProject.name = 'multi-project'
include('app', 'list', 'utilities')
```

```gradle:app/build.gradle
/*
 * This file was generated by the Gradle 'init' task.
 */

plugins {
    id 'multi.project.java-application-conventions'
}

dependencies {
    implementation 'org.apache.commons:commons-text'
    implementation project(':utilities')
}

application {
    // Define the main class for the application.
    mainClass = 'multi.project.app.App'
}
```

appにはmain関数がある。

```java:app/src/main/java/multi/project/app/App.java
/*
 * This Java source file was generated by the Gradle 'init' task.
 */
package app.project;

public class App {
    public String getGreeting() {
        return "Hello World!";
    }

    public static void main(String[] args) {
        System.out.println(new App().getGreeting());
    }
}
```

```gradle:list/build.gradle
/*
 * This file was generated by the Gradle 'init' task.
 */

plugins {
    id 'multi.project.java-library-conventions'
}
```

ライブラリにはmain関数はない。

```java:list/src/main/java/multi/project/list/LinkedList.java
/*
 * This Java source file was generated by the Gradle 'init' task.
 */
package multi.project.list;

public class LinkedList {
    private Node head;

    public void add(String element) {
        Node newNode = new Node(element);

        Node it = tail(head);
        if (it == null) {
            head = newNode;
        } else {
            it.next = newNode;
        }
    }

    private static Node tail(Node head) {
        Node it;

        for (it = head; it != null && it.next != null; it = it.next) {}

        return it;
    }

    public boolean remove(String element) {
        boolean result = false;
        Node previousIt = null;
        Node it = null;
        for (it = head; !result && it != null; previousIt = it, it = it.next) {
            if (0 == element.compareTo(it.data)) {
                result = true;
                unlink(previousIt, it);
                break;
            }
        }

        return result;
    }

    private void unlink(Node previousIt, Node currentIt) {
        if (currentIt == head) {
            head = currentIt.next;
        } else {
            previousIt.next = currentIt.next;
        }
    }

    public int size() {
        int size = 0;

        for (Node it = head; it != null; ++size, it = it.next) {}

        return size;
    }

    public String get(int index) {
        Node it = head;
        while (index > 0 && it != null) {
            it = it.next;
            index--;
        }

        if (it == null) {
            throw new IndexOutOfBoundsException("Index is out of range");
        }

        return it.data;
    }

    private static class Node {
        final String data;
        Node next;

        Node(String data) {
            this.data = data;
        }
    }
}
```


```gradle:utilities/build.gradle 
/*
 * This file was generated by the Gradle 'init' task.
 */

plugins {
    id 'multi.project.java-library-conventions'
}

dependencies {
    api project(':list')
}
```

コンパイル

```shell
% ./gradlew assemble

BUILD SUCCESSFUL in 14s
18 actionable tasks: 18 executed
```

```shell
% find . -name *.jar
./app/build/libs/app.jar
./gradle/wrapper/gradle-wrapper.jar
./utilities/build/libs/utilities.jar
./buildSrc/build/libs/buildSrc.jar
./list/build/libs/list.jar
```

# libraryプロジェクトの作成

```shell
% mkdir library-project
% cd library-project/
```

```shell
% gradle init

Select type of project to generate:
  1: basic
  2: application
  3: library
  4: Gradle plugin
Enter selection (default: basic) [1..4] 3

Select implementation language:
  1: C++
  2: Groovy
  3: Java
  4: Kotlin
  5: Scala
  6: Swift
Enter selection (default: Java) [1..6] 3

Select build script DSL:
  1: Groovy
  2: Kotlin
Enter selection (default: Groovy) [1..2] 1

Generate build using new APIs and behavior (some features may change in the next minor release)? (default: no) [yes, no] 
Select test framework:
  1: JUnit 4
  2: TestNG
  3: Spock
  4: JUnit Jupiter
Enter selection (default: JUnit Jupiter) [1..4] 4

Project name (default: library-project): 
Source package (default: library.project): 

> Task :init
Get more help with your project: https://docs.gradle.org/7.5.1/samples/sample_building_java_libraries.html

BUILD SUCCESSFUL in 44s
2 actionable tasks: 2 executed
```

```shell
% tree
.
├── gradle
│   └── wrapper
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── lib
│   ├── build.gradle
│   └── src
│       ├── main
│       │   ├── java
│       │   │   └── library
│       │   │       └── project
│       │   │           └── Library.java
│       │   └── resources
│       └── test
│           ├── java
│           │   └── library
│           │       └── project
│           │           └── LibraryTest.java
│           └── resources
└── settings.gradle

14 directories, 8 files
```

```gradle:settings.gradle
% cat settings.gradle 
/*
 * This file was generated by the Gradle 'init' task.
 *
 * The settings file is used to specify which projects to include in your build.
 *
 * Detailed information about configuring a multi-project build in Gradle can be found
 * in the user manual at https://docs.gradle.org/7.5.1/userguide/multi_project_builds.html
 */

rootProject.name = 'library-project'
include('lib')
```

```gradle:lib/build.gradle
/*
 * This file was generated by the Gradle 'init' task.
 *
 * This generated file contains a sample Java library project to get you started.
 * For more details take a look at the 'Building Java & JVM projects' chapter in the Gradle
 * User Manual available at https://docs.gradle.org/7.5.1/userguide/building_java_projects.html
 */

plugins {
    // Apply the java-library plugin for API and implementation separation.
    id 'java-library'
}

repositories {
    // Use Maven Central for resolving dependencies.
    mavenCentral()
}

dependencies {
    // Use JUnit Jupiter for testing.
    testImplementation 'org.junit.jupiter:junit-jupiter:5.8.2'

    // This dependency is exported to consumers, that is to say found on their compile classpath.
    api 'org.apache.commons:commons-math3:3.6.1'

    // This dependency is used internally, and not exposed to consumers on their own compile classpath.
    implementation 'com.google.guava:guava:31.0.1-jre'
}

tasks.named('test') {
    // Use JUnit Platform for unit tests.
    useJUnitPlatform()
}
```

Libraryの場合はmainメソッドがない。

```java:Library.java
/*
 * This Java source file was generated by the Gradle 'init' task.
 */
package library.project;

public class Library {
    public boolean someLibraryMethod() {
        return true;
    }
}
```

```shell
% ./gradlew assemble

BUILD SUCCESSFUL in 794ms
2 actionable tasks: 2 executed
```

```shell
% find . -name *.jar
./gradle/wrapper/gradle-wrapper.jar
./lib/build/libs/lib.jar
```

# pluginプロジェクトを作成する。

```shell
% mkdir plugin-project
% cd plugin-project/
```

gradle init

```shell
% gradle init

Select type of project to generate:
  1: basic
  2: application
  3: library
  4: Gradle plugin
Enter selection (default: basic) [1..4] 4

Select implementation language:
  1: Groovy
  2: Java
  3: Kotlin
Enter selection (default: Java) [1..3] 1

Select build script DSL:
  1: Groovy
  2: Kotlin
Enter selection (default: Groovy) [1..2] 1

Generate build using new APIs and behavior (some features may change in the next minor release)? (default: no) [yes, no] 
Project name (default: plugin-project): 
Source package (default: plugin.project): 

> Task :init
Get more help with your project: https://docs.gradle.org/7.5.1/userguide/custom_plugins.html

BUILD SUCCESSFUL in 19s
2 actionable tasks: 2 executed
```

作成されるファイルは以下のとおり。

```shell
% tree
.
├── gradle
│   └── wrapper
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── plugin
│   ├── build.gradle
│   └── src
│       ├── functionalTest
│       │   └── groovy
│       │       └── plugin
│       │           └── project
│       │               └── PluginProjectPluginFunctionalTest.groovy
│       ├── main
│       │   ├── groovy
│       │   │   └── plugin
│       │   │       └── project
│       │   │           └── PluginProjectPlugin.groovy
│       │   └── resources
│       └── test
│           ├── groovy
│           │   └── plugin
│           │       └── project
│           │           └── PluginProjectPluginTest.groovy
│           └── resources
└── settings.gradle

18 directories, 9 files
```

```gradle:settings.gradle
/*
 * This file was generated by the Gradle 'init' task.
 *
 * The settings file is used to specify which projects to include in your build.
 *
 * Detailed information about configuring a multi-project build in Gradle can be found
 * in the user manual at https://docs.gradle.org/7.5.1/userguide/multi_project_builds.html
 */

rootProject.name = 'plugin-project'
include('plugin')
```

```gradle:plugin/build.gradle
/*
 * This file was generated by the Gradle 'init' task.
 *
 * This generated file contains a sample Gradle plugin project to get you started.
 * For more details take a look at the Writing Custom Plugins chapter in the Gradle
 * User Manual available at https://docs.gradle.org/7.5.1/userguide/custom_plugins.html
 */

plugins {
    // Apply the Java Gradle plugin development plugin to add support for developing Gradle plugins
    id 'java-gradle-plugin'

    // Apply the Groovy plugin to add support for Groovy
    id 'groovy'
}

repositories {
    // Use Maven Central for resolving dependencies.
    mavenCentral()
}

dependencies {
    // Use the awesome Spock testing and specification framework
    testImplementation 'org.spockframework:spock-core:2.1-groovy-3.0'
}

gradlePlugin {
    // Define the plugin
    plugins {
        greeting {
            id = 'plugin.project.greeting'
            implementationClass = 'plugin.project.PluginProjectPlugin'
        }
    }
}

// Add a source set for the functional test suite
sourceSets {
    functionalTest {
    }
}

configurations.functionalTestImplementation.extendsFrom(configurations.testImplementation)

// Add a task to run the functional tests
tasks.register('functionalTest', Test) {
    testClassesDirs = sourceSets.functionalTest.output.classesDirs
    classpath = sourceSets.functionalTest.runtimeClasspath
    useJUnitPlatform()
}

gradlePlugin.testSourceSets(sourceSets.functionalTest)

tasks.named('check') {
    // Run the functional tests as part of `check`
    dependsOn(tasks.functionalTest)
}

tasks.named('test') {
    // Use JUnit Jupiter for unit tests.
    useJUnitPlatform()
}
```

```groovy:plugin/src/main/groovy/plugin/project/PluginProjectPlugin.groovy
/*
 * This Groovy source file was generated by the Gradle 'init' task.
 */
package plugin.project

import org.gradle.api.Project
import org.gradle.api.Plugin

/**
 * A simple 'hello world' plugin.
 */
class PluginProjectPlugin implements Plugin<Project> {
    void apply(Project project) {
        // Register a task
        project.tasks.register("greeting") {
            doLast {
                println("Hello from plugin 'plugin.project.greeting'")
            }
        }
    }
}
```