2025-02-22T01:13:24

This commit is contained in:
2025-02-22 01:13:24 +09:00
parent 1fb14102bb
commit fb0a05d18f
83 changed files with 4955 additions and 23 deletions

View File

@@ -1 +1,64 @@
# Gradle Examples
# **Gradle 실전 가이드 (Kotlin DSL 기반)**
## **1. Gradle 소개**
1.1 빌드 도구란?
1.2 Gradle의 역사와 특징
1.3 Gradle과 다른 빌드 도구 비교 (Maven, Ant)
1.4 Gradle 설치 및 환경 설정
## **2. Gradle 프로젝트 시작하기**
2.1 Gradle 프로젝트 구조 이해
2.2 `settings.gradle.kts``build.gradle.kts` 파일 개요
2.3 Gradle Wrapper 사용법
2.4 첫 번째 Gradle 빌드 실행
## **3. Gradle의 기본 개념**
3.1 프로젝트와 태스크(Task) 개념
3.2 Gradle 라이프사이클 및 실행 과정
3.3 기본 태스크 정의 및 실행
3.4 Gradle의 주요 API와 Kotlin DSL
## **4. 의존성 관리**
4.1 Gradle의 의존성 관리 개요
4.2 `dependencies` 블록과 의존성 선언
4.3 라이브러리 버전 관리 (`version catalog`, `buildSrc`)
4.4 로컬/원격 저장소 사용 (Maven Central, JitPack, 내부 Nexus)
4.5 의존성 분류 (implementation, api, compileOnly, runtimeOnly)
## **5. Gradle 플러그인과 확장**
5.1 플러그인의 개념과 역할
5.2 공식 Gradle 플러그인 사용하기 (Java, Kotlin, Application 등)
5.3 커스텀 Gradle 플러그인 만들기
5.4 플러그인과 태스크의 연계
## **6. Gradle과 테스트 자동화**
6.1 Gradle에서 JUnit 및 Kotest 설정
6.2 테스트 태스크 실행 및 결과 분석
6.3 Jacoco를 활용한 코드 커버리지 측정
6.4 CI/CD 환경에서의 Gradle 테스트 자동화
## **7. 멀티 모듈 프로젝트**
7.1 멀티 모듈 프로젝트 구조
7.2 `settings.gradle.kts`에서 하위 프로젝트 구성
7.3 모듈 간 의존성 관리
7.4 공통 설정 및 코드 공유 방법
## **8. Gradle 빌드 성능 최적화**
8.1 Gradle 캐싱과 병렬 빌드
8.2 `buildSrc``version catalog` 활용
8.3 속도 개선을 위한 설정 (`configuration cache`, `incremental build`)
8.4 Gradle Enterprise를 활용한 빌드 분석
## **9. Gradle과 CI/CD**
9.1 GitHub Actions에서 Gradle 빌드 자동화
9.2 Jenkins, GitLab CI/CD와 Gradle 연동
9.3 Docker 및 Kubernetes 배포 자동화
9.4 빌드 결과물 배포 (JitPack, Maven Central)
## **10. 실전 프로젝트 적용 사례**
10.1 Spring Boot 프로젝트에서 Gradle 사용하기
10.2 Android 프로젝트에서 Gradle 최적화
10.3 Kotlin Multiplatform 프로젝트 빌드
10.4 Gradle을 활용한 서버/프론트엔드 통합 빌드
---

13
app.sh Executable file
View File

@@ -0,0 +1,13 @@
#! /usr/bin/env bash
case $1 in
gitup)
echo "Pushing to git"
git add -A
git commit -m $(date "+%Y-%m-%dT%H:%M:%S")
git push origin
;;
*)
echo "Launching editor"
code .
esac

114
doc/01_Gradle.md Normal file
View File

