package org.apache.maven.plugin.nar; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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. */ import java.io.File; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import net.sf.antcontrib.cpptasks.CCTask; import net.sf.antcontrib.cpptasks.CUtil; import net.sf.antcontrib.cpptasks.CompilerDef; import net.sf.antcontrib.cpptasks.LinkerDef; import net.sf.antcontrib.cpptasks.OutputTypeEnum; import net.sf.antcontrib.cpptasks.RuntimeType; import net.sf.antcontrib.cpptasks.SubsystemEnum; import net.sf.antcontrib.cpptasks.types.LibrarySet; import net.sf.antcontrib.cpptasks.types.LibraryTypeEnum; import net.sf.antcontrib.cpptasks.types.LinkerArgument; import net.sf.antcontrib.cpptasks.types.SystemLibrarySet; import org.apache.maven.artifact.Artifact; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.Project; /** * Compiles native test source files. * * @goal nar-testCompile * @phase test-compile * @requiresDependencyResolution test * @author Mark Donszelmann */ public class NarTestCompileMojo extends AbstractCompileMojo { /** * Skip running of NAR integration test plugins. * * @parameter expression="${skipNar}" default-value="false" */ protected boolean skipNar; public final void narExecute() throws MojoExecutionException, MojoFailureException { // make sure destination is there getTestTargetDirectory().mkdirs(); for ( Iterator i = getTests().iterator(); i.hasNext(); ) { createTest( getAntProject(), (Test) i.next() ); } } private void createTest( Project antProject, Test test ) throws MojoExecutionException, MojoFailureException { String type = "test"; // configure task CCTask task = new CCTask(); task.setProject( antProject ); // subsystem SubsystemEnum subSystem = new SubsystemEnum(); subSystem.setValue( "console" ); task.setSubsystem( subSystem ); // outtype OutputTypeEnum outTypeEnum = new OutputTypeEnum(); outTypeEnum.setValue( Library.EXECUTABLE ); task.setOuttype( outTypeEnum ); // outDir File outDir = new File( getTestTargetDirectory(), "bin" ); outDir = new File( outDir, getAOL().toString() ); outDir.mkdirs(); // outFile File outFile = new File( outDir, test.getName() ); getLog().debug( "NAR - output: '" + outFile + "'" ); task.setOutfile( outFile ); // object directory File objDir = new File( getTestTargetDirectory(), "obj" ); objDir = new File( objDir, getAOL().toString() ); objDir.mkdirs(); task.setObjdir( objDir ); // failOnError, libtool task.setFailonerror( failOnError( getAOL() ) ); task.setLibtool( useLibtool( getAOL() ) ); // runtime RuntimeType runtimeType = new RuntimeType(); runtimeType.setValue( getRuntime( getAOL() ) ); task.setRuntime( runtimeType ); // add C++ compiler CompilerDef cpp = getCpp().getCompiler( type, test.getName() ); if ( cpp != null ) { task.addConfiguredCompiler( cpp ); } // add C compiler CompilerDef c = getC().getCompiler( type, test.getName() ); if ( c != null ) { task.addConfiguredCompiler( c ); } // add Fortran compiler CompilerDef fortran = getFortran().getCompiler( type, test.getName() ); if ( fortran != null ) { task.addConfiguredCompiler( fortran ); } // add java include paths getJava().addIncludePaths( task, type ); // add dependency include paths for ( Iterator i = getNarManager().getNarDependencies( "test" ).iterator(); i.hasNext(); ) { Artifact artifact = (Artifact) i.next(); // check if it exists in the normal unpack directory File include = getLayout().getIncludeDirectory( getUnpackDirectory(), artifact.getArtifactId(), artifact.getVersion() ); if ( !include.exists() ) { // otherwise try the test unpack directory include = getLayout().getIncludeDirectory( getTestUnpackDirectory(), artifact.getArtifactId(), artifact.getVersion() ); } if ( include.exists() ) { task.createIncludePath().setPath( include.getPath() ); } } // add javah generated include path File jniIncludeDir = getJavah().getJniDirectory(); if (jniIncludeDir.exists()) { task.createIncludePath().setPath(jniIncludeDir.getPath()); } // add linker LinkerDef linkerDefinition = getLinker().getLinker( this, antProject, getOS(), getAOL().getKey() + ".linker.", type ); task.addConfiguredLinker( linkerDefinition ); // FIXME hardcoded values String libName = getMavenProject().getArtifactId(); File includeDir = getLayout().getIncludeDirectory( getTargetDirectory(), getMavenProject().getArtifactId(), getMavenProject().getVersion() ); File libDir = getLayout().getLibDirectory( getTargetDirectory(), getMavenProject().getArtifactId(), getMavenProject().getVersion(), getAOL().toString(), test.getLink() ); // copy shared library // FIXME why do we do this ? /* * Removed in alpha-10 if (test.getLink().equals(Library.SHARED)) { try { // defaults are Unix String libPrefix * = NarUtil.getDefaults().getProperty( getAOLKey() + "shared.prefix", "lib"); String libExt = * NarUtil.getDefaults().getProperty( getAOLKey() + "shared.extension", "so"); File copyDir = new * File(getTargetDirectory(), (getOS().equals( "Windows") ? "bin" : "lib") + "/" + getAOL() + "/" + * test.getLink()); FileUtils.copyFileToDirectory(new File(libDir, libPrefix + libName + "." + libExt), * copyDir); if (!getOS().equals(OS.WINDOWS)) { libDir = copyDir; } } catch (IOException e) { throw new * MojoExecutionException( "NAR: Could not copy shared library", e); } } */ // FIXME what about copying the other shared libs? // add include of this package if ( includeDir.exists() ) { task.createIncludePath().setLocation( includeDir ); } // add library of this package if ( libDir.exists() ) { LibrarySet libSet = new LibrarySet(); libSet.setProject( antProject ); libSet.setLibs( new CUtil.StringArrayBuilder( libName ) ); LibraryTypeEnum libType = new LibraryTypeEnum(); libType.setValue( test.getLink() ); libSet.setType( libType ); libSet.setDir( libDir ); task.addLibset( libSet ); } // add dependency libraries List depLibOrder = getDependencyLibOrder(); List depLibs = getNarManager().getNarDependencies( "test" ); // reorder the libraries that come from the nar dependencies // to comply with the order specified by the user if ( ( depLibOrder != null ) && !depLibOrder.isEmpty() ) { List tmp = new LinkedList(); for ( Iterator i = depLibOrder.iterator(); i.hasNext(); ) { String depToOrderName = (String) i.next(); for ( Iterator j = depLibs.iterator(); j.hasNext(); ) { NarArtifact dep = (NarArtifact) j.next(); String depName = dep.getGroupId() + ":" + dep.getArtifactId(); if ( depName.equals( depToOrderName ) ) { tmp.add( dep ); j.remove(); } } } tmp.addAll( depLibs ); depLibs = tmp; } for ( Iterator i = depLibs.iterator(); i.hasNext(); ) { NarArtifact dependency = (NarArtifact) i.next(); // FIXME no handling of "local" // FIXME, no way to override this at this stage String binding = dependency.getNarInfo().getBinding( getAOL(), Library.NONE ); getLog().debug( "Using Binding: " + binding ); AOL aol = getAOL(); aol = dependency.getNarInfo().getAOL( getAOL() ); getLog().debug( "Using Library AOL: " + aol.toString() ); if ( !binding.equals( Library.JNI ) && !binding.equals( Library.NONE ) ) { // check if it exists in the normal unpack directory File dir = getLayout().getLibDirectory( getUnpackDirectory(), dependency.getArtifactId(), dependency.getVersion(), aol.toString(), binding ); getLog().debug( "Looking for Library Directory: " + dir ); if ( !dir.exists() ) { getLog().debug( "Library Directory " + dir + " does NOT exist." ); // otherwise try the test unpack directory dir = getLayout().getLibDirectory( getTestUnpackDirectory(), dependency.getArtifactId(), dependency.getVersion(), aol.toString(), binding ); getLog().debug( "Looking for Library Directory: " + dir ); } if ( dir.exists() ) { LibrarySet libSet = new LibrarySet(); libSet.setProject( antProject ); // FIXME, no way to override String libs = dependency.getNarInfo().getLibs( getAOL() ); if ( ( libs != null ) && !libs.equals( "" ) ) { getLog().debug( "Using LIBS = " + libs ); libSet.setLibs( new CUtil.StringArrayBuilder( libs ) ); libSet.setDir( dir ); task.addLibset( libSet ); } } else { getLog().debug( "Library Directory " + dir + " does NOT exist." ); } // FIXME, look again at this, for multiple dependencies we may need to remove duplicates String options = dependency.getNarInfo().getOptions( getAOL() ); if ( ( options != null ) && !options.equals( "" ) ) { getLog().debug( "Using OPTIONS = " + options ); LinkerArgument arg = new LinkerArgument(); arg.setValue( options ); linkerDefinition.addConfiguredLinkerArg( arg ); } String sysLibs = dependency.getNarInfo().getSysLibs( getAOL() ); if ( ( sysLibs != null ) && !sysLibs.equals( "" ) ) { getLog().debug( "Using SYSLIBS = " + sysLibs ); SystemLibrarySet sysLibSet = new SystemLibrarySet(); sysLibSet.setProject( antProject ); sysLibSet.setLibs( new CUtil.StringArrayBuilder( sysLibs ) ); task.addSyslibset( sysLibSet ); } } } // Add JVM to linker getJava().addRuntime( task, getJavaHome( getAOL() ), getOS(), getAOL().getKey() + ".java." ); // execute try { task.execute(); } catch ( BuildException e ) { throw new MojoExecutionException( "NAR: Test-Compile failed", e ); } } }