An important feature of Depot is the support for transitive dependency management.
Dependencies between project are maintained relative to the following scopes:
build | Declaration of one or build sequence dependencies. When a project declares a build scoped dependency on another project - Depot will ensure that the dependee project is built before the dependee project. |
runtime | Declaration of one or runtime dependencies. Runtime dependencies are used by Depot to construct classloader chains resulting in the potential automation of several common build requirements (such as source code compilation). Runtime dependencies are fully transitive in that the runtime dependencies of a project are constructed by expanding the runtime dependencies of any projects declared as runtime dependencies, and any runtime dependencies of the dependee projects (etc., etc.). |
test | Declaration of one or more test dependencies. Test scoped dependencies are used to suppliment transitive runtime dependencies and are typically applied to test-case automation . An important aspect of of test scoped dependencies is the ability to separate test concerns from runtime concerns - ensuring that runtime meta-data is not polluted with test related information. |
Our index file has been updated to declare two projects : clock-api and clock-impl. The API project declares an interface and the impl project is an implementation of that API. As such, the impl project has a runtime dependency on the API (and the test-time dependencies on ant-junit).
<?xml version="1.0" encoding="ISO-8859-1"?> <index xmlns="dpml:library"> <imports> <import uri="link:module:org/apache/ant"/> <import uri="link:module:dpml"/> </imports> <project name="clock-api" basedir="api"> <types> <type id="jar"/> </types> </project> <project name="clock-impl" basedir="impl"> <types> <type id="jar"/> </types> <dependencies> <runtime> <include key="clock-api"/> </runtime> <test> <include ref="org/apache/ant/ant-junit"/> <include ref="dpml/transit/dpml-transit-main"/> </test> </dependencies> </project> </index>
If we set our current directory to the parent directoriy of the two projects and invoke the build-list (or build -l for short), we get a listing of all of the projects in scope:
$ build -list Selection: [2] [1] project:widget#SNAPSHOT [2] project:gizmo#SNAPSHOT
Using the -e (expand) and -s (select) option we can view the full dependency scenario:
$ build -list -expand -select clock-impl Listing project: clock-impl project:clock-impl#SNAPSHOT version: SNAPSHOT basedir: D:\dpml\tutorials\tooling\complex\build\impl types: (1) jar runtime providers: (1) project:clock-api#SNAPSHOT test providers: (7) resource:org/apache/ant/ant-launcher#1.7.0 resource:org/apache/ant/ant-trax#1.7.0 resource:org/apache/ant/ant-xslp#1.7.0 resource:org/apache/ant/ant#1.7.0 resource:junit/junit#3.8.1 resource:org/apache/ant/ant-junit#1.7.0 resource:dpml/transit/dpml-transit-main#SNAPSHOT
In the following build example the build command is invoked in the parent directory. As such the build tool will evaluate all projects declared in the index and establish a build selection that includes all projects with a basedir that is equal to or deeper that our current directory. This selection is subsequently sorted resulting in the api project appearing before the implementation project. The build tool then initiates the build of each project sequentally. If there is a failure of an indivial build then the multi-project build sequence will fail.
$ build [2036 ] [INFO ] (depot.build): Initiating build sequence: (2) (1) clock-api (2) clock-impl ------------------------------------------------------------------------- clock-api#SNAPSHOT ------------------------------------------------------------------------- init: prepare: [x:prepare] Created dir: D:\dpml\tutorials\tooling\complex\build\api\target [x:prepare] Created dir: D:\dpml\tutorials\tooling\complex\build\api\target\build\main [x:prepare] Copying 1 file to D:\dpml\tutorials\tooling\complex\build\api\target\build\main build: [javac] Created dir: D:\dpml\tutorials\tooling\complex\build\api\target\classes\main [javac] Compiling 1 source file to D:\dpml\tutorials\tooling\complex\build\api\target\classes\main package: [jar] Created dir: D:\dpml\tutorials\tooling\complex\build\api\target\deliverables\jars [jar] Building jar: D:\dpml\tutorials\tooling\complex\build\api\target\deliverables\jars\clock-api-SNAPSHOT.jar [jar] Creating md5 checksum test: install: [x:install] Copying 2 files to D:\system\dpml\data\cache BUILD SUCCESSFUL Total time: 3 seconds ------------------------------------------------------------------------- clock-impl#SNAPSHOT ------------------------------------------------------------------------- init: prepare: [x:prepare] Created dir: D:\dpml\tutorials\tooling\complex\build\impl\target [x:prepare] Created dir: D:\dpml\tutorials\tooling\complex\build\impl\target\build\main [x:prepare] Copying 1 file to D:\dpml\tutorials\tooling\complex\build\impl\target\build\main [x:prepare] Created dir: D:\dpml\tutorials\tooling\complex\build\impl\target\build\test [x:prepare] Copying 1 file to D:\dpml\tutorials\tooling\complex\build\impl\target\build\test [x:prepare] Created dir: D:\dpml\tutorials\tooling\complex\build\impl\target\test build: [javac] Created dir: D:\dpml\tutorials\tooling\complex\build\impl\target\classes\main [javac] Compiling 1 source file to D:\dpml\tutorials\tooling\complex\build\impl\target\classes\main [javac] Created dir: D:\dpml\tutorials\tooling\complex\build\impl\target\classes\test [javac] Compiling 1 source file to D:\dpml\tutorials\tooling\complex\build\impl\target\classes\test package: [jar] Created dir: D:\dpml\tutorials\tooling\complex\build\impl\target\deliverables\jars [jar] Building jar: D:\dpml\tutorials\tooling\complex\build\impl\target\deliverables\jars\clock-impl-SNAPSHOT.jar [jar] Creating md5 checksum test: [junit] Created dir: D:\dpml\tutorials\tooling\complex\build\impl\target\reports\test [junit] Executing forked test. [junit] Running org.acme.impl.test.DemoTestCase [junit] [13005] [INFO ] (test): 11:28 PM, CST [junit] Tests run: 1, Failures: 0, Errors: 0, Time elapsed: 0.218 sec install: [x:install] Copying 2 files to D:\system\dpml\data\cache BUILD SUCCESSFUL Total time: 2 seconds
This tutorial has introduced the subject of scoped dependencies and how these dependency declarations impact build sequencing and classpath construction. In addition the tutorial has demonstrated multi-project build sequencing (covering information listing and build execution). The next tutorial introduces the use of modules as a mechanisms through which we can improve resource name management and reduce the potential for naming conflicts.