@@ -0,0 +1,114 @@
# Gradle: 강력한 빌드 자동화 도구
소프트웨어 개발에서 빌드는 단순히 코드를 컴파일하는 것을 넘어, 의존성 관리, 테스트 실행, 배포 등의 여러 단계를 포함하는 중요한 과정이다. 이 모든 과정을 수동으로 수행하는 것은 비효율적이며, 실수를 유발할 가능성이 크다. 이를 해결하기 위해 등장한 것이 **빌드 도구(build tool)**다.
## 빌드 도구란?
빌드 도구는 소스 코드에서 실행 가능한 소프트웨어를 생성하는 과정(컴파일, 테스트, 패키징, 배포 등)을 자동화하는 도구다. 빌드 도구가 없다면 개발자는 코드를 수정할 때마다 수작업으로 컴파일하고, 필요한 라이브러리를 수동으로 추가하고, 여러 명이 협업하는 프로젝트에서는 의존성 충돌을 해결하는 데 많은 시간을 소비해야 한다.
대표적인 빌드 도구의 역할은 다음과 같다.
- 소스 코드 컴파일 및 패키징
- 라이브러리 의존성 관리
- 테스트 자동화
- 배포 및 CI/CD 연동
- 멀티 모듈 프로젝트 관리
이제 Gradle이 등장하기 전의 주요 빌드 도구들을 살펴보자.
## 빌드 도구의 발전과 Gradle의 등장
### Make → Ant → Maven → Gradle
1. Make (1977)
- 초기 빌드 도구로, 주로 C/C++ 프로젝트에서 사용됨.
- `Makefile`을 기반으로 동작하며, 파일 간의 종속성을 정의하여 빌드를 수행.
- 플랫폼 의존적이며 XML과 같은 구조적 설정이 부족.
2. Apache Ant (2000)
- Java 생태계에서 등장한 XML 기반 빌드 도구.
- Make보다 강력한 기능을 제공하지만, XML 설정이 장황하고 유지보수성이 떨어짐.
- 의존성 관리 기능이 부족하여, 추가 도구(Ivy 등)를 사용해야 함.
3. Apache Maven (2004)
- Ant의 단점을 보완하기 위해 XML 기반으로 등장.
- 프로젝트 관리 모델(POM, Project Object Model)을 도입하여 의존성 관리 기능 강화.
- 표준화된 프로젝트 구조와 라이프사이클을 제공하지만, 유연성이 부족하고 XML 설정이 여전히 복잡함.
4. Gradle (2009)
- Maven의 단점을 해결하고, 유연성과 성능을 극대화한 빌드 도구로 등장.
- Groovy 기반의 DSL(Domain Specific Language)로 설정을 간결하게 작성할 수 있음.
- 이후 Kotlin DSL 지원이 추가되면서, 더욱 강력한 기능을 제공.
## Gradle의 특징
Gradle은 현대적인 빌드 도구로서 다음과 같은 강력한 기능을 제공한다.
### 유연한 DSL
Gradle은 Groovy와 Kotlin 기반의 DSL을 제공하여 직관적이고 간결한 설정이 가능하다. 특히, Kotlin DSL은 정적 타입 체크와 코드 자동 완성 기능을 지원하여 개발자의 생산성을 높인다.
```kotlin
plugins {
kotlin("jvm") version "1.8.0"
}
dependencies {
implementation("org.jetbrains.kotlin:kotlin-stdlib")
}
```
### 고성능 빌드
Gradle은 다음과 같은 기술을 활용하여 빌드 속도를 최적화한다.
- **태스크 캐싱(Task Caching):** 이전 빌드 결과를 재사용하여 불필요한 작업을 줄임.
- **병렬 빌드(Parallel Execution):** 멀티코어를 활용하여 여러 태스크를 동시에 실행.
- **증분 빌드(Incremental Build):** 변경된 파일만 다시 빌드하여 시간을 절약.
### 강력한 의존성 관리
Gradle은 Maven Central, JCenter, JitPack 등 다양한 저장소에서 의존성을 쉽게 가져올 수 있으며, 의존성 충돌을 자동으로 해결하는 기능도 제공한다.
### 멀티 모듈 프로젝트 지원
대규모 프로젝트에서 여러 개의 서브 프로젝트를 관리할 수 있도록 멀티 모듈 빌드를 지원한다.
### 플러그인 기반 확장성
Gradle은 공식 및 커스텀 플러그인을 활용하여 빌드 프로세스를 확장할 수 있다. 예를 들어, Spring Boot 플러그인을 적용하면 Spring Boot 애플리케이션을 쉽게 패키징할 수 있다.
## Gradle vs Maven vs Ant
| 기능 | Gradle | Maven | Ant |
|------|--------|--------|------|
| 설정 방식 | Groovy/Kotlin DSL | XML | XML |
| 성능 | 빠름 (증분 빌드, 캐싱) | 느림 | 느림 |
| 의존성 관리 | 지원 | 지원 | 별도 도구 필요 (Ivy) |
| 빌드 스크립트 가독성 | 간결함 | 장황함 | 장황함 |
| 확장성 | 매우 높음 | 제한적 | 제한적 |
| 표준화 | 유연함 | 표준적 | 유연하지만 복잡 |
Gradle은 성능과 확장성 면에서 Maven과 Ant보다 우수하며, 특히 Kotlin DSL을 활용하면 코드 자동 완성과 타입 안정성을 누릴 수 있다.
## Gradle 설치 및 환경 설정
### Gradle 설치
1. Gradle 다운로드
- 공식 사이트([gradle.org](https://gradle.org/releases/))에서 최신 버전을 다운로드한다.
2. 압축 해제 및 환경 변수 설정
- 압축을 원하는 디렉터리에 해제하고, `GRADLE_HOME` 환경 변수를 설정한 후 `PATH`에 추가한다.
**Linux/macOS (bash/zsh)**
```sh
export GRADLE_HOME=/opt/gradle
export PATH=$GRADLE_HOME/bin:$PATH
```
**Windows (PowerShell)**
```powershell
[System.Environment]::SetEnvironmentVariable("GRADLE_HOME", "C:\Gradle", "User")
[System.Environment]::SetEnvironmentVariable("Path", "$env:Path;C:\Gradle\bin", "User")
```
3. 설치 확인
```sh
gradle -v
```

View File

@@ -1,22 +0,0 @@
# 그래들
* 프로젝트: 개발 중인 응용프로그램 또는 라이브러리 소프트웨어입니다. 싱글 프로젝트는 루트 프로젝트 하나만 있는 프로젝트이며, 멀티프로젝트는 하나의 루트 프로젝트와 여러 개의 서브 프로젝트로 구성됩니다.
* 빌드 스크립트
* 의존성 관리
* 태스크
* 플러그인
## 그래들 래퍼
시스템에 `gradle`을 설치하는 대신에 `gradlew`를 사용합니다.
## settings.gradle.kts
```kotlin
rootProject.name = "my-project" // 루트 프로젝트의 이름을 정의합니다.
include("sub-project-1") // 서브 프로젝트의 이름을 모두 정의합니다.
include("sub-project-2")
include("sub-project-3")
```
## build.gradle.kts

View File

@@ -0,0 +1,218 @@
# Gradle 프로젝트
Gradle을 사용하면 프로젝트의 빌드 과정을 자동화할 수 있으며, 프로젝트의 크기와 복잡도에 따라 다양한 방식으로 구성할 수 있다.
# Gradle 프로젝트란?
Gradle에서 프로젝트(Project)는 빌드가 수행되는 단위를 의미한다. 하나의 프로젝트는 애플리케이션, 라이브러리 또는 다른 빌드 가능한 항목일 수 있으며, 여러 개의 프로젝트를 포함하는 멀티 프로젝트 구조도 가능하다.
다음 명령을 사용해서 Gradle 프로젝트를 시작할 수 있다.
```bash
mkdir my-project
cd my-project
gradle init --type java-application --dsl kotlin
```
Gradle 래퍼를 사용해서 빌드 명령을 수행하는 예시이다.
```bash
./gradlew build
```
## Gradle 프로젝트 구조
Gradle 프로젝트는 일반적으로 다음과 같은 구조를 가진다.
```
my-project/
├── app
│   ├── build.gradle.kts # 빌드 설정 파일 (Kotlin DSL)
│   └── src # 소스 코드 디렉터리
│   ├── main # 애플리케이션 코드
│   │   ├── java # Java 소스 코드
│   │   │   └── org
│   │   │   └── example
│   │   │   └── App.java
│   │   └── resources # 설정 파일 및 기타 리소스
│   └── test # 테스트 코드
│   ├── java # Java 테스트 코드
│   │   └── org
│   │   └── example
│   │   └── AppTest.java
│   └── resources # 테스트 관련 리소스
├── gradle
│   ├── libs.versions.toml # 버전 카탈로그 파일
│   └── wrapper
│   ├── gradle-wrapper.jar
│   └── gradle-wrapper.properties
├── gradle.properties # 프로젝트 전역 설정 파일
├── gradlew # Gradle Wrapper 실행 파일 (Linux/macOS)
├── gradlew.bat # Gradle Wrapper 실행 파일 (Windows)
├── settings.gradle.kts # 프로젝트 설정 파일
```
각 파일과 디렉터리의 역할을 살펴보자.
- `src/main/java` : 애플리케이션의 주요 소스 코드가 위치하는 곳.
- `src/main/resources`: 애플리케이션 실행에 필요한 설정 파일 또는 기타 리소스 파일을 포함한다.
- `src/test/java` : 테스트 코드가 위치하는 곳.
- `build/`: Gradle이 빌드한 결과물이 저장되는 디렉터리로, 컴파일된 클래스 파일과 패키징된 JAR 파일 등이 여기에 생성된다.
- `gradle/`: Gradle Wrapper 관련 파일이 저장되는 곳.
- `gradlew`, `gradlew.bat`: Gradle Wrapper 실행 파일로, 프로젝트에서 지정된 Gradle 버전을 사용할 수 있도록 도와준다.
## 설정 파일과 빌드 파일
Gradle 프로젝트에는 `settings.gradle.kts``build.gradle.kts`라는 두 개의 주요 설정 파일이 있다.
### `settings.gradle.kts`: 프로젝트 설정 파일
이 파일은 프로젝트의 전반적인 설정을 담당하며, 멀티 모듈 프로젝트를 구성할 때 각 모듈을 정의하는 역할을 한다.
```kotlin
plugins {
// Apply the foojay-resolver plugin to allow automatic download of JDKs
id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0"
}
rootProject.name = "my-project"
```
만약 멀티 모듈 프로젝트라면 다음과 같이 하위 모듈을 정의할 수도 있다.
```kotlin
rootProject.name = "my-project"
include("module1", "module2")
```
### `build.gradle.kts`: 빌드 설정 파일
이 파일은 프로젝트의 빌드 과정을 정의하는 곳이다.
```kotlin
// build.gradle.kts
plugins {
application // 실행 가능한 애플리케이션 빌드를 위한 플러그인
}
repositories {
mavenCentral() // 라이브러리 저장소 설정
}
dependencies {
testImplementation(libs.junit.jupiter) // JUnit 테스트 라이브러리 추가
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
implementation(libs.guava)
}
java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(21))
}
}
application {
mainClass.set("com.example.App") // 실행할 메인 클래스 지정
}
tasks.named<Test>("test") {
// Use JUnit Platform for unit tests.
useJUnitPlatform()
}
```
### `gradle.properties`: 전역 속성 설정 파일
이 파일은 프로젝트의 전역 설정을 관리하는 데 사용된다.
```properties
org.gradle.configuration-cache=true
org.gradle.jvmargs=-Xmx2g # JVM 메모리 설정
```
이제 Gradle Wrapper를 사용하여 프로젝트를 더욱 쉽게 관리하는 방법을 살펴보자.
### `libs.versions.toml` : 버전 카탈로그 파일
Gradle **버전 카탈로그(Version Catalog)** 는 프로젝트에서 **의존성 관리의 일관성을 유지하고, 중복을 줄이며, 가독성을 높이기 위해** 도입된 기능이다.
Gradle 7.0부터 정식으로 지원되며, `libs.versions.toml` 파일을 사용하여 설정할 수 있다.
```toml
[versions]
guava = "33.3.1-jre"
junit-jupiter = "5.11.1"
springBoot = "3.1.0"
[libraries]
guava = { module = "com.google.guava:guava", version.ref = "guava" }
junit-jupiter = { module = "org.junit.jupiter:junit-jupiter", version.ref = "junit-jupiter" }
spring-boot-starter = { module = "org.springframework.boot:spring-boot-starter", version.ref = "springBoot" }
groovy-core = { module = "org.codehaus.groovy:groovy", version.ref = "groovy" }
groovy-json = { module = "org.codehaus.groovy:groovy-json", version.ref = "groovy" }
groovy-nio = { module = "org.codehaus.groovy:groovy-nio", version.ref = "groovy" }
[bundles]
groovy = ["groovy-core", "groovy-json", "groovy-nio"]
[plugins]
springBoot = { id = "org.springframework.boot", version.ref = "springBoot" }
```
> `junit-jupiter`를 빌드 설정 파일에서 참조할 때에는 `-` 대신 `.`을 써서 `libs.junit.jupiter`와 같이 사용한다.
`build.gradle.kts`
```kotlin
plugins {
alias(libs.plugins.springBoot)
}
dependencies {
implementation(libs.kotlin.stdlib)
implementation(libs.spring.boot.starter)
}
```
* `[versions]` 섹션
- 라이브러리 및 플러그인의 버전을 정의하는 부분
- `version.ref`를 사용하여 참조 가능
* `[libraries]` 섹션
- 라이브러리를 정의하는 부분
- `module`에 그룹과 아티팩트 ID를 명시
- `version.ref`를 사용해 `[versions]`에서 정의한 버전 참조 가능
* `[plugins]` 섹션
- Gradle 플러그인을 정의하는 부분
- `id`는 플러그인의 ID, `version.ref``[versions]`에서 정의한 버전 참조
## Gradle Wrapper 사용하기
Gradle Wrapper(그래들 래퍼)는 프로젝트에서 일관된 Gradle 버전을 사용할 수 있도록 도와주는 기능이다.
### Gradle Wrapper 생성
Gradle이 설치되어 있다면 다음 명령을 실행하여 Gradle Wrapper를 생성할 수 있다.
```sh
gradle wrapper --gradle-version 8.2
```
이 명령을 실행하면 `gradlew`, `gradlew.bat`, 그리고 `gradle/` 디렉터리가 생성된다.
### Gradle Wrapper로 빌드 실행
Gradle Wrapper를 사용하면 Gradle이 설치되지 않은 환경에서도 프로젝트를 빌드할 수 있다.
```sh
./gradlew build # Linux/macOS
```
```sh
gradlew.bat build # Windows
```
Wrapper는 지정된 Gradle 버전을 자동으로 다운로드하여 사용한다. 따라서, 개발팀 내에서 같은 Gradle 버전을 유지할 수 있으며, CI/CD 환경에서도 동일한 빌드 환경을 보장할 수 있다.
### Wrapper 업데이트
Gradle 버전을 최신으로 업데이트하려면 다음 명령을 실행한다.
```sh
./gradlew wrapper --gradle-version 8.12
```
```bash
./gradlew wrapper --gradle-version latest
```
이제 `gradlew` 실행 시 자동으로 새로운 Gradle 버전이 적용된다.

353
doc/03_Gradle 태스크.md Normal file
View File

@@ -0,0 +1,353 @@
# 태스크(Task)
Gradle은 태스크(Task) 기반 빌드 시스템으로, 프로젝트를 구성하고 자동화할 수 있는 강력한 기능을 제공한다.
태스크(Task)는 Gradle에서 실행 가능한 단위이며, 프로젝트를 빌드하는 데 필요한 작업(예: 컴파일, 테스트, 패키징 등)을 정의한다. Gradle은 기본적으로 여러 태스크를 제공하지만, 사용자가 직접 정의하여 실행할 수도 있다.
## 태스크 목록 확인
```bash
./gradlew tasks
```
## 기본적인 태스크 정의와 실행
Gradle에서는 `build.gradle.kts` 파일에서 태스크를 정의할 수 있다.
### 간단한 태스크 정의
Kotlin DSL을 사용하여 기본적인 태스크를 정의하는 방법을 살펴보자.
```kotlin
tasks.register("hello") {
doLast {
println("Hello, Gradle!")
}
}
```
위 태스크는 `hello`라는 이름으로 등록되며, 실행하면 `"Hello, Gradle!"`이 출력된다.
#### `tasks.register` vs `tasks.create`
태스크를 등록하는 방법에는 `tasks.register``tasks.create`가 있다.
```kotlin
// 지연 평가 방식 (Lazy Evaluation)
val lazyTask = tasks.register("lazyTask") {
doLast {
println("이 태스크는 실행 시점에서 평가됩니다.")
}
}
// 즉시 평가 방식 (Eager Evaluation)
val eagerTask = tasks.create("eagerTask") {
doLast {
println("이 태스크는 빌드 스크립트가 로드될 때 즉시 평가됩니다.")
}
}
```
- `tasks.register`**지연 평가(Lazy Evaluation)** 방식으로, 태스크가 실행될 때까지 구성이 지연된다.
- `tasks.create`**즉시 평가(Eager Evaluation)** 방식으로, 스크립트가 로드될 때 바로 실행된다.
일반적으로 성능상의 이유로 `tasks.register`를 사용하는 것이 권장된다.
### 태스크 실행 방법
터미널에서 다음 명령어를 실행하면 정의한 태스크를 실행할 수 있다.
```sh
./gradlew hello
```
### 여러 액션을 포함한 태스크
태스크 내에서 여러 개의 액션을 정의할 수도 있다.
```kotlin
tasks.register("greet") {
doFirst {
println("처음 실행되는 액션")
}
doLast {
println("마지막으로 실행되는 액션")
}
}
```
이 태스크를 실행하면 `"처음 실행되는 액션"`이 먼저 출력되고, `"마지막으로 실행되는 액션"`이 나중에 출력된다.
### 태스크 종속성(Task Dependencies)
특정 태스크가 다른 태스크 이후에 실행되도록 설정할 수 있다.
```kotlin
tasks.register("taskA") {
doLast {
println("Task A 실행")
}
}
tasks.register("taskB") {
dependsOn("taskA") // taskA가 먼저 실행됨
doLast {
println("Task B 실행")
}
}
```
위 예제에서 `taskB`를 실행하면 `taskA`가 먼저 실행된 후 `taskB`가 실행된다.
## 사용자 정의 확장 프로퍼티
Gradle에서는 사용자 정의 확장 프로퍼티를 추가할 수 있다.
```kotlin
val greeting: String by project
tasks.register("customGreet") {
doLast {
println("Greeting message: $greeting")
}
}
```
그리고 `gradle.properties` 파일에 값을 추가하면 실행 시 사용할 수 있다.
```properties
greeting=Hello, Kotlin DSL!
```
## 빝트인 태스크
```kotlin
tasks.register<Copy>("copyTask") {
from("source")
into("target")
include("*.war")
}
```
* Copy - Copy is useful to copy files around.
* Delete - Delete is useful to delete files and directories.
* Exec - Exec is useful to execute arbitrary O/S commands.
* Zip - Zip is useful to bundle files.
---
# **Gradle 빌트인 태스크 정리**
Gradle은 다양한 **빌트인 태스크(Built-in Task)**를 제공하며, 프로젝트 빌드 및 관리를 효율적으로 수행할 수 있도록 돕는다.
특히 `Copy`, `Zip` 등의 태스크는 파일을 조작하고 패키징하는 데 유용하다.
아래에서 주요 빌트인 태스크를 정리하고, 사용 예시를 함께 제공한다.
---
## **1. 주요 빌트인 태스크 목록**
| **태스크(Task)** | **설명** |
|----------------|----------------------------|
| `Copy` | 파일 및 디렉터리를 복사 |
| `Sync` | `Copy`와 유사하지만, 대상 디렉터리를 동기화 |
| `Zip` | ZIP 압축 파일 생성 |
| `Tar` | TAR 압축 파일 생성 (`.tar`, `.tar.gz` 등) |
| `Delete` | 파일 및 디렉터리 삭제 |
| `Exec` | 외부 프로세스 실행 |
| `JavaExec` | Java 애플리케이션 실행 |
| `Task` | 기본적인 사용자 정의 태스크 생성 |
| `DefaultTask` | 기본적으로 실행할 수 있는 커스텀 태스크 생성 |
| `Wrapper` | Gradle Wrapper 스크립트 생성 |
| `Test` | 테스트 실행 |
| `Jar` | JAR 파일 생성 |
| `War` | WAR(Web Application Archive) 파일 생성 |
| `Ear` | EAR(Enterprise Application Archive) 파일 생성 |
| `GenerateBuildConfig` | Android 프로젝트에서 `BuildConfig` 클래스 생성 |
| `CompileJava` | Java 코드 컴파일 |
| `ProcessResources` | 리소스 처리 |
| `Assemble` | 프로젝트 빌드 결과물을 패키징 |
| `Check` | 프로젝트 검증(테스트 포함) |
| `Build` | 전체 빌드 수행 |
| `Clean` | 빌드 결과물 삭제 |
| `Dependencies` | 의존성 정보 출력 |
---
## **2. 파일 조작 관련 태스크**
### **(1) Copy 태스크 - 파일 및 디렉터리 복사**
`Copy` 태스크는 특정 디렉터리나 파일을 다른 위치로 복사하는 데 사용된다.
**사용 예제:**
```kotlin
tasks.register<Copy>("copyFiles") {
from("src/main/resources") // 복사할 원본 디렉터리
into("build/copied-resources") // 복사 대상 디렉터리
}
```
**고급 예제 (파일 필터링 적용):**
```kotlin
tasks.register<Copy>("copySpecificFiles") {
from("src/assets")
into("build/assets")
include("**/*.png") // PNG 파일만 복사
exclude("temp/**") // temp 폴더 제외
}
```
---
### **(2) Sync 태스크 - Copy와 유사하지만 대상 디렉터리를 동기화**
`Sync` 태스크는 `Copy`와 유사하지만, **대상 디렉터리에 없는 파일을 삭제하여 동기화**하는 점이 다르다.
**사용 예제:**
```kotlin
tasks.register<Sync>("syncFiles") {
from("src/main/resources")
into("build/synced-resources")
}
```
---
### **(3) Delete 태스크 - 파일 및 디렉터리 삭제**
`Delete` 태스크는 특정 파일이나 디렉터리를 삭제하는 데 사용된다.
**사용 예제:**
```kotlin
tasks.register<Delete>("cleanOutput") {
delete("build/output")
}
```
---
## **3. 압축 관련 태스크**
### **(1) Zip 태스크 - ZIP 압축 파일 생성**
`Zip` 태스크를 사용하면 특정 파일 및 디렉터리를 `.zip` 파일로 압축할 수 있다.
**사용 예제:**
```kotlin
tasks.register<Zip>("zipFiles") {
from("src/main/resources")
archiveFileName.set("resources.zip") // 생성할 ZIP 파일 이름
destinationDirectory.set(file("build/distributions")) // ZIP 저장 위치
}
```
**고급 예제 (파일 선택 및 압축 내 경로 설정):**
```kotlin
tasks.register<Zip>("zipSelectedFiles") {
from("src/assets") {
include("**/*.jpg") // 특정 파일만 포함
}
archiveFileName.set("images.zip")
destinationDirectory.set(file("build/zipped"))
}
```
---
### **(2) Tar 태스크 - TAR 압축 파일 생성**
TAR 파일(`.tar`, `.tar.gz`, `.tar.bz2`)을 생성하는 데 사용된다.
**사용 예제:**
```kotlin
tasks.register<Tar>("tarFiles") {
from("src/main/resources")
archiveFileName.set("resources.tar")
compression = Compression.GZIP // .tar.gz 압축 설정
destinationDirectory.set(file("build/distributions"))
}
```
---
## **4. 실행 관련 태스크**
### **(1) Exec 태스크 - 외부 프로세스 실행**
`Exec` 태스크는 쉘 명령어 또는 외부 프로세스를 실행할 때 사용된다.
**사용 예제:**
```kotlin
tasks.register<Exec>("runShellCommand") {
commandLine("ls", "-l") // 리눅스/macOS에서 파일 목록 출력
}
```
**Windows에서 사용 예제:**
```kotlin
tasks.register<Exec>("runBatchScript") {
commandLine("cmd", "/c", "dir") // Windows에서 디렉터리 목록 출력
}
```
---
### **(2) JavaExec 태스크 - Java 애플리케이션 실행**
Java 실행 가능한 프로그램을 실행할 때 사용한다.
**사용 예제:**
```kotlin
tasks.register<JavaExec>("runJavaApp") {
mainClass.set("com.example.Main") // 실행할 클래스
classpath = sourceSets.main.get().runtimeClasspath
}
```
---
## **5. 빌드 및 테스트 관련 태스크**
### **(1) CompileJava 태스크 - Java 코드 컴파일**
Java 코드를 컴파일하는 데 사용된다.
**사용 예제:**
```kotlin
tasks.named<JavaCompile>("compileJava") {
options.encoding = "UTF-8"
}
```
---
### **(2) Test 태스크 - 테스트 실행**
JUnit, TestNG 등의 테스트 프레임워크를 실행하는 데 사용된다.
**사용 예제:**
```kotlin
tasks.named<Test>("test") {
useJUnitPlatform() // JUnit 5 사용
}
```
---
### **(3) Assemble 태스크 - 패키징 실행**
프로젝트의 빌드 결과물을 생성하는 태스크이다.
기본적으로 `Jar`, `War` 등의 태스크를 포함한다.
**사용 예제:**
```kotlin
tasks.named("assemble") {
dependsOn("jar") // jar 태스크를 먼저 실행
}
```
---
### **(4) Build 태스크 - 전체 빌드 수행**
`assemble`, `test` 등을 포함하여 프로젝트의 전체 빌드를 수행한다.
**사용 예제:**
```kotlin
tasks.named("build") {
dependsOn("test")
}
```
---
## **결론**
Gradle의 빌트인 태스크는 파일 복사, 압축, 빌드, 테스트, 실행 등 다양한 작업을 자동화할 수 있도록 돕는다.
각 태스크의 동작을 이해하고 적절히 활용하면 **빌드 스크립트를 더욱 효율적으로 구성**할 수 있다.

167
doc/04_의존성 관리.md Normal file
View File

@@ -0,0 +1,167 @@
# 의존성 관리
의존성이란, 프로젝트가 실행되거나 빌드될 때 필요한 외부 라이브러리를 의미한다. Gradle에서는 `dependencies` 블록을 통해 프로젝트에서 사용할 라이브러리를 선언한다.
Gradle은 중앙 저장소(Maven Central, JCenter 등)나 로컬 저장소를 활용하여 필요한 라이브러리를 다운로드하고 프로젝트에 추가할 수 있다.
## `dependencies` 블록 사용법
Gradle에서는 `dependencies` 블록을 사용하여 필요한 라이브러리를 정의할 수 있다.
### 기본적인 의존성 추가
```
group:name:version
```
아래는 Kotlin DSL을 사용하여 `build.gradle.kts`에서 의존성을 추가하는 예제이다.
```kotlin
dependencies {
implementation("org.jetbrains.kotlin:kotlin-stdlib:1.8.0") // Kotlin 표준 라이브러리 추가
testImplementation("org.junit.jupiter:junit-jupiter:5.9.0") // JUnit 테스트 라이브러리 추가
}
```
위 코드는 다음과 같은 역할을 한다.
- `implementation`: 실행과 컴파일 과정에서 필요한 라이브러리 추가
- `testImplementation`: 테스트 코드에서만 필요한 라이브러리 추가
## 버전 관리 방법
### `gradle.properties` 파일을 활용한 버전 관리
의존성 버전을 `gradle.properties` 파일에서 정의하여 프로젝트 전반에서 일관되게 관리할 수 있다.
`gradle.properties` 파일:
```properties
kotlinVersion=1.8.0
junitVersion=5.9.0
```
`build.gradle.kts`에서 참조:
```kotlin
val kotlinVersion: String by project
val junitVersion: String by project
dependencies {
implementation("org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion")
testImplementation("org.junit.jupiter:junit-jupiter:$junitVersion")
}
```
### `versions.gradle.kts` 파일을 활용한 버전 관리
여러 개의 의존성 버전을 중앙에서 관리하려면 `versions.gradle.kts` 파일을 만들고 버전을 정의할 수도 있다.
`gradle/versions.gradle.kts` 파일:
```kotlin
extra["kotlinVersion"] = "1.8.0"
extra["junitVersion"] = "5.9.0"
```
`build.gradle.kts`에서 참조:
```kotlin
val kotlinVersion: String by extra
val junitVersion: String by extra
dependencies {
implementation("org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion")
testImplementation("org.junit.jupiter:junit-jupiter:$junitVersion")
}
```
### `libs.versions.toml` 파일을 활용한 버전 관리
...
## 원격 및 로컬 저장소 설정
Gradle은 원격 저장소(Maven Central, JCenter, Google Maven 등)와 로컬 저장소를 지원한다.
### 원격 저장소 사용
`repositories` 블록에서 사용할 저장소를 설정할 수 있다.
```kotlin
repositories {
mavenCentral() // Maven Central 저장소 사용
google() // Google Maven 저장소 사용 (Android 개발 시 유용)
}
```
### 로컬 저장소 사용
프로젝트 내부에서 관리하는 라이브러리를 직접 추가할 수도 있다.
```kotlin
repositories {
mavenLocal() // 로컬 Maven 저장소 사용
}
```
또는 특정 디렉터리를 로컬 저장소로 지정할 수도 있다.
```kotlin
repositories {
flatDir {
dirs("libs")
}
}
```
이렇게 설정한 후, `libs` 폴더에 저장된 JAR 파일을 의존성으로 추가할 수 있다.
```kotlin
dependencies {
implementation(files("libs/my-library.jar"))
}
```
## 의존성의 분류
Gradle에서는 의존성을 프로젝트에서 어떻게 사용할지에 따라 여러 범주로 분류한다.
### 주요 의존성 유형
| 의존성 유형(Configuration) | 설명 | 적용 대상 | 전이적(Transitive) |
|-----------------|------------------------------------|------------------|------------------|
| `implementation` | 컴파일 시 접근 불가, 런타임에서만 사용 가능 | 애플리케이션 | O (기본) |
| `api` | 다른 모듈에서도 접근 가능 | 라이브러리 | O (기본) |
| `compileOnly` | 컴파일 시에만 필요, 런타임에는 포함되지 않음 | 애플리케이션 & 라이브러리 | X |
| `runtimeOnly` | 런타임에서만 필요, 컴파일 시에는 사용 불가 | 애플리케이션 & 라이브러리 | O |
| `testImplementation` | 테스트 코드에서만 사용 | 테스트 코드 | O |
| `testCompileOnly` | 테스트 코드에서만 컴파일 시 필요 | 테스트 코드 | X |
| `testRuntimeOnly` | 테스트 실행 시에만 필요 | 테스트 코드 | O |
| `annotationProcessor` | 컴파일 시 애노테이션 프로세서를 실행할 때 사용 | 애노테이션 기반 라이브러리 | X |
### 예제
```kotlin
dependencies {
implementation("com.squareup.retrofit2:retrofit:2.9.0") // Retrofit 라이브러리 추가
api("org.apache.commons:commons-lang3:3.12.0") // 다른 모듈에서도 사용 가능
compileOnly("javax.annotation:javax.annotation-api:1.3.2") // 컴파일 시에만 필요
runtimeOnly("org.postgresql:postgresql:42.3.1") // 실행할 때만 필요
testImplementation("org.junit.jupiter:junit-jupiter:5.9.0") // 테스트 코드에서만 필요
}
```
### `api` vs `implementation`
멀티 모듈 프로젝트에서 `api``implementation`의 차이를 이해하는 것이 중요하다.
```kotlin
dependencies {
api("com.example:shared-library:1.0.0") // 다른 모듈에서도 접근 가능
implementation("com.example:internal-library:1.0.0") // 현재 모듈에서만 사용 가능
}
```
- `api`로 추가한 라이브러리는 이 모듈을 의존하는 다른 모듈에서도 사용할 수 있다.
- `implementation`으로 추가한 라이브러리는 현재 모듈에서만 사용 가능하며, 빌드 성능이 향상된다.

172
doc/05_플러그인.md Normal file
View File

@@ -0,0 +1,172 @@
# 플러그인
Gradle의 플러그인은 프로젝트의 빌드 및 관리를 확장하는 강력한 기능을 제공한다. Gradle은 기본적인 빌드 기능을 제공하지만, 플러그인을 사용하면 프로젝트에 특정 기능을 추가하고, 빌드 스크립트에서 불필요한 반복을 줄일 수 있다. 예를 들어, Java 프로젝트를 빌드하거나, Kotlin을 지원하거나, 애플리케이션을 패키징하는 등의 작업을 자동화할 수 있다.
### 플러그인의 종류
Gradle 플러그인은 크게 두 가지로 나뉜다.
- **빌드 스크립트에 포함된 로컬 플러그인**
- 프로젝트 내에서 직접 정의하여 사용하는 플러그인
- **외부 저장소에서 제공하는 공식 플러그인 및 커스텀 플러그인**
- Gradle 공식 플러그인이나 외부 개발자가 만든 플러그인
## Gradle 플러그인 적용 방법
Gradle에서 플러그인을 적용하는 방법은 크게 두 가지가 있다.
### `plugins` 블록 사용
Kotlin DSL(`build.gradle.kts`)에서 플러그인을 적용하는 방식이다.
```kotlin
plugins {
id("java") // Java 프로젝트를 위한 플러그인
id("org.jetbrains.kotlin.jvm") version "1.8.0" // Kotlin JVM 플러그인
}
```
### `apply` 함수 사용
이전 Gradle 방식으로, 현재는 `plugins` 블록을 사용하는 것이 권장된다.
```kotlin
apply(plugin = "java")
apply(plugin = "org.jetbrains.kotlin.jvm")
```
## Gradle의 공식 플러그인
Gradle은 다양한 공식 플러그인을 제공하며, 각 플러그인은 특정한 목적을 위해 사용된다.
### Java 플러그인 (`java`)
Java 애플리케이션을 개발할 때 사용하는 플러그인으로, 컴파일, 테스트, JAR 패키징 등의 기능을 제공한다.
```kotlin
plugins {
id("java")
}
```
기본적으로 제공하는 태스크:
- `compileJava`: Java 코드 컴파일
- `processResources`: 리소스 처리
- `jar`: JAR 파일 생성
- `test`: JUnit 등의 프레임워크로 테스트 실행
### Java Library 플러그인 (`java-library`)
라이브러리 형태의 Java 프로젝트를 위한 플러그인으로, `java` 플러그인보다 좀 더 세분화된 의존성 관리를 제공한다.
```kotlin
plugins {
id("java-library")
}
```
**차이점:**
- `api` 의존성을 사용하여 다른 모듈에서도 접근 가능하게 설정할 수 있다.
- `implementation``api`의 차이를 명확하게 구분하여, 라이브러리 프로젝트에 적합하다.
### Application 플러그인 (`application`)
실행 가능한 애플리케이션을 개발할 때 사용하는 플러그인으로, 실행 가능한 JAR 파일을 생성하고, `mainClass`를 지정할 수 있다.
```kotlin
plugins {
id("application")
}
application {
mainClass.set("com.example.MainKt")
}
```
제공 테스크 :
- `run`: 애플리케이션 실행
- `installDist`: 실행 가능한 패키지 생성
- `distZip`: ZIP 파일로 애플리케이션 배포
### Maven Publish 플러그인 (`maven-publish`)
라이브러리를 Maven 중앙 저장소 또는 내부 Nexus, Artifactory 등의 저장소에 배포할 때 사용한다.
```kotlin
plugins {
id("maven-publish")
}
publishing {
publications {
create<MavenPublication>("maven") {
groupId = "com.example"
artifactId = "my-library"
version = "1.0.0"
from(components["java"])
}
}
}
```
### Android 플러그인 (`com.android.application`)
Android 애플리케이션을 개발할 때 사용하는 플러그인이다.
```kotlin
plugins {
id("com.android.application")
id("kotlin-android")
}
```
- Android 프로젝트 빌드 및 패키징
- `AndroidManifest.xml` 및 리소스 처리
- APK 생성
### Kotlin 플러그인 (`org.jetbrains.kotlin.jvm`)
Kotlin을 사용한 JVM 애플리케이션을 개발할 때 사용한다.
적용 방법:
```kotlin
plugins {
id("org.jetbrains.kotlin.jvm") version "1.8.0"
}
```
기본 제공 태스크:
- Kotlin 코드 컴파일 (`compileKotlin`)
- Kotlin 테스트 실행 (`test`)
- JAR 파일 생성 (`jar`)
### Java Gradle Plugin (`java-gradle-plugin`)
Gradle 플러그인을 직접 개발할 때 사용하는 플러그인이다.
```kotlin
plugins {
id("java-gradle-plugin")
}
```
제공 기능:
- Gradle 플러그인 코드 작성 및 빌드
- 플러그인 테스트 및 배포
---
[Gradle Plugin Portal](https://plugins.gradle.org/)
[플러그인](https://docs.gradle.org/current/userguide/plugin_reference.html#plugin_reference)

View File

@@ -0,0 +1,103 @@
# 테스트 자동화
소프트웨어 개발에서 테스트 자동화는 필수적인 요소다. 코드가 변경될 때마다 수동으로 모든 기능을 점검하는 것은 비효율적이며, 오류가 발생할 확률도 높아진다. 이를 해결하기 위해 테스트 자동화를 도입하면, 코드를 변경할 때마다 빠르게 테스트를 실행하고 안정성을 보장할 수 있다.
Gradle은 테스트를 자동화하는 강력한 기능을 제공하며, JUnit, TestNG, Spock 등 다양한 테스트 프레임워크와 함께 사용할 수 있다.
## Gradle에서 테스트란?
테스트는 코드가 기대한 대로 동작하는지 확인하는 과정이다. 일반적으로 테스트는 다음과 같이 분류할 수 있다.
- **단위 테스트(Unit Test)**: 개별 모듈이나 함수의 동작을 검증
- **통합 테스트(Integration Test)**: 여러 모듈이 올바르게 연동되는지 확인
- **기능 테스트(Functional Test)**: 실제 사용자 시나리오를 검증
## Gradle에서 테스트 실행하기
Gradle은 기본적으로 `test` 태스크를 제공하며, 이를 통해 자동으로 테스트를 실행할 수 있다.
터미널에서 다음 명령어를 실행하면 테스트가 자동으로 실행된다.
```sh
./gradlew test
```
테스트 실행이 완료되면 결과는 `build/reports/tests/test/index.html` 파일에서 확인할 수 있다.
## 테스트 프레임워크 설정
Gradle에서는 다양한 테스트 프레임워크를 지원한다.
### JUnit 5 설정
JUnit 5를 사용하려면 `dependencies` 블록에 다음과 같이 추가한다.
```kotlin
dependencies {
testImplementation("org.junit.jupiter:junit-jupiter:5.9.2")
}
```
## 테스트 태스크 설정
Gradle에서 테스트 태스크를 커스터마이징할 수도 있다.
### 특정 패키지의 테스트만 실행하기
다음과 같이 `include`를 설정하면 특정 패키지만 테스트할 수 있다.
```kotlin
tasks.test {
include("com/example/tests/**")
}
```
반대로, 특정 테스트를 제외할 수도 있다.
```kotlin
tasks.test {
exclude("com/example/experimental/**")
}
```
### 테스트 병렬 실행
테스트 실행 속도를 높이기 위해 병렬 실행을 활성화할 수도 있다.
```kotlin
tasks.test {
maxParallelForks = 2
}
```
## 테스트 리포트 생성
Gradle은 기본적으로 테스트 결과를 HTML 보고서로 제공한다. 추가적으로 `jacoco` 플러그인을 사용하면 코드 커버리지도 확인할 수 있다.
### JaCoCo 플러그인 설정
```kotlin
plugins {
id("jacoco")
}
tasks.jacocoTestReport {
reports {
xml.required.set(true)
html.required.set(true)
}
}
```
테스트 실행 후 다음 명령어를 입력하면 코드 커버리지를 확인할 수 있다.
```sh
.gradlew jacocoTestReport
```
결과는 `build/reports/jacoco/test/html/index.html`에서 확인할 수 있다.

View File

@@ -0,0 +1,174 @@
# 멀티 모듈 프로젝트 구성
소프트웨어 개발에서 프로젝트의 규모가 커질수록 코드 관리가 복잡해진다. 이때 **멀티 모듈(Multi-Module) 프로젝트**를 활용하면 코드의 재사용성을 높이고, 빌드 속도를 최적화하며, 팀 협업을 효율적으로 진행할 수 있다.
Gradle은 멀티 모듈 프로젝트를 손쉽게 구성할 수 있도록 지원하며, 각 모듈을 독립적으로 관리하면서도 전체 프로젝트와 연동할 수 있도록 설계되어 있다.
## 멀티 모듈 프로젝트란?
멀티 모듈 프로젝트는 하나의 **루트 프로젝트**(Root Project)와 여러 개의 **서브 모듈**(Submodule)로 구성된 프로젝트 구조를 의미한다.
### 왜 멀티 모듈을 사용할까?
- **코드 재사용성 증가**: 공통 로직을 별도의 모듈로 분리하여 여러 프로젝트에서 사용할 수 있다.
- **빌드 속도 최적화**: 변경된 모듈만 빌드하여 전체 빌드 시간을 줄일 수 있다.
- **의존성 관리 용이**: 각 모듈에서 필요한 라이브러리만 선언하여 불필요한 의존성을 제거할 수 있다.
- **팀 협업 효율성 증가**: 서로 다른 팀이 독립적으로 모듈을 개발하고 유지할 수 있다.
## Gradle 멀티 모듈 프로젝트 구조
Gradle 멀티 모듈 프로젝트는 다음과 같은 구조로 구성된다.
```
my-project/
├── app
│   ├── build.gradle.kts
│   └── src
│   ├── main
│   │   ├── java
│   │   └── resources
│   └── test
│   ├── java
│   └── resources
├── buildSrc
│   ├── build.gradle.kts
│   ├── settings.gradle.kts
│   └── src
│   └── main
│   └── kotlin
│   ├── buildlogic.java-application-conventions.gradle.kts
│   ├── buildlogic.java-common-conventions.gradle.kts
│   └── buildlogic.java-library-conventions.gradle.kts
├── gradle
│   ├── libs.versions.toml
│   └── wrapper
│   ├── gradle-wrapper.jar
│   └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
├── list
│   ├── build.gradle.kts
│   └── src
│   ├── main
│   │   ├── java
│   │   └── resources
│   └── test
│   ├── java
│   └── resources
├── settings.gradle.kts
└── utilities
├── build.gradle.kts
└── src
├── main
│   ├── java
│   └── resources
└── test
└── resources
```
## Gradle 멀티 모듈 프로젝트 설정
### **3.1 루트 프로젝트 설정**
루트 프로젝트에서는 `settings.gradle.kts` 파일을 사용하여 서브 모듈을 등록한다.
`settings.gradle.kts`
```kotlin
rootProject.name = "my-project"
include("app", "list", "utilities")
```
### 개별 모듈 설정
각 모듈은 `build.gradle.kts` 파일을 가지고 있으며, 필요한 플러그인과 의존성을 선언할 수 있다.
#### 루트 프로젝트의 `build.gradle.kts`
루트 프로젝트에서는 전체 모듈에 적용할 공통 설정을 정의할 수 있다.
```kotlin
plugins {
kotlin("jvm") version "1.9.0" apply false
}
subprojects {
repositories {
mavenCentral()
}
}
```
---
## 모듈 간 의존성 설정
### 모듈 간 의존성 추가
각 모듈에서 다른 모듈을 의존성으로 추가할 수 있다.
예를 들어, `app` 모듈에서 `core` 모듈을 사용하려면 `dependencies` 블록에 다음을 추가한다.
`app/build.gradle.kts`
```kotlin
dependencies {
implementation(project(":core"))
implementation(project(":shared"))
}
```
## 공통 라이브러리 관리
멀티 모듈 프로젝트에서는 모든 모듈에서 공통으로 사용하는 라이브러리를 `libs.versions.toml` 파일로 관리할 수 있다.
`gradle/libs.versions.toml`
```toml
[versions]
kotlin = "1.9.0"
junit = "5.9.2"
[libraries]
kotlin-stdlib = { module = "org.jetbrains.kotlin:kotlin-stdlib", version.ref = "kotlin" }
junit = { module = "org.junit.jupiter:junit-jupiter", version.ref = "junit" }
```
이제 각 모듈에서 라이브러리를 다음과 같이 참조할 수 있다.
`core/build.gradle.kts`
```kotlin
dependencies {
implementation(libs.kotlin.stdlib)
testImplementation(libs.junit)
}
```
## 멀티 모듈 프로젝트 빌드 및 실행
### 전체 프로젝트 빌드
모든 모듈을 빌드하려면 다음 명령어를 실행한다.
```sh
gradle build
```
### 특정 모듈만 빌드
예를 들어, `feature-a` 모듈만 빌드하려면 다음 명령어를 실행한다.
```sh
gradle :feature-a:build
```
### 특정 모듈의 테스트 실행
```sh
gradle :core:test
```

173
doc/08_build.gradle.kts.md Normal file
View File

@@ -0,0 +1,173 @@
# Gradle Kotlin DSL (`build.gradle.kts`) 주요 블록
Gradle에서 **Kotlin DSL**을 사용하면 `build.gradle.kts` 파일로 프로젝트를 구성할 수 있다.
이 파일에는 **빌드 설정, 의존성 관리, 플러그인 추가, 태스크 정의** 등의 내용이 포함된다.
| 블록 | 설명 |
|------|-------------------------------|
| `plugins` | 프로젝트에서 사용할 플러그인을 정의 |
| `group` & `version` | 프로젝트의 그룹 ID와 버전 정보 설정 |
| `repositories` | 의존성을 다운로드할 저장소 지정 |
| `dependencies` | 프로젝트에서 사용할 라이브러리 추가 |
| `application` | 실행할 `mainClass` 지정 (`application` 플러그인 사용 시) |
| `tasks` | 사용자 정의 태스크 추가 |
| `java` | Java 프로젝트의 컴파일러 버전 설정 |
| `jar` | JAR 파일의 메타데이터 설정 |
| `publishing` | 프로젝트를 Maven 저장소에 배포 |
| `wrapper` | Gradle Wrapper의 버전 관리 |
## `plugins` 블록
`plugins` 블록은 **프로젝트에서 사용할 플러그인**을 선언하는 곳이다.
Gradle 플러그인은 빌드 시스템의 기능을 확장하는 역할을 한다.
```kotlin
plugins {
java // Java 프로젝트를 위한 플러그인
application // 실행 가능한 애플리케이션을 위한 플러그인
kotlin("jvm") version "1.9.0" // Kotlin JVM 플러그인
}
```
- `java` → Java 프로젝트를 빌드하는 데 필요
- `application` → 실행 가능한 애플리케이션을 위한 플러그인
- `kotlin("jvm") version "1.9.0"` → Kotlin JVM 개발을 위한 플러그인
## `group` & `version` 블록
이 블록은 **프로젝트의 그룹 ID와 버전**을 정의한다.
- `group` → 프로젝트를 식별하는 네임스페이스
- `version` → 프로젝트의 버전 정보
```kotlin
group = "com.example"
version = "1.0.0"
```
이 설정을 하면 생성된 JAR 파일의 이름이 `example-1.0.0.jar`처럼 된다.
## `repositories` 블록
의존성을 다운로드할 저장소(Repository)를 정의하는 블록이다.
Gradle은 기본적으로 **Maven Central** 또는 **JCenter**에서 의존성을 가져온다.
### **예제**
```kotlin
repositories {
mavenCentral()
maven {
url = 'https://your.secure.repo/url'
credentials {
username = 'your-username'
password = 'your-password'
}
}
mavenLocal()
flatDir {
dirs("libs")
}
}
```
- `mavenCentral()` → Maven Central 저장소에서 라이브러리를 가져온다.
## `dependencies` 블록
프로젝트에서 사용할 **라이브러리(의존성)**를 추가하는 블록이다.
의존성은 크게 `implementation`, `api`, `testImplementation`으로 나뉜다.
```kotlin
dependencies {
implementation("org.apache.commons:commons-lang3:3.12.0") // 런타임과 컴파일에서 사용
api("com.google.guava:guava:32.0.1-jre") // 외부에서 접근 가능
testImplementation("junit:junit:4.13.2") // 테스트 전용 의존성
}
```
- `implementation` → 내부에서만 사용하는 의존성
- `api` → 외부 프로젝트에서도 접근할 수 있는 API
- `testImplementation` → 테스트 시에만 필요한 의존성
## `application` 블록
`application` 플러그인을 사용하는 경우 **애플리케이션의 메인 클래스**를 지정하는 블록이다.
```kotlin
application {
mainClass.set("com.example.Main")
}
```
이 설정을 하면 `gradle run`을 실행했을 때 `com.example.Main`가 실행된다.
## `tasks` 블록
Gradle에서는 **사용자 정의 태스크**를 만들 수 있다.
```kotlin
tasks.register("hello") {
doLast {
println("Hello, Gradle!")
}
}
```
위 태스크를 실행하려면 다음 명령어를 사용한다.
```sh
gradle hello
```
출력:
```
Hello, Gradle!
```
## `java` 블록 (Java 프로젝트 설정)
Java 프로젝트에서 **컴파일 및 JAR 설정을 추가할 때** 사용한다.
```kotlin
java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(17))
}
}
```
- Java 17을 기본 컴파일러 버전으로 설정한다.
## `jar` 블록 (JAR 파일 설정)
JAR 파일 생성 시 메타데이터를 추가하는 데 사용한다.
### **예제**
```kotlin
tasks.jar {
manifest {
attributes["Main-Class"] = "com.example.Main"
}
}
```
- `Main-Class`를 설정하여 실행 가능한 JAR 파일을 만든다.
## `publishing` 블록 (Maven 배포 설정)
Maven 저장소에 배포할 때 사용한다.
```kotlin
publishing {
publications {
create<MavenPublication>("mavenJava") {
from(components["java"])
}
}
repositories {
maven {
url = uri("https://my.repo.com/releases")
}
}
}
```
- `mavenJava`라는 Maven 아티팩트를 생성하고 지정한 저장소에 업로드할 수 있다.
## `wrapper` 블록 (Gradle Wrapper 설정)
Gradle Wrapper의 버전을 관리할 때 사용한다.
```kotlin
tasks.wrapper {
gradleVersion = "8.12"
distributionType = Wrapper.DistributionType.ALL
}
```
- Gradle 8.12 버전을 사용하도록 설정한다.

136
doc/09_buildSrc.md Normal file
View File

@@ -0,0 +1,136 @@
# `buildSrc` 디렉터리
Gradle을 사용하다 보면 여러 프로젝트에서 반복적으로 사용되는 **커스텀 태스크(Task)나 플러그인**을 정의해야 할 때가 있다. 이때, 가장 효과적인 방법 중 하나가 `buildSrc` 디렉터리를 활용하는 것이다.
`buildSrc`는 Gradle에서 **자동으로 인식하는 특별한 디렉터리**이다.
- 이 디렉터리 안에 작성된 코드들은 **Gradle 빌드 로직**에서 바로 사용할 수 있다.
- 플러그인, 커스텀 태스크, 공통 설정 등을 정의할 때 유용하다.
- Gradle의 **빌드 스크립트(`build.gradle.kts`)보다 먼저 컴파일**되므로, 커스텀 빌드 로직을 쉽게 적용할 수 있다.
`buildSrc`의 특징 :
1. **자동 컴파일 & 인식**
- Gradle이 `buildSrc`를 자동으로 감지하고, `build.gradle.kts`에서 바로 사용할 수 있다.
2. **별도의 설정이 필요 없음**
- `settings.gradle.kts`에서 추가적인 설정 없이 바로 적용 가능하다.
3. **멀티 프로젝트에서도 사용 가능**
- 루트 프로젝트(`rootProject/buildSrc`)에 배치하면 모든 서브 프로젝트에서 공유할 수 있다.
## `buildSrc` 기본 구조
`buildSrc`는 Gradle의 일반적인 프로젝트와 동일한 구조를 가진다.
```
├── buildSrc
│   ├── build.gradle.kts # buildSrc 자체 빌드 스크립트
│   ├── settings.gradle.kts
│   └── src
│   └── main
│   └── kotlin
│   ├── buildlogic.java-application.gradle.kts
│   ├── buildlogic.java-common.gradle.kts
│   └── buildlogic.java-library.gradle.kts
```
### `build.gradle.kts` 예제
`buildSrc` 디렉터리는 Gradle의 서브 프로젝트처럼 동작하므로, `build.gradle.kts` 파일을 통해 라이브러리를 추가할 수 있다.
```kotlin
plugins {
kotlin("jvm") version "1.8.10"
}
repositories {
mavenCentral()
}
dependencies {
implementation("org.jetbrains.kotlin:kotlin-stdlib")
}
```
## `buildSrc`를 활용한 커스텀 태스크 생성
Gradle의 기본 태스크 외에 **사용자 정의 태스크(Custom Task)**를 만들 수 있다.
예를 들어, 특정 파일을 복사하는 커스텀 태스크를 만들어 보자.
### 커스텀 태스크 작성 (`CustomTask.kt`)
`buildSrc/src/main/kotlin/myplugin/CustomTask.kt`
```kotlin
package myplugin
import org.gradle.api.DefaultTask
import org.gradle.api.tasks.TaskAction
import java.io.File
abstract class CustomTask : DefaultTask() {
@TaskAction
fun run() {
val source = File("src/main/resources/sample.txt")
val destination = File("build/sample-copy.txt")
if (source.exists()) {
destination.writeText(source.readText())
println("파일 복사 완료: ${destination.absolutePath}")
} else {
println("⚠️ 원본 파일이 존재하지 않습니다!")
}
}
}
```
### 커스텀 태스크 사용하기
이제 `build.gradle.kts`에서 바로 사용할 수 있다.
`build.gradle.kts`
```kotlin
tasks.register<myplugin.CustomTask>("copySampleFile")
```
실행해보자.
```sh
./gradlew copySampleFile
```
## `buildSrc`를 활용한 커스텀 플러그인 생성
커스텀 태스크 외에도, Gradle의 **플러그인(Plugin)**을 정의할 수도 있다.
예를 들어, 프로젝트에 공통적인 설정을 적용하는 `MyCustomPlugin`을 만들어보자.
### 커스텀 플러그인 작성 (`MyCustomPlugin.kt`)
`buildSrc/src/main/kotlin/myplugin/MyCustomPlugin.kt`
```kotlin
package myplugin
import org.gradle.api.Plugin
import org.gradle.api.Project
class MyCustomPlugin : Plugin<Project> {
override fun apply(project: Project) {
project.tasks.register("helloPlugin") {
doLast {
println("MyCustomPlugin이 적용되었습니다!")
}
}
}
}
```
### 커스텀 플러그인 적용하기
이제 `build.gradle.kts`에서 다음과 같이 플러그인을 적용할 수 있다.
`build.gradle.kts`
```kotlin
plugins {
id("myplugin.mycustomplugin")
}
```
플러그인 실행:
```sh
./gradlew helloPlugin
```
출력 결과:
```sh
MyCustomPlugin이 적용되었습니다!
```

131
doc/10_빌드 최적화.md Normal file
View File

@@ -0,0 +1,131 @@
# Gradle 빌드 최적화
Gradle은 강력한 빌드 도구이지만, 프로젝트가 커질수록 빌드 시간이 길어지는 문제가 발생할 수 있다. 이 글에서는 **Gradle 빌드 성능을 최적화하는 방법**을 소개한다.
Gradle 빌드는 여러 단계(초기화, 구성, 실행)를 거치며 실행된다. 빌드 속도를 개선하려면 다음 요소를 고려해야 한다.
- **불필요한 작업 제거**: 변경된 파일만 다시 빌드
- **병렬 실행 활용**: 멀티코어 CPU 활용
- **의존성 관리 최적화**: 캐시 사용 및 중복 제거
- **Gradle 자체 설정 최적화**: 빌드 캐시, 데몬, 워커 설정
## 불필요한 작업 방지 (`UP-TO-DATE`, `INCREMENTAL`, `CACHE`)
Gradle은 빌드를 최적화하기 위해 **변경된 파일만 다시 빌드**하는 기능을 제공한다.
### UP-TO-DATE 체크
Gradle은 이전 빌드와 비교하여 변경되지 않은 작업을 건너뛴다.
```sh
./gradlew build
```
출력 로그에서
```sh
Task :compileJava UP-TO-DATE
```
와 같은 메시지가 나오면, 해당 작업이 **이전과 동일하여 재실행되지 않았음**을 의미한다.
#### 수동으로 캐시 삭제 (강제 실행)
```sh
./gradlew clean build
```
이렇게 하면 모든 파일을 다시 빌드한다. 하지만, 매번 `clean`을 실행하는 것은 빌드 최적화에 도움이 되지 않는다.
### 증분 빌드 (Incremental Build)
특정 작업에서 변경된 파일만 처리하도록 `@InputFiles`, `@OutputFiles` 등을 활용할 수 있다.
```kotlin
tasks.register<Copy>("copyTask") {
from("src")
into("dest")
}
```
이렇게 설정하면, `src` 폴더의 파일이 변경되지 않으면 작업을 재실행하지 않는다.
### 빌드 캐시 활용
빌드 캐시는 이전 빌드 결과를 저장하여 다시 사용할 수 있도록 한다.
```sh
./gradlew build --build-cache
```
Gradle 설정 파일(`gradle.properties`)에 빌드 캐시를 활성화할 수도 있다.
```properties
org.gradle.caching=true
```
## 병렬 빌드 및 워커 설정
Gradle은 기본적으로 여러 작업을 병렬로 실행할 수 있다.
### 병렬 실행 활성화
멀티 프로젝트 빌드에서 병렬 실행을 활성화하면 속도가 크게 향상될 수 있다.
```sh
./gradlew build --parallel
```
또는 `gradle.properties`에서 설정할 수도 있다.
```properties
org.gradle.parallel=true
```
### Gradle 데몬 사용
Gradle 데몬(Daemon)은 빌드 속도를 높이는 데 중요한 역할을 한다.
```sh
./gradlew --daemon
```
또는 `gradle.properties`에서 설정 가능하다.
```properties
org.gradle.daemon=true
```
### 워커 수 증가
멀티코어 CPU를 활용하여 빌드 속도를 높일 수 있다.
```properties
org.gradle.workers.max=4
```
시스템 성능에 맞게 적절한 값을 설정하면 된다.
## 의존성 관리 최적화
### 불필요한 의존성 제거
불필요한 의존성이 많으면 빌드 속도가 느려진다.
`dependencies` 블록을 점검하여 불필요한 라이브러리를 제거한다.
```kotlin
dependencies {
implementation("com.example:unused-library:1.0.0") // 제거 필요
}
```
### `dependencyResolutionManagement` 설정
`settings.gradle.kts`에서 **의존성 해석을 최적화**할 수 있다.
```kotlin
dependencyResolutionManagement {
repositories {
mavenCentral()
}
}
```
이렇게 하면 Gradle이 중복된 의존성을 다운로드하지 않는다.
### 로컬 캐시 활용
의존성을 매번 다운로드하지 않도록 로컬 캐시를 활용할 수 있다.
```sh
./gradlew build --offline
```
이렇게 하면 인터넷 없이 로컬에 있는 의존성만 사용한다.
## 실행 시간 분석 및 프로파일링
Gradle의 `--scan` 옵션을 사용하면 빌드 성능을 분석할 수 있다.
```sh
./gradlew build --scan
```
또한, `--profile` 옵션을 사용하면 빌드 시간 프로파일을 확인할 수 있다.
```sh
./gradlew build --profile
```
생성된 `build/reports/profile` 폴더에서 상세한 분석 결과를 확인할 수 있다.

166
doc/11_java.md Normal file
View File

@@ -0,0 +1,166 @@
# `java`, `java-library`, `application`, `war` 플러그인
Gradle은 다양한 **플러그인(Plugin)**을 제공하여 프로젝트의 빌드, 실행, 배포 과정을 자동화할 수 있도록 돕는다.
그중에서도 Java 프로젝트를 위한 `java`, `java-library`, `application`, `war` 플러그인은 각각 **일반 Java 애플리케이션, 라이브러리, 실행형 애플리케이션, 웹 애플리케이션**을 관리하는 데 사용된다.
## `java` 플러그인
`java` 플러그인은 **일반적인 Java 프로젝트**를 빌드할 때 사용된다.
이 플러그인을 적용하면 **컴파일, 테스트, JAR 생성, 패키징** 등의 작업을 자동으로 수행할 수 있다.
`build.gradle.kts` :
```kotlin
plugins {
java
}
group = "com.example"
version = "1.0.0"
repositories {
mavenCentral()
}
dependencies {
implementation("org.apache.commons:commons-lang3:3.12.0")
testImplementation("junit:junit:4.13.2")
}
```
### 주요 태스크
| 태스크 | 설명 |
|--------|--------------------------------|
| `compileJava` | Java 소스 코드 컴파일 |
| `processResources` | `src/main/resources/`의 리소스를 `build` 폴더로 복사 |
| `classes` | `compileJava` + `processResources` 실행 |
| `jar` | JAR 파일 생성 (`build/libs/`에 저장됨) |
| `test` | 단위 테스트 실행 |
| `clean` | `build/` 디렉터리 삭제 |
| `build` | 전체 빌드 (`compileJava`, `test`, `jar` 포함) |
## `java-library` 플러그인
`java-library` 플러그인은 **라이브러리 개발**을 위한 플러그인으로, `java` 플러그인의 확장판이다.
- `api``implementation` 의존성을 구분할 수 있도록 지원한다.
### `api` vs `implementation`
- **`api`** : 외부 프로젝트에서도 접근할 수 있는 공개 API
- **`implementation`** : 내부에서만 사용하는 의존성
`build.gradle.kts`
```kotlin
plugins {
`java-library`
}
group = "com.example"
version = "1.0.0"
repositories {
mavenCentral()
}
dependencies {
api("com.google.guava:guava:32.0.1-jre") // 외부 프로젝트에서도 사용 가능
implementation("org.apache.commons:commons-lang3:3.12.0") // 내부에서만 사용
}
```
### 주요 태스크
| 태스크 | 설명 |
|--------|--------------------------------|
| `assemble` | JAR 파일 생성 |
| `publish` | 라이브러리를 배포 (예: Maven Central) |
## `application` 플러그인
`application` 플러그인은 **실행 가능한 Java 애플리케이션**을 만들기 위해 사용된다.
- `mainClass`를 지정하여 `run` 태스크를 사용할 수 있다.
`build.gradle.kts`
```kotlin
plugins {
application
}
group = "com.example"
version = "1.0.0"
repositories {
mavenCentral()
}
dependencies {
implementation("org.apache.commons:commons-lang3:3.12.0")
}
application {
mainClass.set("com.example.Main") // 실행할 메인 클래스
}
```
### 주요 태스크
| 태스크 | 설명 |
|--------|--------------------------------|
| `run` | 애플리케이션 실행 |
| `installDist` | 실행 가능한 배포 패키지 생성 (`build/install/`) |
| `distZip` | `.zip` 패키지로 애플리케이션 배포 |
| `distTar` | `.tar` 패키지로 애플리케이션 배포 |
## `war` 플러그인
`war` 플러그인은 **웹 애플리케이션(WAR 파일) 배포를 위한 플러그인**이다.
- **Servlet 기반 웹 애플리케이션을 패키징**할 때 사용된다.
- `java` 플러그인을 자동으로 포함한다.
`build.gradle.kts`
```kotlin
plugins {
war
}
group = "com.example"
version = "1.0.0"
repositories {
mavenCentral()
}
dependencies {
providedCompile("javax.servlet:javax.servlet-api:4.0.1") // 컨테이너가 제공하는 의존성
implementation("org.springframework:spring-webmvc:5.3.23") // 웹 MVC 프레임워크
}
```
### 디렉터리 구조
```
src/
├── main/
│ ├── java/ <-- Java 소스 코드
│ ├── resources/ <-- 정적 리소스
│ ├── webapp/ <-- `WEB-INF` 및 JSP 파일
│ ├── WEB-INF/
│ │ ├── web.xml
│ ├── index.jsp
```
### 주요 태스크
| 태스크 | 설명 |
|--------|--------------------------------|
| `war` | WAR 파일 생성 (`build/libs/app-1.0.0.war`) |
| `explodedWar` | 압축되지 않은 WAR 파일 생성 |
| `assemble` | 전체 빌드 실행 |
## 플러그인 비교 정리
| 플러그인 | 용도 | 실행 방식 | 주요 태스크 |
|----------|--------|------------|------------------------------|
| `java` | 일반 Java 프로젝트 | 실행 X, JAR만 생성 | `compileJava`, `jar`, `build` |
| `java-library` | 라이브러리 개발 | 실행 X, API 관리 | `publish`, `jar`, `build` |
| `application` | 실행 가능한 앱 | `run`으로 실행 가능 | `run`, `installDist`, `distZip` |
| `war` | 웹 애플리케이션 | WAR 파일 생성 | `war`, `explodedWar` |

View File

@@ -0,0 +1,218 @@
# `maven-publish` 플러그인
Gradle의 `maven-publish` 플러그인은 프로젝트의 빌드 아티팩트(예: JAR, POM 파일)를 **Maven 형식**으로 패키징하고 로컬 또는 원격 저장소(예: Maven Central, Artifactory, Nexus)에 배포할 때 사용된다.
이 플러그인은 다음과 같은 기능을 제공한다.
* Maven 저장소에 라이브러리 배포
* 로컬 및 원격 저장소 지원
* 자동 POM 파일 생성
* 다양한 아티팩트 유형(JAR, Sources, Javadoc) 지원
먼저 `maven-publish` 플러그인을 적용해야 한다.
`build.gradle.kts`
```kotlin
plugins {
`maven-publish`
`java-library`
signing
}
group = "com.example" // 그룹 ID
version = "1.0.0" // 버전 정보
repositories {
mavenCentral()
}
dependencies {
implementation("org.apache.commons:commons-lang3:3.12.0")
}
java {
withJavadocJar()
withSourcesJar()
}
publishing {
publications {
create<MavenPublication>("mavenJava") {
from(components["java"]) // Java 라이브러리 컴포넌트 사용
groupId = "com.example"
artifactId = "my-library"
version = "1.0.0"
pom {
name = "My Library"
description = "A concise description of my library"
url = "http://www.example.com/library"
properties = mapOf(
"myProp" to "value",
"prop.with.dots" to "anotherValue"
)
licenses {
license {
name = "The Apache License, Version 2.0"
url = "http://www.apache.org/licenses/LICENSE-2.0.txt"
}
}
developers {
developer {
id = "johnd"
name = "John Doe"
email = "john.doe@example.com"
}
}
scm {
connection = "scm:git:git://example.com/my-library.git"
developerConnection = "scm:git:ssh://example.com/my-library.git"
url = "http://example.com/my-library/"
}
}
}
}
repositories {
maven {
val releasesRepoUrl = layout.buildDirectory.dir("repos/releases")
val snapshotsRepoUrl = layout.buildDirectory.dir("repos/snapshots")
url = uri(if (version.toString().endsWith("SNAPSHOT")) snapshotsRepoUrl else releasesRepoUrl)
}
}
}
signing {
sign(publishing.publications["mavenJava"])
}
tasks.javadoc {
if (JavaVersion.current().isJava9Compatible) {
(options as StandardJavadocDocletOptions).addBooleanOption("html5", true)
}
}
```
- `plugins { maven-publish }``maven-publish` 플러그인 적용
- `publishing { publications { ... } }` → 배포할 아티팩트 설정
- `from(components["java"])``java` 컴포넌트를 기반으로 자동 설정
- `groupId`, `artifactId`, `version` → Maven 아티팩트 정보 지정
## 로컬 Maven 저장소에 배포
Gradle은 기본적으로 **로컬 저장소(`~/.m2/repository`)**를 지원한다.
`build.gradle.kts` :
```kotlin
publishing {
publications {
create<MavenPublication>("mavenJava") {
from(components["java"])
groupId = "com.example"
artifactId = "my-library"
version = "1.0.0"
}
}
repositories {
maven {
url = uri("${buildDir}/repo") // 로컬 저장소 경로
}
}
}
```
로컬 저장소에 배포 실행 :
```sh
gradle publish
```
실행하면 `${buildDir}/repo/com/example/my-library/1.0.0/` 경로에 JAR과 POM 파일이 생성된다.
## 원격 Maven 저장소에 배포
Maven Central 또는 사설 저장소(Nexus, Artifactory)에 업로드하려면 **인증 정보**를 추가해야 한다.
`build.gradle.kts` :
```kotlin
publishing {
publications {
create<MavenPublication>("mavenJava") {
from(components["java"])
groupId = "com.example"
artifactId = "my-library"
version = "1.0.0"
pom {
name.set("My Library")
description.set("This is an example library.")
url.set("https://github.com/example/my-library")
licenses {
license {
name.set("MIT License")
url.set("https://opensource.org/licenses/MIT")
}
}
developers {
developer {
id.set("dev123")
name.set("John Doe")
email.set("john@example.com")
}
}
}
}
}
repositories {
maven {
name = "myRepo"
url = uri("https://maven.example.com/repository/releases/")
credentials {
username = project.findProperty("mavenUser") as String? ?: "defaultUser"
password = project.findProperty("mavenPassword") as String? ?: "defaultPassword"
}
}
}
}
```
다음 명령어를 실행하면 원격 저장소에 업로드된다.
```sh
gradle publish
```
## 추가 아티팩트 (소스 코드, Javadoc)
라이브러리를 배포할 때 **소스 코드 및 Javadoc JAR**을 함께 제공할 수도 있다.
`build.gradle.kts`
```kotlin
tasks.register<Jar>("sourcesJar") {
from(sourceSets.main.get().allSource)
archiveClassifier.set("sources")
}
tasks.register<Jar>("javadocJar") {
from(tasks.javadoc)
archiveClassifier.set("javadoc")
}
publishing {
publications {
create<MavenPublication>("mavenJava") {
from(components["java"])
artifact(tasks["sourcesJar"]) // 소스 코드 추가
artifact(tasks["javadocJar"]) // Javadoc 추가
groupId = "com.example"
artifactId = "my-library"
version = "1.0.0"
}
}
}
```
배포 후 다음과 같은 파일이 생성된다.
```
my-library-1.0.0.jar # 라이브러리 JAR
my-library-1.0.0-sources.jar # 소스 코드 포함
my-library-1.0.0-javadoc.jar # Javadoc 포함
my-library-1.0.0.pom # POM 파일
```

150
doc/13_spring boot.md Normal file
View File

@@ -0,0 +1,150 @@
# Spring Boot 프로젝트
Spring Boot는 **빠른 개발과 배포**를 목표로 하는 프레임워크로, Gradle을 사용하면 프로젝트 빌드, 의존성 관리, 테스트 및 배포 자동화가 더욱 효율적이 된다.
Spring Boot는 Gradle을 사용하여 다음과 같은 이점을 제공한다.
* **빠른 빌드 속도**: Gradle의 캐싱 및 병렬 빌드 기능 덕분에 빌드 시간이 단축된다.
* **유연한 빌드 설정**: Kotlin DSL을 사용하여 직관적으로 빌드 스크립트를 작성할 수 있다.
* **의존성 관리 용이**: `dependencies` 블록을 활용해 손쉽게 라이브러리를 추가할 수 있다.
* **자동화된 빌드 및 테스트**: CI/CD와 연계하여 빌드 및 테스트를 자동화할 수 있다.
## Spring Boot 프로젝트 생성 및 Gradle 설정
Spring Boot 프로젝트를 Gradle 기반으로 생성하려면 **Spring Initializr**를 사용할 수 있다.
[Spring Initializr](https://start.spring.io/) 에 접속한 후 다음을 선택한다.
- **Project:** Gradle - Kotlin 또는 Gradle - Groovy
- **Language:** Java (또는 Kotlin)
- **Spring Boot Version:** 최신 안정 버전
- **Dependencies:** 필요한 라이브러리 추가
### CLI를 사용하여 프로젝트를 생성하는 방법
```sh
curl https://start.spring.io/starter.zip \
-d type=gradle-project \
-d language=java \
-d bootVersion=3.1.2 \
-d dependencies=web,data-jpa,h2 \
-o demo.zip
```
이후 압축을 풀고 프로젝트 디렉터리로 이동한다.
```sh
unzip demo.zip
cd demo
```
Spring Boot Gradle 프로젝트의 기본 `build.gradle.kts` 파일은 다음과 같다.
```kotlin
plugins {
id("org.springframework.boot") version "3.1.2"
id("io.spring.dependency-management") version "1.1.3"
kotlin("jvm") version "1.8.22"
kotlin("plugin.spring") version "1.8.22"
}
group = "com.example"
version = "1.0.0"
java.sourceCompatibility = JavaVersion.VERSION_17
repositories {
mavenCentral()
}
dependencies {
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
implementation("org.jetbrains.kotlin:kotlin-reflect")
runtimeOnly("com.h2database:h2")
testImplementation("org.springframework.boot:spring-boot-starter-test")
}
tasks.withType<Test> {
useJUnitPlatform()
}
```
## 주요 설정
### 플러그인 설정
```kotlin
plugins {
id("org.springframework.boot") version "3.1.2"
id("io.spring.dependency-management") version "1.1.3"
kotlin("jvm") version "1.8.22"
kotlin("plugin.spring") version "1.8.22"
}
```
- `org.springframework.boot` → Spring Boot 플러그인 적용
- `io.spring.dependency-management` → 의존성 자동 관리
- `kotlin("jvm")` → Kotlin JVM 환경 설정
- `kotlin("plugin.spring")` → Spring Boot와 Kotlin 호환성 플러그인
### 의존성 관리
```kotlin
dependencies {
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
runtimeOnly("com.h2database:h2")
testImplementation("org.springframework.boot:spring-boot-starter-test")
}
```
- `implementation` → 실행 시 필요한 라이브러리
- `runtimeOnly` → 실행할 때만 필요한 라이브러리 (예: H2 데이터베이스)
- `testImplementation` → 테스트 코드에서만 사용하는 라이브러리
### 저장소 설정
```kotlin
repositories {
mavenCentral()
}
```
Maven Central 저장소에서 필요한 라이브러리를 가져온다.
### 테스트 설정
```kotlin
tasks.withType<Test> {
useJUnitPlatform()
}
```
**JUnit 5** (JUnit Platform) 기반의 테스트를 실행하도록 설정
## Gradle 태스크
### 애플리케이션 실행
```sh
./gradlew bootRun
```
Spring Boot 애플리케이션을 실행한다.
### 빌드 및 실행 가능한 JAR 생성
```sh
./gradlew bootJar
```
`build/libs/` 디렉터리에 실행 가능한 JAR 파일이 생성된다.
```sh
java -jar build/libs/demo-1.0.0.jar
```
생성된 JAR 파일을 실행한다.
### 종속성 확인
```sh
./gradlew dependencies
```
프로젝트에 포함된 의존성을 확인할 수 있다.
### 테스트 실행
```sh
./gradlew test
```
- JUnit 기반 테스트를 실행한다.

191
doc/14_android.md Normal file
View File

@@ -0,0 +1,191 @@
# Android 프로젝트
Gradle은 **Android 프로젝트의 빌드 시스템**으로 널리 사용된다. 빌드 자동화, 의존성 관리, 다중 빌드 변형(SDK 버전, 제품별 빌드 등) 지원 등의 기능을 제공하여 Android 개발을 더욱 효율적으로 만든다.
Android 프로젝트에서 Gradle은 다음과 같은 장점을 제공한다.
* **자동화된 빌드 시스템** → 코드 컴파일, 리소스 처리, APK 생성까지 자동 수행
* **유연한 빌드 구성** → 빌드 변형(Variants), 제품 플래버(Flavors) 등을 손쉽게 설정 가능
* **강력한 의존성 관리** → 라이브러리를 원격 저장소에서 손쉽게 가져와 사용할 수 있음
* **테스트 및 CI/CD 연계 용이** → 테스트 자동화 및 배포 프로세스 통합 가능
| 명령어 | 설명 |
|--------|------|
| `gradle assembleDebug` | 디버그 빌드 생성 |
| `gradle assembleRelease` | 릴리스 빌드 생성 |
| `gradle clean` | 빌드 결과물 삭제 |
| `gradle dependencies` | 프로젝트 의존성 확인 |
| `gradle lint` | 코드 품질 검사 실행 |
| `gradle test` | 테스트 실행 |
| `gradle bundleRelease` | AAB(Android App Bundle) 빌드 |
## Android 프로젝트에서 Gradle 구조
Android 프로젝트에서 주요 Gradle 파일은 다음과 같다.
프로젝트 루트 디렉터리 (`/`) :
- `settings.gradle.kts` → 서브 프로젝트 포함 여부 설정
- `build.gradle.kts` → 프로젝트 전반의 설정 및 플러그인 관리
모듈(`app/` 또는 `library/`) :
- `app/build.gradle.kts` → 애플리케이션 모듈의 빌드 설정
- `library/build.gradle.kts` → 라이브러리 모듈의 빌드 설정
## 주요 Gradle 파일 설정
### `settings.gradle.kts` (루트 프로젝트)
```kotlin
pluginManagement {
repositories {
google()
mavenCentral()
gradlePluginPortal()
}
}
dependencyResolutionManagement {
repositories {
google()
mavenCentral()
}
}
rootProject.name = "MyAndroidApp"
include(":app")
```
- **`repositories`** → Gradle이 사용할 라이브러리 저장소 설정
- **`rootProject.name`** → 프로젝트 이름 지정
- **`include(":app")`** → `app` 모듈 포함
### `build.gradle.kts` (루트 프로젝트)
```kotlin
buildscript {
dependencies {
classpath("com.android.tools.build:gradle:8.2.0")
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.10")
}
}
```
- Android Gradle 플러그인 및 Kotlin 플러그인 추가
### `app/build.gradle.kts` (모듈 설정)
```kotlin
plugins {
id("com.android.application")
kotlin("android")
}
android {
namespace = "com.example.myandroidapp"
compileSdk = 34
defaultConfig {
applicationId = "com.example.myandroidapp"
minSdk = 24
targetSdk = 34
versionCode = 1
versionName = "1.0"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
isMinifyEnabled = true
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
debug {
isMinifyEnabled = false
}
}
}
dependencies {
implementation("androidx.core:core-ktx:1.12.0")
implementation("androidx.appcompat:appcompat:1.6.1")
implementation("com.google.android.material:material:1.10.0")
testImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test.ext:junit:1.1.5")
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
}
```
**`plugins`** → Android 애플리케이션 플러그인 및 Kotlin 플러그인 적용
- **`android`**
- `compileSdk` → 앱이 빌드될 Android SDK 버전
- `minSdk` → 최소 지원 Android 버전
- `targetSdk` → 테스트 및 최적화 대상 버전
- `versionCode`, `versionName` → 앱의 버전 정보
- **`buildTypes`**
- `release` → 최적화 및 난독화(Proguard) 적용
- `debug` → 개발 및 테스트용 빌드
- **`dependencies`** → 프로젝트에서 사용할 라이브러리 설정
## 의존성 관리
### 라이브러리 추가
Gradle을 사용하면 `dependencies` 블록에서 필요한 라이브러리를 쉽게 추가할 수 있다.
```kotlin
dependencies {
implementation("androidx.core:core-ktx:1.12.0")
implementation("androidx.appcompat:appcompat:1.6.1")
}
```
- `implementation` → 애플리케이션 실행 시 필요한 라이브러리
### 버전 관리 (`gradle/libs.versions.toml` 활용)
Android 프로젝트에서는 **`libs.versions.toml` 파일**을 사용하여 라이브러리 버전을 중앙에서 관리할 수 있다.
`gradle/libs.versions.toml`
```toml
[versions]
core-ktx = "1.12.0"
appcompat = "1.6.1"
[libraries]
core-ktx = { module = "androidx.core:core-ktx", version.ref = "core-ktx" }
appcompat = { module = "androidx.appcompat:appcompat", version.ref = "appcompat" }
```
`build.gradle.kts`에서 참조
```kotlin
dependencies {
implementation(libs.core.ktx)
implementation(libs.appcompat)
}
```
## 빌드 변형(Build Variants) 활용
Gradle을 사용하면 **개발, 스테이징, 프로덕션 등의 환경에 따라 빌드를 분리**할 수 있다.
예제: `flavorDimensions``productFlavors` 활용
```kotlin
android {
flavorDimensions += "version"
productFlavors {
create("free") {
dimension = "version"
applicationIdSuffix = ".free"
versionNameSuffix = "-free"
}
create("pro") {
dimension = "version"
applicationIdSuffix = ".pro"
versionNameSuffix = "-pro"
}
}
}
```
빌드 실행 방법 :
```sh
gradle assembleFreeDebug
gradle assembleProRelease
```

61
doc/15_kotlin.md Normal file
View File

@@ -0,0 +1,61 @@
# Kotlin 프로젝트
Kotlin 프로젝트에서 Gradle을 사용하면 **빌드 자동화, 의존성 관리, 테스트 실행, 패키징** 등을 효율적으로 수행할 수 있다.
## Kotlin 프로젝트 생성 및 Gradle 설정
### 프로젝트 생성
터미널에서 Gradle을 사용하여 Kotlin 프로젝트를 생성하려면 다음 명령어를 실행한다.
```sh
gradle init
```
이후 옵션을 선택하여 Kotlin 프로젝트를 생성할 수 있다.
또는 **Kotlin DSL을 사용한 기본 프로젝트 구조**를 직접 생성할 수도 있다.
```
my-kotlin-project/
├── src/
│ ├── main/
│ │ ├── kotlin/
│ │ ├── resources/
│ ├── test/
│ │ ├── kotlin/
│ │ ├── resources/
├── build.gradle.kts <-- Gradle 설정 파일
├── settings.gradle.kts
├── gradlew <-- Gradle Wrapper 실행 파일
├── gradlew.bat
├── gradle/
│ ├── wrapper/
│ │ ├── gradle-wrapper.jar
│ │ ├── gradle-wrapper.properties
```
### `build.gradle.kts` 설정
`build.gradle.kts`
```kotlin
plugins {
kotlin("jvm") version "1.9.0"
application
}
group = "com.example"
version = "1.0.0"
repositories {
mavenCentral()
}
dependencies {
implementation(kotlin("stdlib")) // Kotlin 표준 라이브러리
testImplementation(kotlin("test")) // Kotlin 테스트 라이브러리
}
application {
mainClass.set("com.example.MainKt") // 애플리케이션의 엔트리 포인트
}
```
이제 Gradle을 사용하여 **빌드, 실행, 테스트**를 수행할 수 있다.

156
doc/16_c.md Normal file
View File

@@ -0,0 +1,156 @@
# C 프로젝트
Gradle은 주로 Java, Kotlin과 같은 JVM 언어를 위한 빌드 도구로 알려져 있지만, **C/C++ 프로젝트도 빌드할 수 있는 강력한 기능**을 제공한다. Gradle의 **`cpp-application`** 또는 **`cpp-library`** 플러그인을 사용하면 C 프로젝트의 빌드를 자동화할 수 있다.
## Gradle 프로젝트 설정
C 프로젝트를 Gradle로 빌드하려면 먼저 Gradle 프로젝트를 초기화해야 한다.
```sh
gradle init
```
이후 "Application" 또는 "Library" 유형을 선택하고, 언어로 `C++`을 선택할 수 있다. 하지만, 직접 `build.gradle.kts` 파일을 작성해도 된다.
Gradle을 사용하는 C 프로젝트의 기본적인 디렉터리 구조는 다음과 같다.
```
C-Project/
├── src/
│ ├── main/
│ │ ├── c/
│ │ │ ├── main.c
│ │ │ ├── utils.c
│ │ │ ├── utils.h
│ ├── test/
│ │ ├── c/
│ │ │ ├── test_main.c
│ │ │ ├── test_utils.c
├── build.gradle.kts
├── settings.gradle.kts
├── gradlew
├── gradlew.bat
├── gradle/
└── build/
```
## `cpp-application` 플러그인을 사용한 C 프로젝트 빌드
Gradle의 **`cpp-application`** 플러그인은 실행 가능한 C 프로그램을 만들 때 사용된다.
`build.gradle.kts` 설정
```kotlin
plugins {
id("cpp-application")
}
application {
targetMachines.add(machines.linux.x86_64) // 빌드 타겟 (Linux 64-bit)
targetMachines.add(machines.windows.x86_64) // Windows 지원 추가
}
tasks.withType<CppCompile>().configureEach {
compilerArgs.add("-Wall") // 모든 경고 표시
}
```
이 설정을 통해:
- `cpp-application` 플러그인을 적용한다.
- 빌드할 대상 아키텍처(Windows, Linux)를 지정한다.
- `-Wall` 플래그를 추가하여 경고를 활성화한다.
### 빌드 및 실행
```sh
./gradlew build # 빌드 실행
./build/install/main/debug/main # 실행 (Linux)
build\install\main\debug\main.exe # 실행 (Windows)
```
Gradle은 `build/install/main/debug/` 폴더에 실행 파일을 생성한다.
## `cpp-library` 플러그인을 사용한 C 라이브러리 프로젝트
라이브러리를 생성할 경우 **`cpp-library`** 플러그인을 사용하면 된다.
`build.gradle.kts` 설정
```kotlin
plugins {
id("cpp-library")
}
library {
targetMachines.add(machines.linux.x86_64)
targetMachines.add(machines.windows.x86_64)
}
```
### 라이브러리 코드 (`utils.c`, `utils.h`)
`utils.h`
```c
#ifndef UTILS_H
#define UTILS_H
void print_message();
#endif
```
`utils.c`
```c
#include <stdio.h>
#include "utils.h"
void print_message() {
printf("Hello from the C Library!\n");
}
```
## 테스트 추가 (`cpp-unit-test` 플러그인 사용)
Gradle에서 C 프로젝트에 대한 유닛 테스트를 추가할 수도 있다.
`test_main.c`
```c
#include <stdio.h>
#include "utils.h"
int main() {
print_message();
printf("Test Passed!\n");
return 0;
}
```
`build.gradle.kts`
```kotlin
plugins {
id("cpp-application")
id("cpp-unit-test") // 테스트 플러그인 추가
}
application {
targetMachines.add(machines.linux.x86_64)
targetMachines.add(machines.windows.x86_64)
}
tasks.withType<CppCompile>().configureEach {
compilerArgs.add("-Wall")
}
testing {
suites {
val test by getting(CppTestSuite::class) {
targets {
all {
testTask.configure {
shouldRunAfter(tasks.named("build"))
}
}
}
}
}
}
```
### 테스트 실행
```sh
./gradlew check
```
테스트 결과는 `build/reports/tests/test` 폴더에 저장된다.

12
src/kotlin/.gitattributes vendored Normal file
View File

@@ -0,0 +1,12 @@
#
# https://help.github.com/articles/dealing-with-line-endings/
#
# Linux start script should use lf
/gradlew text eol=lf
# These are Windows script files and should use crlf
*.bat text eol=crlf
# Binary files should be left untouched
*.jar binary

5
src/kotlin/.gitignore vendored Normal file
View File

@@ -0,0 +1,5 @@
# Ignore Gradle project-specific cache directory
.gradle
# Ignore Gradle build output directory
build

View File

@@ -0,0 +1,46 @@
/*
* This file was generated by the Gradle 'init' task.
*
* This generated file contains a sample Kotlin application project to get you started.
* For more details on building Java & JVM projects, please refer to https://docs.gradle.org/8.12.1/userguide/building_java_projects.html in the Gradle documentation.
*/
plugins {
// Apply the org.jetbrains.kotlin.jvm Plugin to add support for Kotlin.
alias(libs.plugins.kotlin.jvm)
// Apply the application plugin to add support for building a CLI application in Java.
application
}
repositories {
// Use Maven Central for resolving dependencies.
mavenCentral()
}
dependencies {
// Use JUnit Jupiter for testing.
testImplementation(libs.junit.jupiter)
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
// This dependency is used by the application.
implementation(libs.guava)
}
// Apply a specific Java toolchain to ease working on different environments.
java {
toolchain {
languageVersion = JavaLanguageVersion.of(21)
}
}
application {
// Define the main class for the application.
mainClass = "org.example.AppKt"
}
tasks.named<Test>("test") {
// Use JUnit Platform for unit tests.
useJUnitPlatform()
}

View File

@@ -0,0 +1,15 @@
/*
* This source file was generated by the Gradle 'init' task
*/
package org.example
class App {
val greeting: String
get() {
return "Hello World!"
}
}
fun main() {
println(App().greeting)
}

View File

@@ -0,0 +1,15 @@
/*
* This source file was generated by the Gradle 'init' task
*/
package org.example
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.Assertions.assertNotNull
class AppTest {
@Test
fun appHasAGreeting() {
val classUnderTest = App()
assertNotNull(classUnderTest.greeting, "app should have a greeting")
}
}

View File

@@ -0,0 +1,5 @@
# This file was generated by the Gradle 'init' task.
# https://docs.gradle.org/current/userguide/build_environment.html#sec:gradle_configuration_properties
org.gradle.configuration-cache=true

View File

@@ -0,0 +1,13 @@
# This file was generated by the Gradle 'init' task.
# https://docs.gradle.org/current/userguide/platforms.html#sub::toml-dependencies-format
[versions]
guava = "33.3.1-jre"
junit-jupiter = "5.11.1"
[libraries]
guava = { module = "com.google.guava:guava", version.ref = "guava" }
junit-jupiter = { module = "org.junit.jupiter:junit-jupiter", version.ref = "junit-jupiter" }
[plugins]
kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version = "2.0.21" }

Binary file not shown.

View File

@@ -0,0 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12.1-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

251
src/kotlin/gradlew vendored Executable file
View File

@@ -0,0 +1,251 @@
#!/bin/sh
#
# Copyright © 2015-2021 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.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.
#
# SPDX-License-Identifier: Apache-2.0
#
##############################################################################
#
# Gradle start up script for POSIX generated by Gradle.
#
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
app_path=$0
# Need this for daisy-chained symlinks.
while
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
[ -h "$app_path" ]
do
ls=$( ls -ld "$app_path" )
link=${ls#*' -> '}
case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
done
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
warn () {
echo "$*"
} >&2
die () {
echo
echo "$*"
echo
exit 1
} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "$( uname )" in #(
CYGWIN* ) cygwin=true ;; #(
Darwin* ) darwin=true ;; #(
MSYS* | MINGW* ) msys=true ;; #(
NONSTOP* ) nonstop=true ;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD=$JAVA_HOME/jre/sh/java
else
JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD=java
if ! command -v java >/dev/null 2>&1
then
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
fi
# Increase the maximum file descriptors if we can.
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
fi
# Collect all arguments for the java command, stacking in reverse order:
# * args from the command line
# * the main class name
# * -classpath
# * -D...appname settings
# * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
fi
# Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
done
fi
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Collect all arguments for the java command:
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# and any embedded shellness will be escaped.
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
# treated as '${Hostname}' itself on the command line.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \
"$@"
# Stop when "xargs" is not available.
if ! command -v xargs >/dev/null 2>&1
then
die "xargs is not available"
fi
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@"

94
src/kotlin/gradlew.bat vendored Normal file
View File

@@ -0,0 +1,94 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@rem SPDX-License-Identifier: Apache-2.0
@rem
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=.
@rem This is normally unused
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute
echo. 1>&2
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo. 1>&2
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if %ERRORLEVEL% equ 0 goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

View File

@@ -0,0 +1,14 @@
/*
* This file was generated by the Gradle 'init' task.
*
* The settings file is used to specify which projects to include in your build.
* For more detailed information on multi-project builds, please refer to https://docs.gradle.org/8.12.1/userguide/multi_project_builds.html in the Gradle documentation.
*/
plugins {
// Apply the foojay-resolver plugin to allow automatic download of JDKs
id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0"
}
rootProject.name = "kotlin"
include("app")

12
src/tutorial-c/.gitattributes vendored Normal file
View File

@@ -0,0 +1,12 @@
#
# https://help.github.com/articles/dealing-with-line-endings/
#
# Linux start script should use lf
/gradlew text eol=lf
# These are Windows script files and should use crlf
*.bat text eol=crlf
# Binary files should be left untouched
*.jar binary

5
src/tutorial-c/.gitignore vendored Normal file
View File

@@ -0,0 +1,5 @@
# Ignore Gradle project-specific cache directory
.gradle
# Ignore Gradle build output directory
build

View File

@@ -0,0 +1,19 @@
/*
* This file was generated by the Gradle 'init' task.
*
* This generated file contains a sample C++ project to get you started.
* For more details on building C++ applications and libraries, please refer to https://docs.gradle.org/8.12.1/userguide/building_cpp_projects.html in the Gradle documentation.
*/
plugins {
// Apply the cpp-application plugin to add support for building C++ executables
`cpp-application`
// Apply the cpp-unit-test plugin to add support for building and running C++ test executables
//`cpp-unit-test`
}
// Set the target operating system and architecture for this application
application {
targetMachines.add(machines.linux.x86_64)
}

View File

@@ -0,0 +1,12 @@
/*
* This source file was generated by the Gradle 'init' task
*/
#include <stdlib.h>
int main () {
printf("Hello, World!");
return 0;
}

View File

@@ -0,0 +1,5 @@
# This file was generated by the Gradle 'init' task.
# https://docs.gradle.org/current/userguide/build_environment.html#sec:gradle_configuration_properties
org.gradle.configuration-cache=true

View File

@@ -0,0 +1,2 @@
# This file was generated by the Gradle 'init' task.
# https://docs.gradle.org/current/userguide/platforms.html#sub::toml-dependencies-format

Binary file not shown.

View File

@@ -0,0 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12.1-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

251
src/tutorial-c/gradlew vendored Executable file
View File

@@ -0,0 +1,251 @@
#!/bin/sh
#
# Copyright © 2015-2021 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.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.
#
# SPDX-License-Identifier: Apache-2.0
#
##############################################################################
#
# Gradle start up script for POSIX generated by Gradle.
#
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
app_path=$0
# Need this for daisy-chained symlinks.
while
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
[ -h "$app_path" ]
do
ls=$( ls -ld "$app_path" )
link=${ls#*' -> '}
case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
done
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
warn () {
echo "$*"
} >&2
die () {
echo
echo "$*"
echo
exit 1
} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "$( uname )" in #(
CYGWIN* ) cygwin=true ;; #(
Darwin* ) darwin=true ;; #(
MSYS* | MINGW* ) msys=true ;; #(
NONSTOP* ) nonstop=true ;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD=$JAVA_HOME/jre/sh/java
else
JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD=java
if ! command -v java >/dev/null 2>&1
then
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
fi
# Increase the maximum file descriptors if we can.
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
fi
# Collect all arguments for the java command, stacking in reverse order:
# * args from the command line
# * the main class name
# * -classpath
# * -D...appname settings
# * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
fi
# Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
done
fi
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Collect all arguments for the java command:
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# and any embedded shellness will be escaped.
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
# treated as '${Hostname}' itself on the command line.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \
"$@"
# Stop when "xargs" is not available.
if ! command -v xargs >/dev/null 2>&1
then
die "xargs is not available"
fi
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@"

