## Building
-AspectJ has a multi module maven build. Although various modules produce intermediate results, the key artifacts at the end of the build are:
+AspectJ has a multi-module Maven build. Although various modules produce intermediate results, the key artifacts at the end of the build are:
* `aspectjrt` - the AspectJ runtime
* `aspectjweaver` - the AspectJ weaver
* `aspectjtools` - the AspectJ compiler
+* `aspectjmatcher` - the AspectJ matcher
-These are the artifacts published to maven central for each release. In addition there is an installer that can be run with `java -jar` to install AspectJ onto Windows/Mac/Linux. This installer is produced by the installer sub module.
+These are the artifacts published to Maven Central for each release. In addition, there is an installer that can be run with `java -jar` to install AspectJ onto Windows/Mac/Linux. This installer is produced by the `installer` sub-module.
In the root of a cloned AspectJ simply run:
`./mvnw clean install`
This will build all the modules, run all the tests and install the key artifacts in your local repository.
-Once built access the maven dependencies from your local repository or run the installer to install AspectJ locally:
+Once built, access the Maven dependencies from your local repository or run the installer to install AspectJ locally:
```
java -jar installer/target/aspectj-<VERSION>.jar
```
-## Running the tests in eclipse
+## Running the tests in Eclipse
Once you have imported all the projects using `m2e`, there is a special module called `run-all-junit-tests` and within that a `RunTheseBeforeYouCommitTests` class that can be run with the JUnit launcher to execute thousands of tests.
Ensure you run this with a JDK - the more recent the better since some tests will not execute on older JDKs - tests that verify language features that only exist in the more up to date JDK version.
-## Documentation
+## Documentation for AspectJ users
-[Complete documentation quicklinks](https://www.eclipse.org/aspectj/docs.php)
+* [Complete documentation quicklinks](https://www.eclipse.org/aspectj/docs.php)
+* [Getting started with AspectJ](https://www.eclipse.org/aspectj/doc/released/progguide/starting.html)
+* [Programming Guide](https://www.eclipse.org/aspectj/doc/released/progguide/index.html)
+* [READMEs for each version of AspectJ](docs/dist/doc)
-[Getting started with AspectJ](https://www.eclipse.org/aspectj/doc/released/progguide/starting.html)
+## Documentation for AspectJ developers
-[Programming Guide](https://www.eclipse.org/aspectj/doc/released/progguide/index.html)
-
-[READMEs for each version of AspectJ](https://github.com/eclipse/org.aspectj/tree/master/docs/dist/doc)
+* [How to contribute to AspectJ](CONTRIBUTING.md)
+* [How to release AspectJ](docs/developer/RELEASE.md)
## Maven releases
--- /dev/null
+# How to release AspectJ
+
+AspectJ is built and released with Maven. As of writing this, there is a Maven wrapper in the project root folder,
+pointing to Maven 3.6.3, but we are going to use simple `mvn` commands instead of `./mvnw` here, assuming that there is
+a local Maven installation on your workstation. You can easily substitute one for the other command.
+
+When deploying final releases to Sonatype OSSRH, the build uses Nexus Staging Maven plugin instead of Maven Deploy
+plugin. This helps to create a staging repository for the release and later release it to Maven Central without having
+to log into the [Sonatype Nexus web UI](https://oss.sonatype.org/). Everything can be done from the command line.
+
+Snapshots do not need to be staged and released separately, Maven Deploy does the job in this case. so let us begin with
+the simple case:
+
+## Snapshot releases
+
+Assuming that you are currently working on version 1.9.7-SNAPSHOT, you simply call:
+
+```shell
+mvn clean deploy
+
+# OR: If you ran tests locally before, or the CI workflow on GitHub did
+mvn -DskipTests=true clean deploy
+
+# OR: Speed it up some more, skipping documentation generation. Depending on
+# your shell, you might not have to escape the '!' character for deactivating
+# the 'create-docs' profile. On a (Git) Bash you have to, though.
+mvn -P \!create-docs -DskipTests=true clean deploy
+```
+
+This only deploys the main artifacts
+ - AspectJ runtime `aspectjrt-[VERSION].jar`,
+ - AspectJ tools/compiler `aspecttools-[VERSION].jar`,
+ - AspectJ weaver `aspectjweaver-[VERSION].jar`,
+ - AspectJ matcher `aspectjmatcher-[VERSION].jar`.
+
+The AspectJ installer (`installer/target/aspectj-[VERSION].jar`) needs to be published separately, if you wish to make
+it available to the public for this snapshot.
+
+## Public releases (milestone, release candidate, final)
+
+The artifacts released are the same as for snapshots, the procedure needs a few more steps, though. I am explaining the
+manual versioning process without using Maven Release plugin. It might work using Maven Release too, i.e.
+ - setting the release version in all POMs,
+ - building a release,
+ - running tests (can be skipped),
+ - committing the release POMs,
+ - tagging the release,
+ - deploying the release,
+ - setting the next snapshot version in all POMs,
+ - committing the snapshot POMs,
+ - pushing the previous commits and the release tag to the upstream Git repository.
+
+In order to show the details and give you more control over the process, you can do it step by step as follows:
+
+```shell
+# Make sure we are on JDK 16, because javadoc generation is JDK version sensitive
+# and might throw unexpected errors on other versions
+java -version
+# java version "16" 2021-03-16 (...)
+
+# Verify that we are working on a clean working directory.
+# There should be no staged, unstaged or untracked files.
+git status
+
+# Set release version in all POMs
+mvn versions:set -DnewVersion=1.9.7.M2
+
+# Verify if the POM changes are OK, then remove the POM backup files
+mvn versions:commit
+
+# Commit the release POMs to Git
+git commit -am "Set version to 1.9.7.M2"
+
+# Set some environment variables needed by Nexus Staging Maven plugin on JDK 16,
+# until https://issues.sonatype.org/browse/OSSRH-66257 is resolved
+export MAVEN_OPTS="--add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.base/java.lang.reflect=ALL-UNNAMED --add-opens=java.base/java.text=ALL-UNNAMED --add-opens=java.desktop/java.awt.font=ALL-UNNAMED"
+
+# Build and deploy the release to a Nexus staging repository.
+# The 'release' profile will activate
+# - Maven GPG plugin for signing artifacts (stand by to enter your passpharase!),
+# - Maven Javadoc plugin,
+# - Nexus Staging Maven plugin.
+# Optionally, use '-DskipTests=true', if you ran all tests before.
+mvn -P release clean deploy
+```
+
+If this command was successful, it means we have created a staging repository on Sonatype OSSRH, uploaded all artifacts
+and all pre-release checks on the Sonatype server passed, i.e. if the POMs contain all necessary information and if
+there are source and javadoc artifacts attached to the build. Now the only step left is to release the staging
+repository to Maven Central.
+
+Actually, Nexus Staging Maven plugin can also be configured deploy and release to Maven Central in a single command, but
+in order to give you a chance to manually download and verify the artifacts from the staging repository, the default
+plugin configuration in the parent POM is `<autoReleaseAfterClose>false</autoReleaseAfterClose>`. Switching the value to
+`true` would release straight to Maven Central, given all previous steps were successful.
+
+Before we release the staging repository though, we want to commit and tag the release, then set a new snapshot version:
+
+```shell
+# Commit the release POMs to Git (better do this from your IDE, verifying the
+# changes before staging them for Git commit)
+git commit -am "Set version to 1.9.7.M2"
+
+# Tag release
+git tag V1_9_7_M2
+
+# Set new snapshot version, increasing the version number after a final release
+mvn versions:set -DnewVersion=1.9.7-SNAPSHOT
+
+# Verify if the POM changes are OK, then remove the POM backup files
+mvn versions:commit
+
+# Commit the snapshot POMs to Git
+git commit -am "Set version to 1.9.7-SNAPSHOT"
+
+# Push the previous commits to GitHub
+git push origin
+
+# Push the release tag to GitHub
+git push origin V1_9_7_M2
+```
+
+OK, the Git house-keeping is done. Now finally, let us enjoy the fruits of our work and release the staging repository
+to Maven Central:
+
+```shell
+# Probably we forgot to write down the staging repository ID before.
+# It was written somewhere in the Maven log:
+# [INFO] * Created staging repository with ID "orgaspectj-1106".
+# [INFO] * Staging repository at https://oss.sonatype.org:443/service/local/staging/deployByRepositoryId/orgaspectj-1106
+# ...
+# [INFO] * Uploading locally staged artifacts to profile org.aspectj
+# [INFO] * Upload of locally staged artifacts finished.
+# [INFO] * Closing staging repository with ID "orgaspectj-1106".
+#
+# But it is too far to scroll up. So let us just ask Nexus, which staging
+# repositories there are.
+mvn nexus-staging:rc-list
+# [INFO] ID State Description
+# [INFO] orgaspectj-1106 CLOSED org.aspectj:aspectjrt:1.9.7.M2
+
+# Use the ID of the corresponding CLOSED staging repository for releasing to
+# Maven Central
+ mvn nexus-staging:rc-release -DstagingRepositoryId=orgaspectj-1106
+```
+
+Tadaa! We have performed an AspectJ release. In a few minutes, the artifacts should appear on Maven Central somewhere
+under https://repo1.maven.org/maven2/org/aspectj/, e.g. AspectJ Tools 1.9.7.M2 would appear under
+https://repo1.maven.org/maven2/org/aspectj/aspectjtools/1.9.7.M2/. As soon as you see the artifacts there instead of
+"404 not found", you can announce release availability on the AspectJ mailing list and wherever else appropriate.
+
+Finally, probably want to publish the AspectJ installer (`installer/target/aspectj-[VERSION].jar`), e.g. by creating a
+GitHub release and attaching artifacts and/or updating the Eclipse AspectJ website. You also want to update the AspectJ
+documentation, if there were any changes.