As an example of a working Gant script this is the Gant script that is Gant's own Gant script as at 2008-05-20T08:15:00+00:00. This assumes Gant 1.2.0 or greater. If you find any errors in inefficiencies, do let me know, either on the Gant developer mailing list or directly russel.winder@concertant.com.
// Gant -- A Groovy build framework based on scripting Ant tasks. // // Copyright © 2006-8 Russel Winder // // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in // compliance with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software distributed under the License is // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or // implied. See the License for the specific language governing permissions and limitations under the // License. // // Author : Russel Winder <russel.winder@concertant.com> final zipExtension = '.zip' final tarExtension = '.tar' final tgzExtension = '.tgz' ant.property ( file : 'local.build.properties' ) ant.property ( file : 'build.properties' ) gantVersion = ant.project.properties.gantVersion groovyVersion = ant.project.properties.groovyVersion try { usingCobertura } catch ( MissingPropertyException mpe ) { usingCobertura = false } try { ignoreTestFailures } catch ( MissingPropertyException mpe ) { ignoreTestFailures = false } groovyHome = System.properties.'groovy.home' if ( ( groovyHome == null ) || ( groovyHome == '' ) ) { println ( 'Real problem: property groovy.home is not set and this is Gant executing.' ) return } // The Gant source is structured according to the standard Maven 2 structure. final sourceDirectory = 'src/main/groovy' final testsDirectory = 'src/test/groovy' final jarfilesDirectory = 'jarfiles' final scriptsDirectory = 'scripts' final buildDirectory = 'target' final buildClassesDirectory = buildDirectory + '/classes' final buildTestClassesDirectory = buildDirectory + '/test-classes' final buildTestReportsDirectory = buildDirectory + '/test-reports' final buildCoberturaClassesDirectory = buildDirectory + '/cobertura-classes' final buildCoberturaReportsDirectory = buildDirectory + '/cobertura-reports' final buildFilteredScriptsDirectory = buildDirectory + '/filteredScripts' final buildInstallDirectory = buildDirectory + '/install' final documentationDirectory = buildDirectory + '/documentation' final apiDocumentationDirectory = documentationDirectory + '/api' final buildMetadataDirectory = buildClassesDirectory + '/META-INF' // Labels for supporting use of the Maven Ant task. NB Installing Gant installs the Maven and Ivy Ant // tasks jars into the Groovy library. Should the antlib: or urn: string be used here? final antlibXMLns = 'antlib:org.apache.maven.artifact.ant' final mavenPOMId = 'maven.pom' // Details of what is going to appear in the distribution. final distributionTopLevelFiles = [ 'build.gant' , 'buildMaven.gant' , 'build.properties' , 'build.xml' , '.classpath' , '.project' , 'LICENCE.txt' , 'README_Distribution.txt' , 'README_Install.txt' , 'releaseNotes.txt' ] final distributionDirectories = [ 'documentation' , 'examples' , '.settings' , scriptsDirectory , jarfilesDirectory , sourceDirectory , testsDirectory ] // The versions of Gant in the Maven repository to build distribution version of Gant against. // Deb production assumes that the standalone build is the last one undertaken. Pragmatically this is the // case since iterating over the items in the map happens in lexical order of the keys. However, this is // an assumption, so this really needs changing. final distributionVersions = [ // Introducing the Gant Ant Task written in Java means we have to use the // joint compiler to compile Gant and this means we cannot build Gant against // Groovy 1.0 since the joint compiler only arrived with 1.5.0. Opinion on // the user list indicated that it seemed reasonable to drop support for // Groovy 1.0. // // The target distribution assumes that the groovyc fork mode works, which // means we cannot build against any version prior to 1.5.2. Using a forked // Java task is not an option because there is no --classpath option in the // 1.5.0 and 1.5.1 versions of Groovyc and this is essential to get things to // work correctly. // // Gant can still be built and distributed against Groovy 1.5.0 and 1.5.1 but // it has to be done the hard (manual) way. // ( 'groovy-' + groovyVersion ) : [ groupId : 'org.codehaus.groovy' , artifactId : 'groovy' , version : groovyVersion ] , 'groovy-1.6-beta-1-SNAPSHOT' : [ groupId : 'org.codehaus.groovy' , artifactId : 'groovy' , version : '1.6-beta-1-SNAPSHOT' ] , standalone : [ groupId : 'org.codehaus.groovy' , artifactId : 'groovy-all' , version : groovyVersion ] ] // As Jürgen Hermann pointed out the trailing / on the URL is very important. final distributionURL = 'https://dav.codehaus.org/dist/gant/' // The server hierarchy is fixed and known. final serverDistributionsDirectory = 'distributions' final serverJarsDirectory = 'jars' final serverPomsDirectory = 'poms' // This is a map with key local source path and value server path. final serverUploadProducts = [ : ] // The various compilation and test actions are parameterized so they can be used with different classpaths. // Currently these Closures do not have the GantMetaClass as their metaclass so there is no delegated // lookup on Ant so we have to use it explicitly. final performCompile = { classpathRef , boolean fork -> ant.mkdir ( dir : buildClassesDirectory ) ant.taskdef ( name : 'groovyc' , classname : 'org.codehaus.groovy.ant.Groovyc' , classpathref : classpathRef ) ant.groovyc ( srcdir : sourceDirectory , destdir : buildClassesDirectory , fork : fork ? 'true' : 'false' , failonerror : 'true' ) { classpath { pathelement ( location : buildClassesDirectory ) path ( refid : classpathRef ) } javac ( source : '1.5' , target : '1.5' , debug : 'on' ) } } final performCompileTests = { classpathRef , boolean fork -> ant.mkdir ( dir : buildTestClassesDirectory ) ant.taskdef ( name : 'groovyc' , classname : 'org.codehaus.groovy.ant.Groovyc' , classpathref : classpathRef ) ant.groovyc ( srcdir : testsDirectory , destdir : buildTestClassesDirectory , fork : fork ? 'true' : 'false' , failonerror : 'true' ) { classpath { pathelement ( location : buildClassesDirectory ) path ( refid : classpathRef ) } javac ( source : '1.5' , target : '1.5' , debug : 'on' ) } } final performTests = { classpathRef -> ant.mkdir ( dir : buildTestReportsDirectory ) if ( usingCobertura ) { ant.mkdir ( dir : buildCoberturaClassesDirectory ) ant.mkdir ( dir : buildCoberturaReportsDirectory ) ant."${antlibXMLns}:dependencies" ( pathId : 'coberturaPathId' ) { dependency ( groupId : 'net.sourceforge.cobertura' , artifactId : 'cobertura' , version : '1.9' ) } ant.taskdef ( resource : 'tasks.properties' , classpathref : 'coberturaPathId' ) ant.'cobertura-instrument' ( todir : buildCoberturaClassesDirectory ) { fileset ( dir : buildClassesDirectory ) } } ant.junit ( printsummary : 'yes' , failureproperty : 'testsFailed' , fork : 'true' ) { formatter ( type : 'plain' ) batchtest ( todir : buildTestReportsDirectory ) { fileset ( dir : buildTestClassesDirectory , includes : '**/ant/tests/*_Test.class' ) } classpath { if ( usingCobertura ) { // MUST appear in classpath before the uninstrumented classes. pathelement ( location : buildCoberturaClassesDirectory ) path ( refid : 'coberturaPathId' ) } pathelement ( location : buildTestClassesDirectory ) } } ant.junit ( printsummary : 'yes' , failureproperty : 'testsFailed' , fork : 'true' ) { formatter ( type : 'plain' ) batchtest ( todir : buildTestReportsDirectory ) { fileset ( dir : buildTestClassesDirectory , includes : '**/*_Test.class' , excludes : '**/ant/tests/*' ) } classpath { if ( usingCobertura ) { // MUST appear in classpath before the uninstrumented classes. pathelement ( location : buildCoberturaClassesDirectory ) path ( refid : 'coberturaPathId' ) } pathelement ( location : buildTestClassesDirectory ) pathelement ( location : buildClassesDirectory ) path ( refid : classpathRef ) } } if ( usingCobertura ) { ant.'cobertura-report' ( srcdir : sourceDirectory , destdir : buildCoberturaReportsDirectory ) } ant.project.properties.testsFailed == null } final makeManifest = { -> ant.mkdir ( dir : buildMetadataDirectory ) ant.copy ( todir : buildMetadataDirectory , file : 'LICENCE.txt' ) ant.manifest ( file : buildMetadataDirectory + '/MANIFEST.MF' ) { attribute ( name : 'Built-By' , value : System.properties.'user.name' ) attribute ( name : 'Extension-Name' , value : 'gant' ) attribute ( name : 'Specification-Title' , value : 'Gant: scripting Ant tasks with Groovy.' ) attribute ( name : 'Specification-Version' , value : gantVersion ) attribute ( name : 'Specification-Vendor' , value : 'The Codehaus' ) attribute ( name : 'Implementation-Title' , value : 'Gant: Scripting Ant tasks with Groovy.' ) attribute ( name : 'Implementation-Version' , value : gantVersion ) attribute ( name : 'Implementation-Vendor' , value : 'The Codehaus' ) } } final setInstallationDirectory = { path -> if ( path == null ) { println ( 'Property installationDirectory is not set, cannot undertake (un)install actions.' ) System.exit ( 1 ) } installationDirectory = path } final prepareInstallDirectory = { path , gantJarName , isStandalone , item -> setInstallationDirectory ( path ) def installationBinDirectory = installationDirectory + '/bin' def groovyJarName = null if ( item != null ) { groovyJarName = ( isStandalone ? 'groovy-all-' : 'groovy-' ) + item.version + '.jar' } else { assert ! isStandalone ant.pathconvert ( property : 'groovyJarName' ) { // Have to specify ant.path here for some reason that is not entirely clear. ant.path { fileset ( dir : groovyHome + '/lib' , includes : 'groovy-1.*.jar' ) } mapper ( type : 'flatten' ) } groovyJarName = ant.project.properties.groovyJarName } ant.copy ( todir : installationBinDirectory ) { fileset ( dir : scriptsDirectory + ( isStandalone ? '/bin_standalone' : '/bin_requiresGroovy' ) ) fileset ( dir : scriptsDirectory + '/bin' ) filterset { filter ( token : 'GANT_VERSION' , value : gantVersion ) } filterset { filter ( token : 'GROOVYJAR' , value : groovyJarName ) } } ant.chmod ( perm : 'a+x' ) { fileset ( dir : installationBinDirectory , includes : 'gant*' ) } ant.copy ( todir : installationDirectory ) { fileset ( dir : scriptsDirectory , includes : 'conf/gant-starter.conf' ) } filesetId = 'filesetId' ant."${antlibXMLns}:dependencies" ( filesetId : filesetId ) { dependency ( groupId : 'org.apache.ivy' , artifactId : 'ivy' , version : ant.project.properties.ivyVersion ) if ( isStandalone ) { dependency ( groupId : item.groupId , artifactId : item.artifactId , version : item.version ) dependency ( groupId : 'commons-cli' , artifactId : 'commons-cli' , version : ant.project.properties.commonsCliVersion ) } remoteRepository ( url : 'http://snapshots.repository.codehaus.org' ) remoteRepository ( url : 'http://repository.codehaus.org' ) remoteRepository ( url : 'http://repo1.maven.org' ) } ant.copy ( todir : installationDirectory + '/lib' ) { fileset ( dir : buildDirectory , includes : gantJarName ) fileset ( dir : jarfilesDirectory , includes : 'maven*.jar' ) fileset ( refid : filesetId ) mapper ( type : 'flatten' ) } } final prepareZipFromTarAndRegisterForUpload = { String root , Closure closure -> path = buildDirectory + System.properties.'file.separator' + root closure ( ) ant.zip ( destfile : path + zipExtension ) { tarfileset ( src : path + tarExtension ) } ant.gzip ( src : path + tarExtension , destfile : path + tgzExtension ) serverUploadProducts [ path + tgzExtension ] = serverDistributionsDirectory + '/' + root + tgzExtension serverUploadProducts [ path + zipExtension ] = serverDistributionsDirectory + '/' + root + zipExtension } // Create the compilation context of the Groovy with which Gant will be installed. This is not used for // the distributions. compileJarSet = 'compileJarSet' ant.path ( id : compileJarSet ) { fileset ( dir : groovyHome + '/lib' , includes : 'groovy*.jar' ) fileset ( dir : groovyHome + '/lib' , includes : 'commons-cli*.jar' ) fileset ( dir : groovyHome + '/lib' , includes : 'asm*.jar' ) fileset ( dir : groovyHome + '/lib' , includes : 'ant*.jar' ) // Picks up antlr as well as ant. This is intended. } testJarSet = 'testJarSet' ant.path ( id : testJarSet ) { path ( refid : compileJarSet ) fileset ( dir : groovyHome + '/lib' , includes : 'junit*.jar' ) } // Set up all the targets. includeTargets << gant.targets.Clean cleanPattern << [ '**/*~' , 'cobertura.ser' , 'texput.log' ] cleanDirectory << buildDirectory includeTool << gant.tools.Execute target ( reallyClean : 'Ensure all clean operations for the entire tree get actioned.' ) { clobber ( ) Execute.shell ( "cd packaging/debian && gant clobber" ) } target ( compile : 'Compile everything needed for a Gant installation.' ) { performCompile ( compileJarSet , false ) } target ( compileTests : 'Compile all the tests for a newly built Gant.' ) { depends ( compile ) performCompileTests ( testJarSet , false ) } target ( test : 'Test a build.' ) { depends ( compileTests ) def returnCode = performTests ( compileJarSet ) println ( 'Tests ' + ( returnCode ? 'suceeded' : 'failed' ) + '.' ) returnCode ? 0 : 1 } target ( coberturaTest : 'Test a build using Cobertura to get a coverage report.' ) { usingCobertura = true depends ( tests ) } target ( 'package' : 'Create the jar file.' ) { depends ( compile ) makeManifest ( ) jar ( destfile : buildDirectory + "/gant-${gantVersion}.jar" , basedir : buildClassesDirectory , manifest : buildMetadataDirectory + '/MANIFEST.MF' ) } target ( documentation : 'Create the API documentation.' ) { taskdef ( name : 'groovydoc' , classname : 'org.codehaus.groovy.ant.Groovydoc' ) def javaApiDocumentationDirectory = apiDocumentationDirectory + '/java' def groovyApiDocumentationDirectory = apiDocumentationDirectory + '/groovy' mkdir ( dir : javaApiDocumentationDirectory ) mkdir ( dir : groovyApiDocumentationDirectory ) javadoc ( sourcepath : sourceDirectory , destdir : javaApiDocumentationDirectory , packagenames : 'gant.*,org.codehaus.gant.*', overview : 'overview.html' , 'private' : 'true' , encoding : 'UTF-8' , use : 'true' , author : 'true' , windowtitle : "Gant (${gantVersion})" , doctitle : "Gant (${gantVersion})" , header : "Gant (${gantVersion})" , footer : 'Copyright © 2006–8 The Codehaus. All rights reserved.' , source : 1.5 ) { classpath ( refid : testJarSet ) } groovydoc ( destdir : groovyApiDocumentationDirectory , sourcepath : sourceDirectory , packagenames : 'gant.*,org.codehaus.gant.*' , //overview : 'overview.html' , //author : 'true' , //version : 'true' , use : 'true' , 'private' : 'false' , windowtitle : "Gant (${gantVersion})" , //doctitle : "Gant (${gantVersion})" , //encoding : 'UTF-8' , //footer : 'Copyright © 2006–8 The Codehaus. All rights reserved.' ) } target ( install : "Compile everything and install it." ) { depends ( 'package' ) prepareInstallDirectory ( ant.project.properties.installDirectory , 'gant-' + gantVersion + '.jar' , false , null ) } target ( uninstall : "Uninstall Gant." ) { setInstallationDirectory ( ant.project.properties.installDirectory ) delete ( dir : installationDirectory ) } // Returns a boolean stating whether there were any test failures. target ( distribution : 'Create the distribution.' ) { // Use the Ant Maven plugin to ensure that the groovy jar of a given release is in the local Maven // repository and ensure that it is the only version of Groovy used in the compilation. def prefix = 'gant-' + gantVersion def distributionClasspathId = 'classpath' clean ( ) someTestsFailed = false distributionVersions.each { label , item -> def isStandalone = label == 'standalone' // This is a closure that doesn't have the right metaclass so we have to specify Ant. Need to // rearrange things to deal with this problem as is done in the target Closure. def pathIdentifier = distributionClasspathId + item.version ant."${antlibXMLns}:dependencies" ( pathId : pathIdentifier ) { dependency ( groupId : item.groupId , artifactId : item.artifactId , version : item.version ) dependency ( groupId : 'org.apache.ant' , artifactId : 'ant' , version : ant.project.properties.antVersion ) dependency ( groupId : 'commons-cli' , artifactId : 'commons-cli' , version : ant.project.properties.commonsCliVersion ) dependency ( groupId : 'junit' , artifactId : 'junit' , version : ant.project.properties.junitVersion ) remoteRepository ( url : 'http://snapshots.repository.codehaus.org' ) remoteRepository ( url : 'http://repository.codehaus.org' ) remoteRepository ( url : 'http://repo1.maven.org' ) } // Must remove the compilation products of the last compilation! ant.delete ( dir : buildClassesDirectory ) ant.delete ( dir : buildTestClassesDirectory ) ant.delete ( dir : buildFilteredScriptsDirectory ) ant.delete ( dir : buildInstallDirectory ) performCompile ( pathIdentifier , true ) performCompileTests ( pathIdentifier , true ) if ( ! performTests ( pathIdentifier ) ) { someTestsFailed = true } makeManifest ( ) def discriminator = prefix + '_groovy-' + item.version if ( isStandalone ) { discriminator = prefix } def jarName = discriminator + '.jar' def jarPath = buildDirectory + System.properties.'file.separator' + jarName ant.jar ( destfile : jarPath , basedir : buildClassesDirectory , manifest : buildMetadataDirectory + '/MANIFEST.MF' ) serverUploadProducts [ jarPath ] = serverJarsDirectory + '/' + jarName prepareInstallDirectory ( buildInstallDirectory , jarName , isStandalone , item ) prepareZipFromTarAndRegisterForUpload ( discriminator ) { // NB Rely on Closures not being closures: path is only resolved when the Closure is executed. ant.tar ( destfile : path + tarExtension ) { tarfileset ( dir : buildInstallDirectory , mode : '511' , prefix : prefix ) { include ( name : 'bin/*' ) } tarfileset ( dir : buildInstallDirectory , prefix : prefix ) { include ( name : '**' ) exclude ( name : 'bin/*' ) } tarfileset ( dir : '.' , includes : 'README*' , prefix : prefix ) } } } // Create the source distribution. prepareZipFromTarAndRegisterForUpload ( 'gant_src-' + gantVersion ) { // NB Rely on Closures not being closures: path is only resolved when the Closure is executed. ant.tar ( destfile : path + tarExtension ) { tarfileset ( dir : '.' , includes : distributionTopLevelFiles.join ( ',' ) , prefix : prefix ) distributionDirectories.each { directory -> tarfileset ( dir : directory , prefix : prefix + System.properties.'file.separator' + directory ) } } } // Create the API documentation distribution. documentation ( ) prepareZipFromTarAndRegisterForUpload ( 'gant_doc-' + gantVersion ) { // NB Rely on Closures not being closures: path is only resolved when the Closure is executed. ant.tar ( destfile : path + tarExtension ) { tarfileset ( dir : documentationDirectory , prefix : prefix + System.properties.'file.separator' + 'doc' ) } } // Return the result of the test executions so that uploadDistributions can choose not to upload a failed // compilation. ! someTestsFailed } target ( uploadDistribution : 'Upload a complete distribution.' ) { if ( ! distribution ( ) && ! ignoreTestFailures ) { println ( 'Not uploading as some tests failed.' ) return } // // Slide has been retired by the Apache Foundation in favour of Jackrabbit, but we use Slide anyway. // "${antlibXMLns}:dependencies" ( pathId : 'slidePathId' ) { //dependency ( groupId : 'org.apache.jackrabbit' , artifactId : 'jackrabbit-webdav' , version : '1.3.3' ) dependency ( groupId : 'slide' , artifactId : 'slide-webdavlib' , version : '2.1' ) } // // Is there a way of extracting the username and password information from the Maven Ant Task? For the // moment simply read the ~/.m2/settings.xml file. // def loader = getClass ( ).getClassLoader ( ) def path = ant.path ( refid : 'slidePathId' ) ( path.list ( ) as List ).each { location -> loader.addURL ( new URL ( 'file://' + location ) ) } def settings = ( new XmlSlurper ( ) ).parse ( System.properties.'user.home' + '/.m2/settings.xml' ).servers.server.find { item -> item.id == 'dav.codehaus.org' } def credentials = loader.loadClass ( 'org.apache.commons.httpclient.UsernamePasswordCredentials' ).getConstructor ( String , String ).newInstance ( settings.username.toString ( ) , settings.password.toString ( ) ) // Have to put resource in the binding so that the Closures can access it. resource = loader.loadClass ( 'org.apache.webdav.lib.WebdavResource' ).getConstructor ( String , loader.loadClass ( 'org.apache.commons.httpclient.Credentials' ) , boolean ).newInstance ( distributionURL , credentials , true ) if ( resource.statusCode != 200 ) { println ( 'Failed to open ' + distributionURL ) } else { serverUploadProducts [ 'pom.xml' ] = serverPomsDirectory + '/gant-' + gantVersion + '.pom' serverUploadProducts.each { source , destination -> def serverPath = resource.path + '/' + destination print ( 'Uploading ' + source + ' -> ' + destination + ' : ' ) def result = 'Failed.' if ( resource.putMethod ( serverPath , new File ( source ) ) ) { result = 'OK.' } println ( result + ' Status : ' + resource.statusMessage ) } } if ( resource != null ) { resource.close ( ) } } setDefaultTarget ( test )
Labels
(None)