94
src/tutorial-c/gradlew.bat vendored Normal file
View File

@@ -0,0 +1,94 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@rem SPDX-License-Identifier: Apache-2.0
@rem
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=.
@rem This is normally unused
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute
echo. 1>&2
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo. 1>&2
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if %ERRORLEVEL% equ 0 goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

View File

@@ -0,0 +1,9 @@
/*
* This file was generated by the Gradle 'init' task.
*
* The settings file is used to specify which projects to include in your build.
* For more detailed information on multi-project builds, please refer to https://docs.gradle.org/8.12.1/userguide/multi_project_builds.html in the Gradle documentation.
*/
rootProject.name = "tutorial-c"
include("app")

12
src/tutorial-multi/.gitattributes vendored Normal file
View File

@@ -0,0 +1,12 @@
#
# https://help.github.com/articles/dealing-with-line-endings/
#
# Linux start script should use lf
/gradlew text eol=lf
# These are Windows script files and should use crlf
*.bat text eol=crlf
# Binary files should be left untouched
*.jar binary

5
src/tutorial-multi/.gitignore vendored Normal file
View File

@@ -0,0 +1,5 @@
# Ignore Gradle project-specific cache directory
.gradle
# Ignore Gradle build output directory
build

View File

@@ -0,0 +1,17 @@
/*
* This file was generated by the Gradle 'init' task.
*/
plugins {
id("buildlogic.java-application-conventions")
}
dependencies {
implementation("org.apache.commons:commons-text")
implementation(project(":utilities"))
}
application {
// Define the main class for the application.
mainClass = "org.example.app.App"
}

