Skip to content

Commit

Permalink
Merge pull request #10 from graalvm/tim/add-gradle-demos
Browse files Browse the repository at this point in the history
Add gradle plugin to GraalPy demos
  • Loading branch information
timfel authored Nov 19, 2024
2 parents b005b79 + e1bb7bb commit 1958c9a
Show file tree
Hide file tree
Showing 37 changed files with 1,959 additions and 47 deletions.
11 changes: 10 additions & 1 deletion .github/workflows/graalpy-freeze-dependencies-guide.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,15 @@ jobs:
shell: bash
run: |
cd graalpy/graalpy-freeze-dependencies-guide
git clean -fdx
./mvnw --no-transfer-progress compile
./mvnw --no-transfer-progress exec:java -Dexec.mainClass=org.example.App | tee /tmp/output
grep darent /tmp/output
grep darent /tmp/output
- name: Build, test, and run 'graalpy-freeze-dependencies-guide' using Gradle
shell: bash
run: |
cd graalpy/graalpy-freeze-dependencies-guide
git clean -fdx
./gradlew build
./gradlew run | tee /tmp/output
grep darent /tmp/output
24 changes: 23 additions & 1 deletion .github/workflows/graalpy-micronaut-guide.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
run:
name: 'graalpy-micronaut-guide'
runs-on: ubuntu-latest
timeout-minutes: 30
timeout-minutes: 45
steps:
- uses: actions/checkout@v4
- uses: graalvm/setup-graalvm@v1
Expand All @@ -30,18 +30,40 @@ jobs:
- name: Build, test, and run 'graalpy-micronaut-guide' using Maven
run: |
cd graalpy/graalpy-micronaut-guide
git clean -fdx
./mvnw --no-transfer-progress clean test -Dmicronaut.http.client.read-timeout=1m
./mvnw --no-transfer-progress mn:run &
mnpid="$!"
sleep 30
curl --fail-with-body --silent --dump-header - -o /dev/null http://localhost:8080/
kill $mnpid
- name: Build, test, and run 'graalpy-micronaut-guide' using Gradle
run: |
cd graalpy/graalpy-micronaut-guide
git clean -fdx
./gradlew test -Dmicronaut.http.client.read-timeout=1m
./gradlew run &
mnpid="$!"
sleep 30
curl --fail-with-body --silent --dump-header - -o /dev/null http://localhost:8080/
kill $mnpid
- name: Build and run native 'graalpy-micronaut-guide' using Maven
run: |
cd graalpy/graalpy-micronaut-guide
git clean -fdx
./mvnw --no-transfer-progress clean package -DskipTests -Dpackaging=native-image
./target/graalpy-micronaut &
mnpid="$!"
sleep 20
curl --fail-with-body --silent --dump-header - -o /dev/null http://localhost:8080/
kill $mnpid
- name: Build and run native 'graalpy-micronaut-guide' using Gradle
run: |
cd graalpy/graalpy-micronaut-guide
git clean -fdx
./gradlew nativeCompile
./build/native/nativeCompile/demo &
mnpid="$!"
sleep 20
curl --fail-with-body --silent --dump-header - -o /dev/null http://localhost:8080/
kill $mnpid
14 changes: 13 additions & 1 deletion .github/workflows/graalpy-spring-boot-guide.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
run:
name: 'graalpy-spring-boot-guide'
runs-on: ubuntu-latest
timeout-minutes: 30
timeout-minutes: 45
steps:
- uses: actions/checkout@v4
- uses: graalvm/setup-graalvm@v1
Expand All @@ -30,15 +30,27 @@ jobs:
- name: Build, test, and run 'graalpy-spring-boot-guide' using Maven
run: |
cd graalpy/graalpy-spring-boot-guide
git clean -fdx
./mvnw --no-transfer-progress clean test -Dspring.mvc.async.request-timeout=60000
./mvnw --no-transfer-progress spring-boot:run &
sbpid="$!"
sleep 30
curl --fail-with-body --silent --dump-header - -o /dev/null http://localhost:8080/
kill $sbpid
- name: Build, test, and run 'graalpy-spring-boot-guide' using Gradle
run: |
cd graalpy/graalpy-spring-boot-guide
git clean -fdx
./gradlew test -Dspring.mvc.async.request-timeout=60000
./gradlew bootRun &
sbpid="$!"
sleep 30
curl --fail-with-body --silent --dump-header - -o /dev/null http://localhost:8080/
kill $sbpid
- name: Build and run native 'graalpy-spring-boot-guide' using Maven
run: |
cd graalpy/graalpy-spring-boot-guide
git clean -fdx
./mvnw --no-transfer-progress clean -DskipTests -Pnative native:compile
./target/graalpy-springboot &
sbpid="$!"
Expand Down
108 changes: 95 additions & 13 deletions graalpy/graalpy-freeze-dependencies-guide/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,9 @@ However, you can go right to the [completed example](https://github.com/graalvm/

## 3. Writing the application

You can start with any Maven application that runs on JDK 17 or newer.
We will use a default Maven application [generated](https://maven.apache.org/archetypes/maven-archetype-quickstart/) from an archetype.
You can start with any Maven or Gradle application that runs on JDK 17 or newer.
We will demonstrate on both build systems.
A default Maven application [generated](https://maven.apache.org/archetypes/maven-archetype-quickstart/) from an archetype.

```shell
mvn archetype:generate -DarchetypeGroupId=org.apache.maven.archetypes \
Expand All @@ -46,15 +47,35 @@ mvn archetype:generate -DarchetypeGroupId=org.apache.maven.archetypes \
-Dversion=1.0-SNAPSHOT -DinteractiveMode=false
```

And a default Gradle Java application [generated](https://docs.gradle.org/current/samples/sample_building_java_applications.html#run_the_init_task) with the init task.

```shell
gradle init --type java-application --dsl kotlin --test-framework junit-jupiter \
--package org.example --project-name example --java-version 17 \
--no-split-project --no-incubating
```

## 4. Adding packages

Most Python packages are hosted on [PyPI](https://pypi.org) and can be installed via the `pip` tool.
The Python ecosystem has conventions about the filesystem layout of installed packages that need to be kept in mind when embedding into Java.
You can use the GraalPy plugin to manage Python packages for you.
You can use the GraalPy plugins for Maven or Gradle to manage Python packages for you.

For Maven, add dependency on GraalPy runtime, and configure the GraalPy Maven plugin:

`pom.xml`
```xml
<dependency>
<groupId>org.graalvm.polyglot</groupId>
<artifactId>python</artifactId>
<version>24.1.1</version>
<type>pom</type>
</dependency>
```

`pom.xml`
```xml
<build>
<build>
<plugins>
<plugin>
<groupId>org.graalvm.python</groupId>
Expand All @@ -77,25 +98,72 @@ You can use the GraalPy plugin to manage Python packages for you.
</build>
```

For Gradle, add the GraalPy plugin, configure it, and add the dependency on the GraalPy runtime:

`build.gradle.kts`
```kotlin
plugins {
application
id("org.graalvm.python") version "24.1.1"
}
```

`build.gradle.kts`
```kotlin
graalPy {
packages = setOf("vaderSentiment==3.3.2") //
}

dependencies {
implementation("org.graalvm.python:python:24.1.1")
}
```

❶ The `packages` section lists all Python packages optionally with [requirement specifiers](https://pip.pypa.io/en/stable/reference/requirement-specifiers/).
In this case, we install the `vaderSentiment` package and pin it to version `3.3.2`. Because we are not
specifying `<pythonResourcesDirectory>` the Maven plugin will embed the packages into the
specifying `<pythonResourcesDirectory>` the plugins will embed the packages into the
resulting JAR as a standard Java resource.

## 5. Determining and Pinning Transitive Dependencies

Package the application using Maven, this should install all the transitive dependencies
When you package the application, it installs all the transitive dependencies
in a newly created [virtual environment](https://docs.python.org/3/library/venv.html):

```shell
mvn package
./mvnw package
```

If the compilation is successful, one can run the following command to get
versions of all the installed Python packages:
```shell
./gradlew assemble
```

If the compilation is successful, one can run the following command to get versions of all the installed Python packages if you use Maven:

On macOS and Linux:
```shell
./target/classes/org.graalvm.python.vfs/venv/bin/pip3 freeze -l
```

On Windows:
```shell
.\target\classes\org.graalvm.python.vfs\venv\Scripts\pip3.exe freeze -l
```

If you are using Gradle, run the following command:

On macOS and Linux:
```shell
./app/build/generated/graalpy/resources/org.graalvm.python.vfs/venv/bin/pip3 freeze -l
```

On Windows:
```shell
.\app\build\generated\graalpy\resources\org.graalvm.python.vfs\venv\Scripts\pip3.exe freeze -l
```

The output will look something like this:

```
certifi==2024.8.30
charset-normalizer==3.1.0
idna==3.8
Expand All @@ -104,8 +172,8 @@ urllib3==2.2.2
vaderSentiment==3.3.2
```

Copy and paste the package names and versions to the `pom.xml`, and wrap
them in `<package>` xml tag:
Copy and paste the package names and versions.
If you use Maven, paste them in the `pom.xml` section of the packages and wrap them in `<package>` xml tag:

`pom.xml`
```xml
Expand Down Expand Up @@ -137,6 +205,20 @@ them in `<package>` xml tag:
</build>
```

For Gradle, paste them into the packages block:

`build.gradle.kts`
```kotlin
packages = setOf(
"vaderSentiment==3.3.2",
"certifi==2024.8.30",
"charset-normalizer==3.1.0",
"idna==3.8",
"requests==2.32.3",
"urllib3==2.2.2"
)
```

Note: one can use other Python tools, such as `pipdeptree` to generate the following
dependency tree, where we can also see the version ranges.

Expand All @@ -151,7 +233,7 @@ vaderSentiment==3.3.2

*Warning:
Is it not recommended to manually alter the virtual environment.
Any changes will be overridden by the GraalPy Maven plugin.*
Any changes will be overridden by the GraalPy build plugins.*

## 8. Next steps

Expand All @@ -165,4 +247,4 @@ Any changes will be overridden by the GraalPy Maven plugin.*

- Learn more about the GraalPy [Maven plugin](https://www.graalvm.org/latest/reference-manual/python/Embedding-Build-Tools/)
- Learn more about the Polyglot API for [embedding languages](https://www.graalvm.org/latest/reference-manual/embed-languages/)
- Explore in depth with GraalPy [reference manual](https://www.graalvm.org/latest/reference-manual/python/)
- Explore in depth with GraalPy [reference manual](https://www.graalvm.org/latest/reference-manual/python/)
53 changes: 53 additions & 0 deletions graalpy/graalpy-freeze-dependencies-guide/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
plugins {
application
id("org.graalvm.python") version "24.1.1"
}

// To make the paths of this reference solution (without 'app' subdirectory for sources)
// and "gradle init ..." based solution (with sources in 'app') the same for README.md
layout.buildDirectory.set(layout.projectDirectory.dir("app/build"))

if ("true".equals(System.getProperty("no.transitive.dependencies"))) {
graalPy {
packages = setOf("vaderSentiment==3.3.2") //
}
dependencies {
implementation("org.graalvm.python:python:24.1.1")
}
} else {
// The default profile shows the end result: all our transitive
// dependencies are explicitly pinned to a specific version.
graalPy {
packages = setOf(
"vaderSentiment==3.3.2",
"certifi==2024.8.30",
"charset-normalizer==3.1.0",
"idna==3.8",
"requests==2.32.3",
"urllib3==2.2.2"
)
}
dependencies {
implementation("org.graalvm.python:python:24.1.1")
}
}

repositories {
mavenLocal()
maven {
url = uri("https://repo.maven.apache.org/maven2/")
}
}

// This dependency is necessary only for the example Java code, not for building and running pip freeze:
dependencies.add("implementation", "org.graalvm.python:python-embedding:24.1.1")

group = "org.example"
version = "1.0-SNAPSHOT"
description = "javase"
java.sourceCompatibility = JavaVersion.VERSION_17

application {
mainClass = "org.example.App"
applicationDefaultJvmArgs = listOf("-Dgraalpy.resources=" + System.getProperty("graalpy.resources"))
}
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
Loading

0 comments on commit 1958c9a

Please sign in to comment.