mirror of
https://github.com/corda/corda.git
synced 2025-04-11 13:21:26 +00:00
Merged in clint-gradleplugins (pull request #401)
Added Gradle Plugins required for Cordapp development
This commit is contained in:
commit
d2983d6a7a
build.gradle
core
docs/source
gradle-plugins
README.rst
settings.gradlecordformation
publish-utils
quasar-utils
src/main/java
@ -264,6 +264,9 @@ task installTemplateNodes(dependsOn: 'buildCordaJAR') << {
|
||||
}
|
||||
}
|
||||
|
||||
// Aliasing the publishToMavenLocal for simplicity.
|
||||
task(install, dependsOn: 'publishToMavenLocal')
|
||||
|
||||
publishing {
|
||||
publications {
|
||||
corda(MavenPublication) {
|
||||
|
@ -1,7 +1,6 @@
|
||||
apply plugin: 'kotlin'
|
||||
apply plugin: QuasarPlugin
|
||||
// Applying the maven plugin means this will get installed locally when running "gradle install"
|
||||
apply plugin: 'maven'
|
||||
apply plugin: DefaultPublishTasks
|
||||
|
||||
buildscript {
|
||||
|
@ -106,10 +106,58 @@ root directory of Corda
|
||||
This will publish corda-$version.jar, contracts-$version.jar, core-$version.jar and node-$version.jar to the
|
||||
group com.r3corda. You can now depend on these as you normally would a Maven dependency.
|
||||
|
||||
In Gradle you can depend on these by adding/modifying your build.gradle file to contain the following:
|
||||
Gradle Plugins for Cordapps
|
||||
===========================
|
||||
|
||||
There are several Gradle plugins that reduce your build.gradle boilerplate and make development of Cordapps easier.
|
||||
The available plugins are in the gradle-plugins directory of the Corda repository.
|
||||
|
||||
Building Gradle Plugins
|
||||
-----------------------
|
||||
|
||||
To install to your local Maven repository the plugins that Cordapp gradle files require, run the following from the
|
||||
root of the Corda project:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
./gradlew publishToMavenLocal
|
||||
|
||||
The plugins will now be installed to your local Maven repository in ~/.m2 on Unix and %HOMEPATH%\.m2 on Windows.
|
||||
|
||||
Using Gradle Plugins
|
||||
--------------------
|
||||
|
||||
To use the plugins, if you are not already using the Cordapp template project, you must modify your build.gradle. Add
|
||||
the following segments to the relevant part of your build.gradle.
|
||||
|
||||
Template build.gradle
|
||||
=====================
|
||||
|
||||
To build against Corda and the plugins that cordapps use, update your build.gradle to contain the following:
|
||||
|
||||
.. code-block:: groovy
|
||||
|
||||
buildscript {
|
||||
ext.corda_version = '<enter the corda version you build against here>'
|
||||
... your buildscript ...
|
||||
|
||||
repositories {
|
||||
... other repositories ...
|
||||
mavenLocal()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
... your dependencies ...
|
||||
classpath "com.r3corda.plugins:cordformation:$corda_version"
|
||||
classpath "com.r3corda.plugins:quasar-utils:$corda_version"
|
||||
classpath "com.r3corda.plugins:publish-utils:$corda_version"
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'com.r3corda.plugins.cordformation'
|
||||
apply plugin: 'com.r3corda.plugins.quasar-utils'
|
||||
apply plugin: 'com.r3corda.plugins.publish-utils'
|
||||
|
||||
repositories {
|
||||
mavenLocal()
|
||||
... other repositories here ...
|
||||
@ -122,3 +170,78 @@ In Gradle you can depend on these by adding/modifying your build.gradle file to
|
||||
compile "com.r3corda:corda:$corda_version"
|
||||
... other dependencies here ...
|
||||
}
|
||||
|
||||
... your tasks ...
|
||||
|
||||
// Sets the classes for Quasar to scan. Loaded by the the quasar-utils plugin.
|
||||
quasarScan.dependsOn('classes', ... your dependent subprojects...)
|
||||
|
||||
// Standard way to publish Cordapps to maven local with the maven-publish and publish-utils plugin.
|
||||
publishing {
|
||||
publications {
|
||||
jarAndSources(MavenPublication) {
|
||||
from components.java
|
||||
// The two lines below are the tasks added by this plugin.
|
||||
artifact sourceJar
|
||||
artifact javadocJar
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Cordformation
|
||||
=============
|
||||
|
||||
Cordformation is the local node deployment system for Cordapps, the nodes generated are intended to be used for
|
||||
experimenting, debugging, and testing node configurations and setups but not intended for production or testnet
|
||||
deployment.
|
||||
|
||||
To use this gradle plugin you must add a new task that is of the type `com.r3corda.plugins.Cordform` to your
|
||||
build.gradle and then configure the nodes you wish to deploy with the Node and nodes configuration DSL.
|
||||
This DSL is specified in the `JavaDoc <api/index.html>`_. An example of this is in the template-cordapp and below
|
||||
is a three node example;
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
task deployNodes(type: com.r3corda.plugins.Cordform, dependsOn: ['build']) {
|
||||
directory "./build/nodes" // The output directory
|
||||
networkMap "Controller" // The artemis address of the node named here will be used as the networkMapAddress on all other nodes.
|
||||
node {
|
||||
name "Controller"
|
||||
dirName "controller"
|
||||
nearestCity "London"
|
||||
notary true // Sets this node to be a notary
|
||||
advertisedServices []
|
||||
artemisPort 12345
|
||||
webPort 12346
|
||||
cordapps []
|
||||
}
|
||||
node {
|
||||
name "NodeA"
|
||||
dirName "nodea"
|
||||
nearestCity "London"
|
||||
advertisedServices []
|
||||
artemisPort 31337
|
||||
webPort 31339
|
||||
cordapps []
|
||||
}
|
||||
node {
|
||||
name "NodeB"
|
||||
dirName "nodeb"
|
||||
nearestCity "New York"
|
||||
advertisedServices []
|
||||
artemisPort 31338
|
||||
webPort 31340
|
||||
cordapps []
|
||||
}
|
||||
}
|
||||
|
||||
You can create more configurations with new tasks that extend Cordform.
|
||||
|
||||
New nodes can be added by simply adding another node block and giving it a different name, directory and ports. When you
|
||||
run this task it will install the nodes to the directory specified and a script will be generated (for UNIX users only
|
||||
at present) to run the nodes with one command.
|
||||
|
||||
Other cordapps can also be specified if they are already specified as classpath or compile dependencies in your
|
||||
build.gradle.
|
11
gradle-plugins/README.rst
Normal file
11
gradle-plugins/README.rst
Normal file
@ -0,0 +1,11 @@
|
||||
Gradle Plugins for Cordapps
|
||||
===========================
|
||||
|
||||
The projects at this level of the project are gradle plugins for cordapps and are published to Maven Local with
|
||||
the rest of the Corda libraries.
|
||||
|
||||
.. note::
|
||||
|
||||
Some of the plugins here are duplicated with the ones in buildSrc. While the duplication is unwanted any
|
||||
currently known solution (such as publishing from buildSrc or setting up a separate project/repo) would
|
||||
introduce a two step build which is less convenient.
|
1
gradle-plugins/cordformation/README.rst
Normal file
1
gradle-plugins/cordformation/README.rst
Normal file
@ -0,0 +1 @@
|
||||
Please refer to the documentation in <corda-root>/doc/build/html/creating-a-cordapp.html#cordformation.
|
23
gradle-plugins/cordformation/build.gradle
Normal file
23
gradle-plugins/cordformation/build.gradle
Normal file
@ -0,0 +1,23 @@
|
||||
apply plugin: 'maven-publish'
|
||||
apply plugin: 'groovy'
|
||||
|
||||
dependencies {
|
||||
compile gradleApi()
|
||||
compile localGroovy()
|
||||
|
||||
compile "com.typesafe:config:1.3.0"
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
publishing {
|
||||
publications {
|
||||
plugin(MavenPublication) {
|
||||
from components.java
|
||||
groupId 'com.r3corda.plugins'
|
||||
artifactId 'cordformation'
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,92 @@
|
||||
package com.r3corda.plugins
|
||||
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
import java.nio.file.Path
|
||||
import java.nio.file.Paths
|
||||
import org.gradle.api.Project
|
||||
|
||||
/**
|
||||
* Creates nodes based on the configuration of this task in the gradle configuration DSL.
|
||||
*
|
||||
* See documentation for examples.
|
||||
*/
|
||||
class Cordform extends DefaultTask {
|
||||
protected Path directory = Paths.get("./build/nodes")
|
||||
protected List<Node> nodes = new ArrayList<Node>()
|
||||
protected String networkMapNodeName
|
||||
|
||||
/**
|
||||
* Set the directory to install nodes into.
|
||||
*
|
||||
* @param directory The directory the nodes will be installed into.
|
||||
* @return
|
||||
*/
|
||||
public void directory(String directory) {
|
||||
this.directory = Paths.get(directory)
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the network map node.
|
||||
*
|
||||
* @warning Ensure the node name is one of the configured nodes.
|
||||
* @param nodeName The name of the node that will host the network map.
|
||||
*/
|
||||
public void networkMap(String nodeName) {
|
||||
networkMapNodeName = nodeName
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a node configuration.
|
||||
*
|
||||
* @param configureClosure A node configuration that will be deployed.
|
||||
*/
|
||||
public void node(Closure configureClosure) {
|
||||
nodes << project.configure(new Node(project), configureClosure)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a node by name.
|
||||
*
|
||||
* @param name The name of the node as specified in the node configuration DSL.
|
||||
* @return A node instance.
|
||||
*/
|
||||
protected Node getNodeByName(String name) {
|
||||
for(Node node : nodes) {
|
||||
if(node.name.equals(networkMapNodeName)) {
|
||||
return node
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
/**
|
||||
* Installs the run script into the nodes directory.
|
||||
*/
|
||||
protected void installRunScript() {
|
||||
project.copy {
|
||||
from Cordformation.getPluginFile(project, "com/r3corda/plugins/runnodes")
|
||||
filter { String line -> line.replace("JAR_NAME", Node.JAR_NAME) }
|
||||
// Replaces end of line with lf to avoid issues with the bash interpreter and Windows style line endings.
|
||||
filter(org.apache.tools.ant.filters.FixCrLfFilter.class, eol: org.apache.tools.ant.filters.FixCrLfFilter.CrLf.newInstance("lf"))
|
||||
into "${directory}/"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This task action will create and install the nodes based on the node configurations added.
|
||||
*/
|
||||
@TaskAction
|
||||
void build() {
|
||||
installRunScript()
|
||||
Node networkMapNode = getNodeByName(networkMapNodeName)
|
||||
nodes.each {
|
||||
if(it != networkMapNode) {
|
||||
it.networkMapAddress(networkMapNode.getArtemisAddress())
|
||||
}
|
||||
it.build(directory.toFile())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
27
gradle-plugins/cordformation/src/main/groovy/com/r3corda/plugins/Cordformation.groovy
Normal file
27
gradle-plugins/cordformation/src/main/groovy/com/r3corda/plugins/Cordformation.groovy
Normal file
@ -0,0 +1,27 @@
|
||||
package com.r3corda.plugins
|
||||
|
||||
import org.gradle.api.Plugin
|
||||
import org.gradle.api.Project
|
||||
|
||||
/**
|
||||
* The Cordformation plugin deploys nodes to a directory in a state ready to be used by a developer for experimentation,
|
||||
* testing, and debugging. It will prepopulate several fields in the configuration and create a simple node runner.
|
||||
*/
|
||||
class Cordformation implements Plugin<Project> {
|
||||
void apply(Project project) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a resource file from this plugin's JAR file.
|
||||
*
|
||||
* @param project The project environment this plugin executes in.
|
||||
* @param filePathInJar The file in the JAR, relative to root, you wish to access.
|
||||
* @return A file handle to the file in the JAR.
|
||||
*/
|
||||
static File getPluginFile(Project project, String filePathInJar) {
|
||||
return project.resources.text.fromArchiveEntry(project.buildscript.configurations.classpath.find {
|
||||
it.name.contains('cordformation')
|
||||
}, filePathInJar).asFile()
|
||||
}
|
||||
}
|
@ -0,0 +1,240 @@
|
||||
package com.r3corda.plugins
|
||||
|
||||
import org.gradle.api.internal.file.AbstractFileCollection
|
||||
import org.gradle.api.Project
|
||||
import java.nio.file.Files
|
||||
import java.nio.charset.StandardCharsets
|
||||
import com.typesafe.config.Config
|
||||
import com.typesafe.config.ConfigFactory
|
||||
import com.typesafe.config.ConfigValueFactory
|
||||
import com.typesafe.config.ConfigRenderOptions
|
||||
|
||||
/**
|
||||
* Represents a node that will be installed.
|
||||
*/
|
||||
class Node {
|
||||
static final String JAR_NAME = 'corda.jar'
|
||||
static final String DEFAULT_HOST = 'localhost'
|
||||
|
||||
/**
|
||||
* Name of the node.
|
||||
*/
|
||||
public String name
|
||||
/**
|
||||
* A list of advertised services ID strings.
|
||||
*/
|
||||
protected List<String> advertisedServices = []
|
||||
/**
|
||||
* Set thThe list of cordapps to install to the plugins directory.
|
||||
*
|
||||
* @note Your app will be installed by default and does not need to be included here.
|
||||
*/
|
||||
protected List<String> cordapps = []
|
||||
|
||||
private String dirName
|
||||
private Config config = ConfigFactory.empty()
|
||||
//private Map<String, Object> config = new HashMap<String, Object>()
|
||||
private File nodeDir
|
||||
private def project
|
||||
|
||||
/**
|
||||
* Set the name of the node.
|
||||
*
|
||||
* @param name The node name.
|
||||
*/
|
||||
void name(String name) {
|
||||
this.name = name
|
||||
config = config.withValue("myLegalName", ConfigValueFactory.fromAnyRef(name))
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the directory the node will be installed to relative to the directory specified in Cordform task.
|
||||
*
|
||||
* @param dirName Subdirectory name for node to be installed to. Must be valid directory name on all OSes.
|
||||
*/
|
||||
void dirName(String dirName) {
|
||||
this.dirName = dirName
|
||||
config = config.withValue("basedir", ConfigValueFactory.fromAnyRef(dirName))
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the nearest city to the node.
|
||||
*
|
||||
* @param nearestCity The name of the nearest city to the node.
|
||||
*/
|
||||
void nearestCity(String nearestCity) {
|
||||
config = config.withValue("nearestCity", ConfigValueFactory.fromAnyRef(nearestCity))
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether this node will use HTTPS communication.
|
||||
*
|
||||
* @param isHttps True if this node uses HTTPS communication.
|
||||
*/
|
||||
void https(Boolean isHttps) {
|
||||
config = config.withValue("useHTTPS", ConfigValueFactory.fromAnyRef(isHttps))
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the artemis port for this node.
|
||||
*
|
||||
* @param artemisPort The artemis messaging queue port.
|
||||
*/
|
||||
void artemisPort(Integer artemisPort) {
|
||||
config = config.withValue("artemisAddress",
|
||||
ConfigValueFactory.fromAnyRef("$DEFAULT_HOST:$artemisPort".toString()))
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the HTTP web server port for this node.
|
||||
*
|
||||
* @param webPort The web port number for this node.
|
||||
*/
|
||||
void webPort(Integer webPort) {
|
||||
config = config.withValue("webAddress",
|
||||
ConfigValueFactory.fromAnyRef("$DEFAULT_HOST:$webPort".toString()))
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the network map address for this node.
|
||||
*
|
||||
* @warning This should not be directly set unless you know what you are doing. Use the networkMapName in the
|
||||
* Cordform task instead.
|
||||
* @param networkMapAddress Network map address.
|
||||
*/
|
||||
void networkMapAddress(String networkMapAddress) {
|
||||
config = config.withValue("networkMapAddress",
|
||||
ConfigValueFactory.fromAnyRef(networkMapAddress))
|
||||
}
|
||||
|
||||
Node(Project project) {
|
||||
this.project = project
|
||||
}
|
||||
|
||||
/**
|
||||
* Install the nodes to the given base directory.
|
||||
*
|
||||
* @param baseDir The base directory for this node. All other paths are relative to it + this nodes dir name.
|
||||
*/
|
||||
void build(File baseDir) {
|
||||
nodeDir = new File(baseDir, dirName)
|
||||
installCordaJAR()
|
||||
installBuiltPlugin()
|
||||
installCordapps()
|
||||
installDependencies()
|
||||
installConfig()
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the artemis address for this node.
|
||||
*
|
||||
* @return This node's artemis address.
|
||||
*/
|
||||
String getArtemisAddress() {
|
||||
return config.getString("artemisAddress")
|
||||
}
|
||||
|
||||
/**
|
||||
* Installs the corda fat JAR to the node directory.
|
||||
*/
|
||||
private void installCordaJAR() {
|
||||
def cordaJar = verifyAndGetCordaJar()
|
||||
project.copy {
|
||||
from cordaJar
|
||||
into nodeDir
|
||||
rename cordaJar.name, JAR_NAME
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Installs this project's cordapp to this directory.
|
||||
*/
|
||||
private void installBuiltPlugin() {
|
||||
def pluginsDir = getAndCreateDirectory(nodeDir, "plugins")
|
||||
project.copy {
|
||||
from project.jar
|
||||
into pluginsDir
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Installs other cordapps to this node's plugins directory.
|
||||
*/
|
||||
private void installCordapps() {
|
||||
def pluginsDir = getAndCreateDirectory(nodeDir, "plugins")
|
||||
def cordapps = getCordappList()
|
||||
project.copy {
|
||||
from cordapps
|
||||
into pluginsDir
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Installs other dependencies to this node's dependencies directory.
|
||||
*/
|
||||
private void installDependencies() {
|
||||
def cordaJar = verifyAndGetCordaJar()
|
||||
def cordappList = getCordappList()
|
||||
def depsDir = getAndCreateDirectory(nodeDir, "dependencies")
|
||||
def appDeps = project.configurations.runtime.filter { it != cordaJar && !cordappList.contains(it) }
|
||||
project.copy {
|
||||
from appDeps
|
||||
into depsDir
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Installs the configuration file to this node's directory and detokenises it.
|
||||
*/
|
||||
private void installConfig() {
|
||||
// Adding required default values
|
||||
config = config.withValue('extraAdvertisedServiceIds',
|
||||
ConfigValueFactory.fromAnyRef(advertisedServices.join(',')))
|
||||
|
||||
def configFileText = config.root().render(new ConfigRenderOptions(false, false, true, false)).split("\n").toList()
|
||||
Files.write(new File(nodeDir, 'node.conf').toPath(), configFileText, StandardCharsets.UTF_8)
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the corda JAR amongst the dependencies.
|
||||
*
|
||||
* @return A file representing the Corda JAR.
|
||||
*/
|
||||
private File verifyAndGetCordaJar() {
|
||||
def maybeCordaJAR = project.configurations.runtime.filter { it.toString().contains("corda-${project.corda_version}.jar")}
|
||||
if(maybeCordaJAR.size() == 0) {
|
||||
throw new RuntimeException("No Corda Capsule JAR found. Have you deployed the Corda project to Maven?")
|
||||
} else {
|
||||
def cordaJar = maybeCordaJAR.getSingleFile()
|
||||
assert(cordaJar.isFile())
|
||||
return cordaJar
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a list of cordapps based on what dependent cordapps were specified.
|
||||
*
|
||||
* @return List of this node's cordapps.
|
||||
*/
|
||||
private AbstractFileCollection getCordappList() {
|
||||
def cordaJar = verifyAndGetCordaJar()
|
||||
return project.configurations.runtime.filter {
|
||||
def jarName = it.name.split('-').first()
|
||||
return (it != cordaJar) && cordapps.contains(jarName)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a directory if it doesn't exist and return the file representation of it.
|
||||
*
|
||||
* @param baseDir The base directory to create the directory at.
|
||||
* @param subDirName A valid name of the subdirectory to get and create if not exists.
|
||||
* @return A file representing the subdirectory.
|
||||
*/
|
||||
private static File getAndCreateDirectory(File baseDir, String subDirName) {
|
||||
File dir = new File(baseDir, subDirName)
|
||||
assert(!dir.exists() || dir.isDirectory())
|
||||
dir.mkdirs()
|
||||
return dir
|
||||
}
|
||||
}
|
1
gradle-plugins/cordformation/src/main/resources/META-INF/gradle-plugins/com.r3corda.plugins.cordformation.properties
Normal file
1
gradle-plugins/cordformation/src/main/resources/META-INF/gradle-plugins/com.r3corda.plugins.cordformation.properties
Normal file
@ -0,0 +1 @@
|
||||
implementation-class=com.r3corda.plugins.Cordformation
|
@ -0,0 +1,22 @@
|
||||
#!/usr/bin/env bash
|
||||
# Will attempt to execute a corda node within all subdirectories in the current working directory.
|
||||
# TODO: Use screens or separate windows when starting instances.
|
||||
|
||||
set -euo pipefail
|
||||
trap 'kill $(jobs -p)' EXIT
|
||||
export CAPSULE_CACHE_DIR=cache
|
||||
|
||||
function runNode {
|
||||
pushd $1
|
||||
( java -jar JAR_NAME )&
|
||||
popd
|
||||
}
|
||||
|
||||
for dir in `ls`; do
|
||||
if [ -d $dir ]; then
|
||||
runNode $dir
|
||||
fi
|
||||
done
|
||||
|
||||
read -p 'Any key to exit'
|
||||
kill $(jobs -p)
|
25
gradle-plugins/publish-utils/README.rst
Normal file
25
gradle-plugins/publish-utils/README.rst
Normal file
@ -0,0 +1,25 @@
|
||||
Publish Utils
|
||||
=============
|
||||
|
||||
Publishing utilities adds a couple of tasks to any project it is applied to that hide some boilerplate that would
|
||||
otherwise be placed in the Cordapp template's build.gradle.
|
||||
|
||||
There are two tasks exposed: `sourceJar` and `javadocJar` and both return a `FileCollection`.
|
||||
|
||||
It is used within the `publishing` block of a build.gradle as such;
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
// This will publish the sources, javadoc, and Java components to Maven.
|
||||
// See the `maven-publish` plugin for more info: https://docs.gradle.org/current/userguide/publishing_maven.html
|
||||
publishing {
|
||||
publications {
|
||||
jarAndSources(MavenPublication) {
|
||||
from components.java
|
||||
// The two lines below are the tasks added by this plugin.
|
||||
artifact sourceJar
|
||||
artifact javadocJar
|
||||
}
|
||||
}
|
||||
}
|
||||
|
21
gradle-plugins/publish-utils/build.gradle
Normal file
21
gradle-plugins/publish-utils/build.gradle
Normal file
@ -0,0 +1,21 @@
|
||||
apply plugin: 'maven-publish'
|
||||
apply plugin: 'groovy'
|
||||
|
||||
dependencies {
|
||||
compile gradleApi()
|
||||
compile localGroovy()
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
publishing {
|
||||
publications {
|
||||
plugin(MavenPublication) {
|
||||
from components.java
|
||||
groupId 'com.r3corda.plugins'
|
||||
artifactId 'publish-utils'
|
||||
}
|
||||
}
|
||||
}
|
23
gradle-plugins/publish-utils/src/main/groovy/com/r3corda/plugins/DefaultPublishTasks.groovy
Normal file
23
gradle-plugins/publish-utils/src/main/groovy/com/r3corda/plugins/DefaultPublishTasks.groovy
Normal file
@ -0,0 +1,23 @@
|
||||
package com.r3corda.plugins
|
||||
|
||||
import org.gradle.api.*
|
||||
import org.gradle.api.tasks.bundling.Jar
|
||||
import org.gradle.api.tasks.javadoc.Javadoc
|
||||
import org.gradle.api.Project
|
||||
|
||||
/**
|
||||
* A utility plugin that when applied will automatically create source and javadoc publishing tasks
|
||||
*/
|
||||
class DefaultPublishTasks implements Plugin<Project> {
|
||||
void apply(Project project) {
|
||||
project.task("sourceJar", type: Jar, dependsOn: project.classes) {
|
||||
classifier = 'sources'
|
||||
from project.sourceSets.main.allSource
|
||||
}
|
||||
|
||||
project.task("javadocJar", type: Jar, dependsOn: project.javadoc) {
|
||||
classifier = 'javadoc'
|
||||
from project.javadoc.destinationDir
|
||||
}
|
||||
}
|
||||
}
|
1
gradle-plugins/publish-utils/src/main/resources/META-INF/gradle-plugins/com.r3corda.plugins.publish-utils.properties
Normal file
1
gradle-plugins/publish-utils/src/main/resources/META-INF/gradle-plugins/com.r3corda.plugins.publish-utils.properties
Normal file
@ -0,0 +1 @@
|
||||
implementation-class=com.r3corda.plugins.DefaultPublishTasks
|
16
gradle-plugins/quasar-utils/README.rst
Normal file
16
gradle-plugins/quasar-utils/README.rst
Normal file
@ -0,0 +1,16 @@
|
||||
Quasar Utils
|
||||
============
|
||||
|
||||
Quasar utilities adds several tasks and configuration that provide a default Quasar setup and removes some boilerplate.
|
||||
One line must be added to your build.gradle once you apply this plugin:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
quasarScan.dependsOn('classes')
|
||||
|
||||
If any sub-projects are added that this project depends on then add the gradle target for that project to the depends
|
||||
on statement. eg:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
quasarScan.dependsOn('classes', 'subproject:subsubproject', ...)
|
21
gradle-plugins/quasar-utils/build.gradle
Normal file
21
gradle-plugins/quasar-utils/build.gradle
Normal file
@ -0,0 +1,21 @@
|
||||
apply plugin: 'maven-publish'
|
||||
apply plugin: 'groovy'
|
||||
|
||||
dependencies {
|
||||
compile gradleApi()
|
||||
compile localGroovy()
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
publishing {
|
||||
publications {
|
||||
plugin(MavenPublication) {
|
||||
from components.java
|
||||
groupId 'com.r3corda.plugins'
|
||||
artifactId 'quasar-utils'
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
package com.r3corda.plugins
|
||||
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.Plugin
|
||||
import org.gradle.api.tasks.testing.Test
|
||||
import org.gradle.api.tasks.JavaExec
|
||||
|
||||
/**
|
||||
* QuasarPlugin creates a "quasar" configuration, adds quasar as a dependency and creates a "quasarScan" task that scans
|
||||
* for `@Suspendable`s in the code
|
||||
*/
|
||||
class QuasarPlugin implements Plugin<Project> {
|
||||
void apply(Project project) {
|
||||
|
||||
project.repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
project.configurations.create("quasar")
|
||||
// To add a local .jar dependency:
|
||||
// project.dependencies.add("quasar", project.files("${project.rootProject.projectDir}/lib/quasar.jar"))
|
||||
project.dependencies.add("quasar", "co.paralleluniverse:quasar-core:${project.rootProject.ext.quasar_version}:jdk8@jar")
|
||||
project.dependencies.add("compile", project.configurations.getByName("quasar"))
|
||||
|
||||
project.tasks.withType(Test) {
|
||||
jvmArgs "-javaagent:${project.configurations.quasar.singleFile}"
|
||||
jvmArgs "-Dco.paralleluniverse.fibers.verifyInstrumentation"
|
||||
}
|
||||
project.tasks.withType(JavaExec) {
|
||||
jvmArgs "-javaagent:${project.configurations.quasar.singleFile}"
|
||||
jvmArgs "-Dco.paralleluniverse.fibers.verifyInstrumentation"
|
||||
}
|
||||
|
||||
project.task("quasarScan") {
|
||||
inputs.files(project.sourceSets.main.output)
|
||||
outputs.files(
|
||||
"$project.sourceSets.main.output.resourcesDir/META-INF/suspendables",
|
||||
"$project.sourceSets.main.output.resourcesDir/META-INF/suspendable-supers"
|
||||
)
|
||||
} << {
|
||||
|
||||
// These lines tell gradle to run the Quasar suspendables scanner to look for unannotated super methods
|
||||
// that have @Suspendable sub implementations. These tend to cause NPEs and are not caught by the verifier
|
||||
// NOTE: need to make sure the output isn't on the classpath or every other run it generates empty results, so
|
||||
// we explicitly delete to avoid that happening. We also need to turn off what seems to be a spurious warning in the IDE
|
||||
ant.taskdef(name:'scanSuspendables', classname:'co.paralleluniverse.fibers.instrument.SuspendablesScanner',
|
||||
classpath: "${project.sourceSets.main.output.classesDir}:${project.sourceSets.main.output.resourcesDir}:${project.configurations.runtime.asPath}")
|
||||
project.delete "$project.sourceSets.main.output.resourcesDir/META-INF/suspendables", "$project.sourceSets.main.output.resourcesDir/META-INF/suspendable-supers"
|
||||
ant.scanSuspendables(
|
||||
auto:false,
|
||||
suspendablesFile: "$project.sourceSets.main.output.resourcesDir/META-INF/suspendables",
|
||||
supersFile: "$project.sourceSets.main.output.resourcesDir/META-INF/suspendable-supers") {
|
||||
fileset(dir: project.sourceSets.main.output.classesDir)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
project.jar.dependsOn project.quasarScan
|
||||
}
|
||||
}
|
1
gradle-plugins/quasar-utils/src/main/resources/META-INF/gradle-plugins/com.r3corda.plugins.quasar-utils.properties
Normal file
1
gradle-plugins/quasar-utils/src/main/resources/META-INF/gradle-plugins/com.r3corda.plugins.quasar-utils.properties
Normal file
@ -0,0 +1 @@
|
||||
implementation-class=com.r3corda.plugins.QuasarPlugin
|
@ -8,4 +8,7 @@ include 'experimental'
|
||||
include 'test-utils'
|
||||
include 'network-simulator'
|
||||
include 'explorer'
|
||||
include 'gradle-plugins:quasar-utils'
|
||||
include 'gradle-plugins:publish-utils'
|
||||
include 'gradle-plugins:cordformation'
|
||||
include 'docs/source/example-code'
|
||||
|
@ -25,15 +25,15 @@ public class CordaCaplet extends Capsule {
|
||||
// defined as public static final fields on the Capsule class, therefore referential equality is safe.
|
||||
if(ATTR_APP_CLASS_PATH == attr) {
|
||||
T cp = super.attribute(attr);
|
||||
List<Path> classpath = (List<Path>) cp;
|
||||
return (T) augmentClasspath(classpath);
|
||||
List<Path> classpath = augmentClasspath((List<Path>) cp, "plugins");
|
||||
return (T) augmentClasspath(classpath, "dependencies");
|
||||
}
|
||||
return super.attribute(attr);
|
||||
}
|
||||
|
||||
// TODO: Make directory configurable via the capsule manifest.
|
||||
// TODO: Add working directory variable to capsules string replacement variables.
|
||||
private List<Path> augmentClasspath(List<Path> classpath) {
|
||||
private List<Path> augmentClasspath(List<Path> classpath, String dirName) {
|
||||
File dir = new File("plugins");
|
||||
if(!dir.exists()) {
|
||||
dir.mkdir();
|
||||
|
Loading…
x
Reference in New Issue
Block a user