View File

@@ -0,0 +1,21 @@
/*
* This source file was generated by the Gradle 'init' task
*/
package org.example.app;
import org.example.list.LinkedList;
import static org.example.utilities.StringUtils.join;
import static org.example.utilities.StringUtils.split;
import static org.example.app.MessageUtils.getMessage;
import org.apache.commons.text.WordUtils;
public class App {
public static void main(String[] args) {
LinkedList tokens;
tokens = split(getMessage());
String result = join(tokens);
System.out.println(WordUtils.capitalize(result));
}
}

View File

@@ -0,0 +1,10 @@
/*
* This source file was generated by the Gradle 'init' task
*/
package org.example.app;
class MessageUtils {
public static String getMessage() {
return "Hello World!";
}
}

View File

@@ -0,0 +1,14 @@
/*
* This source file was generated by the Gradle 'init' task
*/
package org.example.app;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
class MessageUtilsTest {
@Test void testGetMessage() {
assertEquals("Hello World!", MessageUtils.getMessage());
}
}

View File

@@ -0,0 +1,13 @@
/*
* This file was generated by the Gradle 'init' task.
*/
plugins {
// Support convention plugins written in Kotlin. Convention plugins are build scripts in 'src/main' that automatically become available as plugins in the main build.
`kotlin-dsl`
}
repositories {
// Use the plugin portal to apply community plugins in convention plugins.
gradlePluginPortal()
}

