com.github.maven_nar.NarVcprojMojo Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of nar-maven-plugin Show documentation
Show all versions of nar-maven-plugin Show documentation
This plugin compiles native code and publishes native artifacts in the form of nar files.
/*
* #%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.Iterator;
import java.util.LinkedList;
import java.util.List;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.model.Profile;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.ResolutionScope;
import org.apache.maven.shared.artifact.filter.collection.ScopeFilter;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
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.ide.ProjectDef;
import com.github.maven_nar.cpptasks.ide.ProjectWriterEnum;
import com.github.maven_nar.cpptasks.types.DefineArgument;
import com.github.maven_nar.cpptasks.types.DefineSet;
import com.github.maven_nar.cpptasks.types.LibrarySet;
import com.github.maven_nar.cpptasks.types.LinkerArgument;
import com.github.maven_nar.cpptasks.types.SystemLibrarySet;
/**
* Generates a Visual Studio 2005 project file (vcproj) Heavily inspired by
* NarCompileMojo.
*
* @author Darren Sargent
*
*/
@Mojo(name = "nar-vcproj", defaultPhase = LifecyclePhase.GENERATE_RESOURCES,
requiresDependencyResolution = ResolutionScope.COMPILE)
public class NarVcprojMojo extends AbstractCompileMojo {
// FIXME: code duplication with NarCompileMojo
private void createVcProjFile(final Project antProject, final Library library)
throws MojoExecutionException, MojoFailureException {
// configure task
final CCTask task = new CCTask();
task.setProject(antProject);
task.setDebug(true);
// subsystem (console)
final SubsystemEnum subSystem = new SubsystemEnum();
subSystem.setValue(library.getSubSystem());
task.setSubsystem(subSystem);
// outtype
final OutputTypeEnum outTypeEnum = new OutputTypeEnum();
final String type = library.getType();
outTypeEnum.setValue(type);
task.setOuttype(outTypeEnum);
// stdc++
task.setLinkCPP(library.linkCPP());
// TODO: this should match the standard NAR location defined by layout
// similar to Nar Compile
// outDir
File outDir = new File(getTargetDirectory(), "bin");
outDir = new File(outDir, getAOL().toString());
outDir.mkdirs();
// outFile
final 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
final RuntimeType runtimeType = new RuntimeType();
runtimeType.setValue(getRuntime(getAOL()));
task.setRuntime(runtimeType);
// add C++ compiler
final CompilerDef cpp = getCpp().getCompiler(Compiler.MAIN, null);
if (cpp != null) {
task.addConfiguredCompiler(cpp);
}
// add VCPROJ_MOJO def (see UnitTestDriverImpl.cpp generated by Krusoe
// plugin)
final DefineSet defineSet = new DefineSet();
final DefineArgument defineArgument = new DefineArgument();
defineArgument.setName("VCPROJ_MOJO");
defineSet.addDefine(defineArgument);
cpp.addConfiguredDefineset(defineSet);
// add javah include path
final File jniDirectory = getJavah().getJniDirectory();
if (jniDirectory.exists()) {
task.createIncludePath().setPath(jniDirectory.getPath());
}
// add java include paths
getJava().addIncludePaths(task, Library.EXECUTABLE);
getMsvc().configureCCTask(task);
final List dependencies = getNarArtifacts();
// add dependency include paths
for (final Object element : dependencies) {
// FIXME, handle multiple includes from one NAR
final NarArtifact narDependency = (NarArtifact) element;
final String binding = narDependency.getNarInfo().getBinding(getAOL(), Library.STATIC);
getLog().debug("Looking for " + narDependency + " found binding " + binding);
if (!binding.equals(Library.JNI)) {
final File unpackDirectory = getUnpackDirectory();
final File include = getLayout().getIncludeDirectory(unpackDirectory, narDependency.getArtifactId(),
narDependency.getBaseVersion());
getLog().debug("Looking for directory: " + include);
if (include.exists()) {
task.createIncludePath().setPath(include.getPath());
} else {
getLog().warn(String.format("Unable to locate %1$s lib include path '%2$s'", binding, include));
}
}
}
// add linker
final LinkerDef linkerDefinition = getLinker().getLinker(this, task, getOS(), getAOL().getKey() + ".linker.",
type, null);
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)) {
final 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()) {
final List tmp = new LinkedList();
for (final Object aDepLibOrder : depLibOrder) {
final String depToOrderName = (String) aDepLibOrder;
for (final Iterator j = depLibs.iterator(); j.hasNext(); ) {
final NarArtifact dep = (NarArtifact) j.next();
final String depName = dep.getGroupId() + ":" + dep.getArtifactId();
if (depName.equals(depToOrderName)) {
tmp.add(dep);
j.remove();
}
}
}
tmp.addAll(depLibs);
depLibs = tmp;
}
for (final Object depLib : depLibs) {
final NarArtifact dependency = (NarArtifact) depLib;
// FIXME no handling of "local"
// FIXME, no way to override this at this stage
final String binding = dependency.getNarInfo().getBinding(getAOL(), Library.STATIC);
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)) {
final File unpackDirectory = getUnpackDirectory();
final File dir = getLayout()
.getLibDirectory(unpackDirectory, dependency.getArtifactId(), dependency.getBaseVersion(), aol.toString(),
binding);
getLog().debug("Looking for Library Directory: " + dir);
if (dir.exists()) {
final LibrarySet libSet = new LibrarySet();
libSet.setProject(antProject);
// FIXME, no way to override
final 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
final String options = dependency.getNarInfo().getOptions(getAOL());
if (options != null && !options.equals("")) {
getLog().debug("Using OPTIONS = " + options);
final LinkerArgument arg = new LinkerArgument();
arg.setValue(options);
linkerDefinition.addConfiguredLinkerArg(arg);
}
final String sysLibs = dependency.getNarInfo().getSysLibs(getAOL());
if (sysLibs != null && !sysLibs.equals("")) {
getLog().debug("Using SYSLIBS = " + sysLibs);
final 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.");
// DS: generate project file
getLog().debug("NAR: Writing project file...");
final ProjectWriterEnum projectWriterEnum = new ProjectWriterEnum();
projectWriterEnum.setValue("msvc8");
final ProjectDef projectDef = new ProjectDef();
projectDef.setType(projectWriterEnum);
String filename = null;
try {
final File outputDir = new File(getTargetDirectory(), "vcproj");
if (!outputDir.exists()) {
final boolean succeeded = outputDir.mkdir();
if (!succeeded) {
throw new MojoExecutionException("Unable to create directory: " + outputDir);
}
}
filename = outputDir + "/" + getMavenProject().getArtifactId();
final File projFile = new File(filename);
projectDef.setOutfile(projFile.getCanonicalFile());
} catch (final IOException e) {
throw new MojoExecutionException("Unable to create file: " + filename, e);
}
task.addProject(projectDef);
task.setProjectsOnly(true);
// we always want an EXE for debugging
task.setOuttype(new OutputTypeEnum());
// execute
try {
task.execute();
getLog().info("Wrote project file: " + filename + ".vcproj");
} catch (final BuildException e) {
throw new MojoExecutionException("NAR: Compile failed", e);
}
}
}
/**
* List the dependencies needed for compilation, those dependencies are used
* to get the include paths needed for
* compilation and to get the libraries paths and names needed for linking.
*/
@Override
protected ScopeFilter getArtifactScopeFilter() {
return new ScopeFilter( Artifact.SCOPE_COMPILE, null );
}
@Override
public void narExecute() throws MojoExecutionException, MojoFailureException {
// Only do this if MSVC++ compiler is being used.
if (!getOS().equals(OS.WINDOWS)) {
getLog().debug("Skipping -- not running on Windows");
return;
}
// need to run with profile "windows-debug". No other profiles are valid
// for vcproj generation.
boolean debug = false;
final List profiles = NarUtil.collectActiveProfiles(getMavenProject());
for (final Object profile1 : profiles) {
final Profile profile = (Profile) profile1;
if (profile.getId().equalsIgnoreCase("windows-debug")) {
debug = true;
break;
}
}
if (!debug) {
getLog().info("NAR: Skipping vcproj generation. Run with -P windows-debug to enable this step.");
return;
}
if (getLibraries().isEmpty()) {
getLog().info("NAR: Skipping vcproj generation. No libraries to be built.");
return;
}
// super.narExecute();
// arbitrarily grab the first library -- we're going to make treat it as
// an exe anyway, whatever type it's supposed to be.
createVcProjFile(getAntProject(), getLibraries().get(0));
}
}