// Copyright (C) 2024 Gradle, Inc.
//
// Licensed under the Creative Commons Attribution-Noncommercial-ShareAlike 4.0 International License.;
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

[[build_init_plugin]]
= Build Init Plugin

The Build Init plugin can be used to create a new Gradle build. It supports creating brand new Gradle builds of various types as well as converting existing Apache Maven builds to Gradle.

[[sec:sample_usage]]
== Sample usage

[source,bash]
----
gradle init \
  --type java-application \
  --dsl kotlin \
  --test-framework junit-jupiter \
  --package my.project \
  --into ./my-project \
  --project-name my-project  \
  --no-split-project  \
  --java-version 17
----

Gradle enters interactive mode and prompts the user when a required parameter for the selected project type is missing.

== Supported Gradle build types

The Build Init plugin supports generating various build _types_. These are listed below and more detail is available about each type in the following <<#sec:build_init_types,section>>.

.Build init types
[options="header"]
|=================
|Type|Description
|<<#sec:pom_maven_conversion,pom>>|Converts an existing Apache Maven build to Gradle
|<<#sec:basic,basic>>|A basic, empty, Gradle build
|<<#sec:java_application,java-application>>|A command-line application implemented in Java
|<<#sec:java_gradle_plugin,java-gradle-plugin>>|A Gradle plugin implemented in Java
|<<#sec:java_library,java-library>>|A Java library
|<<#sec:kotlin_application,kotlin-application>>|A command-line application implemented in Kotlin/JVM
|<<#sec:kotlin_gradle_plugin,kotlin-gradle-plugin>>|A Gradle plugin implemented in Kotlin/JVM
|<<#sec:kotlin_library,kotlin-library>>|A Kotlin/JVM library
|<<#sec:groovy_application,groovy-application>>|A command-line application implemented in Groovy
|<<#sec:groovy_gradle_plugin,groovy-gradle-plugin>>|A Gradle plugin implemented in Groovy
|<<#sec:groovy_library,groovy-library>>|A Groovy library
|<<#sec:scala_application,scala-application>>|A Scala application
|<<#sec:scala_library,scala-library>>|A Scala library
|<<#sec:cpp_application,cpp-application>>|A command-line application implemented in C++
|<<#sec:cpp_library,cpp-library>>|A C++ library
|=================

[[sec:build_init_tasks]]
== Tasks

The plugin adds the following tasks to the project:

`init` — link:{groovyDslPath}/org.gradle.buildinit.tasks.InitBuild.html[InitBuild]

Generates a Gradle build.