View File

@@ -0,0 +1,14 @@
/*
* This file was generated by the Gradle 'init' task.
*
* This settings file is used to specify which projects to include in your build-logic build.
*/
dependencyResolutionManagement {
// Reuse version catalog from the main build.
versionCatalogs {
create("libs", { from(files("../gradle/libs.versions.toml")) })
}
}
rootProject.name = "buildSrc"

View File

@@ -0,0 +1,11 @@
/*
* This file was generated by the Gradle 'init' task.
*/
plugins {
// Apply the common convention plugin for shared build configuration between library and application projects.
id("buildlogic.java-common-conventions")
// Apply the application plugin to add support for building a CLI application in Java.
application
}

View File

@@ -0,0 +1,37 @@
/*
* This file was generated by the Gradle 'init' task.
*/
plugins {
// Apply the java Plugin to add support for Java.
java
}
repositories {
// Use Maven Central for resolving dependencies.
mavenCentral()
}
dependencies {
constraints {
// Define dependency versions as constraints
implementation("org.apache.commons:commons-text:1.12.0")
}
// Use JUnit Jupiter for testing.
testImplementation("org.junit.jupiter:junit-jupiter:5.11.1")
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
}
// Apply a specific Java toolchain to ease working on different environments.
java {
toolchain {
languageVersion = JavaLanguageVersion.of(21)
}
}
tasks.named<Test>("test") {
// Use JUnit Platform for unit tests.
useJUnitPlatform()
}

