Package com.github.maven_nar

Source Code of com.github.maven_nar.NarCompileMojo

/*
* #%L
* Native ARchive plugin for Maven
* %%
* Copyright (C) 2002 - 2014 NAR Maven Plugin developers.
* %%
* 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.
* #L%
*/
package com.github.maven_nar;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import com.github.maven_nar.cpptasks.CCTask;
import com.github.maven_nar.cpptasks.CUtil;
import com.github.maven_nar.cpptasks.CompilerDef;
import com.github.maven_nar.cpptasks.LinkerDef;
import com.github.maven_nar.cpptasks.OutputTypeEnum;
import com.github.maven_nar.cpptasks.RuntimeType;
import com.github.maven_nar.cpptasks.SubsystemEnum;
import com.github.maven_nar.cpptasks.types.LibrarySet;
import com.github.maven_nar.cpptasks.types.LinkerArgument;
import com.github.maven_nar.cpptasks.types.SystemLibrarySet;

import org.apache.maven.execution.MavenSession;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.ResolutionScope;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.codehaus.plexus.util.FileUtils;
import org.codehaus.plexus.util.StringUtils;

/**
* Compiles native source files.
*
* @requiresSession
* @author Mark Donszelmann
*/
@Mojo(name = "nar-compile", defaultPhase = LifecyclePhase.COMPILE, requiresProject = true, requiresDependencyResolution = ResolutionScope.COMPILE)
public class NarCompileMojo
    extends AbstractCompileMojo
{
    /**
     * The current build session instance.
     */
    @Component
    protected MavenSession session;

    @Override
    protected List/*<Artifact>*/ getArtifacts() {
        return getMavenProject().getCompileArtifacts()// Artifact.SCOPE_COMPILE
    }

    private void copyInclude( Compiler c )
        throws IOException, MojoExecutionException, MojoFailureException
    {
        if ( c == null )
        {
            return;
        }
        c.copyIncludeFiles( getMavenProject(),
                            getLayout().getIncludeDirectory( getTargetDirectory(),
                                                             getMavenProject().getArtifactId(),
                                                             getMavenProject().getVersion() ) );
    }

    public final void narExecute()
        throws MojoExecutionException, MojoFailureException
    {
        super.narExecute();

        // make sure destination is there
        getTargetDirectory().mkdirs();

        // check for source files
        int noOfSources = 0;
        noOfSources += getSourcesFor(getCpp()).size();
        noOfSources += getSourcesFor(getC()).size();
        noOfSources += getSourcesFor(getFortran()).size();
        if ( noOfSources > 0 )
        {
            getLog().info( "Compiling " + noOfSources + " native files" );
            for ( Iterator<Library> i = getLibraries().iterator(); i.hasNext(); )
            {
                createLibrary(getAntProject(), (Library) i.next());
            }
        }
        else
        {
            getLog().info( "Nothing to compile" );
        }

        try
        {
            // FIXME, should the include paths be defined at a higher level ?
            copyInclude(getCpp());
            copyInclude(getC());
            copyInclude(getFortran());
        }
        catch ( IOException e )
        {
            throw new MojoExecutionException( "NAR: could not copy include files", e );
        }

        getNarInfo().writeToDirectory( classesDirectory );
    }

    private List getSourcesFor( Compiler compiler )
        throws MojoFailureException, MojoExecutionException
    {
        if ( compiler == null )
        {
            return Collections.EMPTY_LIST;
        }

        try
        {
            List files = new ArrayList();
            List srcDirs = compiler.getSourceDirectories();
            for ( Iterator i = srcDirs.iterator(); i.hasNext(); )
            {
                File dir = (File) i.next();
                if ( dir.exists() )
                {
                    files.addAll( FileUtils.getFiles( dir, StringUtils.join( compiler.getIncludes().iterator(), "," ),
                                                      null ) );
                }
            }
            return files;
        }
        catch ( IOException e )
        {
            return Collections.EMPTY_LIST;
        }
    }

    private void createLibrary(Project antProject, Library library)
        throws MojoExecutionException, MojoFailureException
    {
        getLog().debug( "Creating Library " + library );
        // configure task
        CCTask task = new CCTask();
        task.setCommandLogLevel( commandLogLevel );
        task.setProject(antProject);

        task.setDecorateLinkerOptions(decorateLinkerOptions);

        task.setDecorateLinkerOptions(decorateLinkerOptions);

        // subsystem
        SubsystemEnum subSystem = new SubsystemEnum();
        subSystem.setValue( library.getSubSystem() );
        task.setSubsystem( subSystem );

        // set max cores
        task.setMaxCores(getMaxCores(getAOL()));

        // outtype
        OutputTypeEnum outTypeEnum = new OutputTypeEnum();
        String type = library.getType();
        outTypeEnum.setValue(type);
        task.setOuttype(outTypeEnum);

        // stdc++
        task.setLinkCPP(library.linkCPP());

        // fortran
        task.setLinkFortran(library.linkFortran());
        task.setLinkFortranMain( library.linkFortranMain() );

        // outDir
        File outDir;
        if ( type.equals( Library.EXECUTABLE ) )
        {
            outDir =
                getLayout().getBinDirectory( getTargetDirectory(), getMavenProject().getArtifactId(),
                                             getMavenProject().getVersion(), getAOL().toString() );
        }
        else
        {
            outDir =
                getLayout().getLibDirectory( getTargetDirectory(), getMavenProject().getArtifactId(),
                                             getMavenProject().getVersion(), getAOL().toString(), type );
        }
        outDir.mkdirs();

        // outFile
        // FIXME NAR-90 we could get the final name from layout
        File outFile = new File(outDir, getOutput(getAOL(), type) );
        getLog().debug("NAR - output: '" + outFile + "'");
        task.setOutfile(outFile);

        // object directory
        File objDir = new File(getTargetDirectory(), "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);

        // IDL, MC, RC compilations should probably be 'generate source' type actions, seperate from main build.
        // Needs resolution of handling for generate sources.
        // Order is somewhat important here, IDL and MC generate outputs that are (often) included in the RC compilation
        if (getIdl() != null) {
            CompilerDef idl = getIdl().getCompiler( Compiler.MAIN, null );
            if ( idl != null )
            {
                task.addConfiguredCompiler( idl );
            }
        }
        if (getMessage() != null) {
            CompilerDef mc = getMessage().getCompiler( Compiler.MAIN, null );
            if ( mc != null )
            {
                task.addConfiguredCompiler( mc );
            }
        }
        if (getResource() != null) {
            CompilerDef res = getResource().getCompiler( Compiler.MAIN, null );
            if ( res != null )
            {
                task.addConfiguredCompiler( res );
            }
        }
       
        // Darren Sargent Feb 11 2010: Use Compiler.MAIN for "type"...appears the wrong "type" variable was being used
        // since getCompiler() expects "main" or "test", whereas the "type" variable here is "executable", "shared" etc.
        // add C++ compiler
        if (getCpp() != null) {
            CompilerDef cpp = getCpp().getCompiler( Compiler.MAIN, null );
            if ( cpp != null )
            {
                task.addConfiguredCompiler( cpp );
            }
        }

        // add C compiler
        if (getC() != null) {
            CompilerDef c = getC().getCompiler( Compiler.MAIN, null );
            if ( c != null )
            {
                task.addConfiguredCompiler( c );
            }
        }

        // add Fortran compiler
        if (getFortran() != null) {
            CompilerDef fortran = getFortran().getCompiler( Compiler.MAIN, null );
            if ( fortran != null )
            {
                task.addConfiguredCompiler( fortran );
            }
        }
        // end Darren

        // add javah include path
        File jniDirectory = getJavah().getJniDirectory();
        if (jniDirectory.exists())
        {
            task.createIncludePath().setPath(jniDirectory.getPath());
        }

        // add java include paths
        getJava().addIncludePaths(task, type);

        List<NarArtifact> dependencies = getNarArtifacts();
        // add dependency include paths
        for ( Iterator i = dependencies.iterator(); i.hasNext(); )
        {
            // FIXME, handle multiple includes from one NAR
            NarArtifact narDependency = (NarArtifact) i.next();
            String binding = narDependency.getNarInfo().getBinding(getAOL(), Library.STATIC);
            getLog().debug( "Looking for " + narDependency + " found binding " + binding);
            if ( !binding.equals(Library.JNI ) )
            {
                File unpackDirectory = getUnpackDirectory();
                File include =
                    getLayout().getIncludeDirectory( unpackDirectory, narDependency.getArtifactId(),
                                                     narDependency.getBaseVersion() );
                getLog().debug( "Looking for include directory: " + include );
                if ( include.exists() )
                {
                    task.createIncludePath().setPath(include.getPath());
                } else {
                    throw new MojoExecutionException(
                            "NAR: unable to locate include path: " + include);
                }
            }
        }

        // add linker
        LinkerDef linkerDefinition =
            getLinker().getLinker( this, antProject, getOS(), getAOL().getKey() + ".linker.", type );
        task.addConfiguredLinker(linkerDefinition);

        // add dependency libraries
        // FIXME: what about PLUGIN and STATIC, depending on STATIC, should we
        // not add all libraries, see NARPLUGIN-96
        if ( type.equals( Library.SHARED ) || type.equals( Library.JNI ) || type.equals( Library.EXECUTABLE ) )
        {

            List depLibOrder = getDependencyLibOrder();
            List depLibs = dependencies;

            // 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 ) && !binding.equals( Library.EXECUTABLE) )
                {
                    File unpackDirectory = getUnpackDirectory();

                    File dir =
                        getLayout().getLibDirectory( unpackDirectory, dependency.getArtifactId(),
                                                     dependency.getBaseVersion(), 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: Compile failed", e);
        }

        // FIXME, this should be done in CPPTasks at some point
        if ( getRuntime( getAOL() ).equals( "dynamic" ) && getOS().equals( OS.WINDOWS )
            && getLinker().getName( null, null ).equals( "msvc" ) && !getLinker().getVersion().startsWith( "6." ) )
        {
            String libType = library.getType();
            if ( libType.equals( Library.JNI ) || libType.equals( Library.SHARED ) )
            {
                String dll = outFile.getPath() + ".dll";
                String manifest = dll + ".manifest";
                int result =
                    NarUtil.runCommand( "mt.exe", new String[] { "/manifest", manifest,
                        "/outputresource:" + dll + ";#2" }, null, null, getLog() );
                if (result != 0)
                {
                    throw new MojoFailureException("MT.EXE failed with exit code: " + result);
                }
            } else if (libType.equals(Library.EXECUTABLE)) {
                String exe = outFile.getPath() + ".exe";
                String manifest = exe + ".manifest";
                int result = NarUtil.runCommand("mt.exe",
                        new String[] { "/manifest", manifest,
                                "/outputresource:" + exe + ";#1" }, null, null, getLog());
                if (result != 0)
                    throw new MojoFailureException(
                            "MT.EXE failed with exit code: " + result);
            }
        }
    }
}
TOP

Related Classes of com.github.maven_nar.NarCompileMojo

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.