Development Experience command line tools. Automating away the development gruntwork.
The devex
tool is built for two operating systems Linux and macOS. Each release on this repository provides
binaries for these two operating systems. To install the tool, either download the binary from the latest release, make
it executable and place it on a reachable path; or use brew
.
brew install miguelaferreira/tools/devex-cli
The usage of the tool is documented at https://miguelaferreira.gitbook.io/devex/devex-cli/overview.
SDKMAN automates the process of installing and upgrading sdks, namely Java sdks. Install is via.
curl -s "https://get.sdkman.io" | bash
Then install GraalVM.
sdk install java 21.3.0.r17-grl
Load the installed GraalVM on the current terminal.
sdk use java 21.3.0.r17-grl
To build native images using GraalVM it is necessary to install the native-image
tool.
~/.sdkman/candidates/java/current/bin/gu install native-image
You should be ready to build the tool.
Gradle is configured to build both executable jars and GraalVM native images. Gradle will also want to run tests, and
the tests require a GitLab token with read_api
scope. The token is picked up from the environment
variable GITLAB_TOKEN
. The tests can be skipped with the gradle flag -x test
, in which case the GitLab token isn't
needed anymore.
To build an executable jar run gradle task build
.
GITLAB_TOKEN="..." ./gradlew clean build
The executable jar is created under build/libs/
, and it will be called something like devex-VERSION-all.jar
.
To execute that jar run java
.
java -jar build/libs/devex-*-all.jar -h
To build a GraalVM native binary run the nativeImage
gradle task.
GITLAB_TOKEN="..." ./gradlew clean nativeImage
The binary will be created under build/native-image/application
. To execute the native binary run it.
build/native-image/application -h
In order to properly build a native binary some configuration needs to be generated from running the app as a jar. That configuration is then included as a resource for the application, and the native image builder will load that to properly create the native binary. That can be done by running the app from jar while setting a JVM agent to collect the configuration. During the app run all functionality should be exercised.
./gradlew clean build
java -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image -jar build/libs/devex-*-all.jar ...
However, not all functionality of the app can be exercised in a single run (eg. cloning via SSH vs HTTPS). Therefore,
different executions need to be made (as many as different and independent features of the app), each generating a set
of config, which at the end needs to be merged. See
the native-image manual
for more information on how this works. Since the tool that merges the configuration (native-image-configure-launcher
)
is not shipped with graalvm releases, it has to be built. This project includes two binaries of the tool, one for macOS
and the other for Linux, under graalvm/bin. During CI workflows that run on PR to main
branch, the
app is executed with the native-image-agent
producing different sets of configurations for different combinations of
input options and parameters. This is done in
script .github/scripts/create-native-image-build-config.sh. Then
the generated configurations are merged into the project's sources by another
script, .github/scripts/merge-native-image-build-config.sh.
Finally, a new commit is made to the PR branch with the updated configuration.