View File

@@ -0,0 +1,11 @@
/*
* This file was generated by the Gradle 'init' task.
*/
plugins {
// Apply the common convention plugin for shared build configuration between library and application projects.
id("buildlogic.java-common-conventions")
// Apply the java-library plugin for API and implementation separation.
`java-library`
}

View File

@@ -0,0 +1,5 @@
# This file was generated by the Gradle 'init' task.
# https://docs.gradle.org/current/userguide/build_environment.html#sec:gradle_configuration_properties
org.gradle.configuration-cache=true

View File

@@ -0,0 +1,2 @@
# This file was generated by the Gradle 'init' task.
# https://docs.gradle.org/current/userguide/platforms.html#sub::toml-dependencies-format

Binary file not shown.

View File

@@ -0,0 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12.1-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

251
src/tutorial-multi/gradlew vendored Executable file
View File

@@ -0,0 +1,251 @@
#!/bin/sh
#
# Copyright © 2015-2021 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.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.
#
# SPDX-License-Identifier: Apache-2.0
#
##############################################################################
#
# Gradle start up script for POSIX generated by Gradle.
#
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
app_path=$0
# Need this for daisy-chained symlinks.
while
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
[ -h "$app_path" ]
do
ls=$( ls -ld "$app_path" )
link=${ls#*' -> '}
case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
done
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
warn () {
echo "$*"
} >&2
die () {
echo
echo "$*"
echo
exit 1
} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "$( uname )" in #(
CYGWIN* ) cygwin=true ;; #(
Darwin* ) darwin=true ;; #(
MSYS* | MINGW* ) msys=true ;; #(
NONSTOP* ) nonstop=true ;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD=$JAVA_HOME/jre/sh/java
else
JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD=java
if ! command -v java >/dev/null 2>&1
then
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
fi
# Increase the maximum file descriptors if we can.
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
fi
# Collect all arguments for the java command, stacking in reverse order:
# * args from the command line
# * the main class name
# * -classpath
# * -D...appname settings
# * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
fi
# Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
done
fi
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Collect all arguments for the java command:
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# and any embedded shellness will be escaped.
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
# treated as '${Hostname}' itself on the command line.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \
"$@"
# Stop when "xargs" is not available.
if ! command -v xargs >/dev/null 2>&1
then
die "xargs is not available"
fi
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@"