Gradle plugins usually need to be _applied_ to a project before they can be used (see <<plugins_intermediate.adoc#using_plugins,Using plugins>>). However, the Build Init plugin is automatically applied to the root project of every build, which means you do not need to apply it explicitly in order to use it. You can simply execute the task named `init` in the directory where you would like to create the Gradle build. There is no need to create a "stub" `build.gradle` file in order to apply the plugin.

[[sec:what_to_set_up]]
== What to create

The simplest, and recommended, way to use the `init` task is to run `gradle init` from an interactive console. Gradle will list the available build types and ask you to select one. It will then ask some additional questions to allow you to fine-tune the result.

There are several command-line options available for the `init` task that control what it will generate. You can use these when Gradle is not running from an interactive console.
You can see available options using the `help` task:

[source,bash]
----
gradle help --task init
----

The build type can be specified by using the `--type` command-line option.
For example, to create a Java library project run:

[source,bash]
----
gradle init --type java-library
----

If a `--type` option is not provided, Gradle will attempt to infer the type from the environment. For example, it will infer a type of "`pom`" if it finds a `pom.xml` file to convert to a Gradle build. If the type could not be inferred, the type "`basic`" will be used.

The `init` task also supports generating build scripts using either the Gradle Kotlin DSL or the Gradle Groovy DSL. The build script DSL defaults to the Kotlin DSL for most build types and to the Groovy DSL for Groovy build types. The DSL can be selected by using the `--dsl` command-line option.

For example, to create a Java library project with Kotlin DSL build scripts, run:

[source,bash]
----
gradle init --type java-library --dsl kotlin
----

You can change the directory for the generated project using the `--into` option. It defaults to the directory where the `init` task is run.

You can change the name of the generated project using the `--project-name` option. It defaults to the name of the directory where the `init` task is run.

You can change the package used for generated source files using the `--package` option. It defaults to the project name.

If the `--incubating` option is provided, Gradle will generate build scripts which may use the latest versions of APIs, which are marked `@Incubating` and remain <<feature_lifecycle.adoc#feature_lifecycle,subject to change>>. To disable this behavior, use `--no-incubating`.

If the `--overwrite` option is provided, Gradle will overwrite any existing files in the directory where the `init` task runs. By default, `init` will prompt the user to continue if Gradle finds any files in the directory.

All build types also set up <<gradle_wrapper.adoc#gradle_wrapper, Gradle Wrapper>> in the build.

=== Options

[cols="2,3,1"]
|===
|Option |Description |Example

|`--comments` / `--no-comments`
|Include clarifying comments in files. User can also use the property `org.gradle.buildinit.comments`.
|

|`--incubating`
|Allow the generated build to use new features and APIs.
|

|`--use-defaults` / `--no-use-defaults`
|Use default values for options not configured explicitly.
|

|`--overwrite`
|Allow existing files in the build directory to be overwritten.
|

|`--split-project` / `--no-split-project`
|Split functionality across multiple subprojects?
|

|`--java-version`
|Provides java version to use in the project.
|`11`

|`--insecure-protocol`
|How to handle insecure URLs used for Maven Repositories.
|`fail`

|`--type`
|Set the type of project to generate.
|`java-application`

|`--dsl`
|Set the build script DSL to be used in generated scripts.
|`groovy`

|`--test-framework`
|Set the test framework to be used.
|`junit-jupiter`

|`--project-name`
|Set the project name. Defaults to the name of the directory.
|`my-project`

|`--package`
|Set the package for source files.
|`my.project`
|===

[[sec:build_init_types]]
== Build init types

[[sec:pom_maven_conversion]]
=== `pom` build type (Maven conversion)

The "`pom`" type can be used to convert an Apache Maven build to a Gradle build. This works by converting the POM to one or more Gradle files. It is only able to be used if there is a valid "`pom.xml`" file in the directory that the `init` task is invoked in or, if invoked via the "`-p`" <<command_line_interface.adoc#command_line_interface,command line option>>, in the specified project directory. This "`pom`" type will be automatically inferred if such a file exists.

The Maven conversion implementation was inspired by the https://github.com/jbaruch/maven2gradle[maven2gradle tool] that was originally developed by Gradle community members.

The conversion process has the following features:

* Uses effective POM and effective settings (support for POM inheritance, dependency management, properties)
* Supports both single module and multimodule projects
* Supports custom module names (that differ from directory names)
* Generates general metadata - id, description and version
* Applies <<publishing_maven.adoc#publishing_maven,Maven Publish>>, <<java_library_plugin.adoc#java_library_plugin,Java Library>> and <<war_plugin.adoc#war_plugin,War>> Plugins (as needed)
* Supports packaging war projects as jars if needed
* Generates dependencies (both external and inter-module)
* Generates download repositories (inc. local Maven repository)
* Adjusts Java compiler settings
* Supports packaging of sources, tests, and javadocs
* Supports TestNG runner
* Generates global exclusions from Maven enforcer plugin settings
* Generates <<#sec:dependency_exclusion,dependency excludes>> from Maven `exclusions`
* Provides <<build_init_plugin.adoc#sec:allow_insecure,an option for handling Maven repositories located at URLs using `http`>>

NOTE: Due to fundamental differences between Maven and Gradle, not all features of a Maven build can be converted to Gradle. For example, Maven exclusions work differently from Gradle exclusions. The generated Gradle build should be considered a starting point for further refinement.

[[sec:allow_insecure]]
==== The `--insecure-protocol` option
This option is used to tell the conversion process how to handle converting Maven repositories located at insecure `http` URLs.  Insecure Repositories Set the
link:{groovyDslPath}/org.gradle.buildinit.tasks.InitBuild.html#org.gradle.buildinit.tasks.InitBuild:getInsecureProtocol[--insecure-protocol] option.  The default value is `warn`.

Available values are:

* `fail` - Abort the build immediately upon encountering an insecure repository URL.
* `allow` - Automatically sets the `allowInsecureProtocol` property to `true` for the Maven repository URL in the generated Gradle build script.
* `warn` - Emits a warning about each insecure URL.  Generates commented-out lines to enable each repository, as per the `allow` option.  You will have to opt-in by editing the generated script and uncommenting each repository URL, or else the Gradle build will fail.
* `upgrade` - Convert `http` URLs to `https` URLs automatically.

[[sec:compile_dependencies]]
==== Compile-time dependencies

Maven automatically exposes dependencies using its implicit `compile` scope to the consumers of that project.
This behavior is undesirable, and Gradle takes steps to help library authors reduce their API footprint using the `api` and `implementation` configurations of the `java-library` plugin.

Nevertheless, many Maven projects rely on this _leaking_ behavior. As such, the `init` task will map `compile`-scoped dependencies to the `api` configuration in the generated Gradle build script. The dependencies of the resulting Gradle project will most closely match the exposed dependencies of the existing Maven project; however, post-conversion to Gradle we strongly encourage moving as many `api` dependencies to the `implementation` configuration as possible. This has several benefits:

* Library maintainability - By exposing fewer transitive dependencies to consumers, library maintainers can add or remove dependencies without fear of causing compile-time breakages for consumers.
* Consumers' dependency hygiene - Leveraging the `implementation` configuration in a library prevents its consumers from implicitly relying on the library's transitive dependencies at compile-time, which is considered a bad practice.
* Increased compile avoidance - Reducing the number of transitive dependencies leaked from a project also reduces the likelihood that an ABI change will trigger recompilation of consumers. Gradle will also spend less time indexing the dependencies for its up-to-date checks.
* Compilation speed increase - Reducing the number of transitive dependencies leaked from a project aids the compiler process of its consumers as there are fewer libraries to classload and fewer namespaces for Gradle's incremental compiler to track.

See the <<java_library_plugin.adoc#sec:java_library_separation,API and implementation separation>> and <<java_plugin.adoc#sec:java_compile_avoidance,Compilation avoidance>> sections for more information.

[[sec:java_application]]
=== `java-application` build type

The "`java-application`" build type is not inferable. It must be explicitly specified.

It has the following features:

* Uses the "`application`" plugin to produce a command-line application implemented in Java
* Uses the "`mavenCentral`" dependency repository
* Uses https://junit.org/junit4/[JUnit 4] for testing
* Has directories in the conventional locations for source code
* Contains a sample class and unit test, if there are no existing source or test files

Alternative test framework can be specified by supplying a `--test-framework` argument value. To use a different test framework, execute one of the following commands:

* `gradle init --type java-application --test-framework junit-jupiter`: Uses https://junit.org[JUnit Jupiter] for testing instead of JUnit 4
* `gradle init --type java-application --test-framework spock`: Uses https://spockframework.org[Spock] for testing instead of JUnit 4
* `gradle init --type java-application --test-framework testng`: Uses https://testng.org/doc/index.html[TestNG] for testing instead of JUnit 4

[[sec:java_version_option]]
==== The `--java-version` option

When creating a java project you must set the java version. You can do that by supplying *the major version* of java you wish to use:

[source,bash]
----
gradle init --type java-application  --java-version 11 --dsl kotlin # and other parameters
----

[[sec:java_library]]
=== `java-library` build type

The "`java-library`" build type is not inferable. It must be explicitly specified.

It has the following features:

* Uses the "`java`" plugin to produce a library implemented in Java
* Uses the "`mavenCentral`" dependency repository
* Uses https://junit.org/junit4/[JUnit 4] for testing
* Has directories in the conventional locations for source code
* Contains a sample class and unit test, if there are no existing source or test files

Alternative test framework can be specified by supplying a `--test-framework` argument value. To use a different test framework, execute one of the following commands:

* `gradle init --type java-library --test-framework junit-jupiter`: Uses https://junit.org[JUnit Jupiter] for testing instead of JUnit 4
* `gradle init --type java-library --test-framework spock`: Uses http://code.google.com/p/spock/[Spock] for testing instead of JUnit 4
* `gradle init --type java-library --test-framework testng`: Uses http://testng.org/doc/index.html[TestNG] for testing instead of JUnit 4

[[sec:java_gradle_plugin]]
=== `java-gradle-plugin` build type

The "`java-gradle-plugin`" build type is not inferable. It must be explicitly specified.

It has the following features:

* Uses the "`java-gradle-plugin`" plugin to produce a Gradle plugin implemented in Java
* Uses the "`mavenCentral`" dependency repository
* Uses https://junit.org/junit4/[JUnit 4] and TestKit for testing
* Has directories in the conventional locations for source code
* Contains a sample class and unit test, if there are no existing source or test files

[[sec:kotlin_application]]
=== `kotlin-application` build type

The "`kotlin-application`" build type is not inferable. It must be explicitly specified.

It has the following features:

* Uses the "`org.jetbrains.kotlin.jvm`" and "`application`" plugins to produce a command-line application implemented in Kotlin
* Uses the "`mavenCentral`" dependency repository
* Uses Kotlin 1.x
* Uses https://kotlinlang.org/api/latest/kotlin.test/index.html[Kotlin test library] for testing
* Has directories in the conventional locations for source code
* Contains a sample Kotlin class and an associated Kotlin test class, if there are no existing source or test files

[[sec:kotlin_library]]
=== `kotlin-library` build type

The "`kotlin-library`" build type is not inferable. It must be explicitly specified.

It has the following features:

* Uses the "`org.jetbrains.kotlin.jvm`" plugin to produce a library implemented in Kotlin
* Uses the "`mavenCentral`" dependency repository
* Uses Kotlin 1.x
* Uses https://kotlinlang.org/api/latest/kotlin.test/index.html[Kotlin test library] for testing
* Has directories in the conventional locations for source code
* Contains a sample Kotlin class and an associated Kotlin test class, if there are no existing source or test files

[[sec:kotlin_gradle_plugin]]
=== `kotlin-gradle-plugin` build type

The "`kotlin-gradle-plugin`" build type is not inferable. It must be explicitly specified.

It has the following features:

* Uses the "`java-gradle-plugin`" and "`org.jetbrains.kotlin.jvm`" plugins to produce a Gradle plugin implemented in Kotlin
* Uses the "`mavenCentral`" dependency repository
* Uses Kotlin 1.x
* Uses https://kotlinlang.org/api/latest/kotlin.test/index.html[Kotlin test library] and TestKit for testing
* Has directories in the conventional locations for source code
* Contains a sample class and unit test, if there are no existing source or test files

[[sec:scala_application]]
=== `scala-application` build type

The "`scala-application`" build type is not inferable. It must be explicitly specified.

It has the following features:

* Uses the "`scala`" plugin to produce an application implemented in Scala
* Uses the "`mavenCentral`" dependency repository
* Uses Scala 2.13
* Uses http://www.scalatest.org[ScalaTest] for testing
* Has directories in the conventional locations for source code
* Contains a sample Scala class and an associated ScalaTest test suite, if there are no existing source or test files

[[sec:scala_library]]
=== `scala-library` build type

The "`scala-library`" build type is not inferable. It must be explicitly specified.

It has the following features:

* Uses the "`scala`" plugin to produce a library implemented in Scala
* Uses the "`mavenCentral`" dependency repository
* Uses Scala 2.13
* Uses http://www.scalatest.org[ScalaTest] for testing
* Has directories in the conventional locations for source code
* Contains a sample Scala class and an associated ScalaTest test suite, if there are no existing source or test files

[[sec:groovy_library]]
=== `groovy-library` build type

The "`groovy-library`" build type is not inferable. It must be explicitly specified.

It has the following features:

* Uses the "`groovy`" plugin to produce a library implemented in Groovy
* Uses the "`mavenCentral`" dependency repository
* Uses Groovy 2.x
* Uses http://spockframework.org[Spock testing framework] for testing
* Has directories in the conventional locations for source code
* Contains a sample Groovy class and an associated Spock specification, if there are no existing source or test files

[[sec:groovy_application]]
=== `groovy-application` build type

The "`groovy-application`" build type is not inferable. It must be explicitly specified.

It has the following features:

* Uses the "`application`" and "`groovy`" plugins to produce a command-line application implemented in Groovy
* Uses the "`mavenCentral`" dependency repository
* Uses Groovy 2.x
* Uses http://spockframework.org[Spock testing framework] for testing
* Has directories in the conventional locations for source code
* Contains a sample Groovy class and an associated Spock specification, if there are no existing source or test files

[[sec:groovy_gradle_plugin]]
=== `groovy-gradle-plugin` build type

The "`groovy-gradle-plugin`" build type is not inferable. It must be explicitly specified.

It has the following features:

* Uses the "`java-gradle-plugin`" and "`groovy`" plugins to produce a Gradle plugin implemented in Groovy
* Uses the "`mavenCentral`" dependency repository
* Uses Groovy 2.x
* Uses http://spockframework.org[Spock testing framework] and TestKit for testing
* Has directories in the conventional locations for source code
* Contains a sample class and unit test, if there are no existing source or test files

[[sec:cpp_application]]
=== `cpp-application` build type

The "`cpp-application`" build type is not inferable. It must be explicitly specified.

It has the following features:

* Uses the "`cpp-application`" plugin to produce a command-line application implemented in C++
* Uses the "`cpp-unit-test`" plugin to build and run simple unit tests
* Has directories in the conventional locations for source code
* Contains a sample C++ class, a private header file and an associated test class, if there are no existing source or test files

[[sec:cpp_library]]
=== `cpp-library` build type

The "`cpp-library`" build type is not inferable. It must be explicitly specified.

It has the following features:

* Uses the "`cpp-library`" plugin to produce a C++ library
* Uses the "`cpp-unit-test`" plugin to build and run simple unit tests
* Has directories in the conventional locations for source code
* Contains a sample C++ class, a public header file and an associated test class, if there are no existing source or test files

[[sec:basic]]
=== `basic` build type

The "`basic`" build type is useful for creating a new Gradle build. It creates sample settings and build files, with comments and links to help get started.

This type is used when no type was explicitly specified, and no type could be inferred.

[[sec:dependency_exclusion]]
=== POM exclusion importing

When generating a Gradle build from an existing Maven project, dependency exclusions in the `pom.xml` are translated into the equivalent Gradle syntax:

[source,xml]
----
<dependencies>
    <dependency>
        <groupId>sample.Project</groupId>
        <artifactId>Project</artifactId>
        <version>1.0</version>
        <exclusions>
            <exclusion>
                <groupId>excluded.group</groupId>
                <artifactId>excluded-artifact</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
</dependencies>
----

Because Maven and Gradle handle dependency resolution and exclusions differently, a direct translation may not always be perfectly equivalent.
To ensure build integrity, generated exclusions include a `TODO` comment for manual verification:

[source,kotlin]
----
dependencies {
    implementation("some.group:some-artifact:1.0") {
        // TODO: This exclude was sourced from a POM exclusion and is NOT exactly equivalent
        exclude(group = "excluded.group", module = "excluded-artifact")
    }
}
----