94
src/tutorial-multi/gradlew.bat vendored Normal file
View File

@@ -0,0 +1,94 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@rem SPDX-License-Identifier: Apache-2.0
@rem
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=.
@rem This is normally unused
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute
echo. 1>&2
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo. 1>&2
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if %ERRORLEVEL% equ 0 goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

View File

@@ -0,0 +1,7 @@
/*
* This file was generated by the Gradle 'init' task.
*/
plugins {
id("buildlogic.java-library-conventions")
}

View File

@@ -0,0 +1,81 @@
/*
* This source file was generated by the Gradle 'init' task
*/
package org.example.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;
}
}
}

View File

@@ -0,0 +1,50 @@
/*
* This source file was generated by the Gradle 'init' task
*/
package org.example.list;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class LinkedListTest {
@Test void testConstructor() {
LinkedList list = new LinkedList();
assertEquals(0, list.size());
}
@Test void testAdd() {
LinkedList list = new LinkedList();
list.add("one");
assertEquals(1, list.size());
assertEquals("one", list.get(0));
list.add("two");
assertEquals(2, list.size());
assertEquals("two", list.get(1));
}
@Test void testRemove() {
LinkedList list = new LinkedList();
list.add("one");
list.add("two");
assertTrue(list.remove("one"));
assertEquals(1, list.size());
assertEquals("two", list.get(0));
assertTrue(list.remove("two"));
assertEquals(0, list.size());
}
@Test public void testRemoveMissing() {
LinkedList list = new LinkedList();
list.add("one");
list.add("two");
assertFalse(list.remove("three"));
assertEquals(2, list.size());
}
}

View File

@@ -0,0 +1,14 @@
/*
* This file was generated by the Gradle 'init' task.
*
* The settings file is used to specify which projects to include in your build.
* For more detailed information on multi-project builds, please refer to https://docs.gradle.org/8.12.1/userguide/multi_project_builds.html in the Gradle documentation.
*/
plugins {
// Apply the foojay-resolver plugin to allow automatic download of JDKs
id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0"
}
rootProject.name = "tutorial-multi"
include("app", "list", "utilities")

View File

@@ -0,0 +1,71 @@
.
├── app
│   ├── build.gradle.kts
│   └── src
│   ├── main
│   │   ├── java
│   │   │   └── org
│   │   │   └── example
│   │   │   └── app
│   │   │   ├── App.java
│   │   │   └── MessageUtils.java
│   │   └── resources
│   └── test
│   ├── java
│   │   └── org
│   │   └── example
│   │   └── app
│   │   └── MessageUtilsTest.java
│   └── resources
├── buildSrc
│   ├── build.gradle.kts
│   ├── settings.gradle.kts
│   └── src
│   └── main
│   └── kotlin
│   ├── buildlogic.java-application-conventions.gradle.kts
│   ├── buildlogic.java-common-conventions.gradle.kts
│   └── buildlogic.java-library-conventions.gradle.kts
├── gradle
│   ├── libs.versions.toml
│   └── wrapper
│   ├── gradle-wrapper.jar
│   └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
├── list
│   ├── build.gradle.kts
│   └── src
│   ├── main
│   │   ├── java
│   │   │   └── org
│   │   │   └── example
│   │   │   └── list
│   │   │   └── LinkedList.java
│   │   └── resources
│   └── test
│   ├── java
│   │   └── org
│   │   └── example
│   │   └── list
│   │   └── LinkedListTest.java
│   └── resources
├── settings.gradle.kts
├── tree.txt
└── utilities
├── build.gradle.kts
└── src
├── main
│   ├── java
│   │   └── org
│   │   └── example
│   │   └── utilities
│   │   ├── JoinUtils.java
│   │   ├── SplitUtils.java
│   │   └── StringUtils.java
│   └── resources
└── test
└── resources
45 directories, 24 files

View File

@@ -0,0 +1,11 @@
/*
* This file was generated by the Gradle 'init' task.
*/
plugins {
id("buildlogic.java-library-conventions")
}
dependencies {
api(project(":list"))
}

View File

@@ -0,0 +1,20 @@
/*
* This source file was generated by the Gradle 'init' task
*/
package org.example.utilities;
import org.example.list.LinkedList;
class JoinUtils {
public static String join(LinkedList source) {
StringBuilder result = new StringBuilder();
for (int i = 0; i < source.size(); ++i) {
if (result.length() > 0) {
result.append(" ");
}
result.append(source.get(i));
}
return result.toString();
}
}

View File

@@ -0,0 +1,39 @@
/*
* This source file was generated by the Gradle 'init' task
*/
package org.example.utilities;
import org.example.list.LinkedList;
class SplitUtils {
public static LinkedList split(String source) {
int lastFind = 0;
int currentFind = 0;
LinkedList result = new LinkedList();
while ((currentFind = source.indexOf(" ", lastFind)) != -1) {
String token = source.substring(lastFind);
if (currentFind != -1) {
token = token.substring(0, currentFind - lastFind);
}
addIfValid(token, result);
lastFind = currentFind + 1;
}
String token = source.substring(lastFind);
addIfValid(token, result);
return result;
}
private static void addIfValid(String token, LinkedList list) {
if (isTokenValid(token)) {
list.add(token);
}
}
private static boolean isTokenValid(String token) {
return !token.isEmpty();
}
}

View File

@@ -0,0 +1,16 @@
/*
* This source file was generated by the Gradle 'init' task
*/
package org.example.utilities;
import org.example.list.LinkedList;
public class StringUtils {
public static String join(LinkedList source) {
return JoinUtils.join(source);
}
public static LinkedList split(String source) {
return SplitUtils.split(source);
}
}

12
src/tutorial/.gitattributes vendored Normal file
View File

@@ -0,0 +1,12 @@
#
# https://help.github.com/articles/dealing-with-line-endings/
#
# Linux start script should use lf
/gradlew text eol=lf
# These are Windows script files and should use crlf
*.bat text eol=crlf
# Binary files should be left untouched
*.jar binary

5
src/tutorial/.gitignore vendored Normal file
View File

@@ -0,0 +1,5 @@
# Ignore Gradle project-specific cache directory
.gradle
# Ignore Gradle build output directory
build

View File

@@ -0,0 +1,43 @@
/*
* 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 on building Java & JVM projects, please refer to https://docs.gradle.org/8.12.1/userguide/building_java_projects.html in the Gradle documentation.
*/
plugins {
// Apply the application plugin to add support for building a CLI application in Java.
application
}
repositories {
// Use Maven Central for resolving dependencies.
mavenCentral()
}
dependencies {
// Use JUnit Jupiter for testing.
testImplementation(libs.junit.jupiter)
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
// This dependency is used by the application.
implementation(libs.guava)
}
// Apply a specific Java toolchain to ease working on different environments.
java {
toolchain {
languageVersion = JavaLanguageVersion.of(21)
}
}
application {
// Define the main class for the application.
mainClass = "org.example.App"
}
tasks.named<Test>("test") {
// Use JUnit Platform for unit tests.
useJUnitPlatform()
}

View File

@@ -0,0 +1,14 @@
/*
* This source file was generated by the Gradle 'init' task
*/
package org.example;
public class App {
public String getGreeting() {
return "Hello World!";
}
public static void main(String[] args) {
System.out.println(new App().getGreeting());
}
}

View File

@@ -0,0 +1,14 @@
/*
* This source file was generated by the Gradle 'init' task
*/
package org.example;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class AppTest {
@Test void appHasAGreeting() {
App classUnderTest = new App();
assertNotNull(classUnderTest.getGreeting(), "app should have a greeting");
}
}

View File

@@ -0,0 +1,5 @@
# This file was generated by the Gradle 'init' task.
# https://docs.gradle.org/current/userguide/build_environment.html#sec:gradle_configuration_properties
org.gradle.configuration-cache=true

View File

@@ -0,0 +1,10 @@
# This file was generated by the Gradle 'init' task.
# https://docs.gradle.org/current/userguide/platforms.html#sub::toml-dependencies-format
[versions]
guava = "33.3.1-jre"
junit-jupiter = "5.11.1"
[libraries]
guava = { module = "com.google.guava:guava", version.ref = "guava" }
junit-jupiter = { module = "org.junit.jupiter:junit-jupiter", version.ref = "junit-jupiter" }

Binary file not shown.

View File

@@ -0,0 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12.1-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

251
src/tutorial/gradlew vendored Executable file
View File

@@ -0,0 +1,251 @@
#!/bin/sh
#
# Copyright © 2015-2021 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.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.
#
# SPDX-License-Identifier: Apache-2.0
#
##############################################################################
#
# Gradle start up script for POSIX generated by Gradle.
#
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
app_path=$0
# Need this for daisy-chained symlinks.
while
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
[ -h "$app_path" ]
do
ls=$( ls -ld "$app_path" )
link=${ls#*' -> '}
case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
done
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
warn () {
echo "$*"
} >&2
die () {
echo
echo "$*"
echo
exit 1
} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "$( uname )" in #(
CYGWIN* ) cygwin=true ;; #(
Darwin* ) darwin=true ;; #(
MSYS* | MINGW* ) msys=true ;; #(
NONSTOP* ) nonstop=true ;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD=$JAVA_HOME/jre/sh/java
else
JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD=java
if ! command -v java >/dev/null 2>&1
then
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
fi
# Increase the maximum file descriptors if we can.
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
fi
# Collect all arguments for the java command, stacking in reverse order:
# * args from the command line
# * the main class name
# * -classpath
# * -D...appname settings
# * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
fi
# Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
done
fi
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Collect all arguments for the java command:
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# and any embedded shellness will be escaped.
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
# treated as '${Hostname}' itself on the command line.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \
"$@"
# Stop when "xargs" is not available.
if ! command -v xargs >/dev/null 2>&1
then
die "xargs is not available"
fi
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@"

94
src/tutorial/gradlew.bat vendored Normal file
View File

@@ -0,0 +1,94 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@rem SPDX-License-Identifier: Apache-2.0
@rem
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=.
@rem This is normally unused
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute
echo. 1>&2
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo. 1>&2
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if %ERRORLEVEL% equ 0 goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

View File

@@ -0,0 +1,14 @@
/*
* This file was generated by the Gradle 'init' task.
*
* The settings file is used to specify which projects to include in your build.
* For more detailed information on multi-project builds, please refer to https://docs.gradle.org/8.12.1/userguide/multi_project_builds.html in the Gradle documentation.
*/
plugins {
// Apply the foojay-resolver plugin to allow automatic download of JDKs
id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0"
}
rootProject.name = "tutorial"
include